Errors
Every non-success response uses a single, predictable envelope. Readcode to branch behaviour, and show the human-readablemessage to your operators.
Error envelope
{
"code": "INVALID_SIGNATURE",
"message": "Invalid X-Signature header.",
"correlationId": "01J7XKQE4E30000000000000"
}Every response — success or failure — includes anX-Correlation-Id response header. Log it. If you need partner support to trace a specific call, that correlation id lets us find the exact request in seconds.
HTTP status conventions
| Status | Meaning |
|---|---|
200 OK | Synchronous success. |
400 Bad Request | Malformed request or permanent client error — do not retry. |
401 Unauthorized | API key, signature, or connection state invalid. |
422 Unprocessable Entity | Business rule declined a synchronous write (redemption validation) — planned, no live endpoint returns 422 yet. |
503 Service Unavailable | Integration paused or receiver not ready — retry per your backoff schedule. |
Error codes
| code | Status | Meaning |
|---|---|---|
MISSING_API_KEY | 401 | X-Api-Key header absent. |
INVALID_API_KEY | 401 | API key unknown, revoked, or from the wrong environment. |
INVALID_SIGNATURE | 401 | HMAC signature does not match the raw body under any active signing secret. |
SIGNATURE_EXPIRED | 401 | Signature timestamp outside the 5-minute tolerance window. |
INTEGRATION_NOT_CONNECTED | 401 | Merchant has never activated the integration. |
INTEGRATION_ALREADY_DISCONNECTED | 401 | Merchant disconnected the integration. Fresh credentials required. |
INTEGRATION_PAUSED | 503 | Merchant paused the integration. Retry per your backoff schedule. |
MISSING_IDEMPOTENCY_KEY | 400 | Planned. Reserved for the upcoming synchronous write endpoints (redemption validate/confirm, refund check). The current /events endpoint deduplicates on eventId and needs no Idempotency-Key. See Idempotency. |
UNKNOWN_EVENT_TYPE | 400 | eventType is not a value the receiver recognises. |
INVALID_PAYLOAD | 400 | Event body is not valid JSON or is missing required fields. |
INVALID_REQUEST | 400 | Query parameters are invalid — e.g. neither or both of phone and customerId on customer lookup. |
EVENT_HANDLER_NOT_REGISTERED | 503 | Event type is legitimate but the receiver has not deployed a handler yet. Retry per your backoff schedule — a later delivery will succeed. |
WRONG_EVENT_DIRECTION | 400 | Event type is emitted by Quroosh (outbound webhook) and must not be POSTed to /events. Stop retrying. |
Event processing codes
Returned from POST /events when an event fails its business checks. A 400 means the event cannot be processed as sent. For payload defects, fix the data and send a new event. For the state-dependent codes (unconfirmed branch mapping, missing customer mapping, frozen customer, inactive program or card), you may instead redeliver the same event after the merchant fixes their setup — failed deliveries are never cached, so a redelivery is processed fresh. A 503 means retry per your backoff schedule.
| code | Status | Meaning |
|---|---|---|
CUSTOMER_MAPPING_NOT_FOUND | 400 | No mapping for externalCustomerId — send CustomerSynced first. |
BRANCH_MAPPING_NOT_FOUND | 400 | No mapping for externalBranchId — send BranchSynced first. |
BRANCH_MAPPING_UNCONFIRMED | 400 | The branch is known but the merchant has not confirmed the pairing in the Quroosh dashboard yet. |
CUSTOMER_INACTIVE | 400 | The customer is frozen for this store. |
MISSING_STAMP_CARD_ID | 400 | earnType = "Stamps" without a stampCardId. |
STAMP_CARD_NOT_FOUND | 400 | stampCardId is unknown for this store. |
STAMP_CARD_INACTIVE | 400 | The stamp card is deactivated. |
STAMP_CARD_FREE_ENTRY_ONLY | 400 | The card's only earning method is FreeEntry — it can never be credited from a partner invoice. |
NO_ACTIVE_POINTS_PROGRAM | 400 | The store has no active points program. |
NO_ACTIVE_EARNING_METHOD | 400 | The points program or stamp card has no active earning method. |
PARTNER_INVOICE_ALREADY_EARNED | 400 | This externalInvoiceId was already credited — rejected even under a new eventId. |
SUBSCRIPTION_LAPSED | 503 | The merchant's Quroosh subscription is not active. Retry — a delivery after renewal succeeds. |
CONCURRENCY_CONFLICT | 503 | A concurrent ledger update collided with this event. Retry. |