API за разпознаване на храни от снимка
Превърни снимка в данни за храна. Четири vision крайни точки покриват целия поток с камерата: декодирай баркод, разпознай продукт по предната му страна, прочети етикета с хранителните стойности и съставките или анализирай чиния с храна с оценки на порциите — съпоставено с 6,1 млн. продукта, на шест езика, включително кирилица.
curl -X POST -H "X-API-Key: food_•••" \
-F "[email protected]" \
"https://foodbase.dev/v1/vision/product"
{
"extracted": {
"name": "Масло краве",
"brand": "Bulgaricum",
"quantity": "250g",
"lang": "bg",
"confidence": 0.95
},
"matches": [
{
"score": 0.95,
"product": {
"id": "c5b352b5-...",
"name_default": "Краве масло 82%"
}
}
],
"cached": false
} Предпочиташ да кликаш? Пробвай търсачката на продукти или фото площадката.
Какво получаваш
POST /vision/barcode
Декодира EAN-13/UPC от снимка и търси продукта. Безплатно — 0 кредита.
POST /vision/product
Разпознава продукт по предната му страна и го съпоставя с каталога. 3 кредита.
POST /vision/label
OCR на панела с хранителни стойности и списъка със съставки. 4 кредита.
POST /vision/meal
Разпознава ястия в чиния с оценки на порцията и kcal. 5 кредита.
confidence
Калибрирана оценка 0–1 за всяко извличане — реши кога да попиташ потребителя.
cached
Идентични изображения се сервират от кеша — същият отговор, мигновено.
Налично във всеки план чрез месечни AI кредити — всяко извикване има фиксирана цена в кредити, а всеки план (включително Free) идва с кредитен лимит. Виж плановете →
Примерен код
Същата заявка на curl, JavaScript и Python. Замени YOUR_API_KEY с ключ от таблото си.
curl "https://foodbase.dev/v1/vision/product" \
-H "X-API-Key: YOUR_API_KEY" \
-F "[email protected]"
const form = new FormData();
form.append("image", fileInput.files[0]); // a File/Blob from an <input type="file">
const res = await fetch("https://foodbase.dev/v1/vision/product", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY" },
body: form,
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
import requests
with open("photo.jpg", "rb") as f:
res = requests.post(
"https://foodbase.dev/v1/vision/product",
headers={"X-API-Key": "YOUR_API_KEY"},
files={"image": f},
timeout=30,
)
res.raise_for_status()
data = res.json()
Как работи
Коя крайна точка за коя снимка
И четирите операции приемат едно multipart/form-data поле с име image. Сървърът проверява байтовете, не името на файла: JPEG, PNG или WebP, до 8 MB, иначе качването се отхвърля, преди да тръгне какъвто и да е модел. Снимките се завъртат автоматично по EXIF и се оразмеряват до 1024 px по най-дългата страна, така че снимка в пълна резолюция струва само време за качване.
POST /v1/vision/barcode декодира EAN-13, EAN-8, UPC-A, UPC-E и Code-128 с обикновено компютърно зрение и търси кода точно като GET /foods/barcode/{code}. Тялото на 200 е { barcode, product } с пълния запис от каталога (id, name_default, brand, nutrition_summary и останалото). Не се изпълнява езиков модел, затова струва 0 кредита и се отчита като извикване на данни.
Другите три са AI извиквания. /vision/product чете предната страна на опаковката в extracted { name, brand, quantity, lang, confidence } плюс подредени matches. /vision/label преписва панела с хранителни стойности в числа на 100 g, ingredients_text, allergens и serving; панел, който отпечатва само стойности на порция, се преобразува на 100 g в код, когато размерът на порцията е отпечатан (basis per_100g, converted: true); когато не е, полетата на 100 са null, а отпечатаните числа се връщат под per_serving (basis per_serving). /vision/meal връща items[] от разпознати ястия с оценки на порцията. Всеки отговор носи request_id и cached.
- Заявка без полето image е 422 Validation Error с details[].field = "image".
Четене на отговор от /vision/product
extracted.lang е езикът, прочетен от опаковката (bg за етикет на кирилица), и управлява езиково-съобразеното търсене в каталога. confidence е от 0 до 1 и ограничава това търсене: каталогът се заявява само когато confidence е поне 0,3 и е прочетено име; иначе matches е празен.
matches съдържа до 5 продукта, най-добрият първи, всеки { score, product } в същата пълна форма FoodItem като запис от API за база данни с храни. score произлиза от confidence и ранга, така че най-горното съвпадение носи самото confidence, а всяко следващо има по-ниска оценка. Запази matches[0].product.id; id-тата са стабилни при повторен внос.
Пропуск изглежда като този отговор на малка снимка на продукт: {"matches":[],"extracted":{"lang":"","name":"","brand":"","quantity":"","confidence":0},"request_id":"bcca8231-f335-4468-81bf-e587b614d9a4","cached":true}. Празните низове и confidence 0 означават, че не е могло да се прочете име; cached: true означава, че същите байтове са били виждани преди, а извикването пак е таксувано с 3 кредита.
Етикети и ястия: прочетено срещу оценено
/vision/label е преписване, не извод. energy_kcal, fat_g, saturated_fat_g, carbs_g, sugars_g, fiber_g, proteins_g и salt_g се четат както са отпечатани, а всичко, което не е на етикета, се връща null, никога налучквано. Четим баркод на същата снимка се връща като extracted.barcode и се търси: съвпадение попълва product с пълния FoodItem, иначе product е null.
/vision/meal е обратното и полето му disclaimer го казва. Всеки елемент има dish, kind, portion_g_est и confidence, плюс match, когато ястието е разрешено до генерична храна от USDA: id, name_default, per_100g { energy_kcal, proteins_g, carbs_g, fat_g } и estimated_kcal, което е per_100g.energy_kcal по portion_g_est, делено на 100. Елементите са или цели ястия (kind „dish“: бургер, лазаня), или отделните компоненти на чинията (kind „component“: ориз, пилешко на скара, салата), никога ястие заедно със собствените му части, така че estimated_total_kcal, сборът от елементите, които имат такова, не брои нищо два пъти; то е null, когато никой елемент няма. Съпоставянето използва английски генерични храни — USDA FNDDS за ястия, както се ядат (лазаня, бурито, pad thai), после USDA SR Legacy за съставки — така че match.name_default е на английски независимо от снимката, а елемент без уверено съвпадение получава match: null вместо грешна храна.
- Показвай текста на disclaimer на крайните потребители на оценките за хранения; ястие с match: null пак струва 5-те кредита.
Кредити, възстановявания и лимитът за vision
Кредитите се удържат преди извода: 3 за product, 4 за label, 5 за meal. Месечният лимит е споделен между всички ключове на акаунта (Free 20, Starter 500, Pro 1 300, Enterprise 3 000) и се нулира на първо число от месеца по UTC. Когато не може да покрие извикване, го плащат кредити от еднократни пакети за презареждане (купени от страницата Billing на таблото, валидни 12 месеца). AI отговорите носят X-Credits-Limit, X-Credits-Remaining (месечни плюс презареждане), X-Credits-Topup-Remaining и X-Credits-Reset; GET /v1/credits връща двата баланса безплатно.
Изчерпването е 402, не 429: { "error": "Insufficient credits", "message": "This call costs 3 credits and your free plan's monthly allowance of 20 is exhausted, with no top-up credits left. Buy more at https://foodbase.dev/dashboard/billing (they apply instantly), or wait for the reset on 2026-12-01.", "top_up_url": "https://foodbase.dev/dashboard/billing" }. Възстановявания има само когато заявката изобщо не е стигнала до отговор: отхвърлено изображение (413 или 422), липсващо поле (422), грешка на доставчика (502, съобщението завършва с „You were not charged.“) или изключен vision (503). Попаденията в кеша се таксуват с пълна цена нарочно.
AI извикванията имат собствен лимит за секунда, без burst: 1/с във Free и Starter, 2/с в Pro, 5/с в Enterprise на ключ и три пъти повече за целия акаунт. Отговорите носят X-RateLimit-Vision-Limit и X-RateLimit-Vision-Remaining; надвишаването е 429 с Retry-After: 1 и без таксуване, защото лимитерът се изпълнява преди удръжката.
Потокът със сканиране и снимката
Първо най-евтиното. Декодирай баркода на устройството и извикай API за търсене по баркод, или остави /vision/barcode да го декодира за 0 кредита. Само когато няма баркод или търсенето върне 404, изпрати предната страна на опаковката към /vision/product. С matches[0].product.id вземи разбивката на 100 g от API за хранителни стойности или оценка с прости думи от API за AI анализ на храни.
Качеството на снимката определя confidence. За /vision/product кадрирай предната страна на опаковката с четливи име, марка и размер на опаковката и нищо друго в кадъра. За /vision/label положи панела плосък, запълни кадъра с таблицата с хранителни стойности и абзаца със съставки и включи баркода, ако се събира. За /vision/barcode правилото е собственото 422 съобщение на сървъра: запълни кадъра с баркода, избягвай отблясъци, дръж го на фокус.
- Повтори 502 след кратка пауза; кредитите ти са възстановени. Не повтаряй 200 с ниско confidence; снимай отново.
Какво можеш да изградиш
Записване на храна със снимка
Снимай продукт или хранене и го запиши — без писане, без търсене на баркод.
Заснемане на етикети
Дигитализирай хранителните стойности и съставките от всяка опаковка, дори продукти, които още не са в база данни.
Умен резервен вариант за скенера
Баркодът не се чете? Премини към разпознаване на предната страна в същия поток.
Лимити по план
| Free | 20 AI кредита/месец; 1 AI заявка/с на ключ; /vision/barcode се брои към 100 заявки/ден |
|---|---|
| Starter | 500 AI кредита/месец; 1 AI заявка/с на ключ; /vision/barcode се брои към 5 000 заявки/ден |
| Pro | 1 300 AI кредита/месец; 2 AI заявки/с на ключ; /vision/barcode се брои към 25 000 заявки/ден |
| Enterprise | 3 000 AI кредита/месец; 5 AI заявки/с на ключ; /vision/barcode се брои към 100 000 заявки/ден |
Всеки отговор съдържа хедъри X-RateLimit-* с оставащия бюджет; всеки 429 съдържа Retry-After . Сравни плановете →
Грешки и как да ги обработиш
402 — Месечните AI кредити и кредитите от презареждане са изразходвани; тялото назовава цената, лимита ти, датата на нулиране и top_up_url.
Купи пакет кредити (прилага се незабавно), изчакай X-Credits-Reset или надстрой. /vision/barcode продължава да работи.
404 — /vision/barcode е декодирал код, който не е в каталога; тялото го връща.
Не повтаряй. Премини към /vision/product със снимка на предната страна.
413 — Качване над 8 MB.
Намали размера от страна на клиента; сървърът така или иначе оразмерява до 1024 px. Кредитите са възстановени.
422 — Липсващо или недекодируемо изображение, грешен формат или няма баркод в кадъра.
Прочети details[] или message и снимай отново. Кредитите са възстановени.
429 — Надвишен лимит за vision за секунда за ключа или акаунта.
Изчакай Retry-After (1 секунда) и изпрати отново. Нищо не е таксувано.
502 — Доставчикът на vision се провали по средата на извикването.
Опитай отново веднъж след пауза; съобщението потвърждава, че не си таксуван.
503 — Vision не е конфигуриран или лимитерът, или хранилището за кредити е недостъпно.
Опитай отново с backoff. Нищо не е таксувано.
В сравнение с други API
Повечето услуги от снимка към храна връщат етикет за онова, което мислят, че виждат, и те оставят сам да намериш продукта. FoodBase разрешава в същото извикване: извличане плюс подредени съвпадения с каталога от 6,1 млн. продукта, или свързан запис, когато снимка на етикет носи баркод. Разграничава четенето от налучкването: стойностите от етикета са преписани или null, а само /vision/meal оценява, с поле disclaimer. Компромисът е, че лоша снимка дава празен списък със съвпадения и пак струва кредитите си, така че насоките за снимане в интерфейса ти се изплащат.
Често задавани въпроси
Струва ли /vision/product кредити, когато нищо не съвпадне? +
Да. Кредитите се удържат преди извода, а 200 с matches: [] е завършено извикване. Снимай отново, вместо да изпращаш същата снимка; повторното изпращане е попадение в кеша на пълна цена.
Защо кеширан отговор пак е таксуван? +
Попаденията в кеша струват нарочно колкото свежите извиквания; кешът прави повторенията бързи и последователни, не безплатни. Дедупликирай идентични снимки от страна на клиента преди второ качване.
Може ли /vision/label да попълни стойности, които етикетът не показва? +
Не. Той преписва панела и връща null за всичко неотпечатано. За интерпретация на тези числа изпрати свързаното id на продукта към API за AI анализ на храни.
Лимитът за vision същият ли е като лимита на моето API? +
Не. AI извикванията ползват отделна, по-ниска кофа: 1/с във Free и Starter, 2/с в Pro, 5/с в Enterprise на ключ и три пъти повече за всички ключове. Само /vision/barcode ползва обикновения лимит и дневна квота на data API.
Как да проверя оставащите кредити, без да харча? +
Извикай GET /v1/credits с ключа си. Връща plan, месечен лимит, използвани кредити и датата на нулиране и не се брои нито към кредитите, нито към дневната квота.
Разгледай още endpoint-и
API за AI анализ на храни
Едно извикване превръща суровите данни за продукта в нещо, което можеш да покажеш на потребителя: резюме от две изречения, добри страни и предупреждения, изчислени от хранителните данни с публикувани прагове, декларираните алергени, съвместимост с диети, която казва откъде идва всеки отговор, и нивото на обработка — на шест езика, стриктно основано на данните от етикета на продукта.
Научи повече →API за търсене по баркод
Сканирай или въведи баркод и получи продукта. Разреши всеки EAN-13 или UPC код до запис за храна — марка, категория, Nutri-Score и обобщение на хранителните стойности — с една заявка. Създадено за приложения със скенер.
Научи повече →API за хранителни стойности
Отиди отвъд основните макроси. Вземи подробна разбивка на над 40 хранителни вещества на продукт — енергия, протеини, въглехидрати, мазнини, захари, фибри, натрий, витамини и минерали — всичко на 100 g, за всяка храна по ID.
Научи повече →Започни да създаваш с API за разпознаване на храни от снимка
Безплатно за начало. Без кредитна карта.
Вземи API ключ Към таблото