Pepesto API Documentation

1. Overview

Pepesto’s API transforms meal planning and grocery shopping by seamlessly linking recipes and shopping lists to real supermarket products. Our industry-leading product-matching technology ensures users can instantly add the right ingredients to their cart and check out with ease.

Who Can Benefit?

Why Partner with Pepesto?

2. Setup & Authentication

Request an API key by contacting us. We'd love to speak with you, understand your needs and equip you with all the information to get started including API key.

Pass the API key in the Authorization header:

curl -X POST https://s.pepesto.com/api/$endpoint \
-H "Authorization: Bearer $PEPESTO_API_KEY" \
-H 'Content-Type: application/json' \
-d '$requestJson'

3. High level overview

Have a look at the API flow below to get a high level overview on how our API works.

API Diagram

4. /parse endpoint

Parses a recipe from a URL or free text. The returned recipe can be used as input to the /products endpoint. Using a URL might be slower compare to sending the free text, since we need to retrieve the recipe from the URL.

Have a look at the following code structure and the example below to better understand how to query the endpoint.

package api

type ParseRecipeRequest struct { // The URL of the recipe to parse. Exactly one of RecipeUrl or RecipeText must be provided. RecipeUrl string json:"recipe_url"

// The recipe text to parse. Exactly one of `RecipeUrl` or `RecipeText` must be provided.
RecipeText string `json:"recipe_text"`

// The locale in which to translate the parsed recipe (e.g., "de-DE"). Defaults to "en-GB" if empty.
Locale Locale `json:"locale"`
// If true, generates a 1024x1024 pixel image suitable for the parsed recipe.
GenerateImage bool `json:"generate_image"`

}

type Locale string

type ParseRecipeResponse struct { // The parsed recipe. Recipe RetrievedRecipe json:"recipe,omitempty" }

curl -X POST https://s.pepesto.com/api/parse \
-H "Authorization: Bearer $PEPESTO_API_KEY" \
-H 'Content-Type: application/json' \
-d '{ "recipe_url": "https://example.com/recipe", "locale": "en-GB", "generate_image": true }'

5. /products endpoint

Returns supermarket product suggestions from recipes (parsed or suggested) and/or a manually created shopping list. It returns a URL that 3rd-party apps and creators can use to earn referral fees by forwarding their users to Pepesto.

Have a look at the following code structure and the example below to better understand how to query the endpoint.

package api

type OfferProductsRequest struct { // Tokens for recipes retrieved by the /suggest or /parse endpoints. RecipeKgTokens []KgToken json:"recipe_kg_tokens"

// A free-text shopping list (e.g., "4 eggs, pasta, 2 chicken breasts"). Maximum length: 5000 characters.
ManualShoppingList string `json:"manual_shopping_list"`

// The supermarket in which to search for products.
// This is optional - if not specified we will automatically pick a supermarket, suitable for the user's location.
SupermarketDomain SupermarketDomain `json:"supermarket_domain"`

// User personalization settings. Used to offer products that align with user preferences (e.g., allergies, past purchases).
UserId UserId `json:"user_id"`

// The locale in which to display item names in the response (e.g., "de-DE").
ItemNamesLocale Locale `json:"item_names_locale"`

}

type OfferProductsReponse struct { // A list of items and their corresponding products. Items []ItemToProducts json:"items,omitempty"

// Currency code of the resolved supermarket.
Currency string `json:"currency,omitempty"`

// URL pointing to Pepesto's web UI (https://buy.pepesto.com/...). Redirecting the user to this URL allows them to adjust their order (e.g., select different products, change quantities).
//
// Crucially, this UI enables users to add products to their supermarket cart. This is a paid action, with users either paying Pepesto a commission or having a subscription.
//
// The returned `AdjustmentsUrl` includes an encoding of your API key.  This allows tracking referrals.
AdjustmentsUrl string `json:"adjustments_url,omitempty"`

}

// For a given item (e.g., “eggs”), a list of possible products that the user can buy. // The list is sorted, with the most appropriate product listed first. // Sorting criteria include user preferences and past purchases, minimizing food waste and costs, choosing higher quality/bio products, and product reviews. // An empty list indicates that no suitable products were found in the index for this item. Appropriate products may still be offered in Pepesto’s UI during checkout. type ItemToProducts struct { // Human-readable item name (e.g., “eggs”). ItemName string json:"item_name,omitempty"

// Concrete supermarket products offered to the user for this item.
Products []ProductAndSuggestedQuantity `json:"products,omitempty"`

}

// Specifies the quantity of a product to buy. // If NumUnitsToBuy is zero, Pepesto suggests treating the product as a checklist item. // In this case, Pepesto doesn’t suggest buying it by default but displays it in the UI as a reminder (useful for pantry staples like salt). type ProductAndSuggestedQuantity struct { // The product. Product IndexedProduct json:"product,omitempty"

// The number of units to buy.  A value of 0 indicates a checklist item.
NumUnitsToBuy int `json:"num_units_to_buy,omitempty"`

}

