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

# Security Model

> How authentication and access control work across the API.

## Two layers

1. **Authentication** — who is calling (API key, shared secret, JWT)
2. **Access policy** — what the caller can do on a specific document

## Authentication

Every request is authenticated via one of:

| Method          | Header                              | Use case                  |
| --------------- | ----------------------------------- | ------------------------- |
| API key         | `Authorization: Bearer okra_sk_...` | Server-to-server          |
| Publishable key | `Authorization: Bearer okra_pk_...` | Browser clients           |
| Shared secret   | `x-document-agent-secret: ...`      | Internal worker-to-worker |

Unauthenticated requests can still interact with documents that have a `public` grant in their access policy.

## Access policy

Each document has a deny-by-default access policy with explicit grants. A grant maps a **principal** (who) to **actions** (what).

```json theme={null}
{
  "access": {
    "default_effect": "deny",
    "grants": [
      { "principal": { "type": "owner" }, "actions": ["admin"] },
      { "principal": { "type": "public" }, "actions": ["query", "read_content"] }
    ]
  }
}
```

See [Access Policy](/api-reference/documents/access-policy) for the full reference.

## Route classes

### Public read surface (`/v1/documents/...`)

Published outputs, CDN-cacheable. Access controlled by document grants.

* `GET /v1/documents/{id}` — metadata
* `GET /v1/documents/{id}/pages/{n}` — page content
* `POST /v1/public/resolve/chat/completions` — public source chat

### Private authenticated surface (`/document/...`)

Mutations and configuration. Requires API key or shared secret.

* `PUT /document/{id}/config` — set access policy
* `POST /document/{id}/reparse` — re-process
* `POST /document/{id}/extract` — trigger extraction

## Caching

* Public routes: `Cache-Control: public` (CDN-safe)
* Private routes: `Cache-Control: private` or `no-store`
