# Authentication

> How a workspace API key (or an MCP sign-in) authenticates on the Platform API, the MCP server and the OpenAI-compatible API, and how it maps to your workspace, role and permissions.

All three API surfaces — the OpenAI-compatible `/v1` API, the MCP server, and
the Platform API — authenticate with the same bearer token: a workspace
API key, created from [Settings → API Keys & Webhooks](/getting-started/api-keys/).

The MCP server, `/mcp`, also lets a person sign in with
their Omni Octo account instead of using a key; the signed-in app then acts
with that person's role, as a key acts with its owner's. See
[Connect an MCP client](/mcp/connect/#oauth-clients).

## Sending the key

```
Authorization: Bearer sk-octo_...
```

The header is `Authorization: Bearer <key>`; a key sent without `Bearer `
(or in `X-API-Key`) is refused with a message saying so.

A missing or invalid key returns `401`. On `/v1` the body is an OpenAI-shaped
error envelope (`code: "invalid_api_key"`), which the OpenAI SDK raises as an
`AuthenticationError`; see [Errors](/openai-api/errors/) for the full table. The
Platform API (`/v1/messages`, `/v1/calls`, `/v1/campaigns`, `/v1/contacts`,
`/v1/conversations`, …) answers the same code in its [error envelope](/platform-api/errors/).

## What the key resolves to

Every key resolves to `{ userId, workspaceId, role }`:

- **`workspaceId`** — every turn, tool call, and conversation created through
  the key is scoped to this workspace. The key is a **workspace credential**,
  not a purely personal one — see [Get an API key](/getting-started/api-keys/)
  for who can see and revoke it.
- **`role`** (`owner` / `admin` / `agent`) — filters the tool catalog exactly
  as it does in the dashboard. A lower-privileged key sees fewer tools; the
  same request made with an `owner`-rooted key and an `agent`-rooted key can
  produce different available actions.

## Workspace-scoped continuation

Conversations created through the API belong to the **workspace**, not to the
individual key that started them. Any key in the workspace can continue or
read any conversation in that workspace (via `previous_response_id` or
`conversation` — see [Statefulness](/openai-api/statefulness/)). This mirrors
how Octo's work belongs to the workspace everywhere else in the product.

## Security model: no step-up factor

This is the part to actually read before wiring up automation:

> An API key inherits its owner's **full role**, and there is **no step-up
> second factor** over the API — the same key both asks for and confirms a
> risky action (see [Confirmations](/openai-api/confirmations/)). A leaked key
> can spend up to the account's limits.

Mitigations that exist today:

- Per-key and per-workspace rate limits: [messaging API](/platform-api/retries/#rate-limits),
  [OpenAI-compatible API](/openai-api/rate-limits/).
- The same cumulative spend / mass-message thresholds that apply everywhere
  else in the product.

Not yet available: restricted-scope keys (read-only, no-spend, or
tool-allowlisted keys) are a deferred follow-up. Until then, **treat every API
key like a password** — don't commit it, don't log it, and rotate it
immediately if it's ever exposed.