Merchable APIReferenceGetting startedAuthentication & scopesDesignsPlacing an orderWebhooksPagination, errors & rate limitsVersioning & changelog

Designs

A design is artwork placed on a product (a tee, hoodie, bottle, …) and sold in your shops. It is what an order line points at. Designs are created and edited in the web app's design studio (or over MCP); the API reads them so your systems can find what to order, at what price, and in which variants.

Everything below is read-only. GET /v1/designs and GET /v1/designs/{id} need the designs:read scope.

Listing designs

GET /v1/designs?status=active&limit=50
Authorization: Bearer mchp_…

Cursor-paginated (see Pagination, errors & rate limits). Filter with status (draft, active or inactive); only active designs can be ordered. Designs you have deleted never appear.

Each row is a summary:

Field Meaning
id Public design id (an 8-character nano id, e.g. d8Xk2mQz). Use it as design_id on order lines
name, status As shown in the web app
product The underlying product: id, title, thumbnail_url
colours, sizes The option names the design is sold in — you can identify an order line by these instead of variant_id
retail_price, currency The tax-inclusive price the design sells for in your shops; null when unpriced
purchase_price, purchase_tax What your account pays Merchable for one unit, ex tax, plus the tax on it — see Two prices
thumbnail_url Front mockup
delivery_type delivery, pickup or delivery_and_pickup — what the design's shop settings allow
created_at, updated_at ISO 8601

GET /v1/shops/{id}/designs lists the designs on sale in one shop with the same rows.

Reading one design

GET /v1/designs/{id} returns the summary plus everything an order line needs:

{
  "data": {
    "id": "d8Xk2mQz",
    "name": "Club Tee",
    "status": "active",
    "retail_price": { "amount": "39.00", "currency": "AUD" },
    "currency": "AUD",
    "purchase_price": { "amount": "23.50", "currency": "AUD" },
    "purchase_tax": { "amount": "2.35", "currency": "AUD" },
    "purchase_breakdown": {
      "product_base": { "amount": "15.00", "currency": "AUD" },
      "extra_placement_fees": { "amount": "8.50", "currency": "AUD" },
      "print_method_premium": { "amount": "0.00", "currency": "AUD" }
    },
    "quantity_tiers": [
      { "min_quantity": 1, "max_quantity": 9, "price": { "amount": "15.00", "currency": "AUD" } },
      { "min_quantity": 10, "max_quantity": null, "price": { "amount": "12.00", "currency": "AUD" } }
    ],
    "description": "Season 2026 club tee",
    "stock_control_enabled": true,
    "preorder_enabled": false,
    "collections": [{ "id": "9b2f…", "name": "Club kit" }],
    "personalisation_zones": [
      { "id": "4d1c8f2a-…", "label": "Player name", "placement": "back", "required": true,
        "min_characters": 1, "max_characters": 12, "placeholder": "SMITH" }
    ],
    "variants": [
      { "id": "7c9e…", "colour": "Black", "size": "L", "sku": null, "active": true,
        "purchase_price": { "amount": "23.50", "currency": "AUD" },
        "purchase_tax": { "amount": "2.35", "currency": "AUD" },
        "status": "available", "quantity": 12 },
      { "id": "1f0a…", "colour": "Black", "size": "XL", "sku": null, "active": true,
        "purchase_price": { "amount": "23.50", "currency": "AUD" },
        "purchase_tax": { "amount": "2.35", "currency": "AUD" },
        "status": "out_of_stock", "quantity": 0 }
    ],
    "previews": { "front": "https://…/front.png", "back": "https://…/back.png" }
  }
}
Field Meaning
purchase_breakdown How purchase_price is made up — see Two prices
quantity_tiers The product's quantity breaks for your country — see Quantity tiers
description Free text from the web app
stock_control_enabled Whether variants track shelf stock (otherwise they are made to order)
preorder_enabled Whether empty shelves are sold as preorders
collections The collections the design belongs to
personalisation_zones Customer-text zones — see Personalisation zones
variants Every colour × size the design exists in — see Variants
previews Placement name → current mockup image URL

A design from another account, or one you have deleted, is a 404.

