Thrive AI Health

Errors

Every error response uses a consistent envelope. Switch on the machine-readable error.code rather than parsing the message.

Standard error shape

{
  "error": {
    "code": "unauthorized",
    "message": "Invalid access token",
    "details": [],
    "request_id": "6a5d5b2d-2cf0-4b7f-a9e3-7f2c66d4c4c9"
  }
}

The details array is always present on the error envelope. It is an empty [] when no per-field context applies (e.g. 401 unauthorized, 404 not_found, 500 internal_error). When the failure is validation-related or spans multiple fields, each entry has the shape:

{
  "field": "weight_unit",
  "code": "invalid_value",
  "message": "Unknown unit. Accepted values: kg, lb."
}
  • field: dotted path into the request body or the name of the offending query/header parameter.
  • code: machine-readable failure reason (required, invalid_value, too_long, etc.).
  • message: human-readable explanation.

The top-level error.code and error.message always describe the request as a whole; entries in details[] are the specific causes.

HTTP status codes

StatusMeaningWhen it happens
200OKRequest succeeded
201CreatedResource created successfully
202AcceptedAsync operation started (e.g. lab processing, backfill)
204No ContentUpdate or delete succeeded; no body returned
304Not ModifiedCached copy is still good
400Bad RequestInvalid request body, missing required fields, malformed JSON
401UnauthorizedMissing, expired, or invalid token
403ForbiddenValid token but insufficient permissions
404Not FoundResource does not exist
405Method Not AllowedHTTP method not supported for the endpoint
409ConflictResource already exists or state conflict
413Payload Too LargeRequest body or upload exceeds size limits
415Unsupported Media TypeUnsupported content-type
422Unprocessable EntityRequest is well-formed but semantically invalid
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected server failure
502Bad GatewayUpstream dependency failure
503Service UnavailableTemporary outage or maintenance

Error codes

The error.code field provides machine-readable error classification. Switch on this field rather than parsing the message.

CodeHTTP statusDescription
invalid_request400Request body is malformed or missing required fields
unauthorized401Token is missing, expired, or invalid
forbidden403Token is valid but does not have access to this resource
not_found404The requested resource does not exist
conflict409Resource already exists or state conflict
validation_error422Request is well-formed but contains invalid values
rate_limited429Rate limit exceeded; retry after the indicated period
internal_error500Unexpected server error
provider_error502Upstream provider returned an error
service_unavailable503The service is temporarily unavailable. Respect the Retry-After header.

Error examples

Error handling best practices

  1. On 401, request a new token from your backend, then retry.
  2. On 429, respect the Retry-After header; do not retry immediately.
  3. On 502 / 503, retry with exponential backoff (recommended: 1s, 2s, 4s, 8s, max 3 retries).
  4. On 409, the resource already exists; read the current state instead of retrying the create.
  5. On 422, check the message for which field/value is invalid; this is a client-side fix.

Rate & token limits

Thrive AI Health enforces per-tenant request rate limits on every endpoint and per-tenant token quotas on endpoints that invoke LLMs (coaching chat, nudge generation, lab and workout analysis, insights). Both are tracked on the tenant; there is no separate user-level quota.

Concrete request and token limits are assigned per tenant during partner onboarding and communicated out-of-band. Read the RateLimit-* and TokenLimit-* response headers on every call to track remaining quota in-band.

# Quota remaining
RateLimit-Limit: 600
RateLimit-Remaining: 598
RateLimit-Reset: 1710601800

# Token quota remaining
TokenLimit-Limit: 60000
TokenLimit-Remaining: 59800
TokenLimit-Reset: 1710601800

# Overages return a Retry-After header
Retry-After: 12

On overage, the response body's error.type field is requests or tokens, indicating which quota was exhausted:

{
  "error": {
    "code": "rate_limited",
    "message": "Rate limit exceeded. Retry after 12 seconds.",
    "type": "requests"
  }
}

On this page