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

# Authentication

> API keys, workflow scopes, and why reading and spending are separate grants.

# Authentication

Every request carries a bearer credential:

```bash theme={null}
curl https://research-api.briefedmedia.com/api/v1/workflows \
  -H "Authorization: Bearer brf_live_..."
```

Three credentials are accepted, and Briefed ID resolves them by different routes:

* an **API key** (`brf_live_…`), for programmatic and agent use
* a **session JWT**, issued to the signed-in browser app
* an **OAuth access token**, issued when you approve a client such as the
  [MCP server](/mcp/overview). It resolves to you rather than to a key, so it
  carries no scopes and is bounded by your entitlement

Create keys at [id.briefedmedia.com/api-keys](https://id.briefedmedia.com/api-keys). A key is shown once at creation and stored only as a hash, so it cannot be recovered later.

## Which plans have API access

The Workflows API is available on **Max** and **Team** seats. Pro includes Workflows in the browser but not programmatic access, and cannot create API keys.

These scopes cover the Workflows surface only. Terminal is reachable as a step inside a workflow graph (`terminal.*`) and has no API of its own. Anya does: [her own surface](/research/anya#anyas-own-api) under `/anya`, gated by the `anya` entitlement rather than by these scopes, and a key granted Workflows scopes is not thereby granted Anya.

A caller on a plan without it receives `402`:

```json theme={null}
{
  "error": "plan_required",
  "message": "The Workflows API requires a Max or Team Briefed Research plan.",
  "required_feature": "workflows_api"
}
```

## Product scoping

A key carries a set of products. To reach this API the key must include `briefed_research` in its products. A key scoped only to Consumer Intelligence resolves as a valid key but is refused here.

## Scopes

Running a workflow **draws on your research usage allowance**. Reading one does not. They are therefore separate grants, so a key handed to an automation, a script, or an MCP server can be made incapable of incurring cost.

| Scope             | Grants                                                                                                     |
| ----------------- | ---------------------------------------------------------------------------------------------------------- |
| `read:workflows`  | List and read workflows, versions, runs and the part catalogue. Validate a draft graph. Resolve companies. |
| `write:workflows` | Everything above, plus create, edit, publish, run, deliver, cancel, and the drafting assistant.            |

`write:workflows` implies `read:workflows`; a key that can publish can obviously list.

A request needing a scope the key lacks returns `403`:

```json theme={null}
{
  "error": "insufficient_scope",
  "message": "This API key needs the write:workflows scope.",
  "required_scope": "write:workflows"
}
```

### Which routes need which

Classification is explicit, not inferred from the HTTP method. Two POSTs are reads because they change nothing and cost nothing. An agent must be able to check its own work without also being able to spend:

* `POST /api/v1/workflows/catalogue/validate-definition`
* `POST /api/v1/workflows/catalogue/resolve-subjects`

Every other mutating route requires `write:workflows`, including any added in future.

<Note>
  A session JWT is not scope-limited. A signed-in user is bounded by their plan entitlement rather than by a key, so scopes apply to API keys only.
</Note>

## Recommended split

Issue two keys rather than one:

* a **read-only** key (`read:workflows`) for dashboards, monitoring, CI checks, and any agent that inspects but must not act
* a **write** key (`write:workflows`) held by the small number of callers that publish or run, with an expiry set

Keys support expiry, revocation, and an IP allowlist. Revoking takes effect within the credential cache TTL of 60 seconds.

## Failure modes

| Status | Code                    | Meaning                                                                                     |
| ------ | ----------------------- | ------------------------------------------------------------------------------------------- |
| 401    | `UNAUTHENTICATED`       | No credential, or a key that is unknown, revoked or expired                                 |
| 402    | `plan_required`         | Valid credential, but the plan lacks `workflows` or `workflows_api`. See `required_feature` |
| 403    | `insufficient_scope`    | Valid key, wrong scope for this route                                                       |
| 403    | `GATE_REQUIRED`         | An acceptance is outstanding on the account and must be cleared first                       |
| 503    | `workflows_unavailable` | Workflows is not available in your region                                                   |
