# Authentication

> Get an On Me API key, send it with every request, keep it safe, and rotate or revoke it when you need to.


The On Me API authenticates every request with a secret API key. Your key belongs to your organization, and anything you do with it, including spending your balance, happens on your organization's behalf.

## Get an API key

Org admins create and manage keys in the business portal, under [Account → Developers](https://business.onme.com/account/developers).

1. Make sure your organization has a [business portal](https://business.onme.com/) account. If it doesn't, [sign up](https://business.onme.com/signup) first.
2. Fund your balance under [Billing](https://business.onme.com/billing). Every order you create through the API is paid for from it.
3. Open [Account → Developers](https://business.onme.com/account/developers) and select **Create key**. Give the key a name that says where it's used, such as "Production server".

If your organization doesn't have API access yet, the Developers page shows a **Request access** button instead. We email your organization's admins as soon as it's on.

Keys start with `omk-`. Keys we issued before self-serve keys launched start with `sk_`, and they keep working.

> **Warning: You only see your key once** We don't store your key in a form we can show you again. Copy it straight into a secrets manager, such as AWS Secrets Manager, Google Secret Manager, 1Password or Vault. If you lose it, revoke it and create a new one.

## Authenticate requests

Send your key as a bearer token in the `Authorization` header of every request:

```http
Authorization: Bearer omk-...
```

The examples in these docs read the key from an environment variable called `ONME_API_KEY`. List the categories to check that yours works:

`GET /v1/categories` ([API reference](https://business.onme.com/docs/reference#tag/categories/GET/v1/categories))

**cURL**

```bash
curl https://api.onme.com/v1/categories \
  -H "Authorization: Bearer $ONME_API_KEY"
```
**Node**

```js
const response = await fetch('https://api.onme.com/v1/categories', {
  headers: { Authorization: `Bearer ${process.env.ONME_API_KEY}` },
})
const categories = await response.json()
console.log(categories.data.map((category) => category.id))
```
**Python**

```python
import os
import requests

response = requests.get(
    "https://api.onme.com/v1/categories",
    headers={"Authorization": f"Bearer {os.environ['ONME_API_KEY']}"},
)
categories = response.json()
print([category["id"] for category in categories["data"]])
```

A `200` with a list of categories means you're in. A `401` means the key is missing or wrong; the error's `code` tells you which (see [authentication errors](#authentication-errors)).

Every endpoint needs a key except two: `GET /v1/health` and `GET /v1/openapi.json`, which serves the API's OpenAPI document.

## Keep your key safe

Your key can spend your organization's balance, so treat it like a password to your bank account.

- **Use it only on your servers.** Never put it in a browser, a mobile app or anything else you ship to users, where anyone can extract it. If your frontend needs to send a gift, have it call your backend, and have your backend call On Me.
- **Keep it out of source control.** Load it from a secrets manager or an environment variable, never from a file you commit.
- **Keep it out of logs.** Make sure your HTTP client and error tracker redact the `Authorization` header.

Your organization can have up to 10 active keys. Use a separate key for each system that calls the API, so you can revoke one without touching the others. Every key has full access to all of your organization's orders and gifts. There are no read-only or per-endpoint keys yet, so limit who and what can read them.

## Rotate or revoke a key

To rotate a key without downtime:

1. Create a new key under [Account → Developers](https://business.onme.com/account/developers).
2. Deploy it everywhere the old key is used.
3. Watch the old key's **Last used** time on the Developers page. Once it stops changing, nothing is using it any more.
4. Revoke the old key.

If you think a key has leaked, revoke it straight away. Revocation takes effect immediately: the next request with that key fails with [`api_key_revoked`](https://business.onme.com/docs/reference#errors/api_key_revoked). It's also permanent, so create a new key to carry on with.

Every admin in your organization gets an email whenever a key is created or revoked.

## Sandbox

Sandbox keys start with `omk-sandbox-`. Create one by switching the business portal to **Sandbox** mode, then adding a key under **Account → Developers**.

**There is no separate sandbox URL.** You call the same base URL either way and your key decides which environment serves the request, so moving to production means swapping the key and changing nothing else. A sandbox key spends a sandbox balance, reaches no real recipient, and charges no card.

Keys are not interchangeable between environments, and that is enforced rather than assumed: a key that somehow reaches the wrong environment is refused with [`api_key_environment_mismatch`](https://business.onme.com/docs/reference#errors/api_key_environment_mismatch) rather than being served. You should never see it.

See [Testing in the sandbox](https://business.onme.com/docs/sandbox) for the recipient addresses that let you choose what happens to a gift.

The **Try it** button in the [API reference](https://business.onme.com/docs/reference) sends its requests to the sandbox, so it is safe to click around.

## Authentication errors

When we can't authenticate a request, you get one of these errors. None of them change anything, so once you've fixed the cause it's safe to send the same request again.

| Code | Status | What it means | What to do |
| --- | --- | --- | --- |
| [`api_key_missing`](https://business.onme.com/docs/reference#errors/api_key_missing) | 401 | The request had no `Authorization: Bearer` header. | Send `Authorization: Bearer omk-...` on every request. |
| [`api_key_invalid`](https://business.onme.com/docs/reference#errors/api_key_invalid) | 401 | We don't recognize the key. | Check for a truncated or mistyped key, or create a new one under [Account → Developers](https://business.onme.com/account/developers). |
| [`api_key_revoked`](https://business.onme.com/docs/reference#errors/api_key_revoked) | 401 | The key was valid but has been revoked. | Switch to a current key, or create one under [Account → Developers](https://business.onme.com/account/developers). |
| [`api_key_environment_mismatch`](https://business.onme.com/docs/reference#errors/api_key_environment_mismatch) | 401 | The request reached the wrong environment for its key. You should not see this. | Call the documented base URL, not a deployment host. If you already do, quote the `request_id` to support. |
| [`organization_suspended`](https://business.onme.com/docs/reference#errors/organization_suspended) | 403 | The organization that owns the key is suspended. | Email support@onme.com. |
