> For the complete documentation index, see [llms.txt](https://docs.claret.app/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.claret.app/api-guide/recipes.md).

# Common Recipes

Practical, copy-paste walkthroughs for the things integrators do most. Each assumes you have a token; see the [Quickstart](/api-guide/quickstart.md) if you don't.

{% hint style="info" %}
Replace `{tenant}` and `{token}` throughout. The base URL is `https://plan.claret.app/{tenant}/api/v1`.
{% endhint %}

## Recipe 1 — Sync inventory from an external system

Push current inventory levels into Claret. This is an asynchronous workflow: you submit the data, get a `job_id`, and poll for completion.

**Required scope:** Workflow Sync (`public_api.workflow`). Add Workflow Replace for `replace` mode.

### Step 1 — Submit the inventory

```bash
curl -X POST "https://plan.claret.app/{tenant}/api/v1/workflows/sync-inventory" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \
  -d '{
    "mode": "upsert",
    "data": [
      {
        "item_name": "Chardonnay Juice",
        "bin_name": "Tank-01",
        "lot_name": "LOT-2026-001",
        "date_filled": "2026-04-01",
        "quantity": 5000,
        "uom": "Liter"
      }
    ]
  }'
```

* `mode` is `upsert` (default) or `replace`. In `replace` mode you must also send a `scope` (`{"location": "...", "item": "..."}`) identifying what to replace, and the token needs the Workflow Replace scope.
* `data` accepts up to **100,000** rows per request.
* Every row needs `item_name`, `bin_name`, `lot_name`, `date_filled` (`YYYY-MM-DD`), `quantity`, and `uom`.
* The `Idempotency-Key` header (a UUID you generate) makes retries safe — reuse the same value when retrying a request.

The response is `202 Accepted` with a `job_id`.

{% hint style="info" %}
Validate before committing by adding `"dry_run": true`. A dry run checks the payload without writing anything and consumes no credits.
{% endhint %}

### Step 2 — Poll for completion

```bash
curl "https://plan.claret.app/{tenant}/api/v1/jobs/{job_id}" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
```

The status moves `pending → in_progress → completed` (or `failed`). Poll every 5 seconds for the first 30 seconds, then every 15 seconds.

{% hint style="info" %}
Prefer file-based ERP exports? Use the CSV variant `POST /workflows/sync-inventory/import` (`multipart/form-data`). See [Sync Inventory](/api-guide/migration/inventory.md).
{% endhint %}

## Recipe 2 — Pull sales data

Read sales records, filtered by date and type, paging through the full set. Sales use [cursor pagination](/api-guide/pagination.md#cursor-pagination-transactional-data).

**Required scope:** Read (`public_api.read`).

### Step 1 — First page

```bash
curl "https://plan.claret.app/{tenant}/api/v1/sales-data?\
filter[sale_type_name]=Forecast&\
filter[sell_date_from]=2026-01-01&\
include=saleType,itemCustomerGroup,uom&\
sort=sell_date&\
per_page=1000" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
```

### Step 2 — Follow the cursor

Read `meta.pagination.next_cursor` from the response and pass it back as `cursor`:

```bash
curl "https://plan.claret.app/{tenant}/api/v1/sales-data?per_page=1000&cursor={next_cursor}" \
  -H "Authorization: Bearer {token}" \
  -H "Accept: application/json"
```

Repeat until `meta.pagination.has_more` is `false`. The same pattern works for `GET /inventory`, `GET /supply-plans`, and `GET /financial-plans`.

## Recipe 3 — Generate a supply plan

Trigger supply plan computation. There are two modes.

**Required scope:** Compute (`public_api.compute`).

### Option A — Single item-location (synchronous)

Returns the computed plan in the response (up to a 30-second timeout):

```bash
curl -X POST "https://plan.claret.app/{tenant}/api/v1/supply-plans/generate" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "internal",
    "item_name": "Chardonnay Juice",
    "location_name": "Napa Winery",
    "view_name": "Default Supply View"
  }'
```

Identify the target by either `item_location_id`, or `item_name` + `location_name`. Identify the view by `view_id` or `view_name`.

### Option B — Whole location (batched, asynchronous)

Queues generation for every item-location at a location and returns a `job_id`:

```bash
curl -X POST "https://plan.claret.app/{tenant}/api/v1/supply-plans/generate-batch" \
  -H "Authorization: Bearer {token}" \
  -H "Content-Type: application/json" \
  -d '{
    "mode": "internal",
    "location_name": "Napa Winery",
    "view_name": "Default Supply View"
  }'
```

Poll `GET /jobs/{job_id}` (Recipe 1, Step 2) until it completes, then read the results with `GET /supply-plans` (Recipe 2's pattern).

{% hint style="warning" %}
Compute and workflow endpoints share a tighter [rate limit](/api-guide/rate-limiting.md) (a burst of 3, about 10 per minute) and cost more [credits](/api-guide/credits-and-usage.md). Generate in batches rather than one item at a time where possible.
{% endhint %}

## Related documentation

* [Authentication & Tokens](/api-guide/authentication.md) and [Scopes Reference](/api-guide/scopes.md)
* [Pagination](/api-guide/pagination.md) and [Filtering & Sorting](/api-guide/filtering-and-sorting.md)
* The **API Reference** — full per-endpoint reference
