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

# Authentication

> Apocor API keys, bearer tokens, and roles.

Apocor uses an **OAuth client-credentials** flow. You exchange an API key for a short-lived bearer token, then send that token on every request. Apocor keys are the *only* credential you manage — all upstream providers are handled for you.

## The flow

```mermaid theme={null}
sequenceDiagram
  participant App as Your service
  participant API as Apocor API

  App->>API: POST /v1/oauth/token (client_id, client_secret)
  API-->>App: access_token (Bearer, expires_in 3600s)
  App->>API: GET /v1/cards + Authorization: Bearer <token>
  API-->>App: { "data": [ … ] }
```

## 1. Get your API key

Your Apocor contact provisions an API key from the dashboard. The **secret is returned only once** — store it in a secret manager.

| Field    | Use                                            |
| -------- | ---------------------------------------------- |
| `prefix` | The `client_id` you send to the token endpoint |
| `secret` | The `client_secret` — shown once, never again  |

## 2. Get an access token

<RequestExample>
  ```bash cURL theme={null}
  curl -s -X POST 'https://sandbox.apocor.ai/v1/oauth/token' \
    -H 'Content-Type: application/json' \
    -d '{ "client_id": "apocor_1a2b3c4d5e6f7g8h", "client_secret": "apocor_sk_live_..." }'
  ```
</RequestExample>

Tokens are valid for **1 hour** (`expires_in: 3600`). Request a new one when it expires — there is no refresh token in the client-credentials flow.

## 3. Call authenticated endpoints

```http theme={null}
Authorization: Bearer YOUR_ACCESS_TOKEN
Content-Type: application/json
```

## Roles & access

Every key and user carries a role that scopes what it can see and do.

| Role                  | Scope                                  |
| --------------------- | -------------------------------------- |
| `APOCOR_ADMIN`        | Apocor staff — full platform access    |
| `RESELLER_ADMIN`      | Manages its own org and child tenants  |
| `ORG_ADMIN`           | Full access within a single tenant org |
| `PROGRAM_MANAGER`     | Manage programs, cards, and applicants |
| `DEVELOPER`           | Machine access for integrations        |
| `SUPPORT` / `AUDITOR` | Read-oriented operational access       |

<Note>
  Requests are always scoped to the caller's organization (and, for resellers, its children). You can only ever read or write resources your token is entitled to.
</Note>

## Errors

A missing or invalid credential returns `401` with a stable code:

```json theme={null}
{ "error": { "code": "INVALID_CLIENT", "message": "Invalid client credentials" } }
```

See [Error codes](/guides/errors) for the full list.
