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

# Create Promotion

> Create a new promotion for a merchant

<Info>
  Scope required: `promos.write`
</Info>

This endpoint creates a new promotion for the specified merchant. It mirrors
the functionality available in the Thanx dashboard: it creates the promotion's
underlying program and redeem configuration, and — depending on how codes are
requested — its initial code pool.

For the full lifecycle — creating a promotion, generating codes, dispensing
them to customers, and replenishing — see the
[Promotions Overview](/partner/promotions/overview).

### Code Pools

How you supply codes at creation determines the pool that is created:

* **`static_code`** — creates a `multi_use` pool containing a single shared
  code that can be redeemed multiple times (a "universal" code). The pool is
  marked complete immediately.
* **`code_count`** — creates a `single_use` pool and enqueues asynchronous
  generation of that many unique one-time codes. Poll
  [Get Promotion](/partner/promotions/get-promotion) until
  `code_generation_status` is `complete`, then fetch the codes with
  [List Promotion Codes](/partner/promotions/list-codes). Additional
  single-use codes can later be generated with
  [Generate Promotion Codes](/partner/promotions/generate-codes).
* **Neither** — the promotion is created without any codes.

`static_code` and `code_count` are mutually exclusive.

### Parameters

<ParamField body="merchant_id" type="string" required>
  Merchant ID
</ParamField>

<ParamField body="name" type="string" required>
  Promotion name
</ParamField>

<ParamField body="discount_type" type="string" required>
  Type of discount: `amount`, `percent`, or `item`
</ParamField>

<ParamField body="discount_value" type="number" required>
  Discount amount. Interpreted according to `discount_type` (for example, a
  percentage for `percent` or a currency amount for `amount`).
</ParamField>

<ParamField body="minimum_spend" type="number">
  Minimum spend required to redeem
</ParamField>

<ParamField body="maximum_discount" type="number">
  Maximum discount that can be applied (where supported by the discount type)
</ParamField>

<ParamField body="fine_print" type="string">
  Terms and conditions
</ParamField>

<ParamField body="instructions" type="string">
  Redemption instructions shown to the customer
</ParamField>

<ParamField body="redemption_venue" type="string">
  Where the promotion can be redeemed: `all`, `instore`, or `online`.
  Defaults to `instore`.
</ParamField>

<ParamField body="starts_at" type="datetime">
  When the promotion becomes active (ISO8601)
</ParamField>

<ParamField body="ends_at" type="datetime">
  When the promotion ends (ISO8601). Must be after `starts_at`.
</ParamField>

<ParamField body="static_code" type="string">
  A single shared code to create as a `multi_use` pool. Mutually exclusive
  with `code_count`.
</ParamField>

<ParamField body="code_count" type="integer">
  Number of unique one-time codes to generate as a `single_use` pool
  (1–4,000,000). Generation runs asynchronously. Mutually exclusive with
  `static_code`.
</ParamField>

<ParamField body="state" type="string">
  Initial state: `active` or `draft`. Defaults to `active`. Draft promotions
  are managed in the Thanx dashboard — the read endpoints
  ([List Promotions](/partner/promotions/list-promotions),
  [Get Promotion](/partner/promotions/get-promotion)) return only `active`
  promotions.
</ParamField>

<ParamField body="redemption_restrictions" type="hash">
  Optional day-of-week and time-of-day restrictions on when the promotion can
  be redeemed. Write-only: these are applied at creation and viewed or edited
  in the Thanx dashboard; they are not returned by the read endpoints.

  <Expandable title="redemption_restrictions">
    <ParamField body="enabled" type="boolean">
      Whether time-based restrictions are enforced
    </ParamField>

    <ParamField body="time_zone" type="string">
      Time zone the restriction hours are evaluated in (IANA name, e.g.
      `America/Los_Angeles`)
    </ParamField>

    <ParamField body="monday" type="array">
      Hours (0–23) the promotion is redeemable on Monday. Repeat for
      `tuesday` through `sunday`.
    </ParamField>

    <ParamField body="location_ids" type="array">
      Restrict redemption to specific location IDs
    </ParamField>
  </Expandable>
</ParamField>

