> ## Documentation Index
> Fetch the complete documentation index at: https://docs.solya.app/llms.txt
> Use this file to discover all available pages before exploring further.

# Recipe — create a plan

> Create a restock plan and add an item, with response-envelope and error handling.

This is the canonical **write** flow: create a [restock plan](/en/inventory-plans/restock),
then add an item. The same shape applies to other plan types (rebalance, etc.) — only the
paths and fields differ.

<Warning>
  This creates real data in your organization. Use a token with the right write permission,
  and test against a non-production organization first if you can.
</Warning>

## 1. Create the plan

`POST /api/restock-plans` with `name` (and optionally `brandId`, `collectionId`,
`description`). It returns the new plan's `id` and `status` (`DRAFT`).

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST https://app.solya.app/api/restock-plans \
      -H "Authorization: Bearer solya_sa_xxx" \
      -H "Content-Type: application/json" \
      -d '{
        "name": "Adidas FW25 Restock Wave 1",
        "brandId": "brand-uuid-adidas",
        "collectionId": "coll-uuid-fw25",
        "description": "First restock order for Adidas FW25"
      }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests
    BASE, TOKEN = "https://app.solya.app", "solya_sa_xxx"
    headers = {"Authorization": f"Bearer {TOKEN}", "Content-Type": "application/json"}

    plan = requests.post(f"{BASE}/api/restock-plans", headers=headers, json={
        "name": "Adidas FW25 Restock Wave 1",
        "brandId": "brand-uuid-adidas",
        "collectionId": "coll-uuid-fw25",
    }).json()
    plan_id = plan["id"]   # e.g. "rop-uuid-001"; status == "DRAFT"
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const BASE = "https://app.solya.app", TOKEN = "solya_sa_xxx"
    const headers = { Authorization: `Bearer ${TOKEN}`, "Content-Type": "application/json" }

    const plan = await (await fetch(`${BASE}/api/restock-plans`, {
      method: "POST", headers,
      body: JSON.stringify({
        name: "Adidas FW25 Restock Wave 1",
        brandId: "brand-uuid-adidas",
        collectionId: "coll-uuid-fw25",
      }),
    })).json()
    const planId = plan.id // status: "DRAFT"
    ```
  </Tab>
</Tabs>

Response:

```json theme={null}
{ "id": "rop-uuid-001", "brandId": "brand-uuid-adidas", "collectionId": "coll-uuid-fw25", "status": "DRAFT" }
```

## 2. Add an item

`POST /api/restock-plans/{planId}/items` with `variantId`, `sizeId`, `shopId`, `quantity`.
It returns `{ "success": true, "itemId": "…" }`.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST https://app.solya.app/api/restock-plans/rop-uuid-001/items \
      -H "Authorization: Bearer solya_sa_xxx" \
      -H "Content-Type: application/json" \
      -d '{ "variantId": "var-uuid-adidas-stan", "sizeId": "sz-uuid-43", "shopId": "shop-uuid-paris-opera", "quantity": 12 }'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    res = requests.post(
        f"{BASE}/api/restock-plans/{plan_id}/items",
        headers=headers,
        json={"variantId": "var-uuid-adidas-stan", "sizeId": "sz-uuid-43",
              "shopId": "shop-uuid-paris-opera", "quantity": 12},
    ).json()

    if not res.get("success"):
        raise RuntimeError(f"add item failed: {res.get('errorCode')}")
    print("added item", res["itemId"])
    ```
  </Tab>

  <Tab title="JavaScript">
    ```javascript theme={null}
    const res = await (await fetch(`${BASE}/api/restock-plans/${planId}/items`, {
      method: "POST", headers,
      body: JSON.stringify({
        variantId: "var-uuid-adidas-stan", sizeId: "sz-uuid-43",
        shopId: "shop-uuid-paris-opera", quantity: 12,
      }),
    })).json()
    if (!res.success) throw new Error(`add item failed: ${res.errorCode}`)
    console.log("added item", res.itemId)
    ```
  </Tab>
</Tabs>

## Handle the response

Adding items runs through [business rules](/en/intelligence-layer/rules-and-rulesets), so
plan for these outcomes:

* **Success** — `{ "success": true, "itemId": "…" }`.
* **Blocked by a rule** — `success: false` with `errorCode: "BUSINESS_RULE_VIOLATION"`;
  read the message and adjust.
* **Validation** — `errorCode: "VARIANT_REQUIRED"`, `"QUANTITY_INVALID"`, etc. Fix the
  payload.
* **Auth** — `401 UNAUTHORIZED` (bad/expired token) or `403 FORBIDDEN` (missing permission).

See [Error codes](/en/developers/error-codes) for the full mapping.

<Note>
  Other plan types follow the same pattern — e.g. rebalance is `POST /api/rebalance-plans`
  then `POST /api/rebalance-plans/{id}/items`. Browse the exact fields per endpoint in the
  **API Reference** tab.
</Note>
