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

# Authentication

> How EnfinitOS authenticates SDK and HTTP API calls — bearer tokens, scopes, rotation, and the sandbox vs. production split.

EnfinitOS authenticates every API call with a **bearer token** in the
`Authorization` header.

```http theme={null}
Authorization: Bearer sk_live_...
```

## Token shape and scope

Every token is scoped to a single **tenant** and carries a set of
capability **scopes** that gate what it can do. Issue each key with the
narrowest set it needs:

| Scope              | Grants                                         |
| ------------------ | ---------------------------------------------- |
| `rights:read`      | List bases, rights, offers, challenges.        |
| `rights:write`     | Issue rights, propose offers, open challenges. |
| `offers:read`      | Read offers your tenant participates in.       |
| `offers:write`     | Accept / reject / counter / withdraw offers.   |
| `challenges:read`  | Read open and resolved rights challenges.      |
| `challenges:write` | Open and resolve challenges.                   |
| `delivery:write`   | Submit delivery events for substrate runtime.  |
| `proof:read`       | Read proof packs and verification chains.      |
| `audit:read`       | Read the append-only audit log.                |
| `settlement:read`  | Read settlement statements and reconciliation. |

A `*` wildcard scope also exists — treat it like a root credential and
avoid it in production integrations.

Tokens are prefixed for hand-checking:

* `sk_live_...` — production traffic.
* `sk_sandbox_...` — sandbox tenant.
* `sk_test_...` — local test fixtures (no real backend).

<Warning>
  A leaked production token gives an attacker the full surface that
  role allows. Treat tokens as production secrets — store them in a
  secrets manager, rotate them on a schedule, never commit them.
</Warning>

## Token rotation

The platform supports overlapping tokens during a rotation window so
there is never a moment when an operator's automation is offline:

1. Generate a new token in the operator dashboard.
2. Roll your services onto it (rolling deploy, blue-green, etc.).
3. Wait until your observability shows zero traffic on the old token.
4. Revoke the old token.

The rotation window is **at least 90 days** by default; you can
shorten it to a value you choose for compliance reasons.

## Sandbox vs. production

| Concern      | Sandbox                                | Production                                |
| ------------ | -------------------------------------- | ----------------------------------------- |
| Base URL     | `https://sandbox.api.enfinitos.com`    | `https://api.enfinitos.com`               |
| Token prefix | `sk_sandbox_`                          | `sk_live_`                                |
| Tenant data  | Synthetic, resettable                  | Real, immutable                           |
| Proof chain  | Signed by the sandbox verification key | Signed by the production verification key |

The sandbox uses a **separate signing key** so any proof pack you fetch
from sandbox cannot impersonate a production pack. The public half of
both keys is published at
[docs.enfinitos.com/compliance/verification-keys](https://docs.enfinitos.com/compliance/verification-keys).

## Rate limits

Each tenant has a request quota set by its plan. The sandbox ships with a
generous quota for evaluation; production quotas are finalised per plan at
the April 2027 launch.

When a quota is exhausted the API returns `429` with a `RATE_LIMITED` error
and a `Retry-After` header. Responses also carry rate-limit headers so you
can track remaining quota, and the SDKs back off and surface a warning as
you approach the limit.

## Errors

Errors use the same `ok` / `error` / `message` shape: `ok` is `false`,
`error` is a machine-readable code, and `message` is human-readable. An
unauthenticated request, for example, returns:

```json theme={null}
{
  "ok": false,
  "error": "AUTH_REQUIRED",
  "message": "Missing or malformed Authorization header. Use `Authorization: Bearer <api-key>`."
}
```

Authentication and authorization codes (with HTTP status):

| Code            | Status | Meaning                                                    |
| --------------- | ------ | ---------------------------------------------------------- |
| `AUTH_REQUIRED` | 401    | No bearer token supplied.                                  |
| `AUTH_INVALID`  | 401    | Malformed, unknown, or revoked token.                      |
| `SCOPE_MISSING` | 403    | Token is valid but lacks the scope this endpoint requires. |

Other endpoints also return `BAD_REQUEST` (400), `VALIDATION_FAILED` (422),
`RESOURCE_NOT_FOUND` (404), `STATE_CONFLICT` (409), `PRECONDITION_FAILED`
(412), `RATE_LIMITED` (429), and `INTERNAL_ERROR` (500).
