API за търсене на храни
Пълнотекстово търсене сред 6,1 милиона хранителни продукта по име, марка или категория — подредени по релевантност, със странициране и бързо. Търси на всеки език, на който е отпечатан етикетът (включително кирилица), и подай lang=en|fr|es|de|it|bg за локализирани имена, категории и алергени. Една GET заявка връща чист JSON, който приложението ти може да визуализира веднага.
curl -H "X-API-Key: food_•••" \
"https://foodbase.dev/v1/foods/search?q=banana&limit=20"
{
"data": [
{
"id": "034becf0-9aa7-c748-41aa-b71dd4df2bae",
"name_default": "Bananes",
"name_localized": "Bananas",
"brand": "Bio Village, Marque Repère",
"barcode": "3564707141710",
"category": "...,Fruits,Fruits tropicaux,Bananes",
"nutriscore": "a"
}
],
"total": 1000,
"limit": 20,
"offset": 0
} Предпочиташ да кликаш? Пробвай търсачката на продукти или фото площадката.
Какво получаваш
id
Стабилен ID на храната — използвай го с останалите крайни точки.
name_default
Име на продукта на основния му език.
name_localized / category_localized
Преводи на поисквания lang (en, fr, es, de, it, bg), когато са налични — иначе оригиналният текст.
brand
Марка / производител, когато е известен.
barcode
EAN-13 / UPC баркод, когато е наличен.
category
Категория от най-високо ниво.
total / limit / offset
Метаданни за странициране на пълния набор от резултати.
Включено в безплатния план — 100 заявки/ден, без кредитна карта. Виж плановете →
Примерен код
Същата заявка на curl, JavaScript и Python. Замени YOUR_API_KEY с ключ от таблото си.
curl "https://foodbase.dev/v1/foods/search?q=banana&limit=20" \
-H "X-API-Key: YOUR_API_KEY"
const res = await fetch("https://foodbase.dev/v1/foods/search?q=banana&limit=20", {
headers: { "X-API-Key": "YOUR_API_KEY" },
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const data = await res.json();
import requests
res = requests.get(
"https://foodbase.dev/v1/foods/search?q=banana&limit=20",
headers={"X-API-Key": "YOUR_API_KEY"},
timeout=30,
)
res.raise_for_status()
data = res.json()
Как работи
Какво прави една заявка за търсене
Търсенето е една GET заявка с текста в q. Думите се сравняват едновременно с името на продукта и с марката, така че q=olympus milk намира продукти, чиито имена никога не казват Olympus, а последната дума се третира като префикс, така че milk olym съвпада още докато потребителят пише. Трябва да съвпаднат всички думи; няма OR. q трябва да е от 1 до 200 символа; липсващо или празно q се отхвърля още преди да започне търсене, затова пази празното поле за търсене от твоя страна.
Продуктите с име точно като въведеното идват първи, така че banana показва бананите преди бананови кисели млека, а greek yogurt — обикновените гръцки кисели млека. След тях резултатите са подредени по релевантност, а когато два продукта съвпадат еднакво добре, по-популярният е по-напред. Търсене по марка като pringles пропуска стъпката с точно име и остава подредено по популярност, а добавянето на втора дума (марка, вкус) е най-бързият начин да изведеш конкретен продукт по-нагоре.
Имената на категориите са резервен вариант, не част от основното съвпадане: само когато търсенето по име и марка не намери нищо, API търси продукти, чиято категория съдържа думите, на какъвто и език да е записана. Именно затова заявка като Seeds & Related Snacks или Fruits tropicaux връща списък, подреден по популярност, вместо празен масив.
- Редът не е нито азбучен, нито по id. Не пренареждай масива data от страна на клиента.
- Ако въведеното е GTIN само от цифри, изпрати го към API за търсене по баркод: то разрешава варианти с водещи нули (0000080042556 намира 80042556), което текстовото търсене не прави.
Как да четеш ред от резултатите
Всеки елемент в data е FoodListItem — по-лека форма от пълния запис: id, barcode, source, name_default, brand, category, image_url, nutriscore и nova_group, плюс name_localized (винаги налично) и category_localized, когато е подаден lang, различен от английски. Тук няма хранителни вещества; списъкът е направен за визуализиране на редове, не за изчисления.
Няколко полета могат да са null и примерът го показва. Бонбоните „Banana land“ на Roshen (4f995c13-c0df-bfcc-b6ec-449d312def75) имат image_url null и nova_group null; brand и barcode също могат да са null. Стойности на nutriscore извън a до e, като „n“ и „u“ в примера, означават, че не е изчислена оценка, затова показвай „без оценка“ вместо суровата буква.
category е пълният път на категорията от Open Food Facts, разделен със запетаи от общо към конкретно („...,Fruits tropicaux,Bananes“ за бананите на Bio Village). Показвай последния сегмент като етикет или първия за груба група и премахвай езиковите префикси като pt: преди показване. image_url е снимка от контрибутор в images.openfoodfacts.org, затова подготви заместваща картинка за случая с null.
Странициране, total и стабилни id-та
limit е от 1 до 100 (по подразбиране 20), а offset — от 0 до 10000. total е ограничен брой: API спира да брои при 1000 съвпадения, така че total 1000 в примера за q=banana с limit=3 означава поне 1000. Показвай го като „1000+“ и не изчислявай номер на последна страница от него.
Странирай, като добавяш limit към offset, докато data върне по-малко от limit елемента. Тъй като offset стига най-много до 10000, заявка с повече съвпадения от това има нужда от по-тесен q, а не от по-дълбока страница.
- Id-тата са стабилни при повторен внос във FoodBase, така че запази id от ред на търсене и го разрешавай по-късно с API за база данни с храни, без да търсиш отново.
- Подреждането се изчислява при всяка заявка и популярността може да се променя, затова offset не е траен курсор. Пази id-та, не позиции на страници.
Търсене на друг език
lang е en по подразбиране. Всеки език търси във вписването на този език в масива с имена на продукта, където доброволец или AI преводът на FoodBase е предоставил такова, и се връща към name_default — името, както е отпечатано на етикета — за продукти без такова вписване; марката винаги участва в съвпадението. Така lang=bg достига до всеки продукт, но предпочита български имена, където съществуват, а етикет на кирилица се намира при всеки lang.
Подаденият lang оформя и изхода. name_localized съдържа преведеното име: примерът, поискан с lang=en, превръща „Puré de plátano y fresa“ в „Banana and Strawberry Puree“ и се връща към name_default, когато няма какво да се превежда, както показва „Banana land“. Показвай name_localized, когато не е null, иначе name_default. category_localized не е задължително поле и липсва в примера, затова го чети защитно.
Автодовършване и преминаване към пълните записи
Търсенето е правилната крайна точка за поле с автодовършване. Забави натисканията на клавиши (debounce), искай limit=8 до 10 и отменяй заявката в процес, когато потребителят пише отново, за да не може бавен по-стар отговор да презапише по-нов. Всяко натискане на клавиш, стигнало до API, е една заявка от дневната ти квота, така че debounce е толкова контрол на разходите, колкото и UX детайл.
Когато потребителят избере ред, извикай API за база данни с храни с id за пълния запис, или API за хранителни стойности, когато ти трябва само таблицата с хранителни вещества на 100 g. Едно търсене плюс една заявка за детайли е по-евтино от теглене на пълни записи за всяко предложение.
Заснетият отговор на търсенето няма заглавка Cache-Control, за разлика от записите за храни, които могат да се кешират 300 секунди. Кеширай резултатите от търсенето сам, с ключ точните q, lang, limit и offset; едни и същи кратки префикси се повтарят непрекъснато в поле с автодовършване. X-RateLimit-Second-Remaining показва колко burst е останал, а при 429 заглавката Retry-After казва колко секунди да изчакаш.
Какво можеш да изградиш
Избор на храна и автодовършване
Задвижи поле за търсене в калориен тракер или приложение за рецепти — резултати в реално време от 6,1 млн. продукта.
Обогатяване на каталози
Свържи собствените си SKU с каноничните записи за храни по име или марка.
Потоци за откриване
Разглеждай по категория или ключова дума, за да изградиш подбрани списъци с храни.
Лимити по план
| Free | 100 заявки/ден, споделени между ключовете на акаунта; 1 заявка/с на ключ, burst 5. Лимитът от 25/ден за разбивка на хранителни вещества не важи за търсенето. |
|---|---|
| Starter | 5 000 заявки/ден; 5 заявки/с на ключ, burst 25. |
| Pro | 25 000 заявки/ден; 20 заявки/с на ключ, burst 100. |
| Enterprise | 100 000 заявки/ден; 50 заявки/с на ключ, burst 250. |
Всеки отговор съдържа хедъри X-RateLimit-* с оставащия бюджет; всеки 429 съдържа Retry-After . Сравни плановете →
Грешки и как да ги обработиш
401 — Заглавката X-API-Key липсва, е неправилно оформена или принадлежи на отменен ключ.
Провери името на заглавката и ключа в таблото си. Не опитвай отново, докато не е поправено.
422 — q липсва или е празно, по-дълго от 200 символа, limit е извън 1 до 100, offset е извън 0 до 10000, или lang не е един от en, fr, es, de, it, bg.
Прочети масива details в тялото Validation Error, за да видиш кой параметър е сбъркан, и поправи заявката от страна на клиента. Никога не повтаряй 422 непроменена.
429 — Burst-ът за секунда на ключа е изчерпан или дневната квота на акаунта е изразходвана.
Изчакай броя секунди от Retry-After и опитай веднъж. При автодовършване пропускай остарялото натискане, вместо да го слагаш на опашка.
В сравнение с други API
Универсалната търсачка или каталогът на онлайн магазин индексира текст; търсенето на FoodBase индексира хранителни продукти, така че всяко съвпадение идва с прикачени баркод, път на категорията, Nutri-Score и NOVA група и с id, което се разрешава до таблица с хранителни вещества с още една заявка. Компромисът е обхватът: търси се по имена на продукти и марки, като имената на категориите са само резерва, а не по всяко поле на записа, а lang, различен от английски, търси в локализирани имена, където ги има, и в имена от етикетите другаде, вместо да превежда заявката ти. Няма клиентска библиотека за инсталиране и няма индекс, който да изграждаш, само една GET заявка и един JSON обект. Ако сравняваш доставчици на хранителни данни, /compare/food-database-apis показва какво покрива всеки.
Често задавани въпроси
Защо total се връща точно 1000? +
Броят е ограничен. Броенето спира при 1000 съвпадения, така че 1000 означава поне толкова. Показвай го като „1000+“ и странирай по offset, докато data върне по-малко от limit реда, вместо да делиш total на limit.
Какво връща API, когато нищо не съвпада? +
200 с празен масив data, не 404. Третирай празния масив като състоянието ти „няма резултати“. Тъй като всяка дума в q трябва да съвпадне, махането на най-неспецифичната дума или на такава с вероятен правопис е обичайното решение, преди да го покажеш.
Мога ли да търся само по марка или само по категория? +
По марка — да: марката е част от това, с което се сравнява всяка дума в q, така че q=Hacendado изброява продуктите на тази марка, а добавянето на дума за продукт стеснява списъка. Имената на категориите се опитват само когато търсенето по име и марка не върне нищо, така че q=Fruits tropicaux връща продуктите, подредени в тази категория, по популярност, а не по релевантност.
Включва ли резултатът от търсенето хранителни вещества? +
Не. Редовете от търсенето са по-лекият вид FoodListItem без полета за хранителни вещества. Подай id на реда към API за хранителни стойности при избор, а не за всяко предложение, защото планът Free позволява 25 разбивки на хранителни вещества на ден.
Кой lang да подава българско приложение? +
lang=bg търси в български локализирани имена и връща name_localized на български, където има превод. Етикети, въведени на кирилица като име по подразбиране, се намират с lang=en, защото en търси в името по подразбиране независимо от писмеността. Заявявай първо bg и преминавай към en при празен резултат.
Подреждането същото ли е като на уебсайта на FoodBase? +
Да. Product explorer на /products и страниците на категориите в /categories/ работят със същата крайна точка, така че можеш да изпробваш заявка там и да очакваш същия ред в приложението си за същите q и lang. Търсенето не ползва AI кредити; всяко извикване е една заявка от дневната квота.
Разгледай още endpoint-и
API за търсене по баркод
Сканирай или въведи баркод и получи продукта. Разреши всеки EAN-13 или UPC код до запис за храна — марка, категория, Nutri-Score и обобщение на хранителните стойности — с една заявка. Създадено за приложения със скенер.
Научи повече →API за база данни с храни
Единен източник за 6,1 милиона храни. Вземи пълен запис за продукт по ID — име, марка, съставки, алергени, Nutri-Score, NOVA група, изображения и още.
Научи повече →API за хранителни стойности
Отиди отвъд основните макроси. Вземи подробна разбивка на над 40 хранителни вещества на продукт — енергия, протеини, въглехидрати, мазнини, захари, фибри, натрий, витамини и минерали — всичко на 100 g, за всяка храна по ID.
Научи повече →Започни да създаваш с API за търсене на храни
Безплатно за начало. Без кредитна карта.
Вземи API ключ Към таблото