Redeem a voucher at an outlet
Atomically validates the PIN, GPS distance, redemption limits, claim/membership requirements, and dispenses a voucher code (when the voucher is configured for codes).
Rate limited to 5 attempts per user per 60 seconds to deter PIN brute-forcing. The window is sliding; when exceeded the response is HTTP 429 with retry-after (seconds) header and { error: "rate_limited", details: { retryAfterSeconds } }.
GPS rules: if both consumerLat and consumerLng are supplied and the user is within 150m of the outlet, status is SUCCESS. If the user is further than 150m, the redemption is rejected with too_far (no row written). If the consumer omits GPS (both fields missing), status is FLAGGED with flagReason="gps_unavailable". If the OUTLET has no coordinates, the geofence can’t run — status stays SUCCESS but flagReason="outlet_not_geolocated" is set as an audit tag for admin follow-up.
Authorizations
Bearer JWT signed by your app, with iss matching the issuer registered on the partner record. Verified against your JWKS URL or static public key.
Body
The voucher being redeemed.
The outlet the user is physically at.
4-digit PIN the outlet staff enters. Compared bcrypt-side; case-sensitive.
^\d{4}$"4829"
Optional. Device latitude. Required to record status=SUCCESS; otherwise the redemption is flagged.
-90 <= x <= 90Optional. Device longitude. Must be provided together with consumerLat.
-180 <= x <= 180Optional. Reported accuracy of the GPS fix; stored for audit.
x >= 0Response
Redemption committed.
Redemption committed.
Bucket key for the voucher's refresh cycle (e.g. 2026-05 for monthly).
SUCCESS, FLAGGED Set when status=FLAGGED.
outlet_not_geolocated, gps_unavailable, null Dispensed voucher code when the voucher is configured with MANUAL/AUTO codes. Show this to the user.