Issue Coupon
Create a coupon from a template. The platform generates the code and returns it once.
Endpoint
POST /v1/coupons
Headers
| Header | Type | Description | Required |
|---|---|---|---|
X-Client-Id | String | Your client ID | ✅ Yes |
X-Client-Secret | String | Your client secret | ✅ Yes |
Content-Type | String | application/json | ✅ Yes |
Request Body
| Field | Type | Description | Required |
|---|---|---|---|
couponTemplateId | String (UUID) | The template to issue from | ✅ Yes |
Discount behaviour, applicability, usage limits and expiry all come from the template — see Setup Flow.
Example Request
curl --location 'https://stage-platform-exlr8-incentives.exlr8now.com/v1/coupons' \
--header 'X-Client-Id: YOUR_CLIENT_ID' \
--header 'X-Client-Secret: YOUR_CLIENT_SECRET' \
--header 'Content-Type: application/json' \
--data '{
"couponTemplateId": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9"
}'
Response
Successful Response — 201 Created
{
"success": true,
"data": {
"couponId": "7c8d9e0f-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
"code": "SAVE20-K4M9XQ"
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
couponId | String | Internal identifier — store it for lookups |
code | String | The code the customer presents to redeem |
:::caution Returned exactly once
Only a hash of code is stored. It cannot be retrieved again by any endpoint. Deliver it to the customer and persist what you need before acknowledging this response.
:::
Unique and shared codes
The template's codeType changes what issuance means.
UNIQUE — every call produces a distinct code. Issue one per customer. This is the usual choice for targeted offers, and typically pairs with a usage limit of one.
SHARED — every customer uses the same code, as with a public promo code. The template is issued once, and you distribute the returned code however you like. Calling this endpoint again for a shared template returns the existing coupon rather than creating another; the response shape is unchanged, so no special handling is needed.
A shared coupon is still redeemed once per customer, each redemption with its own idempotency key.
Behaviour
The campaign must be active. Issuance is refused with PROGRAM_INACTIVE when the campaign is DRAFT, PAUSED, EXPIRED or ARCHIVED. Campaigns expire automatically at their endAt, so this can begin failing without any change on your side.
Only the count cap applies here. Issuing a coupon reserves one unit of the template's issuance count, atomically with the insert, so over-issuance is impossible. Exceeding it returns TEMPLATE_LIMIT_EXCEEDED.
The value budgets — the template's and the campaign's — are not touched at issuance, because a coupon has no cost until someone redeems it. They are charged at redemption instead, which is why a coupon can issue cleanly and still fail to redeem later.
Expiry is set now. FROM_ISSUANCE computes expiry from this moment plus the template's validity period; FIXED_DATE gives every coupon the same date.
Issuance is not idempotent. No idempotency key is taken, so two calls create two coupons for a UNIQUE template. On a timeout, check List Coupons before retrying.
Error Responses
| Error code | HTTP | Cause |
|---|---|---|
BAD_REQUEST | 400 | Missing or malformed couponTemplateId, or an unknown field |
TEMPLATE_NOT_FOUND | 404 | No such template within your merchant |
PROGRAM_NOT_FOUND | 404 | The template points at a campaign that no longer exists |
PROGRAM_INACTIVE | 422 | The campaign is not ACTIVE |
TEMPLATE_LIMIT_EXCEEDED | 422 | The template's issuance count cap is reached |
INTERNAL_SERVER_ERROR | 500 | Platform fault |
{
"success": false,
"errCode": "TEMPLATE_LIMIT_EXCEEDED",
"message": "Template limit exceeded: coupon template issuance count limit reached"
}
Related Endpoints
- Validate Coupon — check applicability without consuming
- Redeem Coupon
- List Coupons