# Workflow: Create a design — build a CreatorSE design, preview it, and order it

- **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.
  - The catalog entities the design references already exist and you know their ids: the base
    `productId`, the product's color assignment (`assignedColor.id`), size assignment
    (`assignedSize.id`), and any motive ids placed on the product. Creating a design does **not**
    create those — you supply their ids.
- **Outcome:** You have assembled a [CreatorSE.Design](data-types/CreatorSE.Design.html) payload,
  rendered a preview image of it over the **public** API, and placed it into an order as a
  custom-designed ordered product.

This document is the **design-centric** slice of the CreatorSE surface: how one design object is
built, previewed, and turned into an order item. The **order-centric** side — creating the order
header, the single-call deferred order (`POST orders/usingCreatorSE`), committing, and the
lifecycle — is [workflow-manage-orders.md](workflow-manage-orders.md); this guide links into it
rather than repeating it.

> **The design object is the single source of truth for both the preview and the order item.** The
> exact same [CreatorSE.Design](data-types/CreatorSE.Design.html) you assemble in
> [Step 1](#step-1--build-the-design-payload) is what you Base64-encode for the preview
> ([Step 2](#step-2--render-a-preview-of-the-design)) and what you POST as the request body to add
> the item to an order ([Step 3](#step-3--add-the-designed-product-to-an-order)). Build it once;
> reuse it.

> **Status-code conventions on these resources (stated once, impl-verified).**
> - **`designedProducts/preview` → `200`** with the rendered image bytes on success. A design that
>   cannot be decoded or rendered returns **`500`**, *not* `400` — the render is delegated to an
>   internal engine and any failure surfaces as a server error. There is no reachable `400` here.
> - **`orderedProducts/usingCreatorSE` → `200`** with the created ordered product. `404` when the
>   `{orderId}` does not resolve to an order you may edit (see the note in Step 3). Invalid design
>   data is rejected downstream as **`500`**, not `400`.
> - **An unknown/foreign `{accountId}`, `{shopId}` or `{orderId}` is `401`** (authorization) on the
>   secured endpoints — see [Error handling](#error-handling-and-retries).
>
> Reference: [rest-resources-designs.md](../reference/rest-resources-designs.md).

---

## Steps

### Step 1 — Build the design payload

A design is a [CreatorSE.Design](data-types/CreatorSE.Design.html) — a base product plus the chosen
color/size and one or more **compositions**, each targeting a product area (front, back, sleeve, …)
and holding the **elements** (motives, DDF artwork, decorations) placed on that area. The full field
list is on the [CreatorSE.Design](data-types/CreatorSE.Design.html) page and its nested types
([CreatorSE.Composition](data-types/CreatorSE.Composition.html),
[CreatorSE.ProductAssignedColor](data-types/CreatorSE.ProductAssignedColor.html)); the essential
skeleton is:

- `productId` — the base catalog product the design is built on.
- `assignedColor.id` / `assignedSize.id` — which color and size variant the customer picked
  (the `ProductAssignedColor` / `ProductAssignedSize` ids from the product configuration).
- `amount` — quantity for this item.
- `sku`, `customReferenceId`, `customLabel` — optional external identifiers you carry through.
- `compositions` — one per decorated product area; each holds `elements`.
- Each **element** references what is placed and, optionally, a
  [Position](data-types/CreatorSE.Position.html). If you omit the position, CreatorSE drops the
  first motive on the product area's hotspot; set an explicit position to override.

An `elements` array is **heterogeneous** — there are three concrete element types, and each entry
names its own type:

- [DesignElementMotive](data-types/CreatorSE.DesignElementMotive.html) — places a `motive`
  (artwork/image) by `id` from the library or inline via `url` / `attachment`. Its optional
  [layers](data-types/CreatorSE.DesignElementLayer.html) replace `text` or `rgbColor` on named SVG
  layers of the motive (dynamic text/colour).
- [DesignElementDdf](data-types/CreatorSE.DesignElementDdf.html) — a production-ready design file: a
  `previewResource` plus a `productionResource` (whose `filename` must include a file extension).
- [DesignElementDecoration](data-types/CreatorSE.DesignElementDecoration.html) — a decoration
  (sticker/label) named by its `sku` and optional `placement`.

The example below uses a single motive element; the other two types slot into the same `elements`
array the same way.

A minimal single-motive design (Jettison JSON — copy the authoritative field shape from the
[CreatorSE.Design](data-types/CreatorSE.Design.html) reference page rather than hand-writing it):

```json
{
  "creatorse_design" : {
    "productId" : 5001,
    "amount" : 1,
    "assignedColor" : { "id" : 34 },
    "assignedSize" : { "id" : 12 },
    "sku" : "TSHIRT-BLK-M",
    "compositions" : {
      "creatorse_composition" : {
        "productArea" : { "id" : 88 },
        "elements" : {
          "creatorse_element" : {
            "motive" : { "id" : 12345 },
            "position" : { "left" : 10, "right" : 10, "top" : 10, "bottom" : 10 }
          }
        }
      }
    }
  }
}
```

- **Positioning:** set both `left`+`right` to fix horizontal position and width, both `top`+`bottom`
  for vertical; the default unit is **millimeters**, append `%` for percent-of-area
  (`"left" : "10%"`), or use `"horizontalCenter" : 0` / `"verticalCenter" : 0` to center. See
  [CreatorSE.Position](data-types/CreatorSE.Position.html).
- **Idempotency:** this step is local — you are only assembling a payload, no API call yet.

### Step 2 — Render a preview of the design

Rasterize the design to an image without persisting anything. The design is passed **in the query
string, Base64-encoded**.

- **Request:** `GET /accounts/{accountId}/shops/{shopId}/designedProducts/preview`
  ([reference](resource_DesignedProduct.html#resource_DesignedProduct-get-accounts-accountId-shops-shopId-designedProducts-preview))
- **Query params:**
  - `design` — the serialized [CreatorSE.Design](data-types/CreatorSE.Design.html) from Step 1,
    **Base64-encoded**. This is the same design object you POST in Step 3, only encoded for
    transport in the URL.
  - `view` — product side to render, a `ViewPosition` name; defaults to `FRONT`.
  - `format` — `SVG`, `PNG`, or `JPEG`; defaults to `SVG`.
  - `width` / `height` — requested pixel dimensions; `0` (the default) lets the engine pick.
- **Response 200:** the raw image bytes (`@returnWrapped byte[]`), with the `Content-Type` set from
  `format` (`image/svg+xml`, `image/png`, or `image/jpeg`).
- **Errors:** a design that cannot be decoded or rendered comes back as **`500`** (the render is
  delegated to an internal engine; its failure is surfaced as a server error, *not* a `400`). Fix
  the design and retry.
- **Idempotency:** safe/idempotent (read) — replay freely; nothing is stored.

> **Note — preview is not access-controlled.** Unlike the order endpoints below, the preview endpoint
> carries no entity-ownership annotation and no role check: it renders only what you pass in the
> `design` parameter and reads no stored data, so `{accountId}`/`{shopId}` are not validated against
> your token. Send your `x-auth-token` for consistency with the rest of the API, but do not rely on
> this endpoint to authorize anything.

### Step 3 — Add the designed product to an order

Turn the design into a real order item on an existing order. You need an `{orderId}` — create one
first via [workflow-manage-orders.md § Create an order](workflow-manage-orders.md#22-create-an-order).

- **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) — the **same** design object from
  Step 1 (sent as the request body, *not* Base64-encoded this time).
- **Response 200:** [OrderedProduct](data-types/OrderedProduct.html) — the created item (Jettison
  root `orderedProduct`). Extract `orderedProduct.id` → the ordered-product id you use to read or
  remove the item later.
- **Errors:**
  - `404` — the `{orderId}` does not resolve to an editable order in this shop. An unknown or
    foreign order is rejected earlier as `401` (ownership is validated before the handler); the `404`
    is the narrow case where the order id belongs to you but the order is no longer live (e.g. it was
    deleted).
  - `500` — the design data was rejected by the composition engine (invalid or incomplete design).
    This is *not* a `400`; correct the design and resubmit.
- **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))
  to check whether the item landed before retrying.

After the item is in place, [commit the order](workflow-manage-orders.md#24-commit-an-order) and
send it to production — both covered in [workflow-manage-orders.md](workflow-manage-orders.md).

---

## Alternative — submit the whole order and its designs in one call

If you are building a fresh order rather than adding to an existing one, you do **not** have to
create the order and add items separately. The **deferred CreatorSE order** endpoint
(`POST /accounts/{accountId}/shops/{shopId}/orders/usingCreatorSE`) accepts a
[CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html) that carries the customer,
shipping, **and** the full list of designs in a single asynchronous request. Each design inside it is
a [CreatorSE.Design](data-types/CreatorSE.Design.html) built exactly as in
[Step 1](#step-1--build-the-design-payload).

That endpoint is documented in
[workflow-manage-orders.md § Preferred — CreatorSE deferred create](workflow-manage-orders.md#221-preferred--creatorse-deferred-create)
and is **not** repeated here. Use it when you want one call and one transaction for the whole order;
use Steps 1–3 above when you are incrementally adding designed items to an order that already exists.

---

## Error handling and retries

- **`401`** — an unknown/foreign `{accountId}`, `{shopId}`, or `{orderId}` on the order endpoint
  (Step 3): ownership is validated in the request filter before the handler runs, so a resource that
  is not yours reads as `401`, not `404`. Treat it as "not yours / does not exist for you".
- **`404`** (Step 3 only) — the order id is yours but the order is not a live, editable order in this
  shop. Do not retry blindly; re-read the order.
- **`500`, not `400`, for bad design data** — both the preview (Step 2) and the add-to-order
  (Step 3) delegate the actual design work to an internal engine, and a decode/validation/render
  failure there surfaces as a **server error**, not a client `400`. An agent must not treat these as
  retryable-as-is: the design payload itself needs correcting first. (The order-level deferred create
  in [workflow-manage-orders.md](workflow-manage-orders.md#221-preferred--creatorse-deferred-create)
  is different — it validates the order envelope up front and returns a real `400` for a missing
  country/address.)
- **Preview is idempotent; adding an item is not.** Replay Step 2 freely. For Step 3, confirm whether
  the item already landed (read the order) before retrying after a timeout.

## Not reachable over the public API (do not script)

- **Converting between design formats** (`DesignCse` ⇄ `DesignPrime`, the Creator JS Widget format)
  is an internal proxy to `creator-engine-service` and is not part of this public workflow.
- **Editing motives, product areas, or hotspots** — the design references catalog ids
  (`productId`, `assignedColor.id`, `motive.id`, `productArea.id`); the entities themselves are
  managed elsewhere (motives via [workflow-manage-motives.md](workflow-manage-motives.md), products
  in the back office / [workflow-manage-products.md](workflow-manage-products.md)).

## Related data types

- [CreatorSE.Design](data-types/CreatorSE.Design.html) — the design object; body of Step 3 and the
  Base64 payload of Step 2 (rendered from `DesignCse`).
- [CreatorSE.Composition](data-types/CreatorSE.Composition.html) — a decorated product area within a
  design, holding its elements.
- [CreatorSE.DesignElementMotive](data-types/CreatorSE.DesignElementMotive.html),
  [CreatorSE.DesignElementDdf](data-types/CreatorSE.DesignElementDdf.html),
  [CreatorSE.DesignElementDecoration](data-types/CreatorSE.DesignElementDecoration.html) — the three
  concrete element types placed in a composition's `elements` array.
- [CreatorSE.DesignElementLayer](data-types/CreatorSE.DesignElementLayer.html) — a named layer for
  dynamic text/colour replacement on a motive element.
- [CreatorSE.ProductAssignedColor](data-types/CreatorSE.ProductAssignedColor.html) — the color
  variant selected on the design.
- [CreatorSE.Position](data-types/CreatorSE.Position.html) — explicit placement of an element within
  a product area.
- [OrderedProduct](data-types/OrderedProduct.html) — the item created by Step 3 (rendered from
  `DesignedOrderedProductPrime`).
- [CreatorSE.OrderDeferred](data-types/CreatorSE.OrderDeferred.html) — the one-call order-plus-designs
  envelope (Alternative section; documented in workflow-manage-orders).
