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

# Authentication

> API keys, scopes, rate limits, and the response envelope.

## API Keys

All REST API calls require a Bearer token:

```http theme={null}
Authorization: Bearer edp_live_<your-key>
```

Generate API keys in your Edpire dashboard under **Integrations → API Keys**.

## Scopes

Each API key can be granted one or more scopes:

| Scope               | Grants access to                                                                     |
| ------------------- | ------------------------------------------------------------------------------------ |
| `read:assessments`  | List/fetch assessments, collections, webhooks. Grade single questions via `/check`.  |
| `write:assessments` | Create/update assessments, manage collections, register webhooks, mint embed tokens. |
| `read:results`      | Fetch submissions, learner results, assessment results, collection results.          |
| `write:submissions` | Submit answers for server-side grading via `POST /assessments/{id}/submit`.          |

<Tip>Grant the minimum scopes your integration needs.</Tip>

## Rate Limits

Limits are applied **per API key**, on a rolling 60-second window:

| Endpoint                        | Limit                 |
| ------------------------------- | --------------------- |
| All REST endpoints (default)    | 300 requests / minute |
| `POST /assessments/{id}/submit` | 100 requests / minute |
| `POST /assessments/{id}/check`  | 600 requests / minute |

When exceeded, the API returns `429 Too Many Requests` with a `Retry-After` header indicating how many seconds to wait.

`/check` also carries a **separate anti-brute-force limit**: 3 checks per question, per session, per rolling hour (configurable per org). It is keyed on `(api key, assessment, question, session_id)`, falling back to `learner_ref` when you omit `session_id`. Exceeding it also returns `429`, with a `Retry-After` that can be up to an hour — so back off on the header value, never on a fixed schedule.

See [Technical Limits](/enterprise/technical-limits) for quotas and overage.

## Response Envelope

All API responses use a consistent envelope:

```json theme={null}
// Success
{ "data": <payload>, "error": null, "meta": <pagination-or-null> }

// Error
{ "data": null, "error": { "message": "..." }, "meta": null }
```

List endpoints include pagination metadata:

```json theme={null}
{
  "data": [...],
  "error": null,
  "meta": { "total": 42, "page": 1, "limit": 20 }
}
```

## The `learner_ref` field

Every submission and session accepts a `learner_ref` — your internal identifier for the learner:

<Warning>
  * Use a **stable, immutable ID** (database primary key or UUID)
  * **Never use mutable values** like email addresses
  * Edpire echoes it back exactly as provided and never validates it
  * Not unique-enforced — the same learner can have multiple submissions
</Warning>