### Response

Returns `201 Created` with the newly created promotion. The response uses the
same shape as [Get Promotion](/partner/promotions/get-promotion).

<ResponseField name="id" type="string">
  Promotion ID
</ResponseField>

<ResponseField name="name" type="string">
  Promotion name
</ResponseField>

<ResponseField name="state" type="string">
  Promotion state (`active` or `draft`)
</ResponseField>

<ResponseField name="discount_type" type="string">
  Type of discount the promotion applies: `percent`, `item`, or `amount`
</ResponseField>

<ResponseField name="discount_value" type="string">
  Discount amount, as a string. Null if not set.
</ResponseField>

<ResponseField name="minimum_spend" type="string">
  Minimum spend required to redeem, as a string. Null if not set.
</ResponseField>

<ResponseField name="maximum_discount" type="string">
  Maximum discount that can be applied, as a string. Null if not set.
</ResponseField>

<ResponseField name="fine_print" type="string">
  Terms and conditions
</ResponseField>

<ResponseField name="redemption_venue" type="string">
  Where the promotion can be redeemed
</ResponseField>

<ResponseField name="starts_at" type="datetime">
  Promotion start timestamp (ISO8601). Null if not set.
</ResponseField>

<ResponseField name="ends_at" type="datetime">
  Promotion end timestamp (ISO8601). Null if not set.
</ResponseField>

<ResponseField name="generation_type" type="string">
  How the pool's codes are generated: `multi_use` or `single_use`. Null if no
  pool was created.
</ResponseField>

<ResponseField name="redemption_count" type="integer">
  Number of times codes in the active pool have been redeemed
</ResponseField>

<ResponseField name="total_codes" type="integer">
  Total number of codes in the active pool
</ResponseField>

<ResponseField name="code_generation_status" type="string">
  Status of asynchronous code generation for the active pool: `none` (no codes
  requested), `in_progress`, `complete`, or `failed`
</ResponseField>

<RequestExample>
  ```bash Create Promotion (single-use codes) theme={null}
  curl https://api.thanxsandbox.com/partner/promotions \
    -X POST \
    -H 'X-ClientId: {client_id}' \
    -H 'Accept-Version: v4.0' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer {access_token}' \
    -d '{
      "merchant_id": "k2lye10h32l5wzo",
      "name": "Summer 20% Off",
      "discount_type": "percent",
      "discount_value": 20,
      "minimum_spend": 25,
      "fine_print": "Limit one per customer",
      "redemption_venue": "online",
      "starts_at": "2026-06-01T00:00:00Z",
      "ends_at": "2026-08-31T23:59:59Z",
      "code_count": 10000
    }'
  ```

  ```bash Create Promotion (universal shared code) theme={null}
  curl https://api.thanxsandbox.com/partner/promotions \
    -X POST \
    -H 'X-ClientId: {client_id}' \
    -H 'Accept-Version: v4.0' \
    -H 'Content-Type: application/json' \
    -H 'Authorization: Bearer {access_token}' \
    -d '{
      "merchant_id": "k2lye10h32l5wzo",
      "name": "Launch Week",
      "discount_type": "amount",
      "discount_value": 5,
      "redemption_venue": "all",
      "static_code": "LAUNCH5"
    }'
  ```
</RequestExample>

<ResponseExample>
  ```json 201 theme={null}
  {
    "promotion": {
      "id": "promo_abc123",
      "name": "Summer 20% Off",
      "state": "active",
      "discount_type": "percent",
      "discount_value": "20.0",
      "minimum_spend": "25.0",
      "maximum_discount": null,
      "fine_print": "Limit one per customer",
      "redemption_venue": "online",
      "starts_at": "2026-06-01T00:00:00Z",
      "ends_at": "2026-08-31T23:59:59Z",
      "generation_type": "single_use",
      "redemption_count": 0,
      "total_codes": 0,
      "code_generation_status": "in_progress"
    }
  }
  ```

  ```json 422 theme={null}
  {
    "error": {
      "code": "UNPROCESSABLE_ENTITY",
      "message": "static_code and code_count are mutually exclusive"
    }
  }
  ```
</ResponseExample>
