Errors
The Luqra Now API uses conventional HTTP status codes and returns structured error responses to help you handle failures gracefully.
Error response format
All error responses follow a consistent structure:
{
"error": {
"code": "ERROR_CODE",
"message": "A human-readable description of the error"
}
}
Validation errors include additional detail:
{
"error": {
"code": "VALIDATION_ERROR",
"message": "Validation error",
"details": [
{
"field": "email",
"issue": "validation_email_required",
"message": "Enter an email address."
},
{
"field": "legalAddress.postalCode",
"issue": "validation_postal_code_format",
"message": "Enter a 5-digit ZIP code."
}
]
}
}
Each entry in details describes one failed field:
| Field | Description |
|---|---|
field |
Dotted path to the field that failed, relative to the request body |
issue |
Identifies the rule that failed. Most rules report a stable validation_* code, which is safe to branch on. Rules that have no code report their description here instead, so treat an issue that is not a validation_* code as informational |
message |
Human-readable description of the rule. Wording may change without notice |
A field can appear more than once when it fails several rules.
HTTP status codes
| Code | Meaning | When it happens |
|---|---|---|
400 |
Bad Request | Invalid request body or query parameters |
401 |
Unauthorized | Missing or invalid API key |
403 |
Forbidden | API key type cannot access this resource |
404 |
Not Found | Resource does not exist or is not accessible |
409 |
Conflict | Operation conflicts with current state (e.g., duplicate contact) |
500 |
Internal Server Error | Unexpected server-side failure |
Common error codes
| Code | Status | Description |
|---|---|---|
VALIDATION_ERROR |
400 | Request body or parameters failed schema validation |
INVALID_JSON |
400 | The request body contained the same JSON key more than once. Remove the duplicate key and retry |
IDEMPOTENCY_KEY_REQUIRED |
400 | The Idempotency-Key header was missing, empty, or longer than 255 characters on POST /v1/payments |
UNAUTHORIZED |
401 | API key is missing, expired, or revoked |
FORBIDDEN |
403 | API key type cannot access this resource |
NOT_FOUND |
404 | The requested resource was not found |
CONFLICT |
409 | Resource already exists or state conflict |
IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_BODY |
409 | An Idempotency-Key previously used to create a payment was sent again with a different request body. Mint a new key. |
INTERNAL_ERROR |
500 | An unexpected error occurred |
Recovering from a FAILED payment
A FAILED payment is terminal for that specific payment, but the underlying issue may still be fixable. Branch on the response's failureCode:
INVALID_ORIGINATOR_DATAorINVALID_CONTACT_DATA-- thefailureMessagenames the offending field. Update the named record, then create a new payment with a freshIdempotency-Key. The sameexternalPaymentIdmay be reused so the two attempts tie together in your reporting.INTERNAL_ERROR-- an unexpected error occurred. Wait a few minutes, then create a new payment with a freshIdempotency-Key. If the error persists, contact support.
See the payment lifecycle for full details.
Handling errors
Best practices for error handling:
- Check the
codefield for programmatic error handling rather than parsing the message string. Within a validation error, branch on each detail'sfieldand itsvalidation_*issuefor the same reason - Log the full error response including the
detailsarray for debugging - Retry on 500 errors with exponential backoff (the server may be temporarily unavailable)
- Do not retry 4xx errors without modifying the request -- these indicate client-side issues
- Always send an
Idempotency-KeyonPOST /v1/paymentsto make retries safe. See Idempotency and Retries.