# Workflow: Add an item to an order — the ordered-product creation modes

- **Audience:** API integrator / LLM agent
- **Base URL:** https://api.shirtplatform.com/webservices/rest
- **Auth:** HTTP Basic on `/auth`, then `x-auth-token` header on every request
  (see [workflow-authenticate.md](workflow-authenticate.md))
- **Preconditions:**
  - You are authenticated; `{accountId}` and `{shopId}` are known and belong to the authenticated user.
  - For every mode **except passthrough**, an editable `{orderId}` already exists — create one via
    [workflow-manage-orders.md § Create an order](workflow-manage-orders.md#22-create-an-order). The
    order must still be editable (not locked in production); items cannot be added to an order that has
    entered fulfilment.
  - The catalog entities the item references already exist and you know their ids (a base `productId`,
    a `designedTemplateProductId`, or the design's `productId` / `assignedColor.id` / `motive.id`).
    Adding an item does **not** create those — you supply their ids.
- **Outcome:** One more item ([OrderedProduct](data-types/OrderedProduct.html)) exists on the order, or
  — for passthrough — a new deferred order carrying the passthrough item(s) has been submitted.

An order's items are **ordered products**. There are two overall ways to get them onto an order, and
they answer different questions:

- **Submit the whole order in one call — the preferred, unified path.** The **deferred order-create**
  (`POST orders/usingCreatorSE`, body [CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html))
  carries the customer, shipping, **and any mix of item types** — designed products, template products,
  **and** passthrough warehouse items — in a single atomic request. This is the recommended way to place
  an order; it is documented in
  [workflow-manage-orders.md § Preferred — CreatorSE deferred create](workflow-manage-orders.md#221-preferred--creatorse-deferred-create).
  Passthrough items can **only** be submitted this way — they have no per-item endpoint. After the
  order-preparing pipeline has processed the submission the order is **automatically committed and sent
  to production** — you do **not** call `commitOrder` or `sendToProduction`.
- **Add items incrementally to an existing order — the alternative.** When you already have an editable
  `{orderId}` and want to append one item at a time, use the per-item `POST`s on the OrderedProduct
  resource ([resource_OrderedProduct.html](resource_OrderedProduct.html)). Each ends in the same
  [OrderedProduct](data-types/OrderedProduct.html) on the order. This path is **not** auto-finalized:
  after adding every item you must finalize the order yourself with two `PUT`s —
  [commitOrder](workflow-manage-orders.md#24-commit-an-order) then
  [sendToProduction](workflow-manage-orders.md#25-send-an-order-to-production). This guide is the
  **decision guide** across those per-item modes (A–C below), plus the passthrough case (Mode D) that
  folds back into the deferred order.

## Which mode do I use?

Prefer the **deferred order** whenever you are placing a fresh order — one call submits every item type
together (see [workflow-manage-orders.md](workflow-manage-orders.md#221-preferred--creatorse-deferred-create)).
Reach for the per-item modes only to add items **incrementally to an order that already exists**.

| I want to… | Approach | Call | Request body |
|---|---|---|---|
| submit a **complete order** (any mix of designed / template / passthrough items) in one call | **Deferred order — preferred** | `POST orders/usingCreatorSE` | [CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html) |
| add a plain catalog product to an existing order | [A — base product](#mode-a--add-a-base-catalog-product) | `POST .../orderedProducts/usingBaseProduct/{productId}` | none (query params) |
| add a ready-made **template** (designer-prepared) product to an existing order | [B — template product](#mode-b--add-a-designed-template-product) | `POST .../orderedProducts/usingTemplateProduct/{designedTemplateProductId}` | none (query params) |
| add a **custom design** you assemble yourself to an existing order | [C — custom CreatorSE design](#mode-c--add-a-custom-creatorse-design) | `POST .../orderedProducts/usingCreatorSE` | [CreatorSE.Design](data-types/CreatorSE.Design.html) |
| add a **passthrough** warehouse item (skips production) | [D — passthrough item](#mode-d--add-a-passthrough-item-via-a-deferred-order) | *(no per-item call)* `POST orders/usingCreatorSE` deferred | [CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html) |

> **The generic `POST .../orderedProducts` is not part of the public API.** A raw ordered-product
> `POST` (body = `DesignedOrderedProductPrime`) exists in the code but is hidden from the reference
> (`@Ignore`d) — do **not** script it. Build items through the deferred order or one of the per-item
> modes above. See [Not reachable over the public API](#not-reachable-over-the-public-api).

> **The per-item modes A, B, and C all require an existing, editable `{orderId}`.** They append exactly
> one item to an order you already created — the incremental alternative to submitting everything at once.
> If you are building a fresh order and want designs, templates, **and** passthrough items in a single
> request, use the **deferred order** instead (see
> [workflow-manage-orders.md § Preferred — CreatorSE deferred create](workflow-manage-orders.md#221-preferred--creatorse-deferred-create)).
> Mode D below is that same deferred order, described from the passthrough angle: passthrough items have
> no per-item endpoint, so they are only ever carried inside the deferred order payload.

> **Status-code conventions on the per-item modes (A/B/C), stated once and impl-verified.**
> - **`200`** with the created [OrderedProduct](data-types/OrderedProduct.html) on success.
> - An unknown/foreign `{accountId}`, `{shopId}`, or `{orderId}` is **`401`** (ownership is validated in
>   the request filter before the handler runs) — not `404`. See
>   [Error handling](#error-handling-and-retries).
> - A `404` on A/B is the narrow "the order id is yours but the order is no longer live" case, **plus**
>   a genuinely unknown sub-entity (base product / template / template SKU) looked up by its own id.
> - Mode C rejects a bad design as **`500`, not `400`** (the design work is delegated to an internal
>   engine) — see [workflow-create-design.md](workflow-create-design.md).
>
> Reference: [rest-resources-orders.md](../reference/rest-resources-orders.md),
> [rest-resources-products.md](../reference/rest-resources-products.md),
> [rest-resources-designs.md](../reference/rest-resources-designs.md).

---

## Mode A — Add a base (catalog) product

Add an existing catalog product to the order as-is, with no design/decoration. This is the simplest
item: you name the `productId` and, optionally, which color/size variant and how many.

- **Request:** `POST /accounts/{accountId}/shops/{shopId}/orders/{orderId}/orderedProducts/usingBaseProduct/{productId}`
  ([reference](resource_OrderedProduct.html#resource_OrderedProduct-post-accounts-accountId-shops-shopId-orders-orderId-orderedProducts-usingBaseProduct-productId))
- **Body:** none.
- **Query params:**
  - `assignedColorId` — the `ProductAssignedColor` id to put on the item; `0` (default) picks the
    product's default color.
  - `assignedSizeId` — the `ProductAssignedSize` id; `0` (default) picks the default size.
  - `amount` — quantity; defaults to `1`.
- **Response 200:** [OrderedProduct](data-types/OrderedProduct.html) (Jettison root `orderedProduct`).
  Extract `orderedProduct.id` → the ordered-product id you use to read or remove the item later.
- **Errors:**
  - `404` — the base `productId` does not exist in this shop, a color/size variant you named does not
    belong to the product, **or** the `{orderId}` is yours but the order is no longer a live, editable
    order (e.g. it was deleted). An unknown/foreign order is `401`, not `404` (see
    [Error handling](#error-handling-and-retries)). **Mode A returns no `400`** — the base-product
    handler resolves every id by lookup, so a bad `productId` or color/size variant is a `404`, never a
    validation `400`. (Mode B *can* return `400`; see below.)
- **Idempotency:** NOT idempotent — each call adds another item to the order. On a timeout, read the
  order back ([workflow-manage-orders.md § Get a single order](workflow-manage-orders.md#12-get-a-single-order))
  before retrying.

## Mode B — Add a designed template product

Add a **template product** — a designer-prepared design already saved in the shop's template
collection — to the order. As with Mode A there is no request body; you name the
`designedTemplateProductId` and optionally the variant and quantity.

- **Request:** `POST /accounts/{accountId}/shops/{shopId}/orders/{orderId}/orderedProducts/usingTemplateProduct/{designedTemplateProductId}`
  ([reference](resource_OrderedProduct.html#resource_OrderedProduct-post-accounts-accountId-shops-shopId-orders-orderId-orderedProducts-usingTemplateProduct-designedTemplateProductId))
- **Body:** none.
- **Query params:**
  - `assignedColorId` / `assignedSizeId` — the color/size variant to assign; `0` (default) uses the
    template's default. **Ignored when `designedTemplateProductSku` is set** — the SKU determines the
    color and size.
  - `designedTemplateProductSku` — optional SKU of the template product; when given, the item's color
    and size are taken from the SKU (and the two `assignedColorId`/`assignedSizeId` params are
    overridden). Default: empty string (use the explicit variant params instead).
  - `amount` — quantity; defaults to `1`.
- **Response 200:** [OrderedProduct](data-types/OrderedProduct.html) (Jettison root `orderedProduct`).
  Extract `orderedProduct.id`.
- **Errors:**
  - `400` — validation failed.
  - `404` — the `designedTemplateProductId` does not exist, the template belongs to a **different
    shop**, the given `designedTemplateProductSku` was not found on that template, **or** the
    `{orderId}` is yours but no longer live. An unknown/foreign order is `401`.
- **Idempotency:** NOT idempotent — each call adds another item.

## Mode C — Add a custom CreatorSE design

Add a design you assemble yourself (a base product plus compositions of motives/artwork). The item's
content is the [CreatorSE.Design](data-types/CreatorSE.Design.html) you send as the request body.

- **Request:** `POST /accounts/{accountId}/shops/{shopId}/orders/{orderId}/orderedProducts/usingCreatorSE`
  ([reference](resource_OrderedProduct.html#resource_OrderedProduct-post-accounts-accountId-shops-shopId-orders-orderId-orderedProducts-usingCreatorSE))
- **Body:** [CreatorSE.Design](data-types/CreatorSE.Design.html).
- **Response 200:** [OrderedProduct](data-types/OrderedProduct.html); extract `orderedProduct.id`.
- **Errors:** `404` when the `{orderId}` is yours but no longer live (unknown/foreign order → `401`);
  a bad/undecodable design → **`500`, not `400`**.

Building the design payload, previewing it before ordering, and this exact add-to-order step are fully
documented in **[workflow-create-design.md](workflow-create-design.md)** — that guide is the
design-centric companion to this one and is **not** repeated here. Use Mode C when the customer
personalises a product in your own UI; use Mode B when they pick a ready-made template.

## Mode D — Add a passthrough item (via a deferred order)

A **passthrough item** is a simple warehouse product that goes through production untouched — no
printing, no decoration, no sewing: it is picked from the warehouse and dropped into the package. Its
whole definition ([CreatorSE.PassthroughItem](data-types/CreatorSE.PassthroughItem.html)) lives in the
order JSON, not in the product catalog.

**Passthrough is not a per-item endpoint.** There is no `POST .../orderedProducts/…` for it. Instead,
passthrough items are carried as a `passthroughItems` array inside the **deferred order-create**
payload ([CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html)), submitted to the Order
resource. One deferred order can mix `designs`, `templates`, **and** `passthroughItems` (max 100
passthrough items per order).

- **Request:** `POST /accounts/{accountId}/shops/{shopId}/orders/usingCreatorSE`
  ([reference](resource_Order.html#resource_Order-post-accounts-accountId-shops-shopId-orders-usingCreatorSE))
- **Body:** [CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html) with a `passthroughItems`
  wrapper. A minimal single-passthrough-item order (Jettison JSON — copy the authoritative field shape
  from the [CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html) and
  [CreatorSE.PassthroughItem](data-types/CreatorSE.PassthroughItem.html) reference pages rather than
  hand-writing it):

    ```json
    {
      "creatorse_productionOrderDeferred" : {
        "uniqueId" : "ext-order-777",
        "country" : { "id" : 12345, "code" : "UK" },
        "passthroughItems" : {
          "creatorse_passthroughItem" : {
            "sku" : "SUP-MUG-78432",
            "name" : "Ceramic mug 330 ml",
            "quantity" : 2,
            "brand" : "MugWorld",
            "color" : "white",
            "referenceId" : "PO-2026-001"
          }
        }
      }
    }
    ```

  - Required passthrough fields: `sku`, `name`, `quantity` (≥ 1). Optional: `brand`, `color`, `size`,
    `description`, `referenceId`, `metadata` (a free-form JSON string, max 10 KB), and `previewImage`
    (Base64-encoded product photo, max ~500 KB encoded).
  - Passthrough items are **never** supplier/stock-validated, even when the order sets
    `validateSuppliers = true` (that flag only checks design and template items).
- **Response 200:** [CreatorSE.OrderSubmited](data-types/CreatorSE.OrderSubmited.html) — carries the
  generated order `id`. The payload has been accepted and queued; fulfilment is processed
  asynchronously.
- **Errors:** `400` validation failed — e.g. missing `country` or customer address.
- **Idempotency:** NOT idempotent — each call creates a **new** order. On a timeout, look the order up
  by your `uniqueId` (`GET .../orders/by-uniqueid/{uniqueId}`, see
  [workflow-manage-orders.md § Get a single order](workflow-manage-orders.md#12-get-a-single-order))
  before retrying.

The deferred-create endpoint, its full envelope (customer, shipping, financial status), and the
lifecycle after submission are documented in
**[workflow-manage-orders.md § Preferred — CreatorSE deferred create](workflow-manage-orders.md#221-preferred--creatorse-deferred-create)**
— this section only adds the passthrough-specific detail.

---

## After the item is added

Modes A, B, and C leave the order in place with one more item; when you have added everything,
[commit the order](workflow-manage-orders.md#24-commit-an-order) and
[send it to production](workflow-manage-orders.md#25-send-an-order-to-production) — both are manual for
the incremental path. Mode D already submitted a complete order for asynchronous processing; the
pipeline commits it and sends it to production automatically, so there is nothing further to do.

To remove an item you added by mistake, delete it:
`DELETE .../orders/{orderId}/orderedProducts/{orderedProductId}`
([reference](resource_OrderedProduct.html#resource_OrderedProduct-delete-accounts-accountId-shops-shopId-orders-orderId-orderedProducts-orderedProductId))
→ `204`. This is a **soft delete**: the item stops appearing in the order's item list
(`GET .../orderedProducts`), which is the source of truth for what the order contains. Deleting an
already-removed item still returns `204` (idempotent); a genuinely unknown item id is `404`. Confirm
removal by re-listing the items, not by reading the item back by its id.

## Error handling and retries

- **`401` vs `404` (Modes A/B/C).** An unknown or foreign `{accountId}`, `{shopId}`, or `{orderId}` is
  rejected as `401` in the request filter **before** the handler runs (`@SecuredOrder` validates the
  order against your account/shop) — treat it as "not yours / does not exist for you". A `404` is the
  narrower case: the order id is yours but the order is no longer a live, editable order (e.g. deleted),
  **or** a sub-entity you named by its own id — the base `productId`, the `designedTemplateProductId`,
  or the `designedTemplateProductSku` — genuinely does not exist. Do not retry a `404` blindly; correct
  the id or re-read the order.
- **`500`, not `400`, for a bad design (Mode C).** The design work is delegated to an internal engine
  and a decode/validation failure there surfaces as a server error, not a client `400`. The design
  payload itself needs correcting before retrying — see
  [workflow-create-design.md § Error handling](workflow-create-design.md#error-handling-and-retries).
- **`400` for a bad envelope (Mode D).** The deferred create validates the order envelope up front and
  returns a real `400` for a missing `country`/address — distinct from the Mode C `500`.
- **None of these modes are idempotent.** A/B/C each add another item on every call; D creates another
  order on every call. On a timeout, verify what landed (read the order back, or look it up by
  `uniqueId` for D) before retrying — do not blind-retry.

## Not reachable over the public API

- **Generic `POST .../orderedProducts`** (raw ordered-product create, body `DesignedOrderedProductPrime`)
  — present in the code but `@Ignore`d, so it is absent from the reference. Use Modes A–D instead.
- **`PUT .../orderedProducts/{orderedProductId}`** (edit an item) and the per-item price re-evaluation
  (`.../evaluate`) are `@Ignore`d internal operations. To change an item, delete it and add it again.
- **Editing the catalog entities an item references** — base products, template collections, motives,
  product areas — is done elsewhere (products in the back office /
  [workflow-manage-products.md](workflow-manage-products.md); motives via
  [workflow-manage-motives.md](workflow-manage-motives.md)); the modes here only *reference* their ids.

## Related data types

- [OrderedProduct](data-types/OrderedProduct.html) — the item created by Modes A/B/C (rendered from
  `DesignedOrderedProductPrime`; Jettison root `orderedProduct`).
- [CreatorSE.Design](data-types/CreatorSE.Design.html) — the request body of Mode C (see
  [workflow-create-design.md](workflow-create-design.md)).
- [CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html) — the deferred order-create
  envelope that carries passthrough items (Mode D).
- [CreatorSE.PassthroughItem](data-types/CreatorSE.PassthroughItem.html) — one passthrough warehouse
  item inside the deferred order (Mode D).
- [CreatorSE.OrderSubmited](data-types/CreatorSE.OrderSubmited.html) — the Mode D response carrying the
  new order `id`.