type IndexedProduct struct { // The product name, capturing the most important aspects. Displayed in the default language for the selected SupermarketDomain. ProductName string json:"product_name,omitempty"

// The quantity per unit of this product.
Quantity QuantityPerUnit `json:"quantity,omitempty"`

// The price per unit of this product.
Price PricePerUnit `json:"price,omitempty"`

// URL of the product page on the supermarket's website.
StoreUrl string `json:"store_url,omitempty"`

// URL of an image of the product.
ImageUrl string `json:"image_url,omitempty"`

// A unique identifier for products sold in multiple supermarket chains.  Allows comparing prices for the same product across different supermarkets.  Populated only for packaged products commonly sold in multiple chains.
UniversalId int64 `json:"universal_id,omitempty"`

Classification ProductClassification `json:"classification,omitempty"`

}

type ProductClassification struct { IsBio bool json:"is_bio,omitempty" IsFrozen bool json:"is_frozen,omitempty" IsSubstitution bool json:"is_substitution,omitempty" }

type QuantityPerUnit struct { // Estimated weight per unit (in grams). Grams float64 json:"grams,omitempty"

// Volume per unit (in milliliters). Used for liquid products (e.g., 100ml of milk).
Milliliters float64 `json:"milliliters,omitempty"`

// Number of pieces per unit (e.g., 2 for a package of 2 chicken breasts).
Pieces float64 `json:"pieces,omitempty"`

// Number of bunches per unit (e.g., 2 bunches of parsley).
Bunches float64 `json:"bunches,omitempty"`

}

type PricePerUnit struct { // Price of the product in the smallest currency unit used by the SupermarketDomain (e.g., 199 represents 1.99 CHF for coop.ch). Price int json:"price,omitempty"

// Price promotion details.
Promotion PricePromotion `json:"promotion,omitempty"`

}

type PricePromotion struct { // true if the product is currently on promotion. Promo bool json:"promo,omitempty"

// Price discount percentage (not always available).  May not be populated, or the promotion may be of a different type (e.g., "buy 2 get 3").
PromoPercentage float64 `json:"promo_percentage,omitempty"`

}

curl -X POST https://s.pepesto.com/api/products \
  -H "Authorization: Bearer $PEPESTO_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "recipe_kg_tokens": ["abc123"], "supermarket_domain": "coop.ch" }'

6. /catalog endpoint

Retrieves all indexed products for a supermarket. Useful for price comparison and business intelligence.

Have a look at the following code structure and the example below to better understand how to query the endpoint.

package api

type RetrieveCatalogRequest struct { // The supermarket for which to retrieve the catalog. SupermarketDomain SupermarketDomain json:"supermarket_domain"

// If true, product names in the response are translated to English. Otherwise, the language corresponding to the `SupermarketDomain` is used (e.g., German for shop.rewe.de).
ProductNamesInEnglish bool `json:"product_names_in_english"`

// If provided, registers (or overwrites) a webhook URL for the given supermarket domain and API key.
// The webhook will be called (using POST) each time the products for this supermarket are re-indexed.
// Note: Only one webhook URL can be registered per supermarket per API key.
WebhookUrl string `json:"webhook_url"`

}

