All posts
ai tutorial

From Photo to Food Data: The Vision Endpoints

Decode barcodes, identify products, read nutrition labels, and analyze meals — all from a single photo, with one multipart request.

FoodBase Team 3 min read

Four things a photo can become

The vision endpoints turn a photo into structured food data. There are four modes, each its own endpoint, each priced in AI credits (every plan — including Free — ships with a monthly allowance):

EndpointWhat it doesCredits
POST /v1/vision/barcodeDecode a barcode from a photo, return the matched product0 (uses your daily quota)
POST /v1/vision/productRecognize a product from its front-of-pack photo3
POST /v1/vision/labelRead a nutrition label: table, ingredients, allergens4
POST /v1/vision/mealIdentify dishes on a plate with portion estimates5

Barcode decode is pure computer vision — no AI model involved — which is why it’s free of credits and metered like a regular data request instead.

You can try all four in the browser, with your own key and photos, on the photo playground.

The request shape

All four take the same multipart request — one image field:

curl -X POST "https://foodbase.dev/v1/vision/product" \
  -H "X-API-Key: food_your_key_here" \
  -F "[email protected]"

Or from JavaScript:

async function vision(endpoint, file) {
  const form = new FormData();
  form.append("image", file);
  const res = await fetch(`https://foodbase.dev/v1/vision/${endpoint}`, {
    method: "POST",
    headers: { "X-API-Key": API_KEY },
    body: form,
  });
  if (!res.ok) throw new Error(`Vision error: ${res.status}`);
  return res.json();
}

Photos are normalized server-side (downscaled, EXIF stripped) before anything touches an AI model, and images are never stored — the photo is analyzed and discarded.

Product recognition

/vision/product extracts what the model can see and matches it against the 6.1M-product catalog, returning score-ranked matches:

{
  "request_id": "…",
  "cached": false,
  "extracted": {
    "name": "Масло Краве",
    "brand": "…",
    "quantity": "250 g",
    "lang": "bg",
    "confidence": 0.95
  },
  "matches": [
    { "score": 0.98, "product": { "id": "…", "name_default": "…", "nutrition_summary": { } } }
  ]
}

It reads non-Latin packaging too — Cyrillic labels resolve to the right catalog entries. Treat matches[0] as the answer when its score is high, and show a short pick-list when several matches score close together.

Label reading

/vision/label OCRs a nutrition panel into the same field names the rest of the API uses — plus ingredients text and detected allergens:

{
  "extracted": {
    "energy_kcal": 539,
    "fat_g": 30.9,
    "saturated_fat_g": 10.6,
    "carbs_g": 57.5,
    "sugars_g": 56.3,
    "proteins_g": 6.3,
    "salt_g": 0.11,
    "ingredients_text": "Sugar, palm oil, hazelnuts 13%…",
    "allergens": ["milk", "nuts"],
    "product_name": "Nutella",
    "confidence": 0.97
  },
  "product": { "id": "…" }
}

Fields the label doesn’t show come back null — the model never invents numbers. If the label includes a barcode or the product is recognized, product links the catalog record.

Meal analysis

/vision/meal identifies the dishes on a plate, estimates portions, and matches each dish to a generic food so you get calorie estimates:

{
  "items": [
    {
      "dish": "grilled chicken breast",
      "portion_g_est": 150,
      "confidence": 0.9,
      "match": {
        "name_default": "Chicken breast, grilled",
        "per_100g": { "energy_kcal": 165, "proteins_g": 31, "carbs_g": 0, "fat_g": 3.6 },
        "estimated_kcal": 248
      }
    }
  ],
  "estimated_total_kcal": 612,
  "disclaimer": "Dish identification and portion sizes are AI estimates from a photo…"
}

Portions from a single photo are estimates — the response says so in disclaimer, and your UI should too, ideally with a quick way for the user to adjust grams.

Credits, caching, and errors

  • Every AI response carries X-Credits-Limit, X-Credits-Remaining and X-Credits-Reset headers — surface them in your app so users are never surprised.
  • Identical images are cached server-side, so repeated requests return instantly — at the same credit price. Design your app to cache results client-side rather than re-submitting the same photo.
  • You are not charged when the request fails: invalid or oversized images, provider errors and not-found barcodes all refund automatically.
  • Expect and handle 402 (out of credits), 429 (per-second vision rate limit — every plan has one), and 413 (image too large).

Where to start

Play with your own photos on the playground, then read the full request/response contracts in the docs. The free plan’s 100 monthly credits are enough to prototype all four modes.

Build it with FoodBase

6.1M products, 40+ nutrients and AI food analysis — free to start, no credit card.