---
title: "List coupons"
method: GET
path: "/coupons"
tags: ["Coupons"]
---

# List coupons

`GET /coupons`

## Request

- Base URL: `https://api.privy.com/v1`
- URL: `https://api.privy.com/v1/coupons`
- Auth: HTTP bearer

Retrieve a paginated list of your coupon pools with their code inventory
and health status.

This is inventory and health only. Privy does not track coupon
redemptions — check an individual code's store-side usage counter with
`GET /v1/coupons/{id}/codes/{code}` — and every response carries an
in-band `note` saying so. Two code counters, each `null` where it
doesn't apply: `coupon_codes_remaining` is a manual unique pool's
unused inventory; `coupon_codes_issued` is how many codes any unique
pool has generated for contacts (approximate, and counted only since
the field was introduced).
Master pools have a single shared code and carry neither.

`attached_to` lists every display and message campaign currently
pointing at each pool, so "is this pool actually wired to my
abandoned-cart flow?" needs no dashboard spot-check.

**Required scope:** `coupons_read`

## Query parameters

- `kind` 'master' | 'unique'
- `platform` 'manual' | 'shopify' | 'bigcommerce' | 'woocommerce'
- `title` string
- `page` integer
- `per_page` integer

## Headers

- `Privy-Account-Id` string

## Response `200`

A paginated list of coupon pools.

- object
  - `data` Coupon[]
    - `id` string: Stable, unique identifier for the coupon pool.
    - `title` string
    - `kind` 'master' | 'unique': `master` is a single shared code; `unique` is a pool of individually generated codes.
    - `platform` 'manual' | 'shopify' | 'bigcommerce' | 'woocommerce': Where the pool's codes live — created by hand in Privy, or synced from the connected store.
    - `master_code` string, nullable: The pool's single shared code. Master pools only — always `null` for unique pools.
    - `prefix_code` string, nullable: The prefix the pool's generated codes start with. Unique pools only — always `null` for master pools, and `null` on unique pools that generate without a prefix.
    - `coupon_codes_remaining` integer, nullable: Unused codes still held in the pool, decreasing as codes are handed out. Manual unique pools only (they hold an uploaded inventory); `null` for store-backed unique pools (Shopify/BigCommerce mint codes on demand and hold no inventory) and for master coupons.
    - `coupon_codes_issued` integer, nullable: Codes Privy has generated for contacts from this pool, increasing over time. Counting began when this field was introduced — earlier issuance is not included, so an older pool can read `0` despite having sent codes. Approximate: a bulk batch whose generation Privy could not confirm is not counted even if the store created its codes. Unique pools only; `null` for master coupons.
    - `healthy` boolean: Whether the pool is syncing and generating codes normally.
    - `failure_message` string, nullable: Human-readable failure detail. `null` when the pool is healthy.
    - `attached_to` object: Every message surface currently pointing at this pool — answers "is this pool actually used anywhere?" without walking the other endpoints. Flow campaign refs cover only each flow's current version (the active one, or the newest draft) — a flow's older versions reference the pool through their own campaign rows and are excluded rather than listed as duplicate same-title refs. Ids round-trip through `GET /v1/displays/{id}` and `GET /v1/campaigns/{id}`.
      - `displays` object[]
        - `id` string
        - `title` string, nullable
      - `campaigns` object[]
        - `id` string
        - `title` string, nullable
        - `type` 'newsletter' | 'flow'
        - `channel` 'email' | 'sms'
  - `note` string: Fixed caveat that redemption/usage data is not tracked by Privy.
  - `pagination` PaginationEnvelope
    - `page` integer
    - `per_page` integer
    - `total_count` integer
    - `total_pages` integer

## Other responses

- `401`: Missing or invalid bearer token.
- `403`: `insufficient_scope` when the token lacks the required scope for this endpoint.
- `422`: One or more fields failed validation.
- `429`: Rate limit exceeded. Retry after the specified time.

## Changes

- **2026-11-05** `cf0885e90d5a`: 8 warning
  - added the new `forbidden` enum value to the `error/code` response property for the response status `401`
  - added the new `forbidden` enum value to the `error/code` response property for the response status `403`
  - added the new `forbidden` enum value to the `error/code` response property for the response status `422`
  - added the new `forbidden` enum value to the `error/code` response property for the response status `429`
  - …4 more
- **2026-11-03** `fe500ab59b3b`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/privy/apis/privy-api/changes/coupons/get.md)

---

[API](https://skmtc.dev/privy/apis/privy-api.md) - [All operations](https://skmtc.dev/privy/apis/privy-api/llms.txt) - [OpenAPI document](https://skmtc.dev/privy/apis/privy-api/revisions/bc29b48dcdd2?raw)
