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

# Admin Coupons API — Create and Manage Discount Coupons

> Create percentage or fixed-amount discount coupons, set usage limits and validity windows, and inspect redemption history per coupon.

The Admin Coupons API lets you build and manage the full lifecycle of discount coupons — from creating a new promotion with a fixed-amount or percentage discount, to updating limits and validity windows, to soft-deleting a coupon when a promotion ends and inspecting every redemption it generated. Coupons are validated at checkout against the customer's cart total, usage limits, and validity window before the discount is applied.

<Note>
  All endpoints under `/admin/coupons` require an authenticated session with the `ADMIN` or `SUPER_ADMIN` role. For every `POST`, `PATCH`, and `DELETE` request, first call `GET /auth/csrf-token` and pass the returned token in the `x-csrf-token` header.
</Note>

***

## List Coupons

Retrieve a paginated list of all coupons. Filter by computed status, search by code or description, and sort by usage, value, or dates.

```
GET /admin/coupons
```

### Query Parameters

<ParamField query="page" type="integer" default="1">
  Page number (1-based).
</ParamField>

<ParamField query="limit" type="integer" default="20">
  Results per page. Range: 1–100.
</ParamField>

<ParamField query="search" type="string">
  Free-text search across coupon codes.
</ParamField>

<ParamField query="status" type="string">
  Filter by computed coupon status. Accepted values: `ACTIVE`, `INACTIVE`, `EXPIRED`, `USAGE_LIMIT_REACHED`.
</ParamField>

<ParamField query="include_deleted" type="string" default="false">
  Pass `"true"` to include soft-deleted coupons in results.
</ParamField>

<ParamField query="sort" type="string" default="-created_at">
  Sort field. Prefix with `-` for descending. Accepted values: `code`, `-code`, `discount_value`, `-discount_value`, `usage_count`, `-usage_count`, `starts_at`, `-starts_at`, `expires_at`, `-expires_at`, `created_at`, `-created_at`.
</ParamField>

### Response

<ResponseField name="success" type="boolean">
  Always `true` on a 200 response.
</ResponseField>