Variants

A variant is one colour × size of the design. An order line names it either by variant_id (the id here) or by colour and/or size; the names must match a single active variant or the line is rejected.

Field Meaning
id Use as variant_id on order lines
colour, size Option names; null when the product has no such option
sku Your SKU from the web app, if set
active Inactive variants cannot be ordered
purchase_price, purchase_tax What one unit of this variant costs your account (at quantity 1)
status, quantity Stock — see below
status Meaning
available Orderable now. quantity is the shelf count for stock-controlled designs, null for made-to-order variants that never run out
preorder Nothing on the shelf, but the design accepts preorders
out_of_stock Nothing on the shelf and no preorders
unavailable The design, the product, or the variant is inactive

Two prices

A design carries two prices, deliberately named apart:

Field Meaning
retail_price The tax-inclusive price customers pay in your shops. Informational for the API — account orders are not charged this
purchase_price / purchase_tax What your account pays Merchable per unit, ex tax, when it places an account order, plus the tax on it. This is what POST /v1/orders charges

purchase_breakdown explains the purchase price: the product's base price for your country, fees for placements beyond the ones the product includes (a back print on top of the front, say), and any premium for the design's print method. The design-level figure and the per-variant figures assume every placement on the design is printed, including personalisation zones.

Both prices are null for gift cards and for designs that cannot be priced for your account's country; such designs cannot be ordered.

Quantity tiers

Products may have quantity breaks. quantity_tiers lists them for your country, lowest quantity first, with the ex-tax product price at each break. Tiers apply to the summed quantity of a product across the whole order, not per line: the tier that total reaches replaces product_base in every line's unit price, while placement fees and the print method premium carry through unchanged. You do not apply tiers yourself — POST /v1/orders/quote returns each line already priced at the tier the order reaches.

Personalisation zones

A personalisation zone is a text area on the design that the customer's own words print into — a player's name across the back, a number on a sleeve. Zones are added to a design in the design studio (Add element → Zone), where the merchant sets the label, character limits, whether it is required, and the typography (font, weight, alignment, fill colour per light/dark garment).

A design with zones lists them under personalisation_zones, in display order:

Field Meaning
id The zone's id. Use it as zone_id when filling the zone on an order line
label What the customer is asked for, e.g. "Player name"
placement The placement the text prints on, lower-cased (front, back, …); null if the zone is not on a placement
required On a personalised line, this zone must be filled
min_characters, max_characters Length limits enforced on text
placeholder Example text shown in the shop

Filling a zone on an order line

Send personalisation on the line, one entry per zone:

{ "design_id": "d8Xk2mQz", "colour": "Black", "size": "L", "quantity": 1,
  "personalisation": [ { "zone_id": "4d1c8f2a-…", "text": "SMITH" } ] }

The rules POST /v1/orders and POST /v1/orders/quote apply:

Validation failures are 422 problems with the offending field in errors:

{
  "status": 422,
  "detail": "items.2.personalisation.0.text: must be at most 12 characters",
  "errors": { "items.2.personalisation.0.text": ["must be at most 12 characters"] }
}
Error Cause
items.N.personalisation.M.zone_id: is not a personalisation zone of this design Unknown or another design's zone
items.N.personalisation.M.zone_id: is given more than once Duplicate zone on one line
items.N.personalisation.M.text: is required Empty text on a required zone
items.N.personalisation.M.text: must be at least/at most X characters Outside the zone's limits
items.N.personalisation: zone "Player name" is required A required zone missing from a personalised line

Ordering a zoned design without personalisation

A line with no personalisation orders the design with every zone empty: nothing prints in the zone and, if the zone is the only element on its placement, that placement is not charged. So a design whose back holds only a name zone costs the back-print fee less when ordered plain. The design read's purchase prices assume the zones are filled; the quote prices each line as sent.

What you get back

Every order item (and quote line) carries personalisationzone_id, label, placement and text — on GET /v1/orders/{id}, in the create and quote responses, and inside every webhook payload, so your fulfilment records match what was printed. Merchable renders the text into the print file once the order is placed and checks it before production; contact support to correct a typo on an order that has not yet entered production.