# API keys

> How ZeroCaptcha API keys work, from their scopes to allowlists, rotation with an overlap and revocation.

Source: https://zerocaptcha.io/docs/keys

Every call to the API carries an API key, and the key decides what the call may do: which scopes
it has and which addresses it may come from. You manage your keys in the dashboard.

## Create a key

An owner of the account creates keys on the dashboard's API keys page, or the first one on the
Overview in one click. Creating a key needs your email address confirmed: until you open the link
we emailed you, creating one is refused with
[`email_unverified`](https://zerocaptcha.io/docs/reference/errors#email_unverified), and the dashboard offers to send
the link again. Keys made before keep working, and you can still rename, rotate and revoke them.

## Send the key

The REST API takes the key as a bearer token:

```sh
curl "$ZEROCAPTCHA_API/v1/tasks" \
  -H "Authorization: Bearer $ZEROCAPTCHA_KEY"
```

The compatible calls, `createTask`, `getTaskResult` and `getBalance`, take it as `clientKey` in the
JSON body instead, as other providers' clients already send it, and the 2Captcha format as the
`key` parameter. See [Authentication](https://zerocaptcha.io/docs/authentication) for keeping keys safe.

## What a key looks like

A key is 41 characters: `zc_live_`, 27 random characters, then a 6-character checksum. The prefix makes a leaked key easy to spot, and the checksum lets a secret scanner confirm
a match without calling us.

A key is shown once, when it is created, and only its hash is stored. Store it in a secret manager at once. Afterwards the dashboard shows each key
by its first and last characters, such as `zc_live_8K2p…f41c`, which is enough to tell your keys
apart and too little to use.

## One kind of key

Every key works the same way: its tasks solve real challenges, and each solved task is charged from
your balance. A key sees every task of its account, whichever key created it.

## Scopes

Each key has one or both of two scopes:

| Scope | What the key may do |
| --- | --- |
| `tasks` | Create tasks and read them, their results and their live updates |
| `balance` | Read the balance |

A call outside a key's scopes is refused with
[`insufficient_scope`](https://zerocaptcha.io/docs/reference/errors#insufficient_scope), or
[`ERROR_ACCESS_DENIED`](https://zerocaptcha.io/docs/reference/errors#ERROR_ACCESS_DENIED) in the compatible dialect.

## Allowed IP addresses

A key can be held to up to 100 IP addresses or CIDR networks, IPv4 or IPv6, such as `203.0.113.24`
or `198.51.100.0/24`. Write a network with no bits set past its prefix: `198.51.100.0/24`, not
`198.51.100.7/24`. A key with an empty list works from any address.

A call from any other address is refused with
[`ip_not_allowed`](https://zerocaptcha.io/docs/reference/errors#ip_not_allowed), or
[`ERROR_IP_NOT_ALLOWED`](https://zerocaptcha.io/docs/reference/errors#ERROR_IP_NOT_ALLOWED). A change to the list, or to
the key's name, applies to the key's next call.

## Rotate a key

Rotate a key to replace it without an outage, on a schedule or as soon as it may have leaked.

1. **Choose an overlap.** Rotating makes a new key with the old one's name, scopes and allowed
   addresses, and shows it once. The old key keeps working for the overlap you choose:
   1 hour, 24 hours or 7 days.

2. **Deploy the new key.** During the overlap both keys work, so your running code never stops.

3. **Let the old key go.** At the end of the overlap the old key stops working. If you finish
   sooner, end the overlap from the keys page and it stops at once.

After its overlap, a call with the old key is refused as revoked:
[`key_revoked`](https://zerocaptcha.io/docs/reference/errors#key_revoked), or
[`ERROR_KEY_REVOKED`](https://zerocaptcha.io/docs/reference/errors#ERROR_KEY_REVOKED), with a description that says the
key was rotated. A key is rotated once: to rotate again, rotate the key that replaced it.

## Revoke a key

Revoking a key stops it at once: every later call with it is refused with `key_revoked`, or
`ERROR_KEY_REVOKED`. Tasks it already created run to their end, charged only if they succeed. A
revoked key stays on the keys page, so older tasks can still be traced to it, and it can never work
again: to replace it, create a new key.

## Cap a key's daily spend

A key can have a daily spend cap, in US dollars: the most its tasks may hold or be charged in one
UTC day. A task that would pass it is refused before any money moves, with
[`spend_cap_reached`](https://zerocaptcha.io/docs/reference/errors#spend_cap_reached), or
[`ERROR_SPEND_CAP_REACHED`](https://zerocaptcha.io/docs/reference/errors#ERROR_SPEND_CAP_REACHED), and HTTP 402. A
task that fails or expires stops counting. A key has no cap until you set one on the keys page,
which lists each key's cap beside it, and the API shows it as `dailyCap` on the key.

## When a key was last used

The keys page shows when each key last made a call it was allowed to make, and the address that
call came from. They are recorded in batches, so they can trail the latest call by up to half a
minute. A refused call does not count as a use.

## Limits

- An account may have 20 active keys. A key being replaced by a rotation, and a revoked key, does
  not count, so rotating a key never needs a free place. Beyond the limit, creating a key is
  refused with [`key_limit_reached`](https://zerocaptcha.io/docs/reference/errors#key_limit_reached).
- Keys are managed from a signed-in dashboard session only: no API key may create, change or
  revoke keys, its own included.

## Errors

| Code | Dialect | When |
| --- | --- | --- |
| [`unauthorized`](https://zerocaptcha.io/docs/reference/errors#unauthorized), [`ERROR_KEY_DOES_NOT_EXIST`](https://zerocaptcha.io/docs/reference/errors#ERROR_KEY_DOES_NOT_EXIST) | REST, compatible | The key is missing, mistyped or unknown |
| [`key_revoked`](https://zerocaptcha.io/docs/reference/errors#key_revoked), [`ERROR_KEY_REVOKED`](https://zerocaptcha.io/docs/reference/errors#ERROR_KEY_REVOKED) | REST, compatible | The key was revoked, or its rotation's overlap ended |
| [`ip_not_allowed`](https://zerocaptcha.io/docs/reference/errors#ip_not_allowed), [`ERROR_IP_NOT_ALLOWED`](https://zerocaptcha.io/docs/reference/errors#ERROR_IP_NOT_ALLOWED) | REST, compatible | The call came from an address the key does not allow |
| [`insufficient_scope`](https://zerocaptcha.io/docs/reference/errors#insufficient_scope), [`ERROR_ACCESS_DENIED`](https://zerocaptcha.io/docs/reference/errors#ERROR_ACCESS_DENIED) | REST, compatible | The key lacks the scope the call needs |
| [`email_unverified`](https://zerocaptcha.io/docs/reference/errors#email_unverified) | Dashboard | A new key, before your email address is confirmed |
| [`key_limit_reached`](https://zerocaptcha.io/docs/reference/errors#key_limit_reached) | Dashboard | The account has as many active keys as it may |
| [`key_state_conflict`](https://zerocaptcha.io/docs/reference/errors#key_state_conflict) | Dashboard | The key cannot change that way, such as a revoked key being rotated |

None of these costs anything. Every code, with what to do about it, is in the
[errors reference](https://zerocaptcha.io/docs/reference/errors).
