Recipe and Ingredient Imports

Demi imports are asynchronous operator workflows. Submit source files, keep the returned import run ID, and poll that run until it reaches a terminal or review state.

Importer authentication

Import endpoints use a Demi user access token with RecipeImporter or IngredientImporter permission. Public API keys such as pk_ are not used for imports. Use the Demi CLI after demi login.

Recommended CLI workflow

The CLI uploads local source files, builds the correct file descriptors, submits the import, and returns the import run used for status polling.

demi login

# Preview the source and importer assumptions first
demi ingredients import --source ./vendor-invoices --dry-run

# Start an ingredient import
demi ingredients import --source ./vendor-invoices --vendor "Vendor Name"

# Start a recipe import
demi recipes import --source ./recipes

# Poll the run ID returned by the start command
demi ingredients import-status <run-id>
demi recipes import-status <run-id>

HTTP endpoints

MethodEndpointPermissionPurpose
POST/api/v1/ingredients/importIngredientImporterStart an ingredient import
GET/api/v1/ingredients/import/{id}IngredientImporterRead an ingredient import run owned by the current user
POST/api/v1/recipes/importRecipeImporterStart a recipe import
GET/api/v1/recipes/import/{id}RecipeImporterRead a recipe import run owned by the current user

Authentication

Authorization: Bearer <demi-user-access-token>
Content-Type: application/json

Access is tenant-scoped and permission-checked. Import-run status is additionally restricted to runs created by the authenticated user.

Ingredient import request

{
  "files": [
    {
      "fullPath": "https://storage.example/signed-or-managed-object",
      "s3Link": "https://storage.example/signed-or-managed-object",
      "fileName": "invoice-july.pdf",
      "fileKey": "managed-object-key",
      "originalFileName": "invoice-july.pdf"
    }
  ],
  "vendor": "Vendor Name",
  "importMode": "import-and-update"
}

files is required. Prefer the CLI for local files because it creates managed upload descriptors automatically. Ingredient imports may use vendorId or vendor; an explicit numeric vendor ID takes precedence. Supported importMode values are import-and-update, import-only, and update-only.

Recipe import request

{
  "files": [
    {
      "fullPath": "https://storage.example/signed-or-managed-object",
      "s3Link": "https://storage.example/signed-or-managed-object",
      "fileName": "recipes.pdf",
      "fileKey": "managed-object-key",
      "originalFileName": "recipes.pdf"
    }
  ],
  "threshold": 0.8,
  "useStreaming": true
}

Asynchronous status and review

  1. Persist the import run ID returned by the start request.
  2. Poll the matching status endpoint with the same Demi user token.
  3. Do not treat queue acceptance as completion.
  4. If the run requires review, complete the review in Demi before relying on imported records.
  5. Verify created or matched records, vendor assignment, pack and price interpretation, and enrichment results.

Error handling

  • 401: missing, invalid, or expired Demi user token.
  • 403: missing importer permission, inaccessible tenant context, or an import run owned by another user.
  • 400/422: invalid source descriptors or importer options. Correct the request before retrying.
  • 404: the run does not exist in the current authorized context.
  • 5xx: transient server failure. Retry status reads with backoff; do not resubmit a start request blindly.
Safe polling: status reads are safe to repeat. Import start requests are not idempotent, so do not resubmit one merely because processing is still underway or the original response was interrupted.