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

# Authentication

> API keys and scopes for the Store API.

The Store API uses an API key. The [Marketplace API](/api/marketplace) needs
nothing.

## Getting a key

**Growth → API** in your shop dashboard.

<Warning>
  You see the key once, when it's created. Only a hash is stored, so there's no
  way to retrieve it later. Lose it and you make a new one.
</Warning>

Keys look like `ex_live_` followed by 64 hex characters.

## Sending it

Either header works:

<CodeGroup>
  ```bash Authorization theme={"system"}
  curl https://exclusivo.one/api/v1/products \
    -H "Authorization: Bearer ex_live_your_key_here"
  ```

  ```bash X-API-Key theme={"system"}
  curl https://exclusivo.one/api/v1/products \
    -H "X-API-Key: ex_live_your_key_here"
  ```
</CodeGroup>

<Warning>
  Server-side only. The Store API isn't CORS-open, and a key shipped in browser
  JavaScript is a published key. If you need this data in a browser, proxy it
  through your own backend.
</Warning>

## Scopes

A key carries an explicit list. A request without the right one gets a `403`
naming what it needed.

| Scope             | Lets you                           |
| ----------------- | ---------------------------------- |
| `products:read`   | List and read products             |
| `products:write`  | Create, update and delete products |
| `orders:read`     | List and read orders               |
| `orders:write`    | Update orders                      |
| `customers:read`  | List and read customers            |
| `customers:write` | Create and update customers        |
| `inventory:read`  | Read stock levels                  |
| `inventory:write` | Adjust stock                       |
| `analytics:read`  | Read analytics                     |
| `webhooks:manage` | Manage webhooks                    |
| `store:read`      | Read shop settings                 |

<Tip>
  Give a key the narrowest set that does its job. A read-only integration
  shouldn't hold a `:write` scope — then a leaked key can't change anything.
</Tip>

## Per-key settings

|                |                                               |
| -------------- | --------------------------------------------- |
| **Rate limit** | Requests per minute, set per key              |
| **Expiry**     | Optional. An expired key stops authenticating |
| **Enabled**    | Switch a key off without deleting it          |

Each key tracks when it was last used and how often, which is how you find out
whether an old one is still in service before you delete it.

## Errors

| Status | Means                                        |
| ------ | -------------------------------------------- |
| `401`  | No key, or it's invalid, disabled or expired |
| `403`  | Valid key, wrong scope                       |
| `429`  | Too many requests                            |

```json A 403 theme={"system"}
{
  "error": "Insufficient permissions. Required scope: products:write"
}
```

## Rotating a key

<Steps>
  <Step title="Make the replacement">
    Same scopes.
  </Step>

  <Step title="Deploy it">
    Update your integration.
  </Step>

  <Step title="Check the old one has gone quiet">
    Its last-used time tells you.
  </Step>

  <Step title="Delete it">
    Or disable it first, if you want a step you can undo.
  </Step>
</Steps>

## Related

* [Rate limits](/api/rate-limits)
* [Errors](/api/errors)
* [Webhooks](/api/webhooks)
