# List promotion codes

> The promotion_codes.list operation: GET /api/v1/promotion_codes in the REST API and the promotion_codes_list tool in the MCP server.

Lists the brand's promotion codes in the request's mode, newest first. Filter by `couponId`, by `active`, or by
`code` to look a code up the way customers type it (case doesn't matter; at most one result).

Paginate with `limit` (1–100, default 10) and `starting_after` (the `next_cursor` of the previous page).

## At a glance

- **REST:** `GET /api/v1/promotion_codes`
- **MCP tool:** `promotion_codes_list`
- **Operation ID:** `promotion_codes.list`
- **Scope:** Brand
- **Permission:** `catalog:read`
- **Risk tier:** `read`
- **Dry run:** Not supported
- **Idempotency:** Not needed (read only)
- **Modes:** Test and live
- **Pagination:** `limit` (at most 100) and `starting_after`
- **Authentication:** API key with the `catalog:read` scope
- **Since:** M5

## Request

### Query parameters

| Field            | Type               | Required | Description                                                                |
| ---------------- | ------------------ | -------- | -------------------------------------------------------------------------- |
| `couponId`       | `cpn_…` ID         | No       | Only the codes of this coupon.                                             |
| `code`           | string             | No       | Find the promotion code customers type as this text (case doesn't matter). |
| `active`         | string             | No       | Only active (true) or archived (false) codes.                              |
| `limit`          | integer (1 to 100) | No       |                                                                            |
| `starting_after` | `promo_…` ID       | No       |                                                                            |

## Response

`200 OK` with a JSON object, a page of the list (newest first):

| Field                                | Type                 | Description                                    |
| ------------------------------------ | -------------------- | ---------------------------------------------- |
| `object`                             | `"list"`             |                                                |
| `data`                               | array of object      |                                                |
| `data[].id`                          | `promo_…` ID         |                                                |
| `data[].object`                      | `"promotion_code"`   |                                                |
| `data[].brandId`                     | `brd_…` ID           |                                                |
| `data[].livemode`                    | boolean              |                                                |
| `data[].couponId`                    | `cpn_…` ID           |                                                |
| `data[].code`                        | string               | As entered; customers may type it in any case. |
| `data[].restrictions`                | object               |                                                |
| `data[].restrictions.firstTimeOnly`  | boolean              |                                                |
| `data[].restrictions.minimumAmount`  | money or null        |                                                |
| `data[].restrictions.customerId`     | string or null       |                                                |
| `data[].restrictions.expiresAt`      | date-time or null    |                                                |
| `data[].restrictions.maxRedemptions` | integer or null      |                                                |
| `data[].timesRedeemed`               | integer              |                                                |
| `data[].active`                      | boolean              |                                                |
| `data[].metadata`                    | object               |                                                |
| `data[].createdAt`                   | date-time            |                                                |
| `data[].updatedAt`                   | date-time            |                                                |
| `has_more`                           | boolean              |                                                |
| `next_cursor`                        | `promo_…` ID or null |                                                |

## Examples

### Look up a code as a customer typed it

```http
GET /api/v1/promotion_codes?code=launch50
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "list",
  "data": [
    {
      "id": "promo_01m4tx5nj8emwbyf7y9vcf47z2",
      "object": "promotion_code",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "livemode": false,
      "couponId": "cpn_01m4tx5nj8emwbyf7y9vcf47z0",
      "code": "LAUNCH50",
      "restrictions": {
        "firstTimeOnly": true,
        "minimumAmount": null,
        "customerId": null,
        "expiresAt": null,
        "maxRedemptions": 200
      },
      "timesRedeemed": 0,
      "active": true,
      "metadata": {},
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

### A coupon's codes

```http
GET /api/v1/promotion_codes?couponId=cpn_01m4tx5nj8emwbyf7y9vcf47z0
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "list",
  "data": [
    {
      "id": "promo_01m4tx5nj8emwbyf7y9vcf47z2",
      "object": "promotion_code",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "livemode": false,
      "couponId": "cpn_01m4tx5nj8emwbyf7y9vcf47z0",
      "code": "LAUNCH50",
      "restrictions": {
        "firstTimeOnly": true,
        "minimumAmount": null,
        "customerId": null,
        "expiresAt": null,
        "maxRedemptions": 200
      },
      "timesRedeemed": 0,
      "active": true,
      "metadata": {},
      "createdAt": "2026-10-13T12:00:00.000Z",
      "updatedAt": "2026-10-13T12:00:00.000Z"
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

## Errors

| Code                                                                                   | HTTP status | When                                       | What to do                                                                      |
| -------------------------------------------------------------------------------------- | ----------- | ------------------------------------------ | ------------------------------------------------------------------------------- |
| [`validation_failed`](https://ownrecord.io/docs/reference/errors.md#validation_failed) | 400         | A filter or pagination value is malformed. | Fix the fields listed in `details.issues` and send the request again.           |
| [`permission_denied`](https://ownrecord.io/docs/reference/errors.md#permission_denied) | 403         | You can't see this brand's catalog.        | Ask an organization owner or admin for a role or scope that allows this action. |

It can also return these [common errors](https://ownrecord.io/docs/reference.md#common-errors): [`api_version_unsupported`](https://ownrecord.io/docs/reference/errors.md#api_version_unsupported), [`authentication_required`](https://ownrecord.io/docs/reference/errors.md#authentication_required), [`api_key_invalid`](https://ownrecord.io/docs/reference/errors.md#api_key_invalid), [`scope_required`](https://ownrecord.io/docs/reference/errors.md#scope_required), [`resource_not_found`](https://ownrecord.io/docs/reference/errors.md#resource_not_found), [`dry_run_not_supported`](https://ownrecord.io/docs/reference/errors.md#dry_run_not_supported), [`rate_limited`](https://ownrecord.io/docs/reference/errors.md#rate_limited), [`internal_error`](https://ownrecord.io/docs/reference/errors.md#internal_error).
