Errors
Errors from the v1 API follow RFC 9457 (Problem Details for HTTP APIs). They’re returned with Content-Type: application/problem+json and a machine-readable type URL whose trailing fragment is a stable error code you can switch on in your client.
Envelope
Section titled “Envelope”{ "type": "https://docs.buildworkpro.com/docs/api/concepts/errors#validation_failed", "title": "Validation failed", "status": 422, "detail": "email must be a valid address", "request_id": "req_8f3c1b2a", "errors": [{ "field": "email", "code": "invalid_format", "message": "must be a valid address" }]}| Field | Description |
|---|---|
type |
URL pointing to docs for the specific error code. Stable. |
title |
Short human-readable summary. Same for every error of this code. |
status |
HTTP status code (also returned in the response status line). |
detail |
Human-readable explanation of this specific occurrence. |
request_id |
Echo this in support tickets to let us trace the request. |
errors |
Optional. Per-field validation breakdown on validation_failed. |
Error code catalog
Section titled “Error code catalog”| Code | HTTP | When | Retry? |
|---|---|---|---|
bad_request |
400 | Malformed request, bad query parameter, invalid JSON. | No. Fix the request. |
unauthorized |
401 | Missing, malformed, or invalid bearer token. | No. Re-authenticate. |
token_expired |
401 | OAuth access token has expired. | No. Refresh the token, then retry. |
forbidden |
403 | Authenticated, but the role lacks permission for this action. | No. The user can’t do this. |
scope_insufficient |
403 | Token is valid but doesn’t carry the required scope. | No. Request a broader scope at consent. |
subscription_inactive |
403 | The tenant has no active subscription (trial expired, payment failed). | No. The customer must update billing. |
tenant_suspended |
403 | The tenant is suspended by platform admin. | No. Contact support. |
not_found |
404 | Resource doesn’t exist or doesn’t belong to the calling tenant. | No. |
conflict |
409 | Generic state conflict (e.g., trying to delete something already deleted). | No without context change. |
idempotency_key_reused |
409 | Same Idempotency-Key was used for a request with a different body. |
No. Use a fresh key for a new operation. |
validation_failed |
422 | Request body or fields failed schema validation. | No. Fix the body. |
rate_limited |
429 | Tenant or per-key rate limit exceeded. | Yes. Honor Retry-After. |
internal_error |
500 | Unexpected server error. | Once, with a short delay. |
service_unavailable |
503 | Temporary outage or upstream dependency down. | Yes. Exponential backoff with jitter. |
maintenance |
503 | Planned maintenance window. | Yes. Honor Retry-After. |
Sample 422 response
Section titled “Sample 422 response”{ "type": "https://docs.buildworkpro.com/docs/api/concepts/errors#validation_failed", "title": "Validation failed", "status": 422, "detail": "Request body failed validation", "request_id": "req_b91e44d0", "errors": [ { "field": "type", "code": "invalid_enum", "message": "must be one of customer, vendor, subcontractor, supplier, employee, partner, other" }, { "field": "email", "code": "invalid_format", "message": "must be a valid email" } ]}Recommended client behavior
Section titled “Recommended client behavior”- Switch on the trailing fragment of
type(e.g.#validation_failed), notstatusortitle. The codes are stable; titles may be reworded. - Treat
internal_error,service_unavailable, andmaintenanceas retriable (see the Retry column above). Retry once forinternal_error; use exponential backoff forservice_unavailableandmaintenance. - On
rate_limited, honorRetry-Afterexactly. Don’t hammer. - On
unauthorizedortoken_expired, refresh credentials before retrying. Never retry blindly with the same expired token.