---
title: "Update one order"
method: PATCH
path: "/orders/{id}"
tags: ["orders"]
---

# Update one order

`PATCH /orders/{id}`

## Request

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

Replaces THREE legacy routes — `patch`, `resolve-design` and `resolve-label` — because from a seller's point of view they were one act: here is the missing piece, put my order back in the queue. What you send decides which.

Sending `image_url` to an order that is ON_HOLD releases it back to where it was held from. Sending `label_url` and `tracking_number` together attaches a shipment through the same code path the scan stations use, so the seller notification and the audit trail are identical.

Absent means leave it alone. Unknown field names are rejected rather than ignored — a typo you can see beats a silent no-op.

`quantity` is the one field locked after assignment: it changes what somebody has to make.

Send an `Idempotency-Key` when you may retry, for example from an offline queue: a replayed label link then returns the first answer instead of attaching again.

## Path parameters

- `id` integer, required

## Headers

- `Idempotency-Key` string

## Request body

- object
  - `note` string: Free text for the floor.
  - `quantity` integer: Only while the order is still PENDING.
  - `add_on` boolean: `true` or `false` ticks or unticks the product's add-on and re-prices the order. Only while it is PENDING and not yet charged.
  - `image_url` string: The design. Releases an ON_HOLD order.
  - `positions` unknown[]: Replaces the whole per-face list (same shape as on create). `[]` or `null` removes it.
    - unknown
  - `external_id` string: Your own order id.
  - `deadline` string: When it must ship by.
  - `shipping` object: Any of `name`, `company`, `email`, `phone`, `line1`, `line2`, `city`, `state`, `zip`, `country`. When sent, `name`, `line1`, `city`, `state`, `zip` and `country` must be real values — a placeholder such as `1`, or an empty value over a real one, is refused and named in `error.fields`. A `state` you send must be its two-letter code, e.g. `IL`.
  - `label_url` string: A label you bought yourself. Must be sent with `tracking_number`.
  - `tracking_number` string: Must be sent with `label_url`.
  - `carrier` string: Optional carrier name for the shipment.

## Response `200`

The updated order in full, so you never need a follow-up GET. `meta.released` says whether a hold was lifted.

## 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.
- `404`: No such record — including records that exist but belong to someone else. The API never confirms another seller's ids.
- `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)
