Skip to main content

fetchCouponCode

Delivers a coupon code to a user. Call this after you have burned the user's coins in your own wallet.

Available
POST /api/fetchCouponCode
EnvironmentURL
Productionhttps://hotdeals.cheggout.com/api/fetchCouponCode
UAThttps://onerupee-store-api-stage.azurewebsites.net/api/fetchCouponCode

AuthenticationAPI key

Ordering is prescribed

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

HeaderRequiredValue
Content-TypeYesapplication/json
X-CHANNELIDYesYour channel identifier
AuthorizationYesCheggoutAppKey <APP_KEY>:<SEC_KEY>

Body

FieldTypeRequiredDescription
offerIdstringYesThe offer, from getCatalogue id
virtualIdstringYesYour pseudonymous user identifier
channelNamestringYesYour channel name
extTransactionIdstringYesYour unique reference for this claim. Idempotency key.
coinsUsedYesCoins 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 claim

Not 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

FieldTypeDescription
statusnumber200 on success
messagestring"Fetched Successfully"
dataobjectThe delivered coupon

data

FieldTypeDescription
idstringThe offer identifier
coupon_codestringThe code to give the user
coupon_validitystringCoupon expiry, ISO 8601
extTransactionIdstringEcho of your reference
purchase_timestringWhen the coupon was issued, ISO 8601
urlstringCheggout redirect URL for the offer
Response (synthetic)
{
"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"
}
}
Persist the coupon immediately

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

statuserrorCodeMessageWhat it meansWhat to do
409COUPON_EXHAUSTEDStock ran outRefund coins. Show "sold out".
403NON_ELIGIBLEUser not eligible for this offer based on targeting rules.Targeting excludes this userRefund coins. Hide the offer.
429MAX_LIMIT_REACHEDMaximum redemption limit reached for this user.purchase_limit hitRefund coins. Show the limit message.
404INVALID_OFFEROffer not found or inactive.Offer withdrawn or unknownRefund coins. Refresh your catalogue cache.
400INVALID_REQUESTMalformed requestFix the request. Refund coins.
401UNAUTHORIZEDInvalid AppKey/SecKey.Auth failureRefund coins. Fix credentials.
500INTERNAL_ERRORSomething went wrong.Platform-side failureRetry with the same extTransactionId, then refund
Timeout or no responseOutcome unknown. The coupon may or may not have been allocatedDo not blindly refund, and do not blindly retry. Reconcile first — see below
Every definite failure needs a coin decision

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.

A timeout is not a failure

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 offerId has 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