Skip to content

Changelog

Changes to the API and the developer documentation, newest first.

Backwards-compatible additions ship continuously; breaking changes only in a new API version (see Versioning).

2026-10-24 — Order requirements checked up front

Orders, estimates and confirmations now check what the production options of every item can accept before anything is created or reserved. An order that no option could make used to be accepted, had its credits reserved, and failed hours later; it is now a 400 that names the field to fix. If at least one option fits, the order goes through as before.

  • Recipient — recipient_field_too_long (with max_length: the longest value at least one option accepts, counted in characters as people count them), recipient_phone_required, recipient_email_required, recipient_tax_id_required, recipient_state_required, po_box_not_supported, military_address_not_supported and recipient_local_script_required, each with param on the recipient field (recipient.city, recipient.phone, …). Messages never repeat the recipient's data.
  • Shipping method — shipping_method_unavailable now also comes with available_shipping_methods when the chosen method is the only problem. POST /shipping/rates only lists methods every item can actually be shipped with to that destination, and prices each method with the grouping an order with that method gets.
  • Quantities — quantity_too_large (with max_quantity, param = items[i].quantity) when the item's production options take fewer units per order. An order can have at most 10,000 units in total (400 parameter_invalid, param: items).
  • Customization options — when a catalog product has options beyond its variants (a frame color, thread colors…), orders of saved products get their values from the product and the options' defaults; problems are reported with the new customization_* codes on items[i].customizations.<key>, every one of them in errors. Yes/no options report allowed_values: [true, false].
  • Artwork URLs — the url layers of an order are downloaded a few at a time within one time budget per order (45 seconds); when it runs out the request fails with artwork_download_budget_exceeded instead of running into a gateway timeout. An order can reference at most 50 different artwork URLs (400 parameter_invalid, param: items); upload larger sets with POST /files first.
  • Errors — an item_unavailable error can list placement_unavailable in errors when no production option prints on one of the item's placements. See Errors.

2026-10-24 — Stricter input validation

Unknown query parameters are now rejected with 400 parameter_invalid, exactly like unknown body parameters. Before, they were ignored — so a misspelled or unsupported filter such as GET /orders?updated_since=… or ?statuss=failed silently returned every order. The error names the parameter (param, message Received unknown parameter: updated_since (query parameter).). The query parameter _ stays accepted and ignored on every endpoint for cache-busters. This ships without a new API version because it only rejects requests that never worked as intended; if your integration appends its own tracking parameters to API URLs, remove them.

  • Cursors — starting_after / ending_before must be the id of an object of that list (ord_… on /orders, prod_… on /products, evt_… on /events, …); another resource's id is a 400 instead of a wrong page. See Pagination.
  • Timestamps — created[gte] / created[lte] read a date-time without an offset (2026-10-01T00:00:00) as UTC (it depended on the server's time zone before) and accept Unix milliseconds; impossible dates (2026-02-30) and years outside 2000–2100 are a 400. See Pagination.
  • Text — NUL characters and unpaired UTF-16 surrogates are rejected with 400 parameter_invalid naming the field on every endpoint (JSON bodies, form uploads, query parameters, path ids, Idempotency-Key); they used to cause a 500 on some endpoints. Recipient names and address lines are stored in Unicode NFC with control and bidi-override characters removed.
  • Empty strings — "" in an optional recipient field (company, address2, state_code, postal_code, phone, tax_id, email) means "not set", for no-code tools that send empty strings for unmapped fields (state_code: "" used to be a 400).
  • Errors — validation errors list every problem of the request in error.errors (param, code, message), and errors carry the accepted values or limits where they apply: allowed_values, available_shipping_methods (shipping_method_unavailable), max_length, max_quantity. See Errors.
  • Orders — packing_slip.logo_file_id is now returned, so a read-modify-write of packing_slip keeps the logo.
  • Product webhooks — product.created, product.updated and product.deleted events carry every variant's wholesale price, the same object as GET /products/{id} (it was null in events).

2026-10-24 — Every order lifecycle step

  • Webhooks — every order lifecycle step is now sent exactly once, also when one status update covers several steps (for example an order produced, shipped and delivered between two status checks). The skipped order.in_production and order.shipped events are created with that update, in lifecycle order, interleaved with the shipment.* events; each carries the current object and previous_attributes.status names the previous step. Their deliveries are spaced about a second apart. See Every lifecycle step, exactly once.
  • Orders — updated_at now changes with every change visible to you, including parcel-only updates such as "out for delivery", and always moves forward.

2026-10-01 — API v1

The first version of the Swaglists API (Api-Version: 2026-10-01).

  • Catalog — GET /catalog/products, GET /catalog/products/{id_or_slug}, GET /catalog/categories with your wholesale prices, placements, recommended artwork sizes and mockup templates.
  • Files — upload artwork by multipart upload or by URL (POST /files), list, retrieve and delete files.
  • Products — create products from catalog products and designs, manage variants and SKUs (/products, /products/{id}/variants, /product_variants/{id}, /products/by_sku/{sku}).
  • Shipping — POST /shipping/rates for every method with price and delivery estimate.
  • Orders — create (by SKU, product variant or catalog variant with inline designs), estimate, update drafts, confirm, cancel, list with filters, look up by ext:<external_id>, order timeline.
  • Credits — wallet, transactions and top-ups.
  • Webhooks — endpoints, Standard Webhooks signatures, secret rotation with overlap, test events, GET /events with 30-day retention.
  • Test mode — sk_test_ keys, free test credits (POST /test/wallet/fund), simulated production and POST /test/orders/{id}/advance, magic values for failure scenarios.
  • Conventions — idempotency keys, cursor pagination, Stripe-style errors with documentation links, rate limit headers, request ids.
  • Docs for AI — /llms.txt, /llms-full.txt and a Markdown version of every docs page.