<ResponseField name="data" type="array">
  Array of coupon objects. See the [coupon object fields](#coupon-object) below.
</ResponseField>

<ResponseField name="meta" type="object">
  Pagination metadata.

  <Expandable title="Pagination fields">
    <ResponseField name="total" type="integer">Total matching coupons.</ResponseField>
    <ResponseField name="totalPages" type="integer">Total number of pages.</ResponseField>
    <ResponseField name="hasNext" type="boolean">Whether a next page exists.</ResponseField>
    <ResponseField name="hasPrev" type="boolean">Whether a previous page exists.</ResponseField>
  </Expandable>
</ResponseField>

```bash Example — list all active coupons sorted by usage theme={null}
curl "https://api.example.com/api/v1/admin/coupons?status=ACTIVE&sort=-usage_count" \
  -H "Cookie: session=<your-session-cookie>"
```

***

## Create Coupon

Create a new discount coupon. Specify the discount type, value, total and per-user usage limits, and optionally a validity window, minimum order amount, and maximum discount cap.

```
POST /admin/coupons
```

<Note>
  Coupon codes are automatically uppercased by the server when customers enter them at checkout — your customers can type `save10`, `SAVE10`, or `Save10` and the system treats all three identically. You do not need to sanitise case on the client side.
</Note>

<Tip>
  Set `usage_limit: 1` and `usage_limit_per_user: 1` to create a single-use coupon. This is ideal for personalised discount links or one-time compensation credits — the coupon becomes unavailable the moment a single customer redeems it.
</Tip>

### Request Body

<ParamField body="code" type="string" required>
  Unique coupon code. Accepts letters, numbers, dashes, and underscores. Length: 3–50 characters. Automatically uppercased. Example: `"SUMMER20"`.
</ParamField>

<ParamField body="discount_type" type="string" required>
  The discount calculation method. Accepted values: `FIXED_AMOUNT` (deducts a flat currency amount), `PERCENTAGE` (deducts a percentage of the order total).
</ParamField>

<ParamField body="discount_value" type="number" required>
  The discount magnitude. For `PERCENTAGE`, must be between 0 (exclusive) and 100 (inclusive). For `FIXED_AMOUNT`, must be greater than 0. Example: `20` for 20% off or `10.00` for a \$10 discount.
</ParamField>

<ParamField body="usage_limit" type="integer" required>
  Total number of times this coupon can be redeemed across all customers (≥ 1).
</ParamField>

<ParamField body="usage_limit_per_user" type="integer" required>
  Maximum number of times a single customer can redeem this coupon (≥ 1).
</ParamField>

<ParamField body="minimum_order_amount" type="number">
  Minimum cart total (before discount) required to apply this coupon. Omit for no minimum.
</ParamField>

<ParamField body="maximum_discount_amount" type="number">
  Cap on the discount value in currency units. Useful for percentage coupons where you want to limit the maximum saving. For example, a 30%-off coupon with `maximum_discount_amount: 50` saves at most \$50. Must be greater than 0.
</ParamField>

<ParamField body="starts_at" type="string">
  ISO 8601 UTC datetime from which the coupon becomes valid. Omit to make it valid immediately.
</ParamField>

<ParamField body="expires_at" type="string">
  ISO 8601 UTC datetime after which the coupon is no longer valid. Must be after `starts_at` when both are provided. Omit for a coupon with no expiry.
</ParamField>

<ParamField body="is_active" type="boolean" default="true">
  Set to `false` to create the coupon in an inactive state — useful for staging promotions before making them live.
</ParamField>

<CodeGroup>
  ```bash Create a percentage coupon theme={null}
  CSRF=$(curl -s https://api.example.com/api/v1/auth/csrf-token \
    -H "Cookie: session=<your-session-cookie>" | jq -r '.data.csrf_token')

  curl -X POST https://api.example.com/api/v1/admin/coupons \
    -H "Cookie: session=<your-session-cookie>" \
    -H "x-csrf-token: $CSRF" \
    -H "Content-Type: application/json" \
    -d '{
      "code": "SUMMER20",
      "discount_type": "PERCENTAGE",
      "discount_value": 20,
      "usage_limit": 500,
      "usage_limit_per_user": 1,
      "minimum_order_amount": 50,
      "maximum_discount_amount": 40,
      "starts_at": "2024-06-01T00:00:00.000Z",
      "expires_at": "2024-08-31T23:59:59.000Z"
    }'
  ```

  ```bash Create a fixed-amount coupon theme={null}
  CSRF=$(curl -s https://api.example.com/api/v1/auth/csrf-token \
    -H "Cookie: session=<your-session-cookie>" | jq -r '.data.csrf_token')

  curl -X POST https://api.example.com/api/v1/admin/coupons \
    -H "Cookie: session=<your-session-cookie>" \
    -H "x-csrf-token: $CSRF" \
    -H "Content-Type: application/json" \
    -d '{
      "code": "WELCOME10",
      "discount_type": "FIXED_AMOUNT",
      "discount_value": 10,
      "usage_limit": 1000,
      "usage_limit_per_user": 1
    }'
  ```

  ```bash Create a single-use coupon theme={null}
  CSRF=$(curl -s https://api.example.com/api/v1/auth/csrf-token \
    -H "Cookie: session=<your-session-cookie>" | jq -r '.data.csrf_token')

  curl -X POST https://api.example.com/api/v1/admin/coupons \
    -H "Cookie: session=<your-session-cookie>" \
    -H "x-csrf-token: $CSRF" \
    -H "Content-Type: application/json" \
    -d '{
      "code": "VIP-JANE-2024",
      "discount_type": "FIXED_AMOUNT",
      "discount_value": 25,
      "usage_limit": 1,
      "usage_limit_per_user": 1
    }'
  ```
</CodeGroup>

```json 201 Response theme={null}
{
  "success": true,
  "data": {
    "public_id": "cpn_01HSUM",
    "code": "SUMMER20",
    "discount_type": "PERCENTAGE",
    "discount_value": 20,
    "usage_limit": 500,
    "usage_limit_per_user": 1,
    "usage_count": 0,
    "status": "ACTIVE",
    "is_active": true,
    "minimum_order_amount": 50,
    "maximum_discount_amount": 40,
    "starts_at": "2024-06-01T00:00:00.000Z",
    "expires_at": "2024-08-31T23:59:59.000Z",
    "created_at": "2024-05-20T08:00:00.000Z"
  }
}
```

***

## Get Coupon

Retrieve a single coupon by its public ID. The response includes current usage count and computed status alongside all configuration fields.

```
GET /admin/coupons/{coupon_public_id}
```

### Path Parameters

<ParamField path="coupon_public_id" type="string" required>
  The coupon's public ID. Must start with `cpn_`.
</ParamField>

### Coupon Object

<ResponseField name="public_id" type="string">
  Unique coupon identifier, prefixed `cpn_`.
</ResponseField>

<ResponseField name="code" type="string">
  Uppercase coupon code as stored.
</ResponseField>

<ResponseField name="discount_type" type="string">
  `FIXED_AMOUNT` or `PERCENTAGE`.
</ResponseField>

<ResponseField name="discount_value" type="number">
  The numeric discount magnitude.
</ResponseField>

<ResponseField name="usage_limit" type="integer">
  Total redemption cap.
</ResponseField>

<ResponseField name="usage_limit_per_user" type="integer">
  Per-user redemption cap.
</ResponseField>

<ResponseField name="usage_count" type="integer">
  Number of times this coupon has been successfully redeemed.
</ResponseField>

<ResponseField name="status" type="string">
  Computed status: `ACTIVE`, `INACTIVE`, `EXPIRED`, or `USAGE_LIMIT_REACHED`.
</ResponseField>

<ResponseField name="is_active" type="boolean">
  Whether the coupon is administratively enabled.
</ResponseField>

<ResponseField name="minimum_order_amount" type="number | null">
  Minimum cart value to apply the coupon, or `null`.
</ResponseField>

<ResponseField name="maximum_discount_amount" type="number | null">
  Discount cap in currency units, or `null`.
</ResponseField>

<ResponseField name="starts_at" type="string | null">
  ISO 8601 UTC start datetime, or `null`.
</ResponseField>

<ResponseField name="expires_at" type="string | null">
  ISO 8601 UTC expiry datetime, or `null`.
</ResponseField>

<ResponseField name="created_at" type="string">
  ISO 8601 UTC creation timestamp.
</ResponseField>

```bash Example — get coupon detail theme={null}
curl https://api.example.com/api/v1/admin/coupons/cpn_01HSUM \
  -H "Cookie: session=<your-session-cookie>"
```

***

## Update Coupon

Update one or more fields of an existing coupon. Only the fields you include in the request body are changed. Pass `null` for optional monetary or date fields to clear them.

```
PATCH /admin/coupons/{coupon_public_id}
```

### Path Parameters

<ParamField path="coupon_public_id" type="string" required>
  The coupon's public ID. Must start with `cpn_`.
</ParamField>

### Request Body

Provide at least one field. All fields follow the same validation rules as on creation.

<ParamField body="code" type="string">
  New coupon code. Length 3–50, alphanumeric/dash/underscore only. Uppercased automatically.
</ParamField>

<ParamField body="discount_type" type="string">
  `FIXED_AMOUNT` or `PERCENTAGE`.
</ParamField>

<ParamField body="discount_value" type="number">
  New discount value. For `PERCENTAGE`, must be 0 (exclusive) to 100 (inclusive).
</ParamField>

<ParamField body="usage_limit" type="integer">
  New total usage cap (≥ 1).
</ParamField>

<ParamField body="usage_limit_per_user" type="integer">
  New per-user cap (≥ 1).
</ParamField>

<ParamField body="minimum_order_amount" type="number | null">
  New minimum order amount, or `null` to remove the requirement.
</ParamField>

<ParamField body="maximum_discount_amount" type="number | null">
  New discount cap, or `null` to remove the cap.
</ParamField>

<ParamField body="starts_at" type="string | null">
  New start datetime (ISO 8601), or `null` to make it immediately valid.
</ParamField>

<ParamField body="expires_at" type="string | null">
  New expiry datetime (ISO 8601). Must be after `starts_at` when both are set. Pass `null` to remove the expiry.
</ParamField>

<ParamField body="is_active" type="boolean">
  Set to `false` to deactivate the coupon without deleting it, or `true` to re-enable it.
</ParamField>

```bash Example — extend expiry and increase usage limit theme={null}
CSRF=$(curl -s https://api.example.com/api/v1/auth/csrf-token \
  -H "Cookie: session=<your-session-cookie>" | jq -r '.data.csrf_token')

curl -X PATCH https://api.example.com/api/v1/admin/coupons/cpn_01HSUM \
  -H "Cookie: session=<your-session-cookie>" \
  -H "x-csrf-token: $CSRF" \
  -H "Content-Type: application/json" \
  -d '{
    "expires_at": "2024-09-30T23:59:59.000Z",
    "usage_limit": 1000
  }'
```

```json 200 Response theme={null}
{
  "success": true,
  "data": {
    "public_id": "cpn_01HSUM",
    "code": "SUMMER20",
    "discount_type": "PERCENTAGE",
    "discount_value": 20,
    "usage_limit": 1000,
    "usage_limit_per_user": 1,
    "usage_count": 47,
    "status": "ACTIVE",
    "is_active": true,
    "expires_at": "2024-09-30T23:59:59.000Z",
    "created_at": "2024-05-20T08:00:00.000Z"
  }
}
```

***

## Delete Coupon

Soft-delete a coupon, removing it from the checkout flow while preserving its full redemption history for reporting. The coupon is no longer redeemable by customers but remains visible in the admin list when `include_deleted=true`.

```
DELETE /admin/coupons/{coupon_public_id}
```

### Path Parameters

<ParamField path="coupon_public_id" type="string" required>
  The coupon's public ID. Must start with `cpn_`.
</ParamField>

```bash Example — delete a coupon theme={null}
CSRF=$(curl -s https://api.example.com/api/v1/auth/csrf-token \
  -H "Cookie: session=<your-session-cookie>" | jq -r '.data.csrf_token')

curl -X DELETE https://api.example.com/api/v1/admin/coupons/cpn_01HSUM \
  -H "Cookie: session=<your-session-cookie>" \
  -H "x-csrf-token: $CSRF"
```

A successful deletion returns `204 No Content` with an empty body.

***

## List Coupon Usages

Retrieve a paginated redemption history for a specific coupon. Each entry identifies the customer who redeemed it, the order it was applied to, and the exact discount amount that was deducted.

```
GET /admin/coupons/{coupon_public_id}/usages
```

### Path Parameters

<ParamField path="coupon_public_id" type="string" required>
  The coupon's public ID. Must start with `cpn_`.
</ParamField>

### Query Parameters

<ParamField query="page" type="integer" default="1">
  Page number (1-based).
</ParamField>

<ParamField query="limit" type="integer" default="20">
  Results per page. Range: 1–100.
</ParamField>

### Response

<ResponseField name="success" type="boolean">
  Always `true` on a 200 response.
</ResponseField>

<ResponseField name="data" type="array">
  Array of usage records.

  <Expandable title="Usage record fields">
    <ResponseField name="public_id" type="string">
      Unique usage record identifier.
    </ResponseField>

    <ResponseField name="coupon_public_id" type="string">
      The coupon that was redeemed, prefixed `cpn_`.
    </ResponseField>

    <ResponseField name="user_public_id" type="string">
      The customer who applied the coupon, prefixed `usr_`.
    </ResponseField>

    <ResponseField name="order_public_id" type="string">
      The order the coupon was applied to, prefixed `ord_`.
    </ResponseField>

    <ResponseField name="discount_applied" type="string">
      Actual discount deducted from the order total as a decimal string, e.g. `"20.00"`.
    </ResponseField>

    <ResponseField name="used_at" type="string">
      ISO 8601 UTC timestamp of when the coupon was redeemed.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="meta" type="object">
  Pagination metadata.

  <Expandable title="Pagination fields">
    <ResponseField name="total" type="integer">Total redemption records for this coupon.</ResponseField>
    <ResponseField name="totalPages" type="integer">Total number of pages.</ResponseField>
    <ResponseField name="hasNext" type="boolean">Whether a next page exists.</ResponseField>
    <ResponseField name="hasPrev" type="boolean">Whether a previous page exists.</ResponseField>
  </Expandable>
</ResponseField>

```bash Example — list redemptions for a coupon theme={null}
curl "https://api.example.com/api/v1/admin/coupons/cpn_01HSUM/usages?page=1&limit=50" \
  -H "Cookie: session=<your-session-cookie>"
```

```json 200 Response theme={null}
{
  "success": true,
  "data": [
    {
      "public_id": "use_01HRD1",
      "coupon_public_id": "cpn_01HSUM",
      "user_public_id": "usr_01HCUST",
      "order_public_id": "ord_01HABC",
      "discount_applied": "20.00",
      "used_at": "2024-06-12T16:45:00.000Z"
    }
  ],
  "meta": {
    "page": 1,
    "limit": 50,
    "total": 47,
    "totalPages": 1,
    "hasNext": false,
    "hasPrev": false
  }
}
```
