> ## Documentation Index
> Fetch the complete documentation index at: https://codebeans-cb-notifylyst.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication & limits

> How to send your API key, the rate limit, paging, and every error code.

## Your API key

Each store has **one** key, managed in **Settings → API key**.

| Action | What happens |
| - | - |
| First visit | A key is created and shown once. Copy it then. |
| **Regenerate key** | A new key is created. The old one stops working immediately. |
| **Revoke key** | The key stops working. No new key is created until you press **Create new key**. |

Send it on every request, in either header:

```bash theme={"system"}
-H "X-API-Key: nl_live_YOUR_KEY"
# or
-H "Authorization: Bearer nl_live_YOUR_KEY"
```

> [!WARNING]
>
> Treat the key like a password. Call the API from a server, never from storefront JavaScript or a
> browser extension — anyone who can see the key can read and add sign-ups for your store.

## Plan

Every endpoint except the `/api/v1` index needs a plan that includes **REST API**. Without it, calls
return `403 feature_not_included`.

## Rate limit

**20 requests a minute** per store. Every reply carries:

| Header | Meaning |
| - | - |
| `X-RateLimit-Limit` | Requests allowed per minute. |
| `X-RateLimit-Remaining` | Requests left in the current minute. |
| `Retry-After` | On a `429` only: seconds to wait. |

Adding many sign-ups? One [bulk call](https://codebeans-cb-notifylyst.mintlify.site/api/subscribers.md#add-sign-ups-in-bulk) carries up to 250 and
counts as one request.

## Paging

List endpoints return newest first and use a **cursor**:

```json theme={"system"}
{
  "data": [ … ],
  "has_more": true,
  "next_cursor": "6731f0c2a9e4b1d2c3f4a5b6"
}
```

Pass `next_cursor` back as `?cursor=` to get the next page. `limit` sets the page size: 1 to 100,
default 25. The waiting list uses `page` and `limit` instead, and returns `total`.

## Dates

Send dates as `YYYY-MM-DD` (the whole day) or a full ISO 8601 time. Times in responses are ISO 8601
in UTC. The waiting list and the analytics summary read a bare date in your **store's** time zone,
like the app's own reports.

## Errors

Every error has the same shape:

```json theme={"system"}
{
  "error": {
    "code": "invalid_request",
    "message": "variant_id must be a numeric Shopify variant id."
  }
}
```

| HTTP | `code` | Meaning |
| - | - | - |
| 400 | `invalid_request` | The body or a query parameter is missing or malformed. `message` says which. |
| 401 | `missing_api_key` | No key in `X-API-Key` (or `Authorization: Bearer`). |
| 401 | `invalid_api_key` | The key is wrong, or was replaced by a newer one. |
| 401 | `api_key_revoked` | The key was revoked in **Settings → API key**. |
| 403 | `feature_not_included` | Your plan does not include REST API. |
| 404 | `not_found` | No such record in your store. |
| 405 | `method_not_allowed` | That HTTP method is not supported on this path. |
| 409 | `conflict` | The record is not in a state that allows this — for example, cancelling a sign-up that was already sent. |
| 429 | `rate_limited` | More than 20 requests in a minute. Wait `Retry-After` seconds. |
| 502 | `shopify_unavailable` | Shopify could not be reached to check the products. Retry later. |
| 500 | `internal_error` | Something failed on our side. Retry later. |


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.