Skip to content
opis.Nutrition API

Errors

Every 4xx and 5xx response is an RFC 9457 (opens in a new tab) problem details document with Content-Type: application/problem+json:

JSON
{
  "type": "https://platform.opis.health/docs/errors/validation_failed",
  "title": "Validation failed",
  "status": 422,
  "detail": "The request body has 2 invalid fields.",
  "code": "validation_failed",
  "request_id": "req_01k68a9nytdxx0x5x0p47zgrm8",
  "errors": [
    {
      "pointer": "/items/2/grams",
      "code": "too_large",
      "detail": "Must be at most 5000."
    },
    {
      "parameter": "If-Match",
      "code": "invalid_format",
      "detail": "Must be a quoted version, e.g. \"3\"."
    }
  ]
}
FieldUse it for
codeBranching in code. A stable, machine-readable value from the table below.
statusThe HTTP status, repeated for convenience.
titleA short summary, stable per code.
detailA human-readable explanation of this occurrence — for logs and developers, not end users. Never parse it.
request_idQuote it when you contact support. Also in the Request-Id header of every response.
errors[]Per-field failures: a JSON pointer into the body (/images/0/url) or a parameter name, plus a field code and detail.
current_stateOn invalid_state and precondition_failed: the resource's status, version, cancellation_reason and confirmation_method, so you can reconcile without another GET.
typeA URL that documents the code — each one links to a page on this site.

The code list is append-only within /v1. Codes are added but never renamed or removed. Treat an unknown code as a generic error of its HTTP status class.

Field codes in errors[]

required, not_allowed, invalid_type, invalid_format, invalid_value, too_small, too_large, too_short, too_long, duplicate (for example an item id twice in a confirmation), unknown_reference (an itm_ id that is not in the identification). Business rules about one field use the problem's own code instead, such as use_reject_instead.

HTTP error codes

CodeStatusMeaning
validation_failed422The request is well formed but a body field, query parameter or header failed validation. errors[] lists each failure with a JSON pointer or parameter name.
invalid_request400The request cannot be parsed: malformed JSON or multipart body, an invalid pagination cursor, or an unparseable If-Match / If-None-Match header.
unauthorized401The Authorization header is missing, or the API key is unknown, revoked or expired.
forbidden403The key is valid but lacks the scope this operation needs, or the caller’s IP address is not on the key’s allowlist.
not_found404The resource or route does not exist, belongs to another project or mode, or was deleted.
conflict409The request conflicts with existing state not covered by a more specific code (for example the webhook-endpoint limit is reached).
invalid_state409The operation is not allowed in the resource’s current status — for example confirming an analysis that is no longer requires_confirmation. The problem carries current_state.
precondition_failed412If-Match does not match the resource’s current ETag: it changed since you read it. The problem carries current_state.
precondition_required428The project requires If-Match on this operation and it was not sent.
idempotency_key_reused422The Idempotency-Key was already used with a different request (method, path or body).
idempotency_request_in_progress409A request with the same Idempotency-Key is still being processed.
rate_limited429The key’s request-rate limit was exceeded.
quota_exceeded429A daily or monthly quota for a meter (identification or nutrition) is used up.
spend_limit_reached402The organization’s monthly spend cap would be exceeded.
too_many_pending_confirmations429The organization has reached its cap on meal analyses waiting in requires_confirmation.
organization_suspended403The organization is suspended; every key is refused.
organization_pending403The organization is awaiting activation, so live keys cannot be used yet. Test keys work.
key_in_query_rejected400An API key was sent in the URL query string. The request is refused and the key is revoked.
invalid_image422The image could not be decoded or breaks an image rule (pixel cap, animation, corrupt data). Also used as error.code when a file is rejected after upload.
unsupported_media_type415The request Content-Type, or an uploaded image’s detected format, is not supported. HEIC is not supported in v1.
image_too_large413An uploaded image part is larger than 15 MiB.
file_not_found404A referenced file_id does not exist in this project and mode, or was deleted.
file_in_use409The file is held by a meal analysis that has not finished, so it cannot be deleted yet.
file_not_ready409The file’s presigned upload has not been completed (nothing was uploaded, or complete was not called).
url_fetch_failed422An image URL could not be fetched: not https, resolves to a private address, redirected to another host, took longer than 10 s, is larger than 15 MiB or is not an image.
pipeline_not_found400The requested pipeline is unknown or retired.
use_reject_instead422A confirmation with action: edit had an empty items list.
confirmed_by_must_be_pseudonymous422confirmed_by looks like an email address or a phone number.
quantity_text_unsupported_locale422quantity_text was sent without grams for a non-English locale.
internal_error500An unexpected error on our side. Also a workflow failure code. Never billed.
maintenance503Intake is paused for maintenance.
request_too_large413The request body exceeds its limit (1 MiB for JSON bodies).
service_unavailable503A dependency is temporarily unavailable; creates are refused rather than run unmetered.

Workflow failure codes

These never appear as an HTTP response. They are the error.code of a meal analysis or nutrition estimate whose status is failed (invalid_image and internal_error can appear in both places).

CodeMeaning
pipeline_deprecatedReserved; not returned in v1. Requests on a deprecated release succeed and carry Deprecation and Sunset headers.
upstream_unavailableWorkflow failure: the model provider stayed unavailable past the stage deadline. Retryable; never billed.
upstream_invalid_responseWorkflow failure: the model provider kept returning unusable output.
processing_timeoutWorkflow failure: a stage did not finish within its deadline after retries. Never billed.
queue_timeoutWorkflow failure: the resource waited in queued for more than 24 hours (for example its image never became ready). Never billed.
pipeline_retiredWorkflow failure: the pinned release was retired before the workflow finished. A platform fault; never billed.

Retrying

StatusRetry?
400, 401, 403, 404, 413, 415, 422No — fix the request first
409 idempotency_request_in_progressYes, after Retry-After, with the same Idempotency-Key
409 invalid_state, 412No — reconcile with current_state, then decide
429Yes, after Retry-After
500, 503Yes, with exponential backoff and the same Idempotency-Key