Recipe, Ingredient, and Option Imports
Upload JSONL recipes, ingredients, and ingredient options using the imports API.
Use Retrend imports to load recipes and their ingredients before tying them to catalog products. This guide covers
preparing JSON Lines files for recipe, recipe_ingredients, and recipe_options imports and calling the two
endpoints you’ll use:
POST <https://api.retrend.ai/v2/imports/upload>uploads a JSONL file for one import type.POST <https://api.retrend.ai/v2/imports/check>polls the background job created during the upload.
These examples assume you already created a session token as described in API Dependencies and you
will authenticate each request with organization-id and x-session headers.
Import workflow
- Prepare a newline-delimited JSONL file whose objects match one of the schemas below.
POST /v2/imports/uploadwithmultipart/form-datathat includes the file plus the matchingimport_type(recipe,recipe_ingredients, orrecipe_options).- Store the
job_idreturned in the upload response. - Periodically
POST /v2/imports/checkwith thejob_iduntilis_complete: true. - Review validation errors in the dashboard (the API responds synchronously only for structural problems).
Upload request format
The upload endpoint accepts multipart/form-data with two fields:
import_type— userecipe,recipe_ingredients, orrecipe_options. Each file targets exactly one type.file— binary attachment of your.jsonlfile.
curl -X POST "https://api.retrend.ai/v2/imports/upload" \
-H "organization-id: $RETREND_ORG_ID" \
-H "x-session: $RETREND_SESSION" \
-F import_type=recipe \
-F file=@recipes.jsonlThe response includes success (boolean) and job_id (UUID). success reflects whether the upload was accepted; data
validation happens asynchronously based on the job_id.
Preparing JSONL payloads
Each JSON object in your file represents one record. Use UTF-8 encoding, avoid trailing commas, and ensure optional
fields are either omitted or set to null.
Recipe schema
Recipes define the core cocktail or menu item rendered to shoppers.
| Field | Type | Required | Notes |
|---|---|---|---|
recipe_id | string | Yes | Stable ID from your system. |
name | string | Yes | Shopper-facing recipe name. |
description | string | Yes | Short description for listing and detail pages. |
instructions | string | No | Steps for preparation. Omit or set to null to let AI generate instructions. |
is_featured | boolean | Yes | Controls spotlight placement. |
serves | integer | Yes | Number of servings produced. |
image_url | string | No | Public image URL for the recipe. |
Example recipe lines:
{"recipe_id":"SPRITZ-01","name":"Citrus Spritz","description":"Bright, low-ABV spritz with orange bitters.","instructions":null,"is_featured":true,"serves":1,"image_url":"https://cdn.example.com/recipes/spritz.webp"}
{"recipe_id":"OLD-FASHIONED","name":"Smoked Old Fashioned","description":"Classic whiskey cocktail with a smoked finish.","instructions":"Stir all ingredients with ice. Strain over a large cube. Express orange peel and serve.","is_featured":false,"serves":1}Recipe ingredient schema
Ingredients attach quantities and flags to a recipe.
| Field | Type | Required | Notes |
|---|---|---|---|
recipe_id | string | Yes | References an imported recipe. |
ingredient_id | string | Yes | Stable ID for this ingredient in your system. |
name | string | Yes | Display name for the ingredient. |
qty | number | Yes | Quantity used in the recipe. |
unit | string | Yes | Unit of measure (e.g., oz, ml, dash). |
is_serveware | boolean | No | Defaults to false. Mark true for glassware or tools. |
is_garnish | boolean | No | Defaults to false. Mark true for garnishes. |
is_standard | boolean | No | Defaults to false. Mark true for standard ingredients. |
Example ingredient lines:
{"recipe_id":"SPRITZ-01","ingredient_id":"APEROL","name":"Aperol","qty":2,"unit":"oz","is_standard":true}
{"recipe_id":"SPRITZ-01","ingredient_id":"SODA","name":"Soda Water","qty":3,"unit":"oz","is_standard":true}
{"recipe_id":"OLD-FASHIONED","ingredient_id":"BITTERS-ORANGE","name":"Orange Bitters","qty":2,"unit":"dash","is_garnish":false}Recipe ingredient option schema
Options map a recipe ingredient to acceptable product variants or categories.
| Field | Type | Required | Notes |
|---|---|---|---|
option_id | string | Yes | Stable ID for this option. |
ingredient_id | string | Yes | References an imported ingredient. |
name | string | Yes | Shopper-facing option name. |
broadtype | string | No | Broad type name for category-based matching. |
subtype | string | No | Subtype name for category-based matching. |
product_id | string | No | Direct product ID for exact matching. |
Example option lines:
{"option_id":"APEROL-OPTS","ingredient_id":"APEROL","name":"Aperitivo Option","broadtype":"Spirits","subtype":"Bitters","product_id":"BITTERS-001"}
{"option_id":"SODA-OPTS","ingredient_id":"SODA","name":"Club Soda","broadtype":"Non-Alcoholic","subtype":"Soda"}Checking import status
Once you have a job_id, poll /v2/imports/check until the response indicates completion:
curl -X POST "https://api.retrend.ai/v2/imports/check" \
-H "organization-id: $RETREND_ORG_ID" \
-H "x-session: $RETREND_SESSION" \
-H "Content-Type: application/json" \
-d "{\"job_id\": \"12345678-1234-1234-1234-123456789012\"}"The API responds with:
{
"is_complete": false
}Keep polling (with exponential backoff) until is_complete switches to true. After completion, review any row-level
issues inside the dashboard's import history to address validation failures.
Tips for smooth recipe imports
- Import order:
recipe→recipe_ingredients→recipe_options. Each step references IDs from the previous. - Keep IDs stable; product links in options depend on your product imports.
- Start with a few sample lines per file to validate formatting before sending large payloads.