Documentation

Cookspert API reference

Authentication, endpoints, errors and limits for the Cookspert Food API. Everything on this page is live — no sign-up needed to read it.

Authentication

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.

Base URLhttps://api.cookspert.com
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"
}'

Rate limits & quotas

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.

PlanRate limitMonthly requestsAPI keys
Free1 / s · 60 / min5,0005
Starter10 / s · 120 / min60,0005
Growth30 / s · 600 / min250,00015
Scale90 / s · 1,200 / min750,00030

The free tier needs only an account; paid tiers are bought from your account's billing page and take effect immediately.

Credit costs

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.

EndpointCredits
POST /v1/parse1Any number of ingredient lines per call
POST /v1/food/ingredients/parse1With gram + nutrition estimates
GET /v1/food/ingredients/search1
GET /v1/food/ingredients/convert1
GET /v1/food/ingredients/{id}1
POST /v1/food/extract — cached2Page already extracted
POST /v1/food/extract — live fetch10Fetches 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

Errors are JSON objects with a stable error code. Validation failures use the standard 422 shape with per-field messages.

401 Unauthorized
{
  "error": "invalid_api_key"
}
402 Payment Required
{
  "error": "plan_limit_exceeded",
  "message": "Monthly API credit allowance reached.",
  "key": "api_credits",
  "limit": 60000,
  "plan": "starter"
}
429 Too Many Requests
{
  "error": "rate_limited",
  "message": "Too many requests — slow down."
}
422 Unprocessable Entity
{
  "message": "The url field is required.",
  "errors": {
    "url": [
      "The url field is required."
    ]
  }
}

Parse & Extract

POST /v1/parse

Parse recipe text

Parse free-form recipe text into structured ingredients and servings.

Parameters

ParameterTypeRequiredDescription
textstringYesThe recipe text to parse (ingredients and steps).
titlestringNoOptional recipe title — improves language detection and matching.
language_idintegerNoOptional parser language override. Omit it: the language is auto-detected from the text and reported back as detected_language.
output_languagestringNoDisplay language for ingredient_name and measure_name: en, bg or es. Defaults to en.

Request

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"
}'

Response

{
  "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"
}
POST /v1/food/extract

Extract recipe from URL

Fetch 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.

Parameters

ParameterTypeRequiredDescription
urlstringYesThe public recipe page to extract.
output_languagestringNoDisplay language for ingredient and category names in the returned recipe: en, bg or es. Defaults to en.

Request

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"
}'

Response

{
  "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"
    }
  }
}

Ingredients

POST /v1/food/ingredients/parse

Parse ingredients

Parse 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.

Parameters

ParameterTypeRequiredDescription
textstringNoIngredient lines as one newline-separated string. Provide either text or lines.
linesstring[]NoIngredient lines as an array of strings. Provide either text or lines.
titlestringNoOptional recipe title — improves language detection.
language_idintegerNoOptional parser language override; auto-detected from the text when omitted.
output_languagestringNoDisplay language for ingredient_name and measure_name: en, bg or es. Defaults to en.

Request

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"
  ]
}'

Response

{
  "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
      }
    }
  ]
}
GET /v1/food/ingredients/{id}

Get ingredient information

Dictionary data for one ingredient: names, nutrition per base amount, diets, allergens and convertible units.

Parameters

ParameterTypeRequiredDescription
idintegerYesThe ingredient id (path parameter).
output_languagestringNoDisplay language for all names (ingredient, type, nutrition, diets, allergens): en, bg or es. Defaults to en. `language` is accepted as an alias.

Request

curl "https://api.cookspert.com/v1/food/ingredients/512?output_language=en" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "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
    }
  ]
}
GET /v1/food/ingredients/convert

Convert amounts

Convert 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.

Parameters

ParameterTypeRequiredDescription
ingredient_idintegerYesThe dictionary ingredient the conversion applies to.
quantitynumberYesThe amount to convert. Must be greater than zero.
unitstring | integerNoSource unit as a measure key (gram, piece, tablespoon, …) or a numeric measure id. Omitted = the ingredient's default unit.
target_unitstring | integerNoTarget unit, same formats as unit. Defaults to gram.
output_languagestringNoDisplay language for the localized unit_name fields: en, bg or es. Defaults to en.

Request

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"

Response

{
  "ingredient_id": 512,
  "source": {
    "quantity": 2,
    "unit": "count",
    "unit_name": "pc"
  },
  "target": {
    "quantity": 240,
    "unit": "gram",
    "unit_name": "g"
  },
  "grams": 240
}