# Authenticating with Assistable

Assistable exposes a REST API (the **Assistable v3 API**) plus an MCP server. This
document explains how an AI agent or developer obtains credentials and calls the
API. The current method is **API-key bearer authentication**.

- **API base URL:** `https://api.assistable.ai/v3`
- **OpenAPI spec:** https://www.assistable.ai/openapi.json
- **API reference:** https://docs.assistable.ai/api-reference
- **MCP server:** `npx -y @assistableai/mcp` (https://docs.assistable.ai/v3/mcp-server)

## Discover

Machine-readable discovery documents for agents:

- Plugin manifest: https://www.assistable.ai/.well-known/ai-plugin.json
- A2A agent card: https://www.assistable.ai/.well-known/agent-card.json (alias: https://www.assistable.ai/.well-known/agent.json)
- MCP descriptor: https://www.assistable.ai/.well-known/mcp.json
- API catalog (RFC 9727): https://www.assistable.ai/.well-known/api-catalog
- OpenAPI: https://www.assistable.ai/openapi.json

The OpenAPI `securitySchemes.bearerAuth` declares the scheme: HTTP `bearer`.

## Pick a method

| Method | Status | Use it for |
| --- | --- | --- |
| API key (bearer) | **Supported today** | Server-to-server access, agents, SDKs, CLI, MCP |
| OAuth 2.1 (agent_auth) | Planned | Delegated, user-scoped agent access |

For `agent_auth` / OAuth 2.1 discovery (`identity_assertion`, `register_uri`,
`id-jag`), see the roadmap note at the end of this file. Today, use an API key.

## Register

1. Create or sign in to your account at https://app.assistable.ai/access.
2. Open **Settings → API keys** in the dashboard.
3. Create a key. You will see it **once** — store it securely (it is stored only
   as a SHA-256 hash on our side).

Key prefixes indicate the environment:

- `ask_live_…` — production
- `ask_test_…` — test
- `ask_staging_…` — staging
- `ask_dev_…` — development

## Claim

The key string returned at creation **is** the credential — there is no separate
claim/exchange step for API-key auth. Optionally restrict a key with **scopes**
(see below) and an **IP allowlist** when you create it.

## Use the credential

Send the key as a bearer token:

```http
GET https://api.assistable.ai/v3/assistants
Authorization: Bearer ask_live_xxxxxxxxxxxxxxxxxxxx
X-Subaccount-Id: <your-subaccount-id>
```

- **Subaccount selection** (priority order): `X-Subaccount-Id` header
  (recommended) → `subaccount_id` in the body → `location_id` in the body
  (legacy alias). Single-subaccount keys resolve automatically.
- **Response envelope:** every response is `{ "data": …, "error": …, "request_id": "…" }`.
  Include `request_id` when contacting support.

### Scopes

Scopes are `resource:action` (for example `assistants:read`, `calls:create`,
`contacts:write`). Presets: `read_only`, `read_write`, `admin`, or a custom set.
A request whose key lacks the required scope returns **403**.

## Errors

| Status | Meaning | What the agent should do |
| --- | --- | --- |
| 401 | Missing/invalid key, or IP not in the allowlist | Re-check the `Authorization` header and the key's IP allowlist |
| 403 | Key lacks the required scope | Create a key with the needed `resource:action` scope |
| 404 | Unknown subaccount or resource | Verify `X-Subaccount-Id` and the resource id |
| 422 | Validation error | Inspect `error` in the response envelope |
| 429 | Rate limited | Back off and retry |

Errors use the same envelope: `{ "data": null, "error": { … }, "request_id": "…" }`.

## Revocation

Revoke a key any time in **Settings → API keys** in the dashboard
(https://app.assistable.ai/access). Revocation is immediate; rotate by
creating a new key, deploying it, then revoking the old one.

---

### Roadmap: OAuth 2.1 agent auth

Delegated, user-scoped `agent_auth` (OAuth 2.1 authorization-code + PKCE-S256,
RFC 8414 authorization-server metadata and RFC 9728 protected-resource metadata,
`WWW-Authenticate: Bearer resource_metadata=…`) is on the roadmap. Until it ships,
this file documents the supported API-key method so agents don't probe for
endpoints that are not yet live. Questions: support@assistable.ai.
