Advanced
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.
