# REST API Reference

## Automatic Memory API

| Method | Route | Purpose |
|---|---|---|
| `GET` | `/v1/auto` | Read automatic-memory policy for the selected scope |
| `PUT` | `/v1/auto` | Enable, pause, or route ACP automatic memory |
| `POST` | `/v1/auto/redaction-audits` | Record redaction metadata without source content |
| `POST` | `/v1/sessions/:id/events` | Local ACP and native-bridge event delivery |
| `POST` | `/v1/sessions/:id/compile` | Local ACP service compilation record |

The Auto API stores user and workspace policy. The local ACP service owns event delivery and compilation; application integrations use explicit Session lifecycle endpoints for deliberate task records.

TokST exposes its authenticated REST API at `https://api.tokst.com/v1` plus an unauthenticated health check. The production API uses the same per-user and workspace access rules as the dashboard and remote MCP server.

The machine-readable OpenAPI 3.1 document is available at [`https://api.tokst.com/openapi.json`](https://api.tokst.com/openapi.json). It describes authentication, typed operations, request parameters, and response shapes for programmatic clients.

TokST Local is a private CLI and stdio MCP profile. Local memory stays in SQLite on the current device and does not expose a network REST listener. Use the cloud API for cloud workspaces and Atlases.

Send structured Markdown in a memory `content` field for decisions, architecture,
meeting notes, and tasks. Short facts can remain plain text. Keep credentials,
private keys, raw reasoning, and transient tool output outside memory records.

## Agent Identity and Messages

Send `X-TokST-Actor: agent` with an API Key to use a trusted Agent identity. The server creates or resolves the API-Key-bound `agt_...` identity; client-provided Agent IDs are rejected. `sourceName` remains a source label.

| Endpoint | Description |
|---|---|
| `GET /v1/agents?workspace_id=<uuid>` | List workspace Agents |
| `POST /v1/agent-messages` | Send a direct or broadcast message |
| `GET /v1/agent-messages/inbox` | Read the current Agent inbox |
| `GET /v1/agent-messages/events` | Open the current Agent real-time event stream |
| `POST /v1/agent-messages/:id/acknowledge` | Acknowledge a receipt |
| `POST /v1/agent-messages/:id/close` | Close a receipt |

## Authentication

Send your TokST API key in the `Authorization` header:

```bash
curl https://api.tokst.com/v1/status \
  -H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxx"
```

Keep API keys in a secret manager or environment variable. URL query authentication exists only for legacy MCP session compatibility and should not be used for REST requests.

## Referrals and Benefits

| Method | Path | Description |
|---|---|---|
| `GET` | `/v1/referrals/me` | Read the referral code, counts, and masked invitee records |
| `GET` | `/v1/benefits/me` | Read Pro benefit entries with base and effective plans |
| `POST` | `/v1/benefits/:id/activate` | Activate one available Pro benefit |

New account attribution is set only during registration through a referral link. A qualifying memory created through this API, the dashboard, CLI, or MCP activates a verified referral automatically.

## OAuth for Remote MCP

Remote MCP clients use OAuth 2.1 authorization code flow with PKCE. Connect the client to `https://api.tokst.com/mcp`; it discovers `/.well-known/oauth-protected-resource` and `/.well-known/oauth-authorization-server`, opens TokST for account and workspace approval, then stores refreshable bearer credentials. REST automations continue to use an API key.

## Endpoint Inventory

### Health and Account

| Method | Path | Auth | Description |
|---|---|---|---|
| `GET` | `/health` | No | Service health check |
| `GET` | `/v1/status` | Yes | Plan, monthly usage, storage, personal workspace and Atlas quotas, Team workspace quota, and totals |

### Agents and Messages

| Method | Path | Description |
|---|---|---|
| `GET` | `/v1/agents` | List trusted Agents in a workspace; requires `workspace_id` |
| `POST` | `/v1/agent-messages` | Send a direct or broadcast message as the trusted Agent |
| `GET` | `/v1/agent-messages/inbox` | Read the trusted Agent inbox; optionally filter by `workspace_id` |
| `GET` | `/v1/agent-messages/events` | Open the trusted Agent SSE stream; optionally filter the initial unread snapshot by `workspace_id` |
| `POST` | `/v1/agent-messages/:id/acknowledge` | Acknowledge a message receipt |
| `POST` | `/v1/agent-messages/:id/close` | Close a message receipt |

The SSE stream requires `Authorization: Bearer $TOKST_API_KEY` and `X-TokST-Actor: agent`. It sends `ready`, `message.created`, `heartbeat`, and `auth.revoked` events. The CLI manages reconnects and unread-message recovery through `tokst agent listen`.

### Memories

| Method | Path | Description |
|---|---|---|
| `POST` | `/v1/memories` | Create a memory and generate its embedding |
| `GET` | `/v1/memories` | List active memories |
| `GET` | `/v1/memories/context` | Build a grouped context snapshot |
| `POST` | `/v1/memories/search` | Keyword-first search with scoped semantic fallback |
| `GET` | `/v1/memories/:id` | Get one memory, including attachment metadata |
| `PATCH` | `/v1/memories/:id` | Update content, title, type, or tags |
| `POST` | `/v1/memories/:id/verify` | Verify a memory with evidence, confidence, or expiry |
| `POST` | `/v1/memories/:id/supersede` | Mark a memory as replaced by a newer record |
| `POST` | `/v1/memories/:id/archive` | Archive a memory |
| `POST` | `/v1/memories/:id/append` | Append content and regenerate the embedding |
| `POST` | `/v1/memories/:id/restore` | Restore an archived memory |
| `DELETE` | `/v1/memories/:id` | Delete a memory and its R2 objects |

### Atlases

| Method | Path | Description |
|---|---|---|
| `GET` | `/v1/atlases` | List accessible atlases |
| `GET` | `/v1/atlases/:id` | Get one atlas |
| `POST` | `/v1/atlases` | Create an atlas |
| `PATCH` | `/v1/atlases/:id` | Rename an atlas or replace routing keywords |
| `DELETE` | `/v1/atlases/:id` | Delete an atlas, its memories, and their R2 objects |

### Workspaces

| Method | Path | Description |
|---|---|---|
| `GET` | `/v1/workspaces` | List accessible workspaces |
| `GET` | `/v1/workspaces/:id` | Get one workspace |
| `POST` | `/v1/workspaces` | Create a workspace |
| `DELETE` | `/v1/workspaces/:id` | Delete an empty workspace; returns `409` when atlases remain |
| `GET` | `/v1/workspaces/:id/members` | List workspace members and roles |
| `GET` | `/v1/workspaces/:id/invitations` | List sent invitations |
| `POST` | `/v1/workspaces/:id/invitations` | Create one or more invitations; `emails`, `role`, and `expiresInDays` |
| `PATCH` | `/v1/workspaces/:id/members/:userId` | Change a member between `admin` and `member`; body requires `confirm: true` |
| `DELETE` | `/v1/workspaces/:id/members/:userId?confirm=true` | Remove a member |
| `POST` | `/v1/workspaces/:id/leave` | Leave a workspace; body requires `confirm: true` |
| `POST` | `/v1/workspaces/:id/owner-transfer` | Transfer ownership to an existing member; body requires `userId` and `confirm: true` |
| `GET` | `/v1/workspace-invitations` | List the caller's pending invitations |
| `POST` | `/v1/workspace-invitations/:id/respond` | Accept or decline an invitation; body requires `accept` and `confirm: true` |
| `DELETE` | `/v1/workspace-invitations/:id` | Revoke a pending invitation; send `?confirm=true` |

## Memory Requests

### Create

```bash
curl -X POST https://api.tokst.com/v1/memories \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "content": "Production deploys require approval on Fridays.",
    "type": "decision",
    "title": "Release policy",
    "tags": ["deploy", "policy"],
    "atlasId": "00000000-0000-0000-0000-000000000000"
  }'
```

`content` is required. `type` defaults to `note`. Supported types are `fact`, `decision`, `preference`, `task`, `architecture`, and `note`. When `workspaceId` is supplied it must match the selected atlas.

### List and Context

```bash
# type accepts one value or a comma-separated list; limit is 1-100
curl "https://api.tokst.com/v1/memories?atlas_id=$ATLAS_ID&type=decision,note&limit=20" \
  -H "Authorization: Bearer $TOKST_API_KEY"

curl "https://api.tokst.com/v1/memories/context?atlas_id=$ATLAS_ID&limit=10" \
  -H "Authorization: Bearer $TOKST_API_KEY"
```

### Search

```bash
curl -X POST https://api.tokst.com/v1/memories/search \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"query":"release approval rules","atlas_id":"'$ATLAS_ID'","mode":"auto","limit":10}'
```

`mode` accepts `auto`, `keyword`, `semantic`, or `hybrid` and defaults to `auto`. The response includes `mode` plus `meta` with the requested/resolved mode, cache level, strong-keyword decision, and stage timings.

- `keyword` returns ranked title/content keyword matches.
- `semantic` returns vector results only.
- `hybrid` always fuses both lists with RRF.
- `keyword_fallback` records a bounded embedding failure while preserving keyword results.

### Update and Append

```bash
curl -X PATCH https://api.tokst.com/v1/memories/mem_xxx \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"Updated policy","type":"decision","tags":[]}'

curl -X POST https://api.tokst.com/v1/memories/mem_xxx/append \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"content":"Approved by the release manager."}'
```

Sending an empty `tags` array clears existing tags. Content updates and appends regenerate the semantic embedding.

### Verify and Supersede

```bash
curl -X POST https://api.tokst.com/v1/memories/mem_xxx/verify \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"evidence":"https://example.com/policy","confidence":0.95,"validUntil":"2027-01-01T00:00:00Z"}'

curl -X POST https://api.tokst.com/v1/memories/mem_old/supersede \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"replacementMemoryId":"mem_new"}'
```

Verification marks a record as reviewed and stores its supporting metadata. Superseding marks the earlier record as `superseded` and preserves a link to the replacement.

## Atlas and Workspace Requests

```bash
curl -X POST https://api.tokst.com/v1/workspaces \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Platform Team"}'

curl -X POST https://api.tokst.com/v1/atlases \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Production","workspaceId":"'$WORKSPACE_ID'","keywords":["deploy","release"]}'
```

Atlas deletion is cascading and also removes attachment objects. Workspace deletion is intentionally non-cascading: delete its atlases first, then delete the empty workspace.

### Team Membership

```bash
# Invite multiple people for seven days.
curl -X POST "https://api.tokst.com/v1/workspaces/$WORKSPACE_ID/invitations" \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"emails":["a@example.com","b@example.com"],"role":"member","expiresInDays":7}'

# The recipient accepts an invitation from their own inbox.
curl -X POST "https://api.tokst.com/v1/workspace-invitations/$INVITATION_ID/respond" \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"accept":true,"confirm":true}'
```

The database enforces workspace roles for every membership RPC. Owner manages all membership changes and ownership transfer. Admin manages ordinary members. Member can leave and can manage only their own memories.

## File Workflow

File transfers use the unified Supabase Edge Function at `/functions/v1/tokst`. These routes accept the short-lived user JWT returned by `POST /auth/exchange`, while normal REST routes accept `tk_live_...` API keys.

| Method | Edge path | Purpose |
|---|---|---|
| `POST` | `/auth/exchange` | Exchange an API key for a user JWT |
| `POST` | `/storage/upload-url` | Validate ownership and quota, create a pending attachment, return a signed PUT URL |
| `POST` | `/storage/confirm-upload` | Verify the R2 object exists, record actual size and MIME, activate the attachment |
| `GET` | `/storage/download-url` | Return a 15-minute signed download URL |
| `POST` | `/storage/delete-objects` | Server-managed, ownership-checked object cleanup |

The CLI, web dashboard, and MCP tools implement this workflow. See [File Attachments](/docs/attachments) for complete examples.

## Response and Error Model

Successful responses return a typed JSON object documented in the OpenAPI 3.1
contract. Errors use one stable shape:

```json
{
  "error": "quota_exceeded",
  "code": "quota_exceeded",
  "message": "The current monthly quota has been reached. Retry after the reported reset time or upgrade capacity."
}
```

`error` remains available for existing clients. `code` is the canonical
machine-readable value. `message` provides recovery guidance and must not be
parsed for program control.

| Status | Meaning | Common codes |
|---|---|---|
| `400` | Invalid body, query, or resource relationship | `invalid_query`, `atlas_workspace_mismatch` |
| `401` | Missing or invalid API key | `missing_api_key`, `invalid_key` |
| `403` | Revoked key or forbidden object access | `revoked`, `forbidden` |
| `404` | Route or accessible resource was not found | `not_found` |
| `409` | Resource state prevents the operation | `workspace_not_empty`, upload object missing |
| `429` | Monthly quota or rolling rate limit reached | `quota_exceeded`, `rate_limited` |
| `500` | Server-side failure | `internal_error` |

Resource lookups are scoped to the authenticated owner and workspace memberships. A resource outside that scope resolves as unavailable.

## Rate Limit Headers

Authenticated REST responses expose the monthly quota window using standard
headers:

| Header | Meaning |
|---|---|
| `RateLimit-Limit` | Total operations allowed in the current quota window |
| `RateLimit-Remaining` | Operations remaining in the current quota window |
| `RateLimit-Reset` | Seconds until the quota window resets |
| `Retry-After` | Seconds to wait before retrying; returned with HTTP `429` |

Clients should slow or pause work when `RateLimit-Remaining` approaches zero.
After `429`, wait for `Retry-After` before retrying. TokST currently exposes
pull-based REST, MCP, and Session event interfaces; public outbound webhooks
are not available.

## Versioning and Deprecation

TokST keeps stable cloud REST routes under `/v1`. Additive fields, endpoints,
and optional request parameters can ship within `/v1`. A change that removes a
field, changes its meaning, or changes authorization behavior receives a new
major API path.

TokST announces a planned endpoint or field retirement in this reference and
the release history at least 90 days before removal. During the announced
period, affected HTTP responses include `Deprecation: true` and a `Sunset`
date where the route can provide those headers. Clients should treat unknown
response fields as forward-compatible and use `error` codes rather than parsed
error text for recovery logic.

## MCP Endpoint

The same host serves the complete 46-tool MCP Streamable HTTP surface at `https://api.tokst.com/mcp`. See the [MCP reference](/docs/mcp); deployments can set `TOKST_MCP_TOOLSET=core` for the focused 11-tool memory surface.

## Session Memory API

Session Memory creates a durable record for an Agent task. Agent clients send `X-TokST-Actor: agent`; TokST injects the trusted `agt_...` identity.

| Method | Endpoint | Purpose |
|---|---|---|
| `POST` | `/v1/sessions` | Start a session and return scoped context |
| `GET` | `/v1/sessions` | List sessions by workspace, Atlas, status, scope, and cursor offset |
| `POST` | `/v1/sessions/bulk` | Archive, restore, or delete up to 100 selected sessions |
| `GET` | `/v1/sessions/candidates` | List reviewable candidates by workspace, Atlas, status, and scope |
| `GET` | `/v1/sessions/:id` | Read session state, candidates, checkpoints, and context |
| `POST` | `/v1/sessions/:id/units` | Create or resume a durable task unit inside an automatic session |
| `POST` | `/v1/sessions/:id/candidates` | Capture durable candidate memory |
| `POST` | `/v1/sessions/:id/units/:unitId/finalize` | Save one task unit to its linked formal memory while the session remains active |
| `POST` | `/v1/sessions/:id/complete` | Close an automatic session after its final task unit is stored |
| `POST` | `/v1/sessions/:id/checkpoints` | Save progress summary |
| `POST` | `/v1/sessions/:id/finalize` | Write snapshot and compile candidates |
| `POST` | `/v1/sessions/:id/reopen` | Resume an ACP Session and update its linked automatic memory |
| `POST` | `/v1/sessions/:id/automatic-memory/revert` | Archive the linked automatic memory and retain Session audit history |
| `POST` | `/v1/sessions/:id/candidates/:candidateId/moderate` | Compile, dismiss, or revert a candidate |
| `POST` | `/v1/sessions/:id/archive` | Archive or restore a session |

```bash
curl -X POST https://api.tokst.com/v1/sessions \
  -H "Authorization: Bearer $TOKST_API_KEY" \
  -H "X-TokST-Actor: agent" \
  -H "Content-Type: application/json" \
  -d '{"atlasId":"<atlas-id>","task":"Implement the API"}'
```

Candidate writes accept `sourceEventId`. Automatic bridges use task units: an independent task creates one formal memory, and a follow-up updates the matching unit. The event `adapter` enum supports `acp`, `workbuddy`, `opencode`, `pi`, `codex`, and `claude`; Claude Desktop remains MCP-assisted. Repeating a session and event ID returns the existing candidate.
Members manage their own sessions. Workspace Owners and Admins may request `scope=managed` and govern candidate promotion. Reverting a compiled candidate archives its linked formal memory.

The [Session Memory guide](/docs/sessions) covers lifecycle expectations, idempotency, Agent handoffs, review permissions, Local behavior, and dashboard governance.
