Authentication, endpoints, errors and limits for the Cookspert Food API. Everything on this page is live — no sign-up needed to read it.
Every request must carry an API key as a bearer token. Create keys on the API keys page — the secret is shown exactly once, at creation.
https://api.cookspert.comcurl https://api.cookspert.com/v1/parse \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "200g plain flour\n2 large eggs"
}'Quotas are metered in credits and rate limits follow your plan, across all endpoints. Running out of credits answers 402 with error plan_limit_exceeded; exceeding a rate limit answers 429 with error rate_limited and a Retry-After header — that one is safe to retry, the first is not.
| Plan | Rate limit | Monthly requests | API keys |
|---|---|---|---|
| Free | 1 / s · 60 / min | 5,000 | 5 |
| Starter | 10 / s · 120 / min | 60,000 | 5 |
| Growth | 30 / s · 600 / min | 250,000 | 15 |
| Scale | 90 / s · 1,200 / min | 750,000 | 30 |
The free tier needs only an account; paid tiers are bought from your account's billing page and take effect immediately.
Quotas are metered in credits, not raw requests: a text parse costs 1 and a live page extraction costs 10, so a plan's allowance reflects the work it actually buys. Every response carries X-Cookspert-Credits-Cost and X-Cookspert-Credits-Remaining.
| Endpoint | Credits | |
|---|---|---|
POST /v1/parse | 1 | Any number of ingredient lines per call |
POST /v1/food/ingredients/parse | 1 | With gram + nutrition estimates |
GET /v1/food/ingredients/search | 1 | |
GET /v1/food/ingredients/convert | 1 | |
GET /v1/food/ingredients/{id} | 1 | |
POST /v1/food/extract — cached | 2 | Page already extracted |
POST /v1/food/extract — live fetch | 10 | Fetches and parses the page |
Extracting from social posts or JavaScript-rendered pages is billed separately at €0.03 per call and is available from the Growth plan up.
Errors are JSON objects with a stable error code. Validation failures use the standard 422 shape with per-field messages.
{
"error": "invalid_api_key"
}{
"error": "plan_limit_exceeded",
"message": "Monthly API credit allowance reached.",
"key": "api_credits",
"limit": 60000,
"plan": "starter"
}{
"error": "rate_limited",
"message": "Too many requests — slow down."
}{
"message": "The url field is required.",
"errors": {
"url": [
"The url field is required."
]
}
}/v1/parseParse free-form recipe text into structured ingredients and servings.
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | Yes | The recipe text to parse (ingredients and steps). |
title | string | No | Optional recipe title — improves language detection and matching. |
language_id | integer | No | Optional parser language override. Omit it: the language is auto-detected from the text and reported back as detected_language. |
output_language | string | No | Display language for ingredient_name and measure_name: en, bg or es. Defaults to en. |
curl https://api.cookspert.com/v1/parse \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"text": "200g plain flour\n2 large eggs\n100g butter\n250ml milk"
}'{
"ingredients": [
{
"title": "plain flour",
"ingredient_id": 741,
"ingredient_name": "flour",
"quantity": "200",
"quantity_value": 200,
"quantity_in_grams": 200,
"measure": "gram",
"measure_id": 1,
"measure_name": "g",
"explanation": "",
"group_name": null
}
],
"servings": null,
"has_structured_ingredient_list": false,
"has_structured_preparation_text": false,
"language_id": 32,
"detected_language": {
"code": "en",
"source": "ngram"
},
"output_language": "en"
}/v1/food/extractFetch a public recipe page and return its structured recipe.
Extraction stores a shared, deduplicated recipe row on Cookspert's servers, so repeat calls for the same page are cache hits (cached: true). Nothing is added to any user's library.
| Parameter | Type | Required | Description |
|---|---|---|---|
url | string | Yes | The public recipe page to extract. |
output_language | string | No | Display language for ingredient and category names in the returned recipe: en, bg or es. Defaults to en. |
curl https://api.cookspert.com/v1/food/extract \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://www.bbcgoodfood.com/recipes/classic-pancakes"
}'{
"cached": false,
"output_language": "en",
"recipe": {
"id": 18234,
"title": "Classic pancakes",
"public_url": "https://www.bbcgoodfood.com/recipes/classic-pancakes",
"servings": 4,
"ingredients": [
"…"
],
"nutrition": "…",
"source": {
"name": "BBC Good Food"
}
}
}/v1/food/ingredients/parseParse ingredient lines into quantity, unit and matched dictionary ingredients, with gram, nutrition and price estimates where available.
Estimates depend on dictionary coverage: lines matching no dictionary ingredient — or ingredients without nutrition or conversion data — return null estimates.
| Parameter | Type | Required | Description |
|---|---|---|---|
text | string | No | Ingredient lines as one newline-separated string. Provide either text or lines. |
lines | string[] | No | Ingredient lines as an array of strings. Provide either text or lines. |
title | string | No | Optional recipe title — improves language detection. |
language_id | integer | No | Optional parser language override; auto-detected from the text when omitted. |
output_language | string | No | Display language for ingredient_name and measure_name: en, bg or es. Defaults to en. |
curl https://api.cookspert.com/v1/food/ingredients/parse \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"lines": [
"2 apples",
"200g plain flour"
]
}'{
"language_id": 32,
"detected_language": {
"code": "en",
"source": "script"
},
"output_language": "en",
"servings": null,
"ingredients": [
{
"title": "apples",
"ingredient_id": 512,
"ingredient_name": "apple",
"measure_name": null,
"quantity": "2",
"quantity_value": 2,
"quantity_in_grams": 300,
"measure": null,
"measure_id": null,
"explanation": "",
"group_name": null,
"price": 2.5,
"price_estimated": 0.75,
"nutrition": {
"calories": 156,
"carbs": 41.4,
"fats": 0.5,
"protein": 0.8
}
}
]
}/v1/food/ingredients/searchAutocomplete ingredient names against the Cookspert dictionary.
| Parameter | Type | Required | Description |
|---|---|---|---|
q | string | Yes | Search prefix, minimum 1 character. |
output_language | string | No | Name language: en, bg or es. Defaults to en. `language` is accepted as an alias. |
limit | integer | No | Maximum results, 1–20. Defaults to 10. |
curl "https://api.cookspert.com/v1/food/ingredients/search?q=toma&output_language=en&limit=5" \ -H "Authorization: Bearer YOUR_API_KEY"
{
"results": [
{
"id": 512,
"name": "tomato",
"icon": "tomato.svg"
},
{
"id": 1284,
"name": "tomato paste",
"icon": null
}
]
}/v1/food/ingredients/{id}Dictionary data for one ingredient: names, nutrition per base amount, diets, allergens and convertible units.
| Parameter | Type | Required | Description |
|---|---|---|---|
id | integer | Yes | The ingredient id (path parameter). |
output_language | string | No | Display language for all names (ingredient, type, nutrition, diets, allergens): en, bg or es. Defaults to en. `language` is accepted as an alias. |
curl "https://api.cookspert.com/v1/food/ingredients/512?output_language=en" \ -H "Authorization: Bearer YOUR_API_KEY"
{
"id": 512,
"name": "tomato",
"title": "Домат",
"type": {
"id": 3,
"name": "Vegetables"
},
"description": null,
"has_nutrition": true,
"nutrition": [
{
"component_id": 1008,
"name": "Calories",
"quantity": 18,
"unit": "kcal",
"per": {
"quantity": 100,
"unit": "gram"
}
}
],
"diets": [
{
"id": 2,
"name": "Vegan",
"compatible": true,
"condition": null
}
],
"allergens": [],
"possible_units": [
{
"measure_id": 10,
"unit": "count",
"grams_per_unit": 120
}
]
}/v1/food/ingredients/convertConvert an ingredient amount between units using the ingredient's own conversion data. Everything routes through grams.
Returns 422 no_conversion_path when the ingredient has no conversion data for the requested units.
| Parameter | Type | Required | Description |
|---|---|---|---|
ingredient_id | integer | Yes | The dictionary ingredient the conversion applies to. |
quantity | number | Yes | The amount to convert. Must be greater than zero. |
unit | string | integer | No | Source unit as a measure key (gram, piece, tablespoon, …) or a numeric measure id. Omitted = the ingredient's default unit. |
target_unit | string | integer | No | Target unit, same formats as unit. Defaults to gram. |
output_language | string | No | Display language for the localized unit_name fields: en, bg or es. Defaults to en. |
curl "https://api.cookspert.com/v1/food/ingredients/convert?ingredient_id=512&quantity=2&unit=count&target_unit=gram" \ -H "Authorization: Bearer YOUR_API_KEY"
{
"ingredient_id": 512,
"source": {
"quantity": 2,
"unit": "count",
"unit_name": "pc"
},
"target": {
"quantity": 240,
"unit": "gram",
"unit_name": "g"
},
"grams": 240
}