# Authentication and keys

> How to authenticate with the Couryo API using ck_live_ and ck_test_ keys, scopes, allowed IPs and good practices.

Source: https://couryo.com/en/docs/authentication

Every request to `https://api.couryo.com/v1` uses an API key in the `Authorization` header:

```http title="Header"
Authorization: Bearer ck_live_...
```

## Key types

| Prefix | Mode | What happens |
|---|---|---|
| `ck_live_` | live | real delivery |
| `ck_test_` | test | never delivers: the email is captured in the dashboard with status `captured` |

## Scopes

| Scope | Can |
|---|---|
| `send` | send and check email (`POST /v1/emails`, `/v1/emails/batch` and `/v1/emails/check`); cannot read |
| `read` | read emails, events, domains, webhooks and suppressions; cannot send |
| `admin` | everything, including creating and verifying domains, creating and changing webhooks and editing the suppression list |

Use the smallest scope you can. Your application server usually needs only `send`; to read an email's timeline, use a `read` key. Keys belong to one project: each project has its own.

## Allowed IPs

Each key can have a list of allowed IPs (addresses or CIDR ranges). A request from any other address gets a `403` with code `ip_not_allowed`.

## How we store your key

- The full key is shown **only once**, at creation. After that, the dashboard shows only the prefix (for example, `ck_live_4f9a`).
- Couryo stores only a hash of the key. If you lose it, create a new one and delete the old one.
- A deleted key stops working immediately (`401 invalid_api_key`).

## Good practices

- Keep the key in an environment variable or a secrets manager. Never in browser or mobile app code.
- One key per application and environment, so you can rotate one without breaking the others.
- Protect the Google account you use to sign in to the dashboard with 2-step verification, and set a [spending limit](https://couryo.com/en/docs/limits.md#spending-limit).

## Authentication errors

| HTTP | `code` | When |
|---|---|---|
| 401 | `missing_api_key` | no `Authorization` header |
| 401 | `invalid_api_key` | key does not exist, was deleted or was copied incorrectly |
| 403 | `insufficient_scope` | the key lacks the required scope |
| 403 | `ip_not_allowed` | the request came from an IP outside the list |

See every code in [Errors](https://couryo.com/en/docs/errors.md).
