Skip to main content
POST
/
api
/
v2
/
customers
/
{id}
/
coupons
/
{coupon_id}
/
validate
/
Validate (use) a coupon
curl --request POST \
  --url https://api.zupy.com/api/v2/customers/{id}/coupons/{coupon_id}/validate/ \
  --header 'X-API-Key: <api-key>'
{
  "data": {
    "customer_id": "<string>",
    "coupon_code": "<string>",
    "status": "validated",
    "remaining_usages": 123,
    "total_usages_allowed": 123,
    "validated_at": "2023-11-07T05:31:56Z",
    "new_balance": 123,
    "new_z_balance": "<string>"
  },
  "meta": {
    "cursor": "<string>",
    "has_next": true,
    "count": 123
  }
}

Authorizations

X-API-Key
string
header
required

Per-company partner API key (zupy_pk_…). Validated by Zupy against the company integration key hash (Story 14.x); send it on every request as the X-API-Key header. Scoped read-write to the owning company's data.

Headers

X-OTP-Session
string

OTP session token returned by POST /auth/verify-otp/. REQUIRED when the company's integration OTP policy enables it (require_otp_for_redemption for redeem, require_otp_for_coupon_usage for validate). Omitting it returns 403 with code "otp-required".

Path Parameters

coupon_id
string
required

Accepts EITHER the RewardRedemption KSUID (e.g. 16a33f27fbbc1801d63d56d2027) OR the customer-facing coupon_code (e.g. CZ-914F15F3 or CP-LEGACY01). Lookup by code is case-insensitive — both CZ-914F15F3 and cz-914f15f3 resolve to the same coupon. The response always echoes the canonical upper-case form.

id
string
required

Unique identifier for this customer.

Response

data
object
required

Coupon validation result with current status, remaining usages, and a settled-state snapshot of the customer's balances. Story W.x: response now mirrors RewardRedeemResponse — partners get customer_id + new_balance + new_z_balance without a follow-up GET.

meta
object
required

Cursor-based pagination metadata matching envelope middleware output.