Applicable Coupons Endpoint
Given a cart, returns the coupons the user already claimed that can actually be used on it — each one priced with the exact discount it would give, best saving first. This is what you render in the "choose a coupon" drawer at checkout.
- Endpoint:
/api/v1/campaigns/coupons/applicable - Method:
POST
Headers
| Header | Value | Required | Description |
|---|---|---|---|
Partner-Access-Token | Base64 String | Yes | Your encrypted AES-256 time-sensitive token. |
Content-Type | application/json | Yes | |
Accept | application/json | Yes | |
X-Currency | e.g. THB | Optional | Currency of grand_total and of every amount returned. Defaults to THB. |
Payload Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
user_id | Integer | Yes | ID of the user whose claimed coupons should be checked. |
product_type | String | Yes | Product code, e.g. pd11. See the table below. |
grand_total | Number | Yes | Cart total in the requested currency. Minimum 0. |
product_id | Integer | String | Optional | The specific product being booked. Required for coupons limited to certain products or destinations. |
Product Types
| Code | Product | Send as product_id |
|---|---|---|
all | Every product | — |
pd4 | More Experiences | More Experiences product ID |
pd6 | Airport Transfer | Transfer airport ID |
pd7 | Airport VIP Assistance | Airport package ID |
pd8 | Tour | Tour ID |
pd9 | Fliggy Airline Ticket | — |
pd11 | TourMind Hotel | Hotel ID or hotel code |
Sample Payload
{
"user_id": 3312,
"product_type": "pd11",
"grand_total": 4500,
"product_id": 749588
}
Sample Response
{
"result": 1,
"message": "success",
"data": {
"currency": "THB",
"coupons": [
{
"id": 9821,
"code": "SONGKRAN10",
"currency": "THB",
"discount_amount": 450,
"status": "claimed",
"discount_type": "percentage",
"discount_value": 10,
"min_purchase_amount": 1000,
"max_discount_amount": 500,
"coupon_expiry": "2026-05-31T23:59:59.000000Z",
"claim_expiry": "2026-04-04T09:00:00.000000Z",
"reward": "TourMind Hotel",
"reward_destinations": [
{
"id": 12,
"name": "Thailand"
}
],
"reward_variations": [],
"rules": [
"Save up to THB 500",
"Min. spend THB 1000"
],
"applicable_for": "Valid for <strong>Hotel</strong> in <strong>Thailand</strong>",
"campaign": {
"id": 41,
"name": "Songkran Hotel Sale",
"slug": "songkran-hotel-sale",
"status": "running",
"promotion_type": "coupon",
"start_at": "2026-04-01T00:00:00.000000Z",
"end_at": "2026-04-30T23:59:59.000000Z",
"coupon_expiry": "2026-05-31T23:59:59.000000Z",
"description": "Save on hotel stays across Thailand.",
"term_and_conditions": "<p>One coupon per booking.</p>",
"images": [],
"applicable_for": "Valid for <strong>Hotel</strong> in <strong>Thailand</strong>"
}
}
]
}
}
Response Fields
| Field | Type | Description |
|---|---|---|
currency | String | Currency of discount_amount and every other amount. |
coupons | Array | Usable coupons, sorted by discount_amount descending. Empty when none fit. |
coupons[].discount_amount | Number | Exact saving this coupon gives on the submitted grand_total. |
How the List Is Built
Every coupon the user holds with status issued is run through the full eligibility check —
timeline, minimum spend, per-user limit, product type, destination, product restrictions, and
partner association. Coupons that fail any rule are silently dropped rather than returned with an
error, so an empty coupons array simply means nothing fits this cart.
Notes
- The destination is resolved automatically from
product_type+product_id, so you never send a destination ID yourself. grand_totalis converted to THB internally before the rules run, then the resulting discount is converted back to your requested currency.- This endpoint reads only. It never claims, reserves, or redeems anything.
- Validation failures (missing
user_id, negativegrand_total, …) return HTTP422with Laravel's standard validation body.