> ## Documentation Index
> Fetch the complete documentation index at: https://docs.integrateledger.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API keys and permissions

> Authenticate requests, choose the environment, and limit what each key can do.

Every request to the Ledger API carries a secret API key. The key identifies your workspace, chooses the environment, and limits what the request may do. Ledger has no publishable keys: every key is secret and belongs on your server.

## Key types

| Prefix | Environment | Example |
| - | - | - |
| `ledger_test_` | Sandbox | `ledger_test_org_3df0…ff7.Xk2…` |
| `ledger_live_` | Live | `ledger_live_org_3df0…ff7.Qp9…` |

A key works only in its own environment. A Sandbox key can't read or change Live data, and the reverse.

## Create a key

**1. Open API keys**

In the dashboard, choose the environment with the switch at the top of the sidebar, then open **Settings › API keys**.

**2. Name it after what will use it**

Choose **Create key** and name the service or deployment that will hold it, such as "Production backend". Names are unique per environment.

**3. Choose its permissions**

Leave **Restricted mode** off for full access, or turn it on and choose None, Read or Write for each group below.

**4. Copy it once**

Ledger shows the key once and stores only a hash of it. Put it in your secret manager or environment, such as `LEDGER_API_KEY`.

Each environment holds up to 8 keys. Create a new key before revoking an old one so you can rotate without downtime: existing keys keep working until revoked, and a revoked key stops working immediately.

## Authenticate requests

Send the key as a bearer token:

```bash theme={"system"}
curl https://api.integrateledger.com/v1/plans \
  -H "Authorization: Bearer $LEDGER_API_KEY"
```

A missing, unknown or revoked key returns `401`:

```json Response (401) theme={"system"}
{
  "error": "unauthorized"
}
```

## Permissions

A restricted key has a level for each of four groups. **Read** grants the read scope; **Write** grants both.

| Group | Read allows | Write also allows |
| - | - | - |
| **Catalog** | `GET /v1/plans`, `/v1/features`, `/v1/add-ons` and their items | Creating, updating and archiving them; `POST /v1/catalog` |
| **Customers** | `GET /v1/customers`, its subscriptions and purchases | `POST` and `DELETE /v1/customers`; overage cap and rate |
| **Credits** | `POST /v1/check` | `POST /v1/track` |
| **Billing** | (no read level) | `POST /v1/billing/attach`, `/v1/billing/upgrade`; stopping or resuming renewal |

A request that the key isn't allowed to make returns the same `401 unauthorized` as an invalid key.

### Suggested keys

| Service | Catalog | Customers | Credits | Billing |
| - | - | - | - | - |
| API server that meters usage | None | None | Write | None |
| Billing page backend | Read | Write | None | Write |
| Catalog deploy job (CI) | Write | None | None | None |

## Keep keys safe

* **Server only.** Never put a key in a browser, mobile app or public repository. Anyone with it can spend your customers' credits.
* **One key per service.** If one leaks, you revoke one key, not your whole integration.
* **Restrict by default.** Give each service only the groups it calls.
* **Rotate on suspicion.** Create a replacement, deploy it, then revoke the old key in **Settings › API keys**.

Ledger never logs API keys. Its request logs record the key's ID instead.

## Next steps

> [card] [Errors](https://docs.integrateledger.com/errors.md)
>
> The error shape and every code.

> [card] [Sandbox and Live](https://docs.integrateledger.com/concepts/environments.md)
>
> What each environment holds.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.