# Quickstart: link a Cardano stake address with CIP-8

> To link a Cardano stake address to the Gatewayz API, request a nonce with POST /auth/wallet/cardano/nonce, sign the returned message with the stake key using CIP-8 (CIP-30 signData in a browser wallet), and send the COSE_Sign1 signature and COSE_Key to POST /auth/wallet/cardano/link with your API key. No transaction or fee is involved.

**In one line:** Ask for a nonce, sign the exact message with the stake key, send back the signature and key: the wallet is linked without a transaction.

To link a Cardano [stake address](/yield/glossary#stake-address) to the Gatewayz API, you ask for a nonce, sign the message it sends back with the stake key using [CIP-8](/yield/glossary#cip-8), and post the signature and public key back. The whole exchange is two HTTPS calls and one local signature: no transaction, no fee and no deposit. After that, staking rewards from the Gatewayz pool start arriving as an [inference discount balance](/yield/glossary#inference-discount-balance) on the account that owns your [API key](/yield/glossary#api-key).

**Pre-launch.** The program is built and switched off on mainnet. A working demo runs on Cardano's preprod testnet with test ADA, by invitation. Not available to US or Canadian persons. Every participant must confirm they are not a US or Canadian person before linking a wallet.

## Key takeaways

- Linking proves you control a stake key by signing a message; CIP-8 signing does not send a transaction or cost a fee.
- Only key-hash stake addresses (`stake1u...` on mainnet) can be linked; script stake addresses (`stake17...`) are rejected.
- Delegation is a separate, ordinary Cardano transaction signed by your own wallet. Gatewayz is not part of it.
- Every call except `GET /delegation/status` needs `Authorization: Bearer <Gatewayz API key>`.
- You must confirm you are not a US or Canadian person, either in the nonce or link call or through `POST /delegation/eligibility`.

## What do you need before you start?

You need a Gatewayz API key, a Cardano wallet whose stake key you control, and `curl`. Set them as environment variables so the examples below run as written.

```bash
export GATEWAYZ_API_KEY="..."          # your Gatewayz API key; never commit it
export STAKE_ADDRESS="stake1u..."      # a key-hash stake address
export API="https://api.gatewayz.ai"
```

The stake address must be a key-hash address. On mainnet those start with `stake1u`. A script stake address, starting with `stake17`, is not supported and is rejected with `script_stake_address_unsupported`. If you have never made an API request before, [Your first Gatewayz API request](/learn/first-gatewayz-api-request) covers keys and headers.

## Step 1: is the program on, and which pool is it?

Call `GET /delegation/status`. It needs no authentication and tells you whether the program is on, the Cardano pool id and network, the reward share, the discount and the disclaimer.

```bash
curl -s "$API/delegation/status"
```

The pool id is at `data.cardano.pool_id` in the response. Until the mainnet pool launches it may be absent; the program is pre-launch and the working demo runs on Cardano's preprod testnet by invitation.

## Step 2: how do you delegate to the pool?

You delegate with a normal Cardano delegation transaction, built and signed by your own wallet, pointing your stake key at the pool id from step 1. Gatewayz does not build, sign or see that transaction.

On Cardano, delegating one staking key takes a single transaction containing a [delegation certificate](/yield/glossary#delegation-certificate) and costs only the usual transaction fee. The first time a stake address is registered there is also a one-time [stake address deposit](/yield/glossary#stake-address-deposit), currently 2 ADA, refunded in full when the address is deregistered. Your ADA stays in your wallet and can be spent at any time. Use any wallet or library you trust; the steps below only need the stake address. You can link before or after delegating, but discounts accrue only for epochs in which your stake is active in the pool. [How Cardano staking works](/yield/learn/how-cardano-staking-works) explains the certificate and the timing.

## Step 3: how do you request a nonce?

`POST /auth/wallet/cardano/nonce` with your stake address and the eligibility attestation. The response is a JSON object with `nonce`, `message` and `expires_at`.

```bash
curl -s -X POST "$API/auth/wallet/cardano/nonce" \
  -H "Authorization: Bearer $GATEWAYZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"stake_address\": \"$STAKE_ADDRESS\", \"not_us_ca_person\": true}"
```

- `message` is the exact text your wallet must sign. Do not trim, reformat or re-encode it as anything other than its UTF-8 bytes.
- `expires_at` is when the nonce stops being accepted. Sign and link before then, or you get `nonce_missing_or_expired` and must request a new one.
- `not_us_ca_person: true` is your confirmation that you are not a US or Canadian person. The program is not available to US or Canadian persons.

## Step 4: how do you sign the message with CIP-8?

Sign the `message` bytes with the stake key, producing a COSE_Sign1 signature and a COSE_Key, both hex-encoded. In a browser wallet this is the [CIP-30](/yield/glossary#cip-30) `signData` call, which uses CIP-8 under the hood.

```js
// In a page that talks to a CIP-30 wallet (Lace shown; Eternl, Yoroi, VESPR work the same way).
const api = await window.cardano.lace.enable();

// CIP-30 gives addresses as hex-encoded bytes. The first reward address is the stake address.
const [stakeAddressHex] = await api.getRewardAddresses();

// The payload must be hex-encoded bytes: hex of the UTF-8 message from step 3.
const message = nonceResponse.message;
const messageHex = Array.from(new TextEncoder().encode(message))
  .map((b) => b.toString(16).padStart(2, "0"))
  .join("");

// Signs with the stake key. Resolves to { signature: COSE_Sign1 hex, key: COSE_Key hex }.
const { signature, key } = await api.signData(stakeAddressHex, messageHex);
```

Two details trip people up. First, `signData` takes the payload as hex-encoded bytes, not as a plain string, so encode the message as UTF-8 and then as hex. Second, CIP-30 passes addresses as hex-encoded bytes; passing the address from `getRewardAddresses()` tells the wallet to sign with the stake key rather than a payment key. The Gatewayz API expects the bech32 form (`stake1u...`) in `stake_address`, which is the same address in a different encoding.

A headless agent without a browser wallet signs the same way with any library that produces a CIP-8 COSE_Sign1 and COSE_Key from its stake signing key. Keep the signing key local to the agent; only the signature and the public COSE_Key leave it.

## Step 5: how do you link the wallet?

`POST /auth/wallet/cardano/link` with the stake address, the signature, the key and the attestation. On success the stake address is linked to the Gatewayz account that owns the API key.

```bash
curl -s -X POST "$API/auth/wallet/cardano/link" \
  -H "Authorization: Bearer $GATEWAYZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{\"stake_address\": \"$STAKE_ADDRESS\", \"signature\": \"$SIGNATURE_HEX\", \"key\": \"$KEY_HEX\", \"not_us_ca_person\": true}"
```

If you did not send `not_us_ca_person` in either call, record it separately before any discount is granted:

```bash
curl -s -X POST "$API/delegation/eligibility" \
  -H "Authorization: Bearer $GATEWAYZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"not_us_ca_person": true}'
```

## Step 6: how do you check the discount balance?

`GET /delegation/rewards` with your API key. It responds with your linked wallets, measured positions, the discount balance and its history, your eligibility and the disclaimer.

```bash
curl -s "$API/delegation/rewards" -H "Authorization: Bearer $GATEWAYZ_API_KEY"
```

Expect an empty history at first. Cardano pays rewards a few epochs after they are earned, so the first discount appears roughly two to three weeks after you first delegate. Polling once a day is enough, since accounting runs daily after a finished epoch is recorded. To recompute any entry yourself from public chain data, see [Verify your discount](/yield/verify).

## Step 7: how do you spend it?

Make inference requests as usual. While the balance lasts, each request through `/v1/chat/completions` or `/v1/messages` costs 1% of its list price from your credits, and the other 99% is drawn from the balance.

```bash
curl -s "$API/v1/chat/completions" \
  -H "Authorization: Bearer $GATEWAYZ_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model": "<model id>", "messages": [{"role": "user", "content": "Hello"}]}'
```

Launch limits: at most $5 of discount per account per day, and at most $50 per day across the whole program. Limits may change.

## What should you do when a call fails?

Read the `code` in the error, not the message text, and follow its remedy. Most link failures mean the signature did not match the issued message or address: request a fresh nonce and sign the exact message again with the right stake key.

Every code, with a decision table for retry, re-sign or stop, is on [Errors](/yield/agents/errors).

## Frequently asked questions

### Does linking a stake address cost a fee?

No. Linking is a CIP-8 signed message, not a transaction, so nothing is submitted to the chain and no fee is paid. Only the delegation itself is a transaction, with the usual Cardano fee and, for a stake address that was never registered, the one-time refundable deposit.

### Why does signData need hex instead of the message text?

CIP-30 defines the payload of `signData` as hex-encoded bytes, so wallets sign exactly the bytes you pass. Encode the message from the nonce response as UTF-8, convert those bytes to hex, and pass that string; any other transformation changes the signed payload and the link call fails with `payload_mismatch`.

### Which address do I pass to signData?

Pass the stake (reward) address, which a CIP-30 wallet gives in hex from `getRewardAddresses()`. Signing with that address makes the wallet use the stake key; signing with a payment address uses a different key and the link call fails with `address_mismatch`.

### How long is a nonce valid?

Until the `expires_at` time in the nonce response. If you sign or send it after that, the link call fails with `nonce_missing_or_expired`, and you simply request a new nonce and sign again.

### Can I link more than one wallet to an account?

The rewards endpoint reports linked wallets in the plural, so an account can hold several. A single stake address can belong to only one Gatewayz account; linking it to a second account fails with `wallet_linked_to_other_account`.

### Do I have to delegate before linking?

No. You can link before or after delegating. Discounts are only calculated for epochs in which your stake is active in the Gatewayz pool, so linking early does not create a discount by itself.

## Sources

- [CIP-0008: Message Signing](https://cips.cardano.org/cip/CIP-0008), as of 2026-10-27
- [CIP-0030: Cardano dApp-Wallet Web Bridge](https://cips.cardano.org/cip/CIP-0030), as of 2026-10-27
- [Cardano Docs: Delegation](https://docs.cardano.org/about-cardano/learn/delegation), as of 2026-10-27
- [Cardano.org Glossary: Stake Address Deposit](https://cardano.org/glossary/stake-address-deposit/), as of 2026-10-27
- [Cardano.org: Stake your ada on Cardano](https://cardano.org/stake-pool-delegation/), as of 2026-10-27

## Related

- [A compute budget that refills itself](https://www.gatewayz.ai/yield/agents)
- [Delegation API reference](https://www.gatewayz.ai/yield/agents/api)
- [Wallet link and delegation error codes](https://www.gatewayz.ai/yield/agents/errors)
- [How yield-as-inference works](https://www.gatewayz.ai/yield/how-it-works)

---

Discounts are a share of staking rewards Gatewayz actually received, can change at any time, and are not a guaranteed return. Not available to US or Canadian persons. Every participant must confirm they are not a US or Canadian person before linking a wallet. Not investment, legal or tax advice. Figures as of 2026-10-27.

Updated 2026-10-27. Canonical page: https://www.gatewayz.ai/yield/agents/quickstart
