Multiple placements

One design on every area of a product — front, back, sleeve — or different artwork per area, as one buyable item.
frontback
A design
The product's placements
×2
One buyable item

How it works

A product is configured on two axes, and you pass a value for each. You pick a variant — size, color — with one opt.<attr> param per attribute (opt.size=m); see Options. And you supply a design — your artwork. A bare asset= prints one design on every printable placement — a pair of slides gets it on both feet, a tee on front, back, and sleeves; asset.<key> (asset.back=…) overrides that one placement while the rest keep the base.

Both are readable params any language builds by hand — no ids to look up, no SDK required. The server resolves price, print geometry, and composites the design into one mockup. One design is one buyable item; a single-placement product (get started) is the same rule with nothing to override.

html
<!-- One design on every area — front, back, both sleeves, collar. -->
<img src="https://img.snowcone.app/KMYKUK?opt.size=m&asset=https%3A%2F%2Fcdn.example.com%2Fart.png&shop=YOUR_SHOP_ID" />

<!-- Same base, a different back — every other area keeps the base. -->
<img src="https://img.snowcone.app/KMYKUK?opt.size=m&asset=https%3A%2F%2Fcdn.example.com%2Fart.png&asset.back=https%3A%2F%2Fcdn.example.com%2Fback.png&shop=YOUR_SHOP_ID" />

asset=default blanks every placement; asset.<key>=default blanks just one. Buy URLs resolve base and overrides the same way, so what you preview is what ships.

Discover the product

Read the product once from the catalog. Placements are the design axis — each has an addressable key — a URL-safe slug of the label (lowercase, non-alphanumerics collapsed to _, so “Left sleeve” → left_sleeve) — a human label, and a type (image or color). Attributes and attributesList are the variant axis — build pickers from them; combinations carries each price. You pass your picks as opt.<attr>; you never pass an internal id.

json
{
  "id": "KMYKUK",
  "name": "Women's Tee",
  "placements": [
    { "key": "front",        "label": "Front",        "type": "image" },
    { "key": "back",         "label": "Back",         "type": "image" },
    { "key": "left_sleeve",  "label": "Left sleeve",  "type": "image" },
    { "key": "right_sleeve", "label": "Right sleeve", "type": "image" },
    { "key": "collar",       "label": "Collar",       "type": "image" }
  ],
  "options": {
    "attributesList": ["Size"],
    "attributes": {
      "Size": { "choices": [{ "label": "S" }, { "label": "M" }, { "label": "L" }] }
    },
    "combinations": [
      { "Size": "S", "price": 2799 },
      { "Size": "M", "price": 2799 },
      { "Size": "L", "price": 2799 }
    ]
  }
}

Render a mockup

It’s a URL: a product code, your opt.<attr> picks, a bare asset= for every placement and/or one asset.<key> per placement that should differ, and your shop. Build it in any language — it’s just a query string. Here the front and back are each set explicitly:

<img src="https://img.snowcone.app/KMYKUK?opt.size=m&asset.front=https%3A%2F%2Fcdn.example.com%2Ffront.png&asset.back=https%3A%2F%2Fcdn.example.com%2Fback.png&shop=YOUR_SHOP_ID" />

Prefer JavaScript? The optional SDK builds the same URL:

tsx
import { getMockupUrl } from "@snowcone-app/sdk";

const src = getMockupUrl("KMYKUK", {
  shop: "YOUR_SHOP_ID",
  options: { size: "m" },
  design: { front: "https://…/front.png", back: "https://…/back.png" },
});

Adjust each placement

A placement is filled by an image (asset.<key>) or, for a color placement like a cap’s crown, a solid color (color.<key>) — plus optional modifiers, keyed the same way.

html
<!-- Tile the front, top-align the back — modifiers are more params, same placement key. -->
<img src="https://img.snowcone.app/KMYKUK?opt.size=m&asset.front=…&tile.front=2&asset.back=…&align.back=top&shop=YOUR_SHOP_ID" />
asseturl | default
The base image, printed on every image placement. `default` blanks them all.
asset.<key>url | default
Override one image placement; the rest keep the base. `default` blanks just that one.
color.<key>hex
Solid color for a color placement (type "color") — e.g. a cap’s crown or strap.
tile.<key>0.25 | 0.5 | 1 | 2 | 4
Repeat the image as a tiled pattern; the number is the tile scale.
align.<key>center | top | bottom | left | right | far-*
How the image sits within the placement. Defaults to center.

Sell it

Swap img → buy and the same params become a hosted checkout for one line item carrying every placement. A self-contained HTML form needs no JavaScript; price resolves server-side from your Shop ID.

<form action="https://buy.snowcone.app/KMYKUK" method="POST">
  <input type="hidden" name="asset.front" value="https://cdn.example.com/front.png" />
  <input type="hidden" name="asset.back"  value="https://cdn.example.com/back.png" />
  <input type="hidden" name="shop"        value="YOUR_SHOP_ID" />
  <select name="opt.size">
    <option value="s">S</option>
    <option value="m" selected>M</option>
    <option value="l">L</option>
  </select>
  <button type="submit">Buy now — $28</button>
</form>

Bring your own checkout

Running your own checkout? The Orders API line item takes the same two maps as JSON — options and design, keyed by key. Modifiers become fields on the fill ({ src, tile }) instead of a bare URL.

bash
curl https://api.snowcone.app/orders -X POST \
  -H "x-api-key: sk_your_orders_add_key" \
  -H "Content-Type: application/json" \
  -d '{
    "json": {
      "reference": "order-123",
      "items": [
        {
          "product": "KMYKUK",
          "options": { "size": "m" },
          "design": {
            "front": "https://cdn.example.com/front.png",
            "back":  "https://cdn.example.com/back.png"
          },
          "quantity": 1
        }
      ],
      "shipTo": {
        "name": "Ada Lovelace", "address1": "5 Bell Yard",
        "city": "London", "postalCode": "WC2A", "country": "GB"
      }
    }
  }'