---
title: Authentication
description: API keys, live and test modes, and access levels.
sidebar:
  order: 2
---

Send your key as a bearer token on every request:

```txt
Authorization: Bearer tc_live_…
```

`X-Api-Key: tc_live_…` works too.

## Live and test keys

The prefix tells you a key's mode at a glance:

- **`tc_live_…`** spends your real balance and retires real credits. Responses say `"livemode": true`.
- **`tc_test_…`** spends a simulated balance. Responses say `"livemode": false`. See [Test mode](/docs/test-mode).

Live and test data are separate: a test key never sees live offsets, and the other way round.

## Access

Each key has one of two access levels, set when you create it:

| Access | Can |
| --- | --- |
| Read only | Get the balance, quotes, offsets and impact. |
| Read and buy | Everything above, and buy offsets. |

Give dashboards and reports a read-only key. A purchase with a read-only key fails with `403 insufficient_permissions`.

## Keep keys secret

- Use keys **only on your server**. The API sends no CORS headers, so browsers can't call it with a key.
- Store keys as secrets (environment variables, a secrets manager), never in code.
- Create one key per system, so you can revoke one without touching the others.
- If a key leaks, revoke it on the developer page at once. Requests with it fail from then on. You are responsible for purchases made with your keys.

## Errors

| Status | Code | When |
| --- | --- | --- |
| 401 | `invalid_api_key` | The key is missing, malformed, unknown or revoked. |
| 403 | `api_access_inactive` | The account isn't approved, or it is suspended. A suspended account can still read. |
| 403 | `insufficient_permissions` | A read-only key tried to buy. |
| 429 | `rate_limited` | Too many requests for this key. See [Limits](/docs/limits). |
