fetchCouponCode
Delivers a coupon code to a user. Call this after you have burned the user's coins in your own wallet.
AvailablePOST /api/fetchCouponCode
| Environment | URL |
|---|---|
| Production | https://hotdeals.cheggout.com/api/fetchCouponCode |
| UAT | https://onerupee-store-api-stage.azurewebsites.net/api/fetchCouponCode |
Authentication — API key
Burn coins first, then request the coupon. If delivery fails after the burn, either retry with
the same extTransactionId or refund the coins. Never deliver a coupon before the burn is
committed, and never leave a burn with neither a coupon nor a refund.
Request
Headers
| Header | Required | Value |
|---|---|---|
Content-Type | Yes | application/json |
X-CHANNELID | Yes | Your channel identifier |
Authorization | Yes | CheggoutAppKey <APP_KEY>:<SEC_KEY> |
Body
| Field | Type | Required | Description |
|---|---|---|---|
offerId | string | Yes | The offer, from getCatalogue id |
virtualId | string | Yes | Your pseudonymous user identifier |
channelName | string | Yes | Your channel name |
extTransactionId | string | Yes | Your unique reference for this claim. Idempotency key. |
coinsUsed | — | Yes | Coins the user spent |
curl -X POST https://hotdeals.cheggout.com/api/fetchCouponCode \
-H "Content-Type: application/json" \
-H "X-CHANNELID: YOURCHANNEL" \
-H "Authorization: CheggoutAppKey REPLACE_APP_KEY:REPLACE_SEC_KEY" \
-d '{
"offerId": "517",
"virtualId": "pub_8f14e45fceea167a",
"channelName": "YOURCHANNEL",
"extTransactionId": "PUB_OFFERBUY_20260731_000045",
"coinsUsed": "10"
}'
extTransactionId must be unique per claimNot per user, not per offer — per claim. Reusing a value across different offers has undefined behaviour and risks returning the wrong coupon. See idempotency below.
TBD The type of coinsUsed is ambiguous — it appears as a quoted string in
the published example although it is semantically numeric. Send it as a string to match the
documented example, and confirm during UAT.
Response
| Field | Type | Description |
|---|---|---|
status | number | 200 on success |
message | string | "Fetched Successfully" |
data | object | The delivered coupon |
data
| Field | Type | Description |
|---|---|---|
id | string | The offer identifier |
coupon_code | string | The code to give the user |
coupon_validity | string | Coupon expiry, ISO 8601 |
extTransactionId | string | Echo of your reference |
purchase_time | string | When the coupon was issued, ISO 8601 |
url | string | Cheggout redirect URL for the offer |
{
"status": 200,
"message": "Fetched Successfully",
"data": {
"id": "517",
"coupon_code": "REPLACE-COUPON-CODE",
"coupon_validity": "2026-12-31T23:59:59.000Z",
"extTransactionId": "PUB_OFFERBUY_20260731_000045",
"purchase_time": "2026-07-31T14:15:31.000Z",
"url": "https://click.cheggout.com/REPLACE"
}
}
Store coupon_code, coupon_validity, extTransactionId and purchase_time before you render
anything. This is the user's purchased good.
orderId
The contract describes an orderId — a Cheggout-generated reference, the official delivery record
for reconciliation.
TBD Whether orderId is present in this response is not confirmed. Do not
build reconciliation that requires it. Reconcile on your own extTransactionId, which is echoed
back reliably, and ask Cheggout to confirm orderId availability before you depend on it.
The url field
url is a Cheggout click-and-redirect URL for the offer. Note that URLs of this kind can carry
identifiers as query parameters — avoid logging them alongside data that could re-identify the user,
and prefer sending users to it directly rather than storing it in analytics.
Errors
status | errorCode | Message | What it means | What to do |
|---|---|---|---|---|
409 | COUPON_EXHAUSTED | — | Stock ran out | Refund coins. Show "sold out". |
403 | NON_ELIGIBLE | User not eligible for this offer based on targeting rules. | Targeting excludes this user | Refund coins. Hide the offer. |
429 | MAX_LIMIT_REACHED | Maximum redemption limit reached for this user. | purchase_limit hit | Refund coins. Show the limit message. |
404 | INVALID_OFFER | Offer not found or inactive. | Offer withdrawn or unknown | Refund coins. Refresh your catalogue cache. |
400 | INVALID_REQUEST | — | Malformed request | Fix the request. Refund coins. |
401 | UNAUTHORIZED | Invalid AppKey/SecKey. | Auth failure | Refund coins. Fix credentials. |
500 | INTERNAL_ERROR | Something went wrong. | Platform-side failure | Retry with the same extTransactionId, then refund |
| — | Timeout or no response | — | Outcome unknown. The coupon may or may not have been allocated | Do not blindly refund, and do not blindly retry. Reconcile first — see below |
Because you burned coins before calling, each of the outcomes above leaves the user short. Your handler must either retry safely or refund — there is no third option that leaves the user whole.
If the call times out you do not know whether a coupon was allocated. Refunding on a timeout can hand the user both the coins and the coupon; retrying blind can burn a second coupon from the pool.
Reconcile before you act. Call getUserCoupons for that user and
offer and look for your extTransactionId in the returned coupons[]. If it is there, the coupon
was delivered — persist it and show it. If it is not, the claim did not complete and you can retry
with the same extTransactionId or refund. The module guide walks through this in
Coupon delivery.
Status codes arrive in the body — see API conventions.
Idempotency
extTransactionId is the idempotency key. Replaying it returns the previously processed result, or
is rejected as a duplicate.
TBD The published contract is ambiguous about which of those two behaviours applies. Until it is clarified:
- Always retry with the same value after a timeout — never generate a new one for the same claim.
- Never reuse a value across different offers. A replay under a different
offerIdhas undefined behaviour. - Keep your own delivery ledger, keyed on
extTransactionId, recording what you requested and what came back. Reconcile against it rather than trusting platform idempotency alone.
The complete flow
Next
getUserCoupons— a user's coupon history.- Coupon status webhook — invalidation notices.
- Coupon delivery module guide