Skip to content

Error Handling

Errors use conventional HTTP status codes with a JSON body containing a human-readable detail message. Client errors (4xx) indicate a problem with the request or account state; 5xx indicates a problem on our side.

Error response body
{
  "detail": "Search query must be at least 2 characters or empty for common foods."
}

Status codes

400Bad request from an explicit validation check (e.g. query too short, bad match_mode). detail is a human-readable string.
401Unauthorized, missing or invalid API key.
402Monthly quota exceeded for your plan.
403Forbidden — commercial use not allowed on your plan, the endpoint is not enabled for your plan, or a food-coverage limit was reached.
404Not found, unknown food ID or barcode with no match in any source.
422Unprocessable entity from schema validation (missing or out-of-range query/body params, e.g. limit=500 or a calc call missing required fields). Here detail is an array of field errors, not a string.
423Locked — your account is on a temporary security hold due to unusual activity. Not retryable; contact support to restore access.
429Rate limited, per-minute limit exceeded; see X-RateLimit-Reset.
500Server error, safe to retry with backoff; report persistent failures.

Retry guidance

  • 429: retry after the X-RateLimit-Reset time with exponential backoff and jitter.
  • 400 and 422: do not retry as-is; fix the request. 422 detail is an array of per-field errors.
  • 402 and 403: do not retry, these persist until the plan or usage state changes.
  • 423: do not retry; the account is on a temporary security hold. Contact [email protected] to restore access.
  • 404 on barcode lookup: fall back to food search so users can log the item manually.
  • 5xx: retry with backoff; if errors persist, check the status page and contact support.

Frequently asked questions

Should I retry 402 quota errors?

No. 402 persists until your monthly cycle resets or you upgrade. Detect it, surface an upgrade path in your admin tooling, and stop retrying.

How do I distinguish a rate limit from a quota error?

Per-minute rate limiting returns 429 with X-RateLimit-* headers; monthly quota exhaustion returns 402. Handle them separately, 429 is transient, 402 is not.