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

# Authentication

> API key format, test keys, agent credentials, scopes, and the BAA requirement.

The HASP AI API authenticates every request via a Bearer token — no OAuth flow, no session cookies. Three credential types share the `Authorization: Bearer <token>` mechanism but serve different callers:

| Prefix            | Credential                          | Who holds it                                                                                                                              |
| ----------------- | ----------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
| `hasp_api_live_*` | **Personal access token (API key)** | A human or service integrating directly — the credential this page is mostly about.                                                       |
| `hasp_agt_live_*` | **Agent credential**                | An AI agent acting with a human's delegated authority. See [Agents overview](/ai-api/agents/overview).                                    |
| `hasp_pat_live_*` | **Developer credential**            | Issued via the `hasp` CLI / OAuth device or PKCE flow for tooling like coding agents. See [OAuth Quickstart](/platform/oauth/quickstart). |

Each type also has a `_test_` variant (see [Test keys](#test-keys) below). The token's prefix is what routes a request to the right auth guard — mixing them up (e.g. sending an agent credential where an API key is expected) fails authentication rather than silently working.

## API key format

```
hasp_api_live_<32 Crockford base32 characters>
```

Keys are issued with the prefix `hasp_api_live_` and are globally unique. The 32-character body uses the Crockford base32 alphabet (ambiguous lookalike characters `0`, `O`, `1`, `l`, `I` excluded). The full token is shown exactly once on creation. HASP stores only a SHA-256 hash — if you lose the token, revoke it and issue a new one.

## Sending the token

Pass the key in the `Authorization` header on every request:

```
Authorization: Bearer hasp_api_live_your_key_here
```

## Test keys

Every key is minted in either `live` or `test` mode, distinguished by prefix: `hasp_api_live_*` vs `hasp_api_test_*`. Test-mode keys are for development against the real API without touching production billing:

* Requests draw from a separate **sandbox token allotment** (per your API tier), not your org's regular AI credit balance.
* Exceeding the allotment, or having no active API subscription / Free Evaluation, returns `402 sandbox_allotment_exhausted` rather than the regular `CONSUMPTION_BLOCKED` credit error.
* Everything else — scopes, BAA requirement, PHI handling, rate limits — behaves identically to a live key. Test mode changes *billing*, not *behavior*.

Agent and developer credentials do not have a meaningful test mode distinction of their own — `isTestMode()` is always `false` for those caller types; only personal access tokens draw from the sandbox allotment.

## Agent credentials

An agent credential (`hasp_agt_live_*`) is a delegated, scope-constrained credential an AI agent uses to act on a human's behalf — distinct from a personal API key a human or service holds directly. Agent credentials carry their own rate limits, concurrency caps, and delegation-chain-depth limits independent of the parent key (see the **(Agent SDK)** codes in the [Error Reference](/ai-api/reference/errors)). Full lifecycle — registering an agent, issuing a credential, granting scopes, revocation — is covered in [Agents overview](/ai-api/agents/overview).

## Device authorization

If you're integrating via the `hasp` CLI on a machine with no browser (SSH, containers), authenticate with the RFC 8628 device authorization grant instead of the standard browser redirect flow. See [Device Authorization](/platform/oauth/device-authorization).

## Scopes

Every API key has one or more scopes, assigned at creation and immutable after (issue a new key to change them). A request to a route protected by a scope the key does not have returns `403 MISSING_SCOPE`. Scope grants are additive — a key with multiple scopes gets the union of what each grants.

| Scope                  | Grants access to                                                                                                                                                                                             |
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `ai:chat`              | `POST /v1/ai/chat`, `POST /v1/messages`, `POST /v1/messages/count_tokens`, `POST /v1/chat/completions`                                                                                                       |
| `ai:documents`         | Document upload and retrieval on the AI surface                                                                                                                                                              |
| `ai:embeddings`        | Embeddings endpoint                                                                                                                                                                                          |
| `ai:summarize`         | Summarize endpoint                                                                                                                                                                                           |
| `knowledge:read`       | `GET /v1/knowledge`, `GET /v1/knowledge/{document}`, and the `knowledge.search` tool call                                                                                                                    |
| `control:read`         | Read access across the control plane: API keys, agents, audit, budget, models, personas, projects, records, schemas, workflows, and settings. Does **not** include webhook or integration reads (see below). |
| `control:webhooks`     | Full webhook management: `GET`/`POST /v1/webhooks`, `PATCH`/`DELETE /v1/webhooks/{id}`, secret rotation, deliveries, and event types.                                                                        |
| `control:integrations` | Full Integrations (BYO-Tool) management: `GET`/`POST /v1/integrations`, secret rotation, deletion, and binding management under `/v1/integrations/{id}/bindings`.                                            |
| `control:author`       | Write access to projects, schemas (entities/fields), and workflow authoring/publishing — the "build" half of the control plane, as opposed to `control:read`'s "view" half.                                  |
| `control:workflows`    | Trigger and read workflow runs (`workflow.run` + `workflow.read`) without granting authoring access — for integrations that only need to kick off an existing workflow.                                      |
| `org.end_users.read`   | `GET /v1/orgs/{organization}/end-users/{runtimeUser}/export`                                                                                                                                                 |

Assign only the scopes a key needs. A key used for chat-only integrations should carry only `ai:chat`.

## Creating keys

**Via the dashboard:** Settings → API Keys → New Key.

**Via the API** (requires a key with a scope granting `Capability::ApiKeyWrite` — currently `control:read`):

```bash theme={null}
curl -X POST https://api.usehasp.com/v1/api_keys \
  -H "Authorization: Bearer hasp_api_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "production-chat-service",
    "scopes": ["ai:chat"]
  }'
```

See [Control: API Keys](/ai-api/control/api-keys) for the full endpoint reference.

## BAA requirement

All requests additionally require an active Business Associate Agreement (BAA) on your organization. If your org has no active BAA, every request — regardless of key validity — returns:

```json theme={null}
{
  "success": false,
  "error": {
    "code": "BAA_REQUIRED",
    "type": "payment_required",
    "message": "An active Business Associate Agreement is required to use the AI API.",
    "retryable": false,
    "request_id": "req_..."
  }
}
```

Sign the BAA in **Settings → Compliance → Business Associate Agreement**.

## Error responses

| Code              | HTTP | Meaning                                 |
| ----------------- | ---- | --------------------------------------- |
| `INVALID_API_KEY` | 401  | Token not found, malformed, or revoked  |
| `BAA_REQUIRED`    | 402  | No active BAA on the org                |
| `MISSING_SCOPE`   | 403  | Key exists but lacks the required scope |

Agent and developer credentials have their own authentication error codes (`AGENT_CREDENTIAL_NOT_FOUND`, `DEVELOPER_CREDENTIAL_REVOKED`, etc.) — see the full [Error Reference](/ai-api/reference/errors).
