Coupons are the core reward delivery mechanism in Zupy. When a customer redeems a reward, a coupon is created with a unique code (Documentation Index
Fetch the complete documentation index at: https://docs.zupy.com/llms.txt
Use this file to discover all available pages before exploring further.
CZ-XXXXXXXX). The partner can then list, display, and validate (use) that coupon at the point of sale.
Prerequisites: Your API key (
zupy_pk_*) and familiarity with the Authentication page. If your integration requires OTP for redemption or coupon usage, see the OTP Flow guide first.Coupon Lifecycle Overview
Every coupon follows this flow:Step 1: Browse Available Rewards
Query the reward catalog to see what rewards are available for a customer. Thecustomer_id parameter enriches each reward with the customer’s redemption status.
| Parameter | Type | Description |
|---|---|---|
customer_id | string | Customer KSUID — enriches response with already_redeemed flag |
redeemable | boolean | If true, only returns rewards the customer can currently afford |
| Field | Type | Description |
|---|---|---|
id | string | Reward KSUID (use in redeem URL) |
name | string | Reward display name |
points_required | integer | Points needed to redeem |
is_available | boolean | Whether the reward is currently active |
already_redeemed | boolean | Whether this customer already redeemed this reward |
validity_days | integer | Days the coupon remains valid after redemption |
Step 2: Redeem Reward (Create Coupon)
Redeem a reward for a customer. This creates a coupon with a unique code and deducts points from the customer’s balance.| Field | Type | Default | Description |
|---|---|---|---|
use_z_tokens | boolean | false | If true, Z Tokens guide](/guides/z-dollar-tokens) |
| Field | Type | Description |
|---|---|---|
customer_id | string | Customer KSUID |
coupon_code | string | Unique coupon code (format: CZ-XXXXXXXX) |
points_used | integer | Points deducted from balance |
z_tokens_used | string | Z$ tokens used (null if use_z_tokens: false) |
new_balance | integer | Customer’s remaining points balance |
new_z_balance | string | Customer’s remaining Z$ balance (null if use_z_tokens: false) |
valid_until | string | ISO 8601 expiration date |
created_at | string | ISO 8601 coupon creation timestamp |
Redemption Errors
| Status | Type | When |
|---|---|---|
| 403 | otp-required | OTP verification required but X-OTP-Session not provided |
| 404 | not-found | Customer or reward not found |
| 422 | validation-error | Customer doesn’t have enough points, or reward already redeemed by this customer |
Step 3: List Customer’s Coupons
Retrieve all coupons for a customer, optionally filtered by status.| Parameter | Type | Description |
|---|---|---|
customer_id | string | Required. Customer KSUID |
status | string | Filter by status: active, used, expired, cancelled |
| Field | Type | Description |
|---|---|---|
id | string | Coupon KSUID (use in validate URL) |
coupon_code | string | Unique coupon code (CZ-XXXXXXXX) |
status | string | active, used, expired, or cancelled |
remaining_usages | integer | How many times the coupon can still be used |
total_usages_allowed | integer | Total uses allowed (1 for single-use coupons) |
valid_until | string | ISO 8601 expiration date |
reward_name | string | Name of the redeemed reward |
Step 4: Validate (Use) Coupon
Validate a coupon to mark it as used. This is an atomic operation — concurrent validate calls are race-safe (uses database-level locking).| Field | Type | Description |
|---|---|---|
coupon_code | string | The validated coupon code |
status | string | "validated" — confirms the coupon was successfully used |
remaining_usages | integer | Remaining uses after validation |
total_usages_allowed | integer | Total uses allowed for this coupon |
validated_at | string | ISO 8601 timestamp of validation |
Validation Errors
| Status | Type | When |
|---|---|---|
| 403 | otp-required | OTP verification required but X-OTP-Session not provided |
| 404 | not-found | Coupon not found or doesn’t belong to this customer |
| 409 | conflict | Coupon already fully used or expired |
Multi-Use Coupons
Some rewards create coupons that can be used more than once. Theremaining_usages and total_usages_allowed fields track usage:
| Coupon Type | total_usages_allowed | Behavior |
|---|---|---|
| Single-use | 1 | After one validate call, remaining_usages becomes 0 and status becomes used |
| Multi-use | 2+ | Each validate call decrements remaining_usages. Status stays active until the last use, then becomes used |
Multi-use coupon example
Multi-use coupon example
A “3x Free Coffee” reward creates a coupon with
total_usages_allowed: 3:Coupon Expiration
Coupons have avalid_until date set at redemption time, calculated as:
- Auto-expires: a validate call on an expired coupon returns
409 Conflict - Check before displaying: partners should compare
valid_untilwith the current time before showing a coupon to the customer - Expired status: coupons past their
valid_untildate will showstatus: "expired"in list responses
Expired coupons cannot be reactivated. The customer must redeem the reward again to get a new coupon (if the reward allows re-redemption).
Full Example: Complete Coupon Flow
End-to-end flow: browse rewards, redeem, list coupons, and validate.Next Steps
Z$ Tokens
Learn how Z$ tokens work and how they can cover points gaps in reward redemption
OTP Flow
Set up customer identity verification for sensitive operations
API Reference
Browse all endpoints with request/response schemas