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

# Authentication

> How to authenticate — API key or OAuth — and how scopes work.

Every authenticated call uses the same header, regardless of token type:

```http theme={null}
Authorization: Bearer <token>
```

There are two ways to get a token. Use whichever fits your case:

<CardGroup cols={2}>
  <Card title="API Key" icon="key">
    To integrate **your own store** with an internal system, script, or private app. You generate the key yourself in the dashboard — no authorization flow needed.
  </Card>

  <Card title="OAuth" icon="plug">
    To build a **public app** that other sellers will install and authorize on their own store. See the [OAuth guide](/en/oauth).
  </Card>
</CardGroup>

## API Key

Generated under **Settings → API** in the Lojou dashboard. Each key is created with a fixed set of scopes chosen at creation time — it doesn't change later without generating a new key.

```bash theme={null}
curl https://api.lojou.app/v1/orders \
  -H "Authorization: Bearer <your_api_key>"
```

## OAuth token

Issued via `POST /v1/oauth/token`, after the seller authorizes your app. It expires in 30 days (the `refresh_token` returned alongside it is meant to renew access without asking for authorization again — build that into your app's backend). An OAuth token's scopes are whatever the **seller approved** on the authorization screen — possibly a subset of what your app requested.

```bash theme={null}
curl https://api.lojou.app/v1/orders \
  -H "Authorization: Bearer <access_token>"
```

From the point of view of `/v1/*` endpoints, an OAuth token and an API key work exactly the same — the only difference is how each one is issued.

## Scopes

Every authenticated call is checked against the token's scopes (API key or OAuth). A scope follows the `resource.action` shape:

| Resource     | Scopes                                                              |
| ------------ | ------------------------------------------------------------------- |
| `user`       | `user.read` (read-only — user data can't be edited through the API) |
| `products`   | `products.read`, `products.write`                                   |
| `plans`      | `plans.read`, `plans.write`                                         |
| `orders`     | `orders.read`, `orders.write`                                       |
| `customers`  | `customers.read`                                                    |
| `files`      | `files.read`, `files.write`                                         |
| `webhooks`   | `webhooks.read`, `webhooks.write`                                   |
| `discounts`  | `discounts.read`, `discounts.write`                                 |
| `affiliates` | `affiliates.read`, `affiliates.write`                               |

<Tip>
  Not sure which scopes your token has? Call `GET /v1/scopes` — it lists every scope the API supports and the endpoints each one unlocks.
</Tip>

If the required scope is missing, the API responds with `403`:

```json theme={null}
{
  "status": "error",
  "message": "Permission denied for this endpoint.",
  "error_code": "insufficient_scope",
  "required_scopes": ["orders.read"],
  "missing_scopes": ["orders.read"],
  "granted_scopes": ["products.read", "products.write"]
}
```

## Authentication errors

| Status                   | Reason                                                                |
| ------------------------ | --------------------------------------------------------------------- |
| `401 Token not provided` | No `Authorization` header was sent.                                   |
| `401 Invalid token`      | The token doesn't exist, was revoked, or expired.                     |
| `403 insufficient_scope` | The token is valid but doesn't have the scope this endpoint requires. |
