# List discounts

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

Lists applied coupons (discounts) in the request's mode, newest first: each with the coupon, the promotion code
it was redeemed with, the customer and subscription it belongs to, the window it applies in (`start` to `end`,
null = forever) and its `status` now. Filter by `customerId`, `subscriptionId` or `couponId`.

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

## At a glance

- **REST:** `GET /api/v1/discounts`
- **MCP tool:** `discounts_list`
- **Operation ID:** `discounts.list`
- **Scope:** Brand
- **Permission:** `subscriptions: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 `subscriptions:read` scope
- **Since:** M5

## Request

### Query parameters

| Field            | Type               | Required | Description                         |
| ---------------- | ------------------ | -------- | ----------------------------------- |
| `customerId`     | `cus_…` ID         | No       | Only this customer's discounts.     |
| `subscriptionId` | `sub_…` ID         | No       | Only this subscription's discounts. |
| `couponId`       | `cpn_…` ID         | No       | Only discounts of this coupon.      |
| `limit`          | integer (1 to 100) | No       |                                     |
| `starting_after` | `disc_…` 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`              | `disc_…` ID                           |                                                                        |
| `data[].object`          | `"discount"`                          |                                                                        |
| `data[].brandId`         | `brd_…` ID                            |                                                                        |
| `data[].livemode`        | boolean                               |                                                                        |
| `data[].couponId`        | `cpn_…` ID                            |                                                                        |
| `data[].promotionCodeId` | string or null                        |                                                                        |
| `data[].customerId`      | `cus_…` ID                            |                                                                        |
| `data[].subscriptionId`  | string or null                        | The subscription it belongs to, or null for a customer-level discount. |
| `data[].start`           | date-time                             |                                                                        |
| `data[].end`             | date-time or null                     | When it stops applying (exclusive), or null for forever.               |
| `data[].redeemedAt`      | date-time or null                     | When its redemption was counted.                                       |
| `data[].status`          | one of `scheduled`, `active`, `ended` | `scheduled` before `start`, `active`, or `ended` from `end` on.        |
| `data[].createdAt`       | date-time                             |                                                                        |
| `data[].updatedAt`       | date-time                             |                                                                        |
| `has_more`               | boolean                               |                                                                        |
| `next_cursor`            | `disc_…` ID or null                   |                                                                        |

## Examples

### A subscription's discounts

```http
GET /api/v1/discounts?subscriptionId=sub_01m4tx5nj8emwbyf7y9vcf47z5
Authorization: Bearer or_test_…
```

Response (`200`):

```json
{
  "object": "list",
  "data": [
    {
      "id": "disc_01m4tx5nj8emwbyf7y9vcf47z3",
      "object": "discount",
      "brandId": "brd_01m4tx5nj8emwbyf7y9vcf47x4",
      "livemode": false,
      "couponId": "cpn_01m4tx5nj8emwbyf7y9vcf47z0",
      "promotionCodeId": "promo_01m4tx5nj8emwbyf7y9vcf47z2",
      "customerId": "cus_01m4tx5nj8emwbyf7y9vcf47z4",
      "subscriptionId": "sub_01m4tx5nj8emwbyf7y9vcf47z5",
      "start": "2026-10-13T12:00:00.000Z",
      "end": "2027-01-13T12:00:00.000Z",
      "redeemedAt": "2026-10-13T12:00:00.000Z",
      "status": "active",
      "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 subscriptions.  | 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).
