# Authentication

> Scoped API keys for your own servers, OAuth tokens for apps other stores install, and how each is checked.

Source: https://shopfa.st/docs/guides/authentication

## API keys

Send a store API key as a bearer token on every request:

```sh
curl https://api.shopfa.st/v1/store/orders -H "Authorization: Bearer sk_live_…"
```

A key is created for exactly one store, so the store comes from the key: every store endpoint starts at
`/v1/store/…` and you never pass a store id. Each one also has an explicit form with the store id in the path,
`/v1/stores/st_…/orders`, which does the same thing (it is what the dashboard uses with its session).

A key:

- works only on **its own store**: `/v1/store/…` is always that store, and any other store id in the explicit form
  answers `404` (it looks like a store that does not exist);
- works only inside its **scopes**, one level per area: `none`, `read` (GET) or `write` (everything, read included);
- acts as **the teammate who created it**, so their role caps it too, and removing them from the team ends it;
- can **expire** (30, 90 or 365 days) and can be **revoked** at any time;
- is stored as an HMAC of its secret with a server-side pepper, so a database read never yields a usable key.

| Area | Reaches |
| --- | --- |
| `store` | Store profile, onboarding, fees, payment model |
| `catalog` | Products, variants, keys, collections, bundles, offers, uploads |
| `orders` | Orders, fulfillment, refunds, disputes, test sales |
| `customers` | Customers and reviews |
| `marketing` | Discounts, gift cards, affiliates, promotions, resellers |
| `storefront` | Themes, pages, domains, SEO, emails |
| `analytics` | Analytics |
| `balance` | Balance and payouts |
| `webhooks` | Webhook endpoints, deliveries and the event explorer |
| `security`, `team`, `audit` | Read only: blocklists, team, audit log |

Billing, payment gateways, store settings, API keys, OAuth apps and plugins are **dashboard only**: no key reaches
them, whatever its scopes. An endpoint's required scope is in the reference as `x-api-key-scope`.

### Test and live keys

Keys minted on a development or staging server start with `sk_test_` and only work there; production keys start
with `sk_live_`. A test key sent to production answers `401 invalid-api-key`.

### IP allowlists

Open a key in **Settings → Developers → API keys** to limit it to IP addresses or CIDR ranges
(`203.0.113.7`, `203.0.113.0/24`, `2001:db8::/32`). Requests from anywhere else answer `403` and appear in the
key's request log with the address they came from. An empty list allows any address.

### Usage and request logs

Every request made with a key or an app token is recorded for 30 days: method, path, route, status, latency, IP,
user agent and the problem type of an error. The dashboard shows usage over 24 hours, 7 or 30 days, the busiest
routes and a log you can filter by key, status class and method.

## OAuth access tokens

Apps that other stores install use [OAuth](https://shopfa.st/docs/guides/oauth) instead of keys. Their access tokens
(`sfo_…`) follow the same rules: one store (so `/v1/store/…` works the same way), the granted scopes, acting as the
teammate who approved the app.

### Dashboard sessions

A signed-in dashboard session can belong to several stores, so it always names one: `/v1/stores/st_…/…`. A
`/v1/store/…` request without a bearer token answers `401 store-implicit-needs-token`.

## Failures

| Status | `type` | Meaning |
| --- | --- | --- |
| 401 | `invalid-api-key` | Unknown, revoked or expired key, or a key from the other environment |
| 401 | `invalid-token` | Expired or revoked OAuth token, or the app was turned off |
| 403 | `forbidden` | Missing scope, a dashboard-only route, or an address outside the allowlist |
| 404 | `not-found` | Another store's id |
| 429 | `rate-limited` | Too many requests ([Rate limits](https://shopfa.st/docs/guides/rate-limits)) |
