> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kash.bot/llms.txt
> Use this file to discover all available pages before exploring further.

# Keys, approval and IP allowlists

> Test keys for the sandbox, live keys after approval, the IP allowlist a live key must carry, scopes and webhook URLs.

A partner key belongs to your organisation and has no user of its own. It can trade for, and withdraw for, every one of your users, and partner accounts have no spending caps, so treat it as more sensitive than any other API key. Keep partner keys and webhook secrets on your servers only.

Send the key in the `X-API-Key` header, as for any [API key](https://docs.kash.bot/developer-docs/rest-api/authentication.md).

## Test and live keys

| | Test key (`kash_test_`) | Live key (`kash_live_`) |
| - | - | - |
| Works on | Staging, `https://api-staging.kash.bot/v1` | Production, `https://api.kash.bot/v1` |
| Issued by | ZeroID, on request | ZeroID, after it approves your organisation |
| IP allowlist | Optional | Required, at least one entry |

ZeroID issues every partner key. You cannot create a partner key yourself. Ask from the info button in the Kash web app → **Feedback**, or in [Discord](https://discord.com/invite/n9eumqjMPb).

## Ask for a test key

Send ZeroID:

* your company name;
* a contact email, where ZeroID reaches you about approval and incidents;
* the technical contact who should receive the key and the webhook secret;
* your staging webhook URL, a public `https` address;
* optionally, your servers' egress addresses, so the test key carries the same [IP allowlist](#ip-allowlist) your live key will need.

If your company already has a Kash organisation, say so, and the key is issued to it. Otherwise ZeroID creates your organisation on staging.

ZeroID sends the key and its webhook signing secret to your technical contact through an expiring, end-to-end encrypted share, and tells you the key's id separately. Store the key and the secret on your server. Neither can be shown again: a lost key is revoked and a new one issued.

## Approval for production

Production needs a one-time approval of your organisation by ZeroID. Ask for it from the info button in the Kash web app → **Feedback**, or in [Discord](https://discord.com/invite/n9eumqjMPb).

Once you are approved, send ZeroID your servers' egress addresses for the IP allowlist and your production webhook URL. ZeroID issues your `kash_live_` key and delivers it, with its webhook secret, in the same way as the test key. See the [go-live checklist](https://docs.kash.bot/developer-docs/partner-integration/go-live.md).

Approval is checked again on every request a live key makes. If ZeroID withdraws your organisation's approval, every `kash_live_` partner key you hold stops working on its next request with `401 API_KEY_REVOKED` and the detail "This API key has been revoked: its organisation is no longer approved for live partner keys. Contact Kash to restore access." No new live key can be created until approval is restored. Test keys need no approval and are not affected.

## IP allowlist

A live partner key must carry an IP allowlist: list the egress addresses of the servers that call the API. A call from any other address is refused with `403 IP_NOT_ALLOWED`.

Every entry must be specific:

* a single IPv4 or IPv6 address;
* an IPv4 range of `/16` or narrower;
* an IPv6 range of `/48` or narrower.

A broader range, such as `0.0.0.0/0`, `::/0`, `10.0.0.0/8` or `2001:db8::/32`, is refused when the key is issued. The same rule applies to an allowlist on a test key, so an allowlist that works on staging carries over to production unchanged. A key holds at most 50 entries.

To change a key's allowlist, send ZeroID the key's id and the complete new list. The new list replaces the old one.

A staging key is not known in production and is refused there with `401 API_KEY_INVALID`. As a further safeguard, production refuses every request with `403 PARTNER_KEY_REQUIRES_IP_ALLOWLIST` when a partner key:

* is a test-type (`kash_test_`) key;
* has no allowlist;
* has an entry broader than the limits above.

The `detail` says which, and names any over-broad entry.

## Scopes

A partner key is issued with these scopes by default:

| Scope | What it allows for a partner key |
| - | - |
| `partner:accounts` | Every `/v1/partner/accounts` route, including withdrawals. Only partner keys can hold it. |
| `markets:read` | `GET /v1/markets`, `GET /v1/markets/{id}`, `GET /v1/markets/{id}/predictions` |
| `markets:quote` | `GET /v1/markets/{id}/quote` |
| `portfolio:read` | `GET /v1/balance`, `GET /v1/portfolio`, `GET /v1/portfolio/positions`, for the account in `Kash-Account` |
| `trades:read` | `GET /v1/trades`, `GET /v1/trades/{id}`, `GET /v1/traces/{correlationId}`, for the account in `Kash-Account` |
| `trades:write` | `POST /v1/trades`, `POST /v1/trades/{id}/confirm`, `POST /v1/redemptions`, for the account in `Kash-Account` |
| `webhooks:manage` | `GET /v1/webhooks/events`, `POST /v1/webhooks/events/{eventId}/redeliver` and `POST /v1/auth/api-keys/me/webhook-secret/rotate`: inspect and replay deliveries, and rotate the signing secret from your server. |

One scope is opt-in. Ask ZeroID to add it when the key is issued if you need it:

| Scope | What it allows |
| - | - |
| `auth:manage` | `GET /v1/account/usage` |

A call without the route's scope is refused with `403 INSUFFICIENT_SCOPE`.

Competitions, market disputes and revenue share are for user keys only. A partner key that calls them is refused with `403 INSUFFICIENT_SCOPE`.

## Webhook URL and secret

Each partner key can have one webhook URL, which must use `https`. ZeroID sets it when it issues the key.

* Each URL has its own signing secret, delivered once with the key.
* To change the URL, send ZeroID the key's id and the new URL, and agree a time for the switch. Replacing the URL creates a new secret, which ZeroID delivers to your technical contact, and the old secret stops signing at once, including an older secret still inside a rotation window. Install the new secret on the new endpoint before the switch.
* To rotate the secret of an unchanged URL yourself, call `POST /v1/auth/api-keys/me/webhook-secret/rotate` from your server with the key itself. It needs the `webhooks:manage` scope, which partner keys have by default. Old and new secrets both sign for 7 days. See [Secret rotation](https://docs.kash.bot/developer-docs/rest-api/webhooks/secret-rotation.md). If a rotation breaks your verifier, ZeroID can restore the previous secret within those 7 days.

See [Webhooks](https://docs.kash.bot/developer-docs/partner-integration/webhooks.md) for what is delivered.

## Key limits and rotation

* An organisation can hold at most **5 active partner keys**.
* ZeroID issues and revokes partner keys. To revoke one, send ZeroID its id.
* A revoked key stops working on its next request (`401 API_KEY_REVOKED`).

To rotate a key, ask ZeroID for a new one, deploy it, confirm the old key has gone quiet, then ask ZeroID to revoke the old key. While two keys have webhook URLs, each receives its own copy of every account, withdrawal and payout event (see [Who receives what](https://docs.kash.bot/developer-docs/partner-integration/webhooks.md#who-receives-what)).

## Next

> [card] [Accounts](https://docs.kash.bot/developer-docs/partner-integration/accounts.md)
>
> Create an account for each user who opts in.

> [card] [Go-live checklist](https://docs.kash.bot/developer-docs/partner-integration/go-live.md)
>
> Everything to have in place before production.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.