Skip to main content
Your integration runs on three runtime credentials, all minted in the dashboard under your store’s Implementation tab (or Settings for individual keys): A single API key carrying both usage scopes works in place of the two scoped keys. Every SDK accepts either form and falls back to the combined key when a scoped key is unset. ZeroClick shows every secret once, at creation, and cannot show it again. The dashboard displays the first characters of each API key for recognition. Put them in your secret manager immediately:

The kid must match exactly

The dashboard shows the signing secret’s key id, the kid (format hsec_…), next to the secret. The kid arrives in every zc-signature header (t=…,kid=hsec_k5nq0v7m3d8p,v1=…). The SDKs use the kid to select which secret verifies each request. The key in your secrets map must match the dashboard’s key id character for character. A mismatched kid fails every request with unknown_kid and the 401 refusal.

Scopes

Send API keys as Authorization: Bearer zc_… to https://api.zeroclick.io. Each key carries one or more of four scopes: Manage keys in the dashboard under Settings → API keys, in a signed-in session only: API keys cannot create or revoke API keys. Requests with a missing scope get 403 {"error":"insufficient_scope"}. See errors.

Split read and write keys

The process that guards requests only needs to read allowances; the process that reports usage only needs to write. Splitting the keys follows least privilege and matches a common deployment shape. The read key lives in the service that serves requests; the write key lives in the worker that reports usage asynchronously.
The read key covers guard and the direct allowance check; the write key covers usage reporting. When you pass both scoped keys, omit the combined apiKey.

Rotate a signing secret

ZeroClick signs each forwarded request with your newest active secret and names it by kid, so rotation is a three-step overlap, not a cutover:
1

Create the new secret in the dashboard

ZeroClick starts signing new requests with it. The signature’s kid changes to the new secret’s id.
2

Hold both kids in your SDK configuration

Requests signed with either secret verify while both are configured:
3

Revoke the old secret, then drop it

Once requests signed with the old secret can no longer be in flight, revoke it in the dashboard. Verification rejects signatures older than the 300-second tolerance anyway, so a few minutes of overlap is enough. Then remove the old kid from your configuration.
Never log or return a signing secret, and never send it anywhere. It exists only to verify signatures inside your backend.

Resolve secrets from a vault

If your secrets live in a secret manager rather than the environment, resolve them by kid instead of passing a static map:
The SDK calls the resolver with each request’s kid. Signal “unknown kid” by returning null (TypeScript), None (Python), or ok=false (Go). That request gets the 401 refusal. An unreachable vault is a different case: raise or return an error so it surfaces loudly instead of refusing valid traffic. Rotation works the same way as the static map: keep the vault serving both kids until the old one ages out. With keys in place, the first obligation is verifying requests.