Docs
Recipe, Ingredient, and Option Imports

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

  1. Prepare a newline-delimited JSONL file whose objects match one of the schemas below.
  2. POST /v2/imports/upload with multipart/form-data that includes the file plus the matching import_type (recipe, recipe_ingredients, or recipe_options).
  3. Store the job_id returned in the upload response.
  4. Periodically POST /v2/imports/check with the job_id until is_complete: true.
  5. 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 — use recipe, recipe_ingredients, or recipe_options. Each file targets exactly one type.
  • file — binary attachment of your .jsonl file.
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.jsonl

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

FieldTypeRequiredNotes
recipe_idstringYesStable ID from your system.
namestringYesShopper-facing recipe name.
descriptionstringYesShort description for listing and detail pages.
instructionsstringNoSteps for preparation. Omit or set to null to let AI generate instructions.
is_featuredbooleanYesControls spotlight placement.
servesintegerYesNumber of servings produced.
image_urlstringNoPublic 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.

FieldTypeRequiredNotes
recipe_idstringYesReferences an imported recipe.
ingredient_idstringYesStable ID for this ingredient in your system.
namestringYesDisplay name for the ingredient.
qtynumberYesQuantity used in the recipe.
unitstringYesUnit of measure (e.g., oz, ml, dash).
is_servewarebooleanNoDefaults to false. Mark true for glassware or tools.
is_garnishbooleanNoDefaults to false. Mark true for garnishes.
is_standardbooleanNoDefaults 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.

FieldTypeRequiredNotes
option_idstringYesStable ID for this option.
ingredient_idstringYesReferences an imported ingredient.
namestringYesShopper-facing option name.
broadtypestringNoBroad type name for category-based matching.
subtypestringNoSubtype name for category-based matching.
product_idstringNoDirect 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: reciperecipe_ingredientsrecipe_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.