Skip to content

Orders

Create, confirm, change and cancel orders; the order lifecycle, statuses, hold reasons, item statuses and how credits move.

An order ships items to one recipient. You create it with the SKUs your customer bought and their address; we price it, reserve the total from your wallet, produce it and ship it.

Create an order

curl -X POST https://swaglists.com/api/v1/orders \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: store-order-1042" \
  -d '{
    "external_id": "1042",
    "shipping_method": "standard",
    "recipient": {
      "name": "Jane Doe",
      "address1": "123 Market St",
      "address2": "Apt 4",
      "city": "San Francisco",
      "state_code": "CA",
      "postal_code": "94107",
      "country_code": "US",
      "phone": "+1 415 555 0100",
      "email": "jane@example.com"
    },
    "items": [
      { "sku": "CA-TEE-BLK-M", "quantity": 2, "external_line_id": "line-1" }
    ],
    "packing_slip": { "message": "Thanks for shopping with Company A!", "customer_order_number": "#1042" },
    "metadata": { "channel": "web" }
  }'

Items

Identify each item with exactly one of:

Reference Use it when
sku You sell products you created — the usual case.
product_variant_id Same, by our variant id (pvar_…).
catalog_variant_id + designs The artwork is different for every order — see Personalized orders.

Plus quantity (1–1,000 per line), and optionally external_line_id (your line item id), metadata and retail_price — what your customer paid per unit, in cents. The retail price (default: the product variant's or product's retail price) is what international packing slips show and what is declared for customs; send it so neither shows our price. An order has 1–100 items.

Item images (mockup_url)

