# Authentication

> Bearer API keys: the key format, test and live environments, who may create keys, rotation and revocation within 30 seconds, and keeping a key secret.

Updated 2026-10-24 · HTML: https://layercrew.com/developers/authentication · Markdown: https://layercrew.com/developers/authentication.md · OpenAPI: https://layercrew.com/openapi.json

Every call to `/v1/*` carries an API key as a bearer token: `Authorization: Bearer lc_live_…` or `lc_test_…`. There is no OAuth exchange and no session — the key is the identity, and it names the partner, the environment and the plan.

## Key format

`lc_` + `live` or `test` + `_` + 16 characters of `[a-z0-9]` (the key id) + `_` + 64 lowercase hex characters (the secret). The whole key is 89 characters long and is parsed by fixed widths before any lookup, so a truncated or edited key is refused as `401 INVALID_API_KEY` without touching the database. Only a hash of the secret is stored; the key is shown once, when you create it.

```text
lc_test_k7m2p9q4r1s8t3u6_9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
│  │    │                │
│  │    │                └─ secret: 64 lowercase hex characters (hashed at rest, shown once)
│  │    └─ key id: 16 characters [a-z0-9] — appears in your request log and dashboard
│  └─ environment: test or live
└─ LayerCrew prefix
```

## Two environments

| Prefix | Environment | What it reaches |
| --- | --- | --- |
| `lc_test_` | test | The same API against the same code, with `environment: test` on every object. Never creates a production order, never touches stock, couriers or invoices; pricing is real; you advance orders yourself. Issued once your account owner has accepted the agreements. See [Test mode](https://layercrew.com/developers/test-mode). |
| `lc_live_` | live | Production. Issued by the account owner once LayerCrew has countersigned both agreements; until then the dashboard answers `AGREEMENT_NOT_COUNTERSIGNED`. |

Files, quotes, orders, events and webhook endpoints belong to one environment. A test key never sees a live object (`404 NOT_FOUND`), and a key whose prefix differs from the environment it was issued for answers `403 SCOPE_MISMATCH`. A key of a suspended or closed account answers `403 PARTNER_INACTIVE`.

## Who may create keys

- **Owner** — test and live keys, every setting, every environment.
- **Developer** — test keys and everything in the test environment; live orders, events and requests read-only when the owner grants it.
- **Viewer** — read-only in both environments, with your customers' contact fields redacted.

Keys are created, named and revoked in your dashboard under Integrations → Keys. One key per system or deployment keeps a leak one revocation away.

## Rotation and revocation

Create the new key, deploy it, then revoke the old one. Revocation, a suspension and a plan change take effect on every server within 30 seconds; for those seconds a revoked key may still answer.

- A revoked or expired key answers `401 API_KEY_REVOKED`.
- Removing a member from your account revokes the keys that member created.
- Every creation and revocation is an event — `key.issued`, `key.revoked` — in your feed and in your dashboard's activity log. The event never carries the secret.

## Keep it secret

- Treat the key like a password: your secret manager or server environment, never a repository, a client-side bundle, a mobile app or a URL.
- Call the API from your servers. If a browser or an app must talk to us, it talks to your backend first.
- Use a test key everywhere until the switch to live, and never log the `Authorization` header.

## Checking a key

```bash
curl "https://engine.layercrew.com/v1/ping" \
  -H "Authorization: Bearer $LAYERCREW_API_KEY"
```

_200_

```json
{
  "data": {
    "partner": {
      "id": "0d2f6a1c-3b4e-4d5f-8a9b-1c2d3e4f5a6b",
      "number": "LC-PT-0007",
      "name": "Studio NS"
    },
    "environment": "live",
    "key_id": "k7m2p9q4r1s8t3u6",
    "plan": {
      "key": "default",
      "name": "Default"
    },
    "rate_limit": {
      "per_second": 2,
      "burst": 10
    },
    "server_time": "2026-10-24T09:30:00Z"
  }
}
```

_401 — the key is wrong_

```json
{
  "error": {
    "code": "INVALID_API_KEY",
    "message": "the API key is missing, malformed or unknown — send a live or test key as Authorization: Bearer lc_live_… / lc_test_…"
  }
}
```

## Request ids

Every response carries `X-Request-ID`, our id for that call. Quote it when you write to us. You may send your own `X-Request-ID` — letters, digits, `. _ -`, up to 128 characters — and it comes back as `X-Client-Request-ID`, stored in your request log next to ours. See [Errors](https://layercrew.com/developers/errors#debugging).
