Errors
Every error has a stable machine-readable code. Build on the code; the message is for
humans and may change.
New codes may be added. If you get a code you do not know, handle it by its HTTP status.
{
"error": {
"code": "voucher_expired",
"message": "Voucher has expired",
"request_id": "req_…"
}
}
Quote request_id when you contact support.
Request and authentication
| HTTP | code | Meaning |
|---|---|---|
400 | invalid_request | The request is malformed or a field is missing |
400 | idempotency_key_required | A POST without an Idempotency-Key header (1–255 characters) |
401 | unauthorized | No key, an unknown, revoked or expired key, or a key for the other environment (a test key on production) |
403 | insufficient_scope | The key is valid but lacks the operation's scope |
403 | plan_capability_missing | Your Space's plan does not include the API (or this feature) |
404 | not_found | Not found in your Space. Another Space's object is always 404, never 403 |
409 | idempotency_key_reused | The Idempotency-Key was already used for a different request |
409 | idempotency_request_in_progress | The first request with this key is still running; retry after Retry-After |
429 | rate_limited | Rate limit — see Rate limits |
500 | internal_error | Our side. Retry with the same Idempotency-Key. |
503 | temporarily_unavailable | Our side, briefly. Retry after Retry-After with the same Idempotency-Key. |
503 | api_not_configured | The API is not enabled on this server |
Every response, success or error, carries X-Request-Id; it is the same value as
error.request_id.
Sponsor redemption codes
POST /v1/sponsor-packages/{id}/redemptions:
| HTTP | code | Meaning |
|---|---|---|
404 | not_found | No such sponsor package in your Space |
404 | code_not_found | That code is not part of this sponsor package |
409 | already_redeemed | This code has already been redeemed |
409 | not_redeemable | The perk is not in a redeemable state |
409 | use_voucher_redeem | The perk is a voucher: redeem it with POST /v1/vouchers/redeem |
422 | credits_exhausted | Not enough credits; top up and retry |
422 | credits_suspended | Your credits account is suspended |
422 | no_payer | The sponsor package has no paying Space |
429 | allowance_exhausted | Your plan's monthly API action allowance is used up; retry after Retry-After (the next month, Asia/Jakarta). Nothing was charged |
503 | temporarily_unavailable | Redemptions are not priced right now; retry with the same key |
Voucher codes
POST /v1/vouchers/validate and POST /v1/vouchers/redeem. Validate answers a refused voucher
with 200 and "valid": false, with the code in error.code. Redeem answers it with 422 and
the code in error.code. A code that is not a voucher of your Space is 404 not_found on both.
code | Meaning |
|---|---|
voucher_void | Cancelled by the merchant |
voucher_not_active | The voucher is in a state that cannot be redeemed |
voucher_not_redeemable | The voucher cannot be redeemed for another reason |
max_redemptions_reached | No redemptions left |
not_yet_valid | Before its start date |
voucher_expired | After its end date |
invalid_day | Not valid on this day of the week |
blockout_date | Not valid on this date |
wrong_location | Not valid at this location |
booking_scoped_voucher | Can only be used with its booking |
crossbrand_redeem_denied | Belongs to another brand of the network |
staff_confirm_required | A perk that must be confirmed by staff at the counter (redeem) |
wrong_outlet | Not valid at this outlet. Comes from a staff member's outlet limits; an API key acts for the whole Space, so you should not see it |
wrong_sub_brand | Not valid for this sub-brand. Same as wrong_outlet: not expected for an API key |
When your Space enforces per-branch voucher allocations, validate and redeem must name the branch the voucher is used at (branch_id, or a location_id that identifies exactly one of your branches). Then you can also get:
code | Meaning |
|---|---|
outlet_required | Name the branch: send branch_id (or a location_id that is a branch or a single-branch location) |
branch_required | The location has several branches; send branch_id |
branch_unknown | No such branch |
branch_inactive | The branch is not active |
branch_not_authorized | The voucher is not valid at this branch |
branch_not_in_listing | branch_id does not belong to location_id |
branch_not_in_space | The branch is not one of your Space's branches |
outlet_not_allocated | The voucher is not allocated to this branch |
outlet_quota_exhausted | This branch's voucher quota is used up |
outlet_quota_invalid | This branch's quota is misconfigured |
outlet_quota_unknown_value | The voucher has no value, so this branch's quota cannot be checked |
If the allocation cannot be checked, you get 503 temporarily_unavailable. Retry with the same Idempotency-Key.
How the quota is counted:
- A redemption uses the quota when it is redeemed. A later refund does not give it back. Only a redemption that is voided before it is used (or a booking reservation released on cancel) frees it.
- Each redemption uses the voucher's full face value, for every punch of a multi-punch pass.
- Redemptions by platform staff count the same as the counter.
- If the allocation cannot be read, the redemption is refused (503); it is never waved through.
- Booking redemptions count too. A pass that secures a booking is held to the quota of the booking's branch, and the booking is refused with the same codes as above.
Check-in codes
POST /v1/events/{id}/check-ins:
| HTTP | code | Meaning |
|---|---|---|
200 | already_used | Ticket already checked in. Returned as check_in.result, not as an error. See the gate-scanner guide for every result |
404 | not_found | No such event in your Space, or no ticket with that code for this event |
409 | cancelled | Ticket cancelled |
409 | expired | Ticket expired |
409 | not_eligible | The ticket is in some other state that cannot be checked in (not active, used, cancelled or expired) |
409 | race_lost | Another scanner checked it in at the same moment |
503 | temporarily_unavailable | We could not verify the event or ticket right now; retry with the same Idempotency-Key |