Error Handling¶
All error responses follow the JSON:API error format, providing structured information about what went wrong.
Error Response Structure¶
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "This field is required.",
"source": {"pointer": "/data/attributes/email"}
}
]
}
| Field | Description |
|---|---|
status |
HTTP status code as a string |
title |
Short, human-readable summary of the error |
detail |
Specific explanation of what went wrong |
source.pointer |
JSON pointer to the request field that caused the error (when applicable) |
Common Error Codes¶
400 -- Bad Request¶
Malformed requests or request-body validation failures detected while parsing the JSON:API document and validating request attributes. This includes both structural issues and semantic or value validation errors raised while handling the request body.
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "This field is required.",
"source": {"pointer": "/data/attributes/email"}
}
]
}
When more than one request field is invalid, the response may include multiple error objects. For example:
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "Ensure this value is greater than or equal to 1.",
"source": {"pointer": "/data/attributes/extra-guest-fee"},
"code": "min_value"
},
{
"status": "400",
"title": "Bad Request",
"detail": "Ensure this value is greater than or equal to 1.",
"source": {"pointer": "/data/attributes/extra-guest-threshold"},
"code": "min_value"
}
]
}
Token request errors: When requesting a token at /o/token/, you may
receive an error if user_id references a user that doesn't exist or isn't
owned by your application, credential_id does not belong to the provided
user_id, user_id is provided with app-level scopes such as user:write, or
user-level scopes are requested without user_id when your application
requires user-scoped tokens. These return a standard OAuth2 error response, not
JSON:API format, with "error": "invalid_scope".
Request ID Header¶
You may send an optional X-Request-ID header on any Public API request to make
log correlation easier when debugging with Beyond support.
- If you send a valid UUID, the API uses that value after normalizing it to the canonical lowercase hyphenated form.
- If you omit the header, or send it blank or whitespace-only, the API generates a UUID for the request.
- Every response except the
/healthzfast-path includes the effectiveX-Request-IDheader so you can log or report the exact value the server used. - If you send a non-empty
X-Request-IDthat is not a valid UUID, the request is rejected with400 Bad Request.
For JSON:API endpoints, the error response identifies the header explicitly:
{
"errors": [
{
"status": "400",
"title": "Bad Request",
"detail": "X-Request-ID header must be a valid UUID.",
"source": {"header": "X-Request-ID"}
}
]
}
For non-JSON:API endpoints such as /o/token/, the API returns a simpler JSON
error body:
401 -- Unauthorized¶
Missing or invalid authentication token.
{
"errors": [
{
"status": "401",
"title": "Unauthorized",
"detail": "Authentication credentials were not provided."
}
]
}
Tip
If you receive a 401, check that your access token has not expired. Tokens are valid for 1 hour. See Token Refresh.
403 -- Forbidden¶
The token is valid but lacks the required scope for this operation, or the token is scoped to a different user.
{
"errors": [
{
"status": "403",
"title": "Forbidden",
"detail": "You do not have permission to perform this action."
}
]
}
Common causes:
- Missing scope: The token doesn't include the required scope for this endpoint.
- User-scoped token restriction: A user-scoped token attempted an app-level operation (e.g., creating or deleting a user).
- Cross-user access: A user-scoped token attempted to access resources belonging to a different user.
- Source IP not allowed: Your application has an IP allowlist configured and the request origin IP is not in that allowlist (applies to both
/o/* OAuth2 endpoints and/api/v1/*resource endpoints).
404 -- Not Found¶
The requested resource does not exist or is not accessible to your application.
422 -- Unprocessable Entity¶
The JSON:API document is structurally valid and request-body validation has already passed, but the operation is still rejected during downstream domain or integration processing. This includes channel-specific validation or authentication failures that are not simple request-body field errors.
{
"errors": [
{
"status": "422",
"source": {"pointer": "/data/attributes/credentials"},
"title": "Invalid Credentials",
"detail": "Channel 'hostaway': Invalid client credentials",
"meta": {"channel": "hostaway", "code": "invalid_credentials"}
}
]
}
429 -- Too Many Requests¶
Rate limit exceeded. See Rate Limiting for details on handling this error.
500 -- Internal Server Error¶
An unexpected server error. If this persists, contact
[api-support@beyondpricing.com](mailto:api-support@beyondpricing.com).
Best Practices¶
- Check the
statusfield to determine the error category - Use
source.pointerto identify which request field caused validation errors - Expect multiple error objects when more than one request attribute is invalid
- Log the full error response for debugging
- Implement retry logic with exponential backoff for 429 and 5xx errors
- Do not retry 400, 401, 403, 404, or 422 errors without changing the request