# Authentication

> Send a MISSIN API key as a bearer token or in x-api-key. Each key has an access level, capped by its creator's role, and a rate limit.

## Sending a key

Send one API key with every request, either as a bearer token or in the `x-api-key` header:

```bash
curl https://api.missin.co.uk/graphql/v1 \
  -H "Authorization: Bearer sk_live_..." \
  -H "Content-Type: application/json" \
  -d @request.json
```

```bash
curl https://api.missin.co.uk/graphql/v1 \
  -H "x-api-key: sk_live_..." \
  -H "Content-Type: application/json" \
  -d @request.json
```

If a request carries two different keys, one in each header, it is refused with `api_key_conflict` rather than guessing which one you meant. Sending the same key in both is fine.

## Two kinds of key

| Key | Starts with | Public API (`/graphql/v1` and `/mcp`) | Access |
|---|---|---|---|
| Secret | `sk_live_` | Accepted, from your own server | Read Write Admin |
| Publishable | `pk_live_` | Refused with `403` and `secret_key_required`, whatever it asks for | Read only |

> **Warning:**
> Using the public API needs a secret key. A publishable key is refused on every request to `/graphql/v1` and `/mcp`, even a read. A secret key is shown once, when you create it: store it like a password and never send it to a browser.

A publishable key also carries a list of origins, and a request made with one from an origin that is not on that list is refused with `origin_not_allowed` before its kind is checked. An origin is a scheme, a host and an optional port, such as `https://shop.example.com`, with no path and no wildcard.

The API answers cross-origin browser requests only from MISSIN's own sites, so call it from a server, with a secret key, never from a page in a browser.

A key can be created for one connection, such as a single store. The API does not narrow a key's reads to that connection, so it refuses a connection-limited key on every request with `connection_key_not_supported`.

## Access levels

| Level | What it can do |
|---|---|
| Read | Run the read operations over your workspace's records. |
| Write | Everything Read can, plus the operations that create and change workspace data, such as partners, campaigns, posts, forms and discounts. |
| Admin | Everything Write can, plus the operations that change workspace settings, connections and the brand. |

Each operation page in the [API reference](https://developer.missin.co.uk/reference.md) shows the level it needs. The [MISSIN MCP server](https://developer.missin.co.uk/mcp/connect-claude.md) takes the same keys and applies the same levels.

A key acts as the member who created it, and its level is capped by that member's role at the time of each request: an Owner or Admin member can hold up to an Admin key, a Member up to a Write key. A Member can only create keys up to Write. If the creator's role is lowered, every key they made is lowered with it on the next request. If the creator leaves the workspace, their keys are refused with `api_key_creator_not_member`.

A key can never create, change or revoke keys, whatever its level.

## Rate limits

Each key may make 600 requests a minute, unless MISSIN set a different limit on it. Failed attempts with the same key text are limited to 60 attempts a minute, so guessing keys is slow; requests with a valid key do not count towards that. A request over either limit is refused with `rate_limited`.

Separately, the API allows 200 requests a minute from one IP address for every request that does not carry a MISSIN login, whichever keys they carry, so key requests share that budget with any other such traffic from the same address. A request over that limit gets a `429` with the code `RATE_LIMITED`. See [Errors](https://developer.missin.co.uk/get-started/errors.md) for both.

Source: https://developer.missin.co.uk/get-started/authentication
