Errors

NutrientAPI uses conventional HTTP status codes to indicate the success or failure of a request. Codes in the 2xx range indicate success, 4xx codes indicate a problem with the request, and 5xx codes indicate a server-side issue.

Error Response Format

All errors return a JSON object with an error key containing a machine-readable code and a human-readable message:

{
  "error": {
    "code": "validation_error",
    "message": "ingredients must be a non-empty array"
  }
}

The code field is a stable string identifier you can match against in your error handling logic. The message field is a description intended for developers; it may change over time and should not be parsed programmatically.

HTTP Status Codes

Status Error Code Description
400 bad_request The request body is not valid JSON or the Content-Type header is missing.
401 unauthorized The Authorization header is missing or malformed.
403 forbidden The API key is invalid, expired, or revoked.
422 validation_error The request body is valid JSON but the content fails validation. See Validation Errors below.
429 rate_limited You have exceeded the requests-per-second limit for your plan. See Rate Limits.
503 service_unavailable The AI parsing service is temporarily unavailable. The request can be retried. See Handling 503 Errors below.

Validation Errors (422)

A 422 Unprocessable Entity response means your JSON is syntactically valid but the data does not meet the API's requirements. These are the most common validation errors:

Missing or empty ingredients

// Request
{
  "title": "My Recipe",
  "ingredients": [],
  "servings": 2
}

// Response (422)
{
  "error": {
    "code": "validation_error",
    "message": "ingredients must be a non-empty array"
  }
}

Invalid servings value

// Request
{
  "title": "My Recipe",
  "ingredients": ["1 cup rice"],
  "servings": 0
}

// Response (422)
{
  "error": {
    "code": "validation_error",
    "message": "servings must be a positive integer"
  }
}

Non-string ingredient entries

// Request
{
  "title": "My Recipe",
  "ingredients": ["1 cup flour", 42, null],
  "servings": 4
}

// Response (422)
{
  "error": {
    "code": "validation_error",
    "message": "each ingredient must be a non-empty string"
  }
}

Missing required fields

// Request (missing ingredients and servings)
{
  "title": "My Recipe"
}

// Response (422)
{
  "error": {
    "code": "validation_error",
    "message": "ingredients is required"
  }
}
Validation is fail-fast. The API reports the first validation error it encounters. Fix that error and re-submit to discover any subsequent issues. This keeps the error response simple and actionable.

Handling 503 Errors

A 503 Service Unavailable response means the AI service used for ingredient parsing and food matching is temporarily unreachable. This is the only error that indicates a transient server-side issue worth retrying.

When the AI backend (used solely for natural language parsing) is unavailable, the API cannot process recipes. This is rare but can happen during upstream provider outages.

Recommended Retry Strategy

Use exponential backoff with jitter:

async function analyzeWithRetry(payload, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch("https://api.nutrientapi.com/v1/analyze", {
      method: "POST",
      headers: {
        "Authorization": `Bearer ${apiKey}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(payload),
    });

    if (response.status !== 503) {
      return response;
    }

    if (attempt < maxRetries) {
      // Exponential backoff: 1s, 2s, 4s + random jitter
      const delay = Math.pow(2, attempt) * 1000;
      const jitter = Math.random() * 500;
      await new Promise(r => setTimeout(r, delay + jitter));
    }
  }

  throw new Error("NutrientAPI unavailable after retries");
}
Only retry 503 errors. Do not retry 400, 401, 403, or 422 errors -- those indicate problems with your request that will not resolve on retry. Retrying 429 errors is acceptable but you should respect the rate limit window.

Quality Gate Rejections

Not all "errors" are HTTP errors. If the API processes your recipe but confidence scores fall below internal quality thresholds, it returns a 200 response with a quality_warnings field describing the issues. This is not an error -- you still get nutrient data -- but the warnings indicate that specific ingredients may be less accurate.

{
  "ingredients": [ ... ],
  "total_nutrients": { ... },
  "quality_warnings": [
    {
      "ingredient": "a handful of mixed herbs",
      "issue": "low_confidence_match",
      "message": "Ingredient matched with low confidence; nutrients may be inaccurate"
    }
  ]
}

You can use these warnings to flag specific ingredients in your UI or prompt users to clarify ambiguous descriptions.

Troubleshooting Guide

I am getting 401 but my key looks correct

  • Verify the header is Authorization: Bearer YOUR_KEY with a space after "Bearer"
  • Check for trailing whitespace or newline characters in your key variable
  • Ensure you are not URL-encoding the header value

I am getting 422 but my JSON looks valid

  • Confirm Content-Type: application/json is set
  • Check that ingredients is an array of strings, not a single string
  • Check that servings is a positive integer, not a string like "4"
  • Ensure none of the ingredient strings are empty ("")

I am getting 503 errors frequently

  • This is unusual. Check status.nutrientapi.com for ongoing incidents
  • Implement the retry strategy described above
  • If you cache results (which all plans allow), cached responses are unaffected by 503 errors

I am getting 429 but I am under my plan's monthly limit

  • The 429 status code applies to the per-second rate limit, not the monthly quota
  • Spread your requests over time rather than sending them in bursts
  • See Rate Limits for the per-second limits on each plan

I am getting unexpected nutrient values

  • This is not an error condition. Check the ingredients array in the response to see which USDA foods were matched
  • Ambiguous ingredient descriptions (e.g., "oil" without specifying the type) may match unexpected foods
  • Be as specific as possible: "extra virgin olive oil" will match better than "oil"
  • Check quality_warnings for any low-confidence matches