Errors
The Qariyb API uses conventional HTTP response codes along with custom API codes to indicate the success or failure of requests. This guide covers the error types you may encounter and how to handle them.
HTTP Status Codes
- Name
200 OK- Description
The request was successful.
- Name
201 Created- Description
A new resource was successfully created.
- Name
400 Bad Request- Description
The request was invalid or cannot be processed.
- Name
401 Unauthorized- Description
Authentication failed or the API key is missing.
- Name
403 Forbidden- Description
You don't have permission to access this resource.
- Name
404 Not Found- Description
The requested resource doesn't exist.
- Name
410 Gone- Description
The checkout cart is no longer usable — it expired, was already completed, or the
payment_intent_idsent does not match it.
- Name
422 Unprocessable Entity- Description
Validation failed for the provided data.
- Name
429 Too Many Requests- Description
Rate limit exceeded.
- Name
500 Internal Server Error- Description
Something went wrong on our end.
API Response Codes
The Qariyb API includes a code field in all responses for more specific error handling.
Success Codes (100-199)
- Name
100- Type
- OK
- Description
Request completed successfully.
- Name
101- Type
- CREATED
- Description
Resource was created successfully.
- Name
102- Type
- UPDATED
- Description
Resource was updated successfully.
- Name
103- Type
- DELETED
- Description
Resource was deleted successfully.
Success response
{
"success": true,
"code": 100,
"message": "OK",
"data": {
// Resource data
}
}
Client Error Codes (200-299)
- Name
200- Type
- VALIDATION_ERROR
- Description
The request data failed validation.
- Name
201- Type
- UNAUTHORIZED
- Description
Authentication is required or failed.
- Name
202- Type
- FORBIDDEN
- Description
You don't have permission for this action.
- Name
203- Type
- NOT_FOUND
- Description
The requested resource was not found.
- Name
204- Type
- METHOD_NOT_ALLOWED
- Description
The HTTP method is not supported for this endpoint.
- Name
205- Type
- CONFLICT
- Description
The request conflicts with existing data.
- Name
206- Type
- TOO_MANY_REQUESTS
- Description
Rate limit exceeded. Also returned for every HTTP 429.
Field validation failure (200)
{
"success": false,
"code": 200,
"locale": "en",
"message": "Please enter a valid email address.",
"data": {
"messages": {
"billing_email": ["Please enter a valid email address."],
"quantity": ["You must purchase at least one ticket."]
}
}
}
Business-rule rejection (200)
{
"success": false,
"code": 200,
"locale": "en",
"message": "This event uses RSVP registration, not checkout.",
"data": null
}
Both kinds of validation failure return HTTP 422 with code 200
(VALIDATION_ERROR); branch on the presence of data, not on the code.
A field validation failure carries the per-field messages under
data.messages, and message repeats the first of them.
A business-rule rejection — a discount code that cannot be applied,
checkout called on an RSVP event — has data: null. The reason exists only in
message, so always surface it rather than substituting your own copy.
ApiCode also defines 405 (VALIDATION_EXCEPTION), but the application
rewrites validation responses to code 200 before they are sent, so 405 is not
a value you will receive.
Checkout Error Codes (500-599)
These codes are specific to the checkout and registration flows.
- Name
500- Type
- EVENT_NOT_AVAILABLE
- Description
The event is not open for registration.
- Name
501- Type
- TICKET_TYPE_NOT_FOUND
- Description
The requested ticket type doesn't exist.
- Name
502- Type
- SOLD_OUT
- Description
The tickets are sold out.
- Name
503- Type
- CART_EXPIRED
- Description
Returned with HTTP 410. The checkout cart is no longer active: it expired, it was already completed, or the
payment_intent_idyou sent does not match the one the cart was created with. The expiry window defaults to 15 minutes but is set per event — readexpires_atfrom the initialize response rather than assuming a fixed duration.
- Name
504- Type
- PAYMENT_FAILED
- Description
Payment processing failed.
- Name
505- Type
- PAYMENT_NOT_CONFIRMED
- Description
Payment was not verified by Stripe.
- Name
506- Type
- CART_NOT_FOUND
- Description
The cart ID is invalid or doesn't exist.
- Name
507- Type
- REGISTRATION_CLOSED
- Description
Registration has been closed for this event.
- Name
508- Type
- PAYMENT_ACCOUNT_NOT_CONNECTED
- Description
The organizer has not finished connecting a Stripe account, so the event cannot take payments yet. Returned with HTTP 422 from
checkout/initialize. A configuration state the organizer must fix — not a transient failure, so do not retry.
Checkout error
{
"success": false,
"code": 502,
"message": "Only 3 tickets available for VIP Access."
}
Cart no longer active (HTTP 410)
{
"success": false,
"code": 503,
"locale": "en",
"message": "This basket is no longer active. Start a new checkout.",
"data": null
}
Handling Errors
Here's how to properly handle API errors in your integration:
async function makeApiRequest(url, options) {
const response = await fetch(url, options)
const data = await response.json()
if (!data.success) {
switch (data.code) {
case 201: // UNAUTHORIZED
// Redirect to login or refresh token
break
case 502: // SOLD_OUT
// Show sold out message to user
break
case 503: // CART_EXPIRED
// Restart checkout flow
break
default:
// Handle generic error
console.error(data.message)
}
}
return data
}
API key errors (600–607)
Returned by the authentication middleware before your request reaches a
controller. Codes 600–605 come from the publishable key used by the widget API
(/api/v1/public/*); 606–607 come from the secret key used by the
server-to-server REST API (/api/v1/*).
| Code | Name | HTTP | Description |
|---|---|---|---|
| 600 | API_KEY_MISSING | 401 | No X-Widget-Key header or widget_key query parameter provided |
| 601 | API_KEY_INVALID | 401 | Publishable key not found, or not in pk_live_… format |
| 602 | API_KEY_INACTIVE | 401 | Publishable key has been deactivated by the organizer |
| 603 | API_KEY_EXPIRED | 401 | Publishable key is past its expires_at |
| 604 | API_KEY_ORIGIN_DENIED | 403 | Request Origin/Referer not in the key's allowed domains list |
| 605 | API_KEY_RATE_LIMITED | 429 | Reserved for widget rate limiting |
Publishable keys are public by design, so 601–603 distinguish why a well-formed key was refused. Secret keys deliberately do not:
| Code | Name | HTTP | Description |
|---|---|---|---|
| 606 | SECRET_KEY_MISSING | 401 | No Authorization: Bearer header or X-Secret-Key header on a /api/v1/* request |
| 607 | SECRET_KEY_INVALID | 401 | Secret key not recognised, expired, inactive, or not in sk_live_… format — including sending a pk_live_… publishable key to a secret endpoint |
SECRET_KEY_INVALID covers every rejection reason on purpose. An unknown key,
a revoked key and an expired key are indistinguishable, so the response cannot
be used to probe which secret keys exist.
Exception handler codes (400–405)
Failures raised by the framework rather than by a controller are mapped onto
their own range. These are the codes you will see for a missing route, a failed
abort(), or a rejected form request.
| Code | Name | HTTP | Description |
|---|---|---|---|
| 400 | HTTP_NOT_FOUND | 404 | A URL that matches no route at all |
| 401 | HTTP_SERVICE_UNAVAILABLE | 503 | Application is in maintenance mode |
| 402 | HTTP_EXCEPTION | varies | Any other HTTP exception, using the exception's own status |
| 403 | UNCAUGHT_EXCEPTION | 500 | Unhandled server error |
| 404 | AUTHENTICATION_EXCEPTION | 401 | Authentication required |
| 405 | VALIDATION_EXCEPTION | 422 | Request body failed field validation; see data.messages |
Code 400 is not HTTP 400. The numeric ranges in this API are independent of
HTTP status codes — always branch on the code field and read status
separately.