Appearance
Error Reference
All API errors follow RFC 7807 Problem Details for HTTP APIs. Every error response uses Content-Type: application/problem+json.
Error Object Shape
json
{
"type": "https://httpstatuses.com/422",
"title": "Validation Error",
"status": 422,
"detail": "The given data was invalid.",
"errors": {
"email": ["The email field must be a valid email address."]
}
}| Field | Type | Description |
|---|---|---|
type | URI | Links to the HTTP status code reference. |
title | string | Human-readable short description of the error class. |
status | integer | HTTP status code (mirrors the response status). |
detail | string | Specific message for this occurrence. |
errors | object | Field-level validation messages. Only present on 422. |
HTTP Status Codes
400 Bad Request
Malformed request syntax (e.g. invalid JSON body).
json
{
"type": "https://httpstatuses.com/400",
"title": "Error",
"status": 400,
"detail": "An error occurred."
}401 Unauthorized
Missing or invalid token.
json
{
"type": "https://httpstatuses.com/401",
"title": "Unauthorized",
"status": 401,
"detail": "Authentication required."
}Common causes:
Authorizationheader missing or misspelled- Token has been revoked
- Token is malformed
403 Forbidden
The token does not have the required scope for this endpoint.
json
{
"type": "https://httpstatuses.com/403",
"title": "Forbidden",
"status": 403,
"detail": "Invalid ability provided."
}Common causes:
- Token was issued without the scope this endpoint requires
- Calling a platform endpoint without super-admin privileges
404 Not Found
The resource does not exist, or it exists but belongs to a different tenant.
json
{
"type": "https://httpstatuses.com/404",
"title": "Not Found",
"status": 404,
"detail": "The requested resource was not found."
}The API deliberately returns 404 (not 403) for cross-tenant access attempts to avoid leaking the existence of resources belonging to other tenants.
422 Unprocessable Entity
Two distinct causes share this status code:
Validation failure — the request body failed field-level validation:
json
{
"type": "https://httpstatuses.com/422",
"title": "Validation Error",
"status": 422,
"detail": "The given data was invalid.",
"errors": {
"email": ["The email field must be a valid email address."],
"phone": ["The phone field must not be greater than 30 characters."]
}
}Business rule violation — the request was structurally valid but violated a business rule (e.g. voiding an already-voided transaction, redeeming with insufficient balance):
json
{
"type": "https://httpstatuses.com/422",
"title": "Unprocessable Entity",
"status": 422,
"detail": "This transaction has already been voided."
}Business rule violations do not include an errors field.
429 Too Many Requests
Rate limit exceeded.
json
{
"type": "https://httpstatuses.com/429",
"title": "Too Many Requests",
"status": 429,
"detail": "Too Many Attempts."
}Check the Retry-After response header for the number of seconds to wait before retrying.
500 Internal Server Error
Unexpected server-side error. If this occurs consistently, contact support at support@yourloyalty.app with the request details and timestamp.
Business Rule Errors (422)
The following table lists the known business-rule detail messages returned by each endpoint.
| Endpoint | Trigger | detail message |
|---|---|---|
POST /transactions/{ulid}/void | Transaction already voided | "This transaction has already been voided." |
POST /redemptions | Insufficient points balance | "Insufficient points balance." |
POST /redemptions | Reward out of stock | "This reward is out of stock." |
POST /redemptions/{ulid}/fulfil | Redemption already fulfilled | "This redemption has already been fulfilled." |
POST /redemptions/{ulid}/fulfil | Redemption voided | "This redemption has been voided." |
POST /coupons/{ulid}/redeem | Voucher already redeemed | "This voucher has already been redeemed." |
POST /coupons/{ulid}/redeem | Voucher expired | "This voucher has expired." |
POST /coupons/{ulid}/redeem | Coupon inactive | "This coupon is no longer active." |
POST /coupons/{ulid}/redeem | Global redemption cap reached | "Maximum redemptions for this coupon have been reached." |
Retry Guidance
| Status | Retry? | Notes |
|---|---|---|
| 400 | No | Fix the request. |
| 401 | No | Reauthorise and obtain a valid token. |
| 403 | No | Issue a token with the required scope. |
| 404 | No | Check the ULID / ID. |
| 422 (validation) | No | Fix the request body. |
| 422 (business rule) | No | The state will not change without user action. |
| 429 | Yes | Wait Retry-After seconds, then retry with exponential back-off. |
| 500 | Yes | Retry after a short delay; contact support if persistent. |