---
title: "Create one multi-item order"
method: POST
path: "/orders/batch"
tags: ["orders"]
---

# Create one multi-item order

`POST /orders/batch`

## Request

- Base URL: `https://0.0.0.0:3000/api/v1`
- URL: `https://0.0.0.0:3000/api/v1/orders/batch`
- Auth: API key in header `x-api-key`

One shipping block, many items — the replacement for legacy's `POST /api/v2/customer/orders/multi`. Each item becomes its own order row, suffixed `-1`, `-2`, … off the shared `external_id`, which is the convention legacy sellers already handle. A single-item batch is NOT suffixed: the same order should not arrive under two different ids depending on how it was sent.

Omit `external_id` and one is generated for you (legacy did this too) — but an id you chose is the one support can search for.

It reports PER ROW. A batch whose third item names a dead SKU creates the other items and tells you about the third; it is never all-or-nothing and never silently partial. Read `results[]`, not just the status code.

The `Idempotency-Key` is derived per row, so retrying a batch that half-succeeded creates exactly the missing half.

At most 500 items per request.

## Headers

- `Idempotency-Key` string, required

## Request body

- object
  - `external_id` string: Your marketplace order id. Generated if omitted.
  - `shipping` object, required: Shared by every item — the same fields, and the same required real recipient, as `POST /orders`.
  - `shipping_type` string, required: REQUIRED, and shared by every item: the rows of a batch ship as ONE parcel, so they cannot be shipped by two different people. Same two values as `POST /orders` — `Ship by OP` or `Ship by Platform`. An item may override it, but a batch whose items disagree becomes orders that cannot be labelled together.
  - `items` unknown[], required: 1–500 entries. Each takes the same per-item fields as `POST /orders` (`product_variant_id` or `product_id`+`options`, `quantity`, `image_url`, `mockup_url`, `note`, `add_on`) and inherits anything set at the top level. Artwork is per item and REQUIRED on every one: one order can hold several products, each printed from its own design and mockup.
    - unknown
  - `marketplace` string: Applied to every row.
  - `placed_at` string: Applied to every row.
  - `mockup_url` string: REQUIRED (or `mockup_id`). The mockup picture — what the listing shows. Stored once per picture per account, so re-sending the same link reuses the same mockup rather than making another.

## Response `201`

201 when at least one row was created, 200 when every row was a replay, 422 when nothing landed.

## Other responses

- `401`: No key, or a key that is unknown, revoked or expired. One message for all four — telling you which would confirm to a guesser that a key exists.
- `403`: The key is valid but its owner may not do this.
- `413`: The request body is over the limit: 2 MB for a JSON body, 50 MB for a proof photo.
- `422`: The body or query is malformed. Field-level detail arrives in `error.fields`.
- `429`: Over the per-key limit. `Retry-After` says how many seconds to wait.
- `500`: Our fault. `error.request_id` matches the X-Request-Id header — quote it to support.

---

[API](https://skmtc.dev/opcreative/apis/opcreative-api.md) · [All operations](https://skmtc.dev/opcreative/apis/opcreative-api/llms.txt) · [OpenAPI document](https://skmtc.dev/opcreative/apis/opcreative-api/revisions/105bb30aa87e?raw)
