Quick Start
Issue an instrument and redeem it, end to end. Everything here runs against UAT and takes a few minutes.
Before you start
You need three things, all supplied by the merchant administrator who set up the campaign (see Setup Flow):
- A client ID and client secret
- A template ID — a gift card template or a coupon template
- Confirmation that the campaign is
ACTIVE
export BASE_URL="https://stage-platform-exlr8-incentives.exlr8now.com"
export CLIENT_ID="YOUR_CLIENT_ID"
export CLIENT_SECRET="YOUR_CLIENT_SECRET"
Gift cards
1. Issue a card
You supply only the template. Denomination, currency, expiry and redemption rules all come from it.
curl --location "$BASE_URL/v1/giftCards" \
--header "X-Client-Id: $CLIENT_ID" \
--header "X-Client-Secret: $CLIENT_SECRET" \
--header 'Content-Type: application/json' \
--data '{
"giftCardTemplateId": "d4c3b2a1-6f5e-4d3c-8b2a-1f0e9d8c7b6a"
}'
{
"success": true,
"data": {
"giftCardId": "9b2c4d6e-8f0a-4b1c-9d3e-5f7a1b2c3d4e",
"digitalCode": "GC-7F3A-9K2M-4XQ8",
"cardNumber": "6011457893214567",
"pin": "4821"
}
}
:::caution Capture the code now
digitalCode, cardNumber and pin are returned exactly once. Only hashes are stored, so this response is your single opportunity to deliver them to the customer. Store the giftCardId too — later refunds and voids reference the card by ID, not by code.
:::
2. Check the balance
When a customer presents a card, look it up by the code they hand you.
curl --location "$BASE_URL/v1/giftCards/inquiry" \
--header "X-Client-Id: $CLIENT_ID" \
--header "X-Client-Secret: $CLIENT_SECRET" \
--header 'Content-Type: application/json' \
--data '{ "code": "GC-7F3A-9K2M-4XQ8" }'
{
"success": true,
"data": {
"giftCardId": "9b2c4d6e-8f0a-4b1c-9d3e-5f7a1b2c3d4e",
"status": "ACTIVE",
"currency": "INR",
"initialBalance": 500,
"remainingBalance": 500,
"expiresAt": "2027-08-25T00:00:00Z",
"expired": false,
"minRedemptionAmount": 50,
"allowPartialRedemption": true
}
}
This tells you what you may spend and under what rules — whether partial redemption is allowed, and the minimum a single redemption may be.
3. Redeem
A redemption is a DEBIT transaction. The card is identified by the code the customer presented.
curl --location "$BASE_URL/v1/giftCards/transactions" \
--header "X-Client-Id: $CLIENT_ID" \
--header "X-Client-Secret: $CLIENT_SECRET" \
--header 'Content-Type: application/json' \
--data '{
"code": "GC-7F3A-9K2M-4XQ8",
"type": "DEBIT",
"amount": 150,
"referenceId": "order-20260825-0042",
"idempotencyKey": "order-20260825-0042-debit-01"
}'
{
"success": true,
"data": {
"transactionId": "1a2b3c4d-5e6f-4a7b-8c9d-0e1f2a3b4c5d",
"giftCardId": "9b2c4d6e-8f0a-4b1c-9d3e-5f7a1b2c3d4e",
"type": "DEBIT",
"amount": 150,
"balanceBefore": 500,
"balanceAfter": 350,
"referenceId": "order-20260825-0042",
"createdAt": "2026-08-25T11:42:07Z"
}
}
balanceBefore and balanceAfter are the authoritative record of the movement. Store the transactionId against your order.
:::info The idempotency key is not optional Every transaction requires one, and it is what makes a retry safe. Repeating this exact call returns the same transaction rather than debiting twice. See How Redemption Works. :::
Coupons
1. Issue a coupon
curl --location "$BASE_URL/v1/coupons" \
--header "X-Client-Id: $CLIENT_ID" \
--header "X-Client-Secret: $CLIENT_SECRET" \
--header 'Content-Type: application/json' \
--data '{
"couponTemplateId": "5e6f7a8b-9c0d-4e1f-a2b3-c4d5e6f7a8b9"
}'
{
"success": true,
"data": {
"couponId": "7c8d9e0f-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
"code": "SAVE20-K4M9XQ"
}
}
2. Validate against the order
Before you commit, check whether the coupon applies — and what discount it would produce. This consumes nothing.
curl --location "$BASE_URL/v1/coupons/validate" \
--header "X-Client-Id: $CLIENT_ID" \
--header "X-Client-Secret: $CLIENT_SECRET" \
--header 'Content-Type: application/json' \
--data '{
"code": "SAVE20-K4M9XQ",
"order": {
"amount": 4500,
"items": [
{ "productId": "sku-9981", "categoryId": "electronics", "quantity": 1, "unitPrice": 4500 }
]
}
}'
{
"success": true,
"data": {
"couponId": "7c8d9e0f-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
"valid": true,
"result": {
"discountAmount": 900,
"description": "20% off (capped at 2000)"
}
}
}
Use result.discountAmount to show the customer their saving before they commit. An invalid coupon returns valid: false with a reason and a machine-readable code.
3. Redeem
curl --location "$BASE_URL/v1/coupons/redeem" \
--header "X-Client-Id: $CLIENT_ID" \
--header "X-Client-Secret: $CLIENT_SECRET" \
--header 'Content-Type: application/json' \
--data '{
"code": "SAVE20-K4M9XQ",
"order": {
"amount": 4500,
"items": [
{ "productId": "sku-9981", "categoryId": "electronics", "quantity": 1, "unitPrice": 4500 }
]
},
"referenceId": "order-20260825-0042",
"idempotencyKey": "order-20260825-0042-coupon-01"
}'
{
"success": true,
"data": {
"couponId": "7c8d9e0f-1a2b-4c3d-9e4f-5a6b7c8d9e0f",
"result": {
"discountAmount": 900,
"description": "20% off (capped at 2000)"
}
}
}
Apply result.discountAmount to the order total. The discount is recomputed at redemption from the order you send here — do not carry over the figure from validation, because the order may have changed in between.
A realistic checkout sequence
Redemption should be the last thing that can fail. A workable order:
- Customer enters a code at checkout
- Inquire (gift card) or validate (coupon) → show them the balance or discount
- Customer confirms; take payment for any remainder
- Redeem, with an idempotency key derived from your order ID
- Store
transactionId(or the couponreferenceId) against the order - On a network failure, retry the identical call — never issue a new key
If step 4 fails permanently after a gift card debit has succeeded elsewhere in your flow, reverse it with a REFUND transaction rather than leaving the balance short. The refund must carry the same referenceId as the debit and a different idempotency key — see Create Transaction.
Next steps
- How Redemption Works — idempotency, partial redemption, failure handling
- API Reference — every endpoint in detail
- Error Codes — what each failure means