Every item has a mockup_url: an image of the item as it is produced, which you can show in your order history or emails (the link doesn't expire).

  • We render it in the background from the order's own designs — the snapshot taken when the order was created — a few seconds after you create the order. Editing a product later never changes the image of an order that was already placed.
  • Until the rendering is done, mockup_url is the product's mockup (sku / product_variant_id items) or the catalog photo of the variant (personalized items). The order.created webhook is built when the order is created, so it carries this first image; GET /orders/{id} returns the rendered one a few seconds later.
  • Rendering never delays production.

Recipient

name, address1, city and country_code (ISO 3166-1 alpha-2) are required. state_code (preferably the ISO subdivision code, e.g. CA, NY, ON, NSW) is required for the US, Canada and Australia and must be a valid state or province for the US and Canada. Full names such as British Columbia or New South Wales are converted to the code for those three countries; elsewhere the region is kept as sent. postal_code is required unless the country has none (e.g. HK, AE). email is used for shipment notifications if you enable them; phone helps carriers.

Other fields

Field Notes
external_id Your order id (up to 128 printable ASCII characters). Unique per mode — a second order with the same id fails with 409 duplicate_external_id (with existing_id). Fetch with GET /orders/ext:<external_id>.
shipping_method economy, standard (default), express or priority. See Shipping.
packing_slip message, brand_name, logo_file_id, customer_order_number — override your account branding for this order.
gift_message, customer_note Free text (500 / 1,000 characters).
metadata Up to 50 string key/value pairs for your own references.
confirm true: reserve credits and start production now. false: create a draft. Default: your account's auto-confirm setting (on by default).

The response is the order (201). Always send an Idempotency-Key — see Idempotency.

Lifecycle

Text
  POST /orders                      POST /orders
  (confirm: false)                  (confirm: true — the default)
        │                                 │
        ▼                                 ▼
   ┌─────────┐   POST …/confirm    ┌──────────────────────┐
   │  draft  │ ──────────────────► │  enough credits?     │
   └─────────┘                     └──────────────────────┘
                                     yes │          │ no (or held for review)
                                         ▼          ▼
                                 ┌────────────┐  ┌───────────┐
                                 │ processing │◄─│  on_hold  │  hold resolved (e.g. credits added)
                                 └────────────┘  └───────────┘
                                         │
                                         ▼
                                ┌───────────────┐
                                │ in_production │  ← from here on: no cancellation
                                └───────────────┘
                                         │
                                         ▼
                              ┌───────────────────┐
                              │ partially_shipped │  (only when parcels ship separately)
                              └───────────────────┘
                                         │
                                         ▼
                                   ┌──────────┐       ┌───────────┐
                                   │ shipped  │ ────► │ delivered │
                                   └──────────┘       └───────────┘

  canceled  ◄── POST /orders/{id}/cancel while draft, on_hold or processing
  failed    ◄── the order could not be produced (reserved credits are released)

delivered, canceled and failed are final. Every change sends a webhook (order.processing, order.in_production, order.shipped, …) and adds an entry to the order timeline (GET /orders/{id}/events).

Statuses

status Meaning
draft Created with confirm: false (or your account does not auto-confirm). Nothing is reserved; edit with PATCH /orders/{id}, then POST /orders/{id}/confirm.
on_hold Waiting — see hold_reason. Held orders resume automatically when the reason is resolved (e.g. credits arrive).
processing Confirmed: the total is reserved from your wallet and the order is being sent to production. Still cancelable.
in_production Being produced. Can no longer be canceled.
partially_shipped Some parcels shipped, others are still in production.
shipped Every item shipped. Tracking is in shipments.
delivered Every shipment was delivered. Final.
canceled Canceled before production; reserved credits released and spent credits refunded. Final.
failed Could not be produced; reserved credits released. Final.

Hold reasons

An order is on_hold when it cannot continue yet. hold_reason says why:

hold_reason What it means How to resolve
insufficient_funds Your available credits did not cover the order total when it was confirmed. Add credits (top-up or auto-recharge). Held orders resume automatically, oldest first. In test mode: POST /test/wallet/fund.
manual_review The order is being reviewed by our team before production (for example while your account is new). No action needed; it continues automatically after review. Contact support if it takes longer than a business day.
artwork_issue A print file could not be produced from the artwork. Our team is notified. Cancel the order and re-create it with corrected artwork, or contact support.
address_issue The shipping address could not be validated or is undeliverable. Contact support with the corrected address, or cancel and re-create the order.
fulfillment_issue A production problem occurred (for example an item became unavailable). We are working on it. Usually no action needed — the order continues or failed items are refunded to your wallet. Contact support if it stays on hold.

You receive order.on_hold when an order is held and order.processing when it continues. Orders on hold can be canceled.

Credits and funds_status

Confirming an order reserves its total from your wallet (it moves from available to held). The reserved credits are spent (captured) once the order is accepted for production, and returned if it is canceled or fails. See Credits & billing.

funds_status Meaning
none Nothing reserved (drafts).
awaiting On hold until enough credits are available.
held The order total is reserved (counted in your wallet's held).
partially_captured Part of the reserved amount was spent (some items accepted for production).
captured The order total was spent.
released Reserved credits were returned to available (canceled or failed before being spent).
partially_refunded Part of the spent amount was refunded to your wallet.
refunded Everything spent on the order was refunded to your wallet.

Not enough credits? By default the order is held (on_hold / insufficient_funds) and continues automatically — oldest first — as soon as credits arrive (top-up, auto-recharge, refund). With hold and release manually, held orders wait until you release them (dashboard Release, single or bulk, or POST /orders/{id}/confirm). If you set Settings → Orders → When credits run out to reject, POST /orders fails with 402 insufficient_funds instead and nothing is created; after adding credits, send the order again with a new Idempotency-Key (why).

Item statuses

Each items[] entry has its own status and shipped_quantity — useful for orders that ship in several parcels:

Item status Meaning
draft The order is a draft.
pending Waiting to go into production.
in_production Being produced.
shipped Every unit shipped (shipped_quantity = quantity).
delivered Every unit was delivered.
canceled Canceled (its credits were returned).
failed Could not be produced (its credits were returned).

Drafts and confirmation

Create an order with "confirm": false (or turn off auto-confirm in Settings → Orders) to get a draft. Drafts reserve nothing and can be changed:

Edit a draft, then confirm it
curl -X PATCH https://swaglists.com/api/v1/orders/ord_01k8x4b2q9w7e3r5t1y8u6i0pa \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "shipping_method": "express", "items": [{ "sku": "CA-TEE-BLK-L", "quantity": 1 }] }'

curl -X POST https://swaglists.com/api/v1/orders/ord_01k8x4b2q9w7e3r5t1y8u6i0pa/confirm \
  -H "Authorization: Bearer $API_KEY" \
  -H "Idempotency-Key: confirm-ord_01k8x4b2q9w7e3r5t1y8u6i0pa"

PATCH accepts external_id, recipient, shipping_method, items (replaces all items), packing_slip, gift_message, customer_note and metadata, and returns 409 order_not_editable once the order is confirmed. Confirming reserves credits exactly like creating with confirm: true.

Tip

Use drafts when a human reviews orders before production, or to show your customer the final price: POST /orders/estimate gives the same totals without creating anything.

Estimate an order

POST /orders/estimate takes the same body as POST /orders and returns an order estimate: item prices, shipping, tax, total, every available shipping method with its price, the delivery estimate and whether your wallet covers it. Nothing is created and nothing is reserved. The estimate is exactly what the order will cost — see Pricing. It runs the same checks as POST /orders (items, designs, files, packing-slip logo) except that url artwork is not downloaded and external_id is not checked for duplicates, so those can still fail when you place the order.

Cancel an order

cURL
curl -X POST https://swaglists.com/api/v1/orders/ord_01k8x4b2q9w7e3r5t1y8u6i0pa/cancel \
  -H "Authorization: Bearer $API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Customer changed their mind" }'
  • You can cancel orders that are draft, on_hold or processing — as long as production has not started.
  • Once an order is in_production (or shipped) it cannot be canceled: 409 order_not_cancelable. The same code, with a "try again in a minute" message, is returned while the order is being sent to production — retry shortly.
  • Reserved credits are released and any spent credits refunded to your wallet immediately; you receive order.canceled.
  • Canceling an order that is already canceled returns it unchanged (safe to retry).

Retrieve and list

Request Notes
GET /orders/{id} By id, or by your id: GET /orders/ext:1042.
GET /orders Newest first. Filters: status (comma-separated), external_id, q (order number, external id, recipient name or email), created[gte], created[lte] (Unix seconds or ISO-8601).
GET /orders/{id}/events The order timeline, oldest first.

After shipping

shipments[] lists each parcel with carrier, tracking number and tracking URL, and tracking_page_url is your branded tracking page — see Shipping & tracking. Problems after delivery (damaged or misprinted items)? Contact support with the order id; refunds are credited to your wallet (order.refunded).