
<ApiOverview api="storefront" />

The Storefront API is the API behind your storefront: the shop and its
settings, products and bundles, carts and checkout, and the account of the
signed-in customer. It is safe to call from the browser with a Storefront API
key; [Subbly.js](/reference/subbly-sdk) wraps it for you.

## Base URL

```text title="Base URL"
https://api.subbly.co/storefront/v1
```

Every path in this reference is relative to it. Requests and responses are
JSON; send `Content-Type: application/json` with a body.

## Authentication

Send your Storefront API key in the `X-API-KEY` header on every request.

Endpoints about one customer — their addresses, subscriptions, orders, wallet —
also need the customer's access token, in the `Authorization` header as a
bearer token. The [Auth](/api/storefront/auth) endpoints issue the token; it
expires after `expires_in` seconds.

```bash title="Both headers"
curl https://api.subbly.co/storefront/v1/customer \
  -H 'X-API-KEY: <api-key>' \
  -H 'Authorization: Bearer <access-token>'
```

### Get your API key

Storefront API keys live in the Subbly admin under
[Settings › API keys](https://www.subbly.co/admin/settings/api-keys). In the
**Storefront API keys** card, click **Generate API key**, then copy the key
with the icon next to it. You can keep several keys; the first one is the key
the Subbly website builder uses. A Storefront key is safe to ship in browser
code: it can only read public shop data and act for the customer whose access
token comes with it.

## Pagination

List endpoints take `page` and `per_page` query parameters and return the
items in `data` next to a `pagination` object:

```json title="A page"
{
  "pagination": {
    "current_page": 1,
    "last_page": 4,
    "from": 1,
    "to": 25,
    "total": 92
  },
  "data": []
}
```

## Errors

The API answers with the usual HTTP status codes. Most `4xx` responses carry a
JSON body with a `message` and a `code` you can branch on; validation errors
(`422`) add an `errors` object keyed by field.

| Status | Meaning |
| --- | --- |
| `400` | The request is malformed, or names a record that is not the customer's. |
| `401` | The API key or the access token is missing or wrong. |
| `402` | The payment needs another step; the body carries the payment intent to confirm. |
| `404` | Nothing at this path, or it belongs to another shop. |
| `410` | The endpoint no longer applies to this record; the description names the replacement. |
| `422` | The body or the query failed validation. |
| `429` | Too many requests; wait and retry. |

There is no `403`. When a customer endpoint is handed a record that belongs to
someone else — another customer's address, pick-up info, payment method or
subscription — it answers `400` with `"code": "bad_request"`. A few guard rules
answer the same way, such as deleting the last payment method in the wallet.

The description of each endpoint lists the errors it can return.