type RetrieveCatalogResponse struct { // A list of indexed products. Products []IndexedProduct json:"products,omitempty" }

curl -X POST https://s.pepesto.com/api/catalog \
  -H "Authorization: Bearer $PEPESTO_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "supermarket_domain": "coop.ch" }'

7. /suggest endpoint

Retrieves recipes from Pepesto's world-leading and most comprehensive recipe database (containing over 1 million recipes) based on user-specified criteria. This is useful for meal planning, and the returned recipes can also be used as input to the /products endpoint.

Have a look at the following code structure and the example below to better understand how to query the endpoint.

package api

type SuggestRecipesRequest struct { // Query specifying the desired recipe type. // This field mimics the structure of typical Large Language Model (LLM) APIs (e.g., OpenAI’s chat completion API, Gemini API), // where the conversation context is represented as a series of messages exchanged between the end-user and the assistant (e.g., Pepesto). // Each RecipeQueryDialogTurn represents a turn in this conversation. // // The Content field within each RecipeQueryDialogTurn contains the actual query or request from the user (or Pepesto). // This can be free text (e.g., “I’m looking for a quick and easy dinner recipe”) or more structured (e.g., “Find me vegetarian recipes with less than 500 calories”). // Multiple turns can be used to refine the search or provide additional context (e.g., “Actually, I don’t like mushrooms”). // // Examples: // // * Free text search: {"content": "Find me a chocolate cake recipe", "role": "user"} // * Free text search: {"content": "5-day meal plan", "role": "user"} // * Multi-turn context: [{"content": "I want a pasta dish", Role: "user"}, {"content": "Sure, here are some ideas", "role": "assistant"}, {"content": "Something with pesto", "role": "user"}] // // Note: This field contributes to the cost of the request. See Pricing section for details. // Maximum length of all concatenated queries is 2000 characters. // +json:query QueryRecipe []RecipeQueryDialogTurn json:"query"

// Optional personalization settings to tailor recipe retrieval to the user's preferences.
// These preferences are stored for future use.
Personalization Personalization `json:"personalization"`

// The number of recipes to retrieve. This field is required and must be a positive integer.
// Note: A higher value increases the cost of the request. See Pricing section for details.
// Maximum allowed number is 50.
NumToFetch int `json:"num_to_fetch"`

// If true, only retrieves recipes categorized as main meals.
MainMealsOnly bool `json:"main_meals_only"`

// Generate fruit bowl recommendations (a "fake" recipe with a few fruit ingredients, and no cooking steps)
FruitBowl bool `json:"fruit_bowl"`

}

type SuggestRecipesResponse struct { // An array of retrieved recipes. Recipes []RetrievedRecipe json:"recipes,omitempty"

// Fruit bowl recommendation, only populated it |FruitBowl| in the request was set to true.
FruitBowl RetrievedRecipe `json:"fruit_bowl,omitempty"`

// A short, human-readable response to the user's query, localized to the user's language.
// For subsequent query turns, this response should be appended to the `Query` field of the next `SuggestRecipesRequest`.
ShortResponse string `json:"short_response,omitempty"`

}

type RecipeQueryDialogTurn struct { // The content of the query turn. This can be free text (e.g., “I’m looking for a quick and easy dinner recipe”) or more structured (e.g., “cuisine:Italian ingredients:tomato”). Content string json:"content,omitempty"

// The role of the participant issuing this query turn. Must be either "user" or "assistant" (Pepesto). This mirrors the structure of chat completion APIs in large language models like OpenAI's.
Role string `json:"role,omitempty"`

// Specifies whether the query represents a strict requirement or a preference.
//
// If `true`, all returned recipes *must* satisfy the query (e.g., "cuisine:Greek" - all recipes should be Greek).
// If `false`, the query is treated as a preference or suggestion (e.g., "I have chickpeas at home" - some recipes may contain chickpeas, but it's not a requirement).
Strict bool `json:"strict,omitempty"`

}

type Personalization struct { // The unique identifier of the user. This field is required. UserId UserId json:"user_id,omitempty"

// User's dietary preferences (e.g., "lactose-free," "keto diet," "diabetes").
// Note: This field contributes to the cost of the request. See Pricing section for details.
// Maximum length is 1000 characters.
Preference string `json:"preference,omitempty"`

// The locale in which recipes should be translated (e.g., "de-DE").  Defaults to "en-UK" if empty.
Locale Locale `json:"locale,omitempty"`

// The number of people the recipes should serve.  Recipes will be scaled accordingly. Defaults to 3.
Portions int `json:"portions,omitempty"`

// The user's preferred supermarket (e.g., "coop.ch").  Used to prioritize recipes with ingredients available at that supermarket or on promotion.
SupermarketDomain SupermarketDomain `json:"supermarket_domain,omitempty"`

// If true, clears all previously stored user preferences before applying the preferences specified in this request.
ClearAllPrefs bool `json:"clear_all_prefs,omitempty"`

}

// List of supported supermarket domains can be found at https://api.pepesto.com/supermarkets type SupermarketDomain string

type RetrievedRecipe struct { // The human-readable title, ingredients, and cooking steps for the recipe. // Typically in English but translated based on the Personalization.Locale setting. Title string json:"title,omitempty" Ingredients []string json:"ingredients,omitempty" Steps []string json:"steps,omitempty"

// URL of a 1024x1024px image of the recipe in WebP format.
ImageUrl string `json:"image_url,omitempty"`

// The nutritional information for the recipe.
Nutrition Nutrition `json:"nutrition,omitempty"`

// An opaque, encrypted token representing the semantic understanding of the recipe's ingredients.
// This token is required when calling the "products" endpoint.
KgToken KgToken `json:"kg_token,omitempty"`

}

type UserId string

type KgToken string

type Nutrition struct { // Number of calories in the recipe. Calories int json:"calories,omitempty" // Number of grams of carbohydrates in the recipe. CarbohydratesGrams int json:"carbohydrates_grams,omitempty" // Number of grams of protein in the recipe. ProteinGrams int json:"protein_grams,omitempty" // Number of grams of fat in the recipe. FatGrams int json:"fat_grams,omitempty" }

curl -X POST https://api.pepesto.com/suggest \
  -H "Authorization: Bearer $PEPESTO_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "query": [{ "content": "Find me a vegan pasta recipe", "role": "user" }], "num_to_fetch": 5 }'

8. Recipe Creators and Food Bloggers Widget

The Pepesto widget allows effortless integration with no API setup for any recipe website. Embed the following code below any recipe and you will quickly get a button that triggers the Pepesto import:

Embed Pepesto Widget
<div id="pepesto-widget-container"></div>
<script src="https://s.pepesto.com/get_recipe.js"></script>

👉 To try it out, open the following link on mobile and tap on the Pepesto button at the bottom.

Key Benefits:

Curious to learn more or have a demo?

Reach out to us today and let's explore how Pepesto's API could help you and your audience.

Try Pepesto Today!

© 2025 Pepesto. All rights reserved.

Made with ❤️ in Zurich, Switzerland.