Skip to content

Front and back on one item

A shirt printed on the front and the back is one item: one order at the printshop, one parcel, one charge. Each side is a design of its own, committed for its own placement on the same blank, and printed on its own. POST /v1/orders then orders the prints together, as one item.

1. Commit a design for each placement

Commit one design per side, each naming the blank and its own placement:

{
  "templateId": "tshirt-back@1",
  "values": { "name": { "content": "Alexandra" } },
  "blankId": "blank_tshirt",
  "placementId": "back"
}

Approve each design and print it, as for any design (Design to order). You now hold a completed print of each side.

A store that sends its customer to the hosted designer hands out one link for the whole item: each side its own template, blank and placement, and the size menu, photos and preselection it sells that side with. The page shows a step per side, offers approving once the customer has opened every side, and sends them back with a proof of each, under the side’s key:

{
  "sides": [
    {
      "key": "front",
      "label": "Front",
      "templateId": "tshirt-front",
      "blankId": "blank_tshirt",
      "placementId": "front",
      "printSizes": [
        { "widthMm": 280, "heightMm": 360, "label": "Large" },
        { "widthMm": 200, "heightMm": 257, "label": "Medium" }
      ],
      "selectedPrintSizeIndex": 1
    },
    {
      "key": "back",
      "label": "Back",
      "templateId": "tshirt-back",
      "blankId": "blank_tshirt",
      "placementId": "back"
    }
  ],
  "returnUrl": "https://shop.example/cart",
  "state": "cart-10482",
  "locale": "sv"
}

The customer comes back to https://shop.example/cart?state=cart-10482&proofToken[front]=…&proofToken[back]=… (the brackets percent-encoded, which PHP reads as the array $_GET['proofToken']), only once every side’s proof is made. Commit each side’s proof with POST /v1/designs and its proofToken, then continue as above. A link with sides must name a returnUrl, holds two to ten sides, and names a side’s options only in its entry. A side without templateId is the path’s template.

A designer is built for up to four sides: a garment’s front, back and two sleeves. A link with more is still made, and its response carries a warning for you, never shown to the customer:

{
  "id": "shl_9a8b7c6d5e4f3a2b1c0d9e8f",
  "token": "EXAMPLE_designer_link_token_not_a_real_one",
  "url": "https://app.pixonaut.example/h/design/EXAMPLE_designer_link_token_not_a_real_one?lang=sv",
  "expiresAt": 1791972000000,
  "name": null,
  "brandId": null,
  "designLimit": null,
  "printAreaFrame": false,
  "placementFrame": false,
  "locale": "sv",
  "warnings": [{ "code": "sides_over_recommended", "recommended": 4, "sides": 5 }]
}

Each side is one more step on the hosted page, one more designer, canvas and photo set in the customer’s browser, and one more proofToken[<key>] on the return address. The SDK warns the same way, in the console, when it is mounted with more than four placements.

2. Order the prints as one item

Send every print of the item, the one you think of as first first. The first is the order’s lead: the order’s printId names it.

{
  "prints": [
    { "printId": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f" },
    { "printId": "d5e6f7a8-b9c0-4d1e-8f2a-3b4c5d6e7f80" }
  ],
  "quantity": 1,
  "externalRef": "WEB-10482-1",
  "recipient": { "name": "Alexandra Lind", "email": "[email protected]" },
  "shippingAddress": {
    "company": "Lind Design AB",
    "line1": "12 High Street",
    "postalCode": "SW1A 1AA",
    "city": "London",
    "country": "GB"
  }
}

The order answers with every print, the lead first, and each print’s placement:

{
  "id": "e1f2a3b4-c5d6-4e7f-8a9b-0c1d2e3f4a5b",
  "tenantId": "acme",
  "printId": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
  "designId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c",
  "printIds": [
    "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
    "d5e6f7a8-b9c0-4d1e-8f2a-3b4c5d6e7f80"
  ],
  "prints": [
    {
      "printId": "c4d5e6f7-a8b9-4c0d-9e1f-2a3b4c5d6e7f",
      "designId": "6f1c8a2b-3d4e-4f5a-8b6c-7d8e9f0a1b2c",
      "designRevision": 1,
      "placementId": "front",
      "printedAs": "Front",
      "spotOutput": "process",
      "status": "completed",
      "placementFields": []
    },
    {
      "printId": "d5e6f7a8-b9c0-4d1e-8f2a-3b4c5d6e7f80",
      "designId": "7a2d9b3c-4e5f-4a6b-9c7d-8e9f0a1b2c3d",
      "designRevision": 1,
      "placementId": "back",
      "printedAs": "Back",
      "spotOutput": "process",
      "status": "completed",
      "placementFields": []
    }
  ],
  "adapter": "printful",
  "quantity": 1,
  "externalRef": "WEB-10482-1",
  "recipient": {
    "name": "Alexandra Lind",
    "email": "[email protected]"
  },
  "shippingAddress": {
    "company": "Lind Design AB",
    "line1": "12 High Street",
    "postalCode": "SW1A 1AA",
    "city": "London",
    "country": "GB"
  },
  "shipTo": null,
  "printshopConnectionId": "0b1c2d3e-4f5a-4b6c-8d7e-9f0a1b2c3d4e",
  "printshopName": "Printful",
  "spotOutput": "process",
  "externalOrderRef": "PF-889123",
  "status": "queued",
  "lastError": null,
  "failureKind": null,
  "hold": null,
  "tracking": null,
  "submittedAt": 1791886447000,
  "lastCheckedAt": null,
  "updatedAt": 1791886448000,
  "replacesOrderId": null,
  "replacedByOrderId": null,
  "personalDataErasedAt": null,
  "blankId": "blank_classic_tee",
  "variantRef": "v_3f9a1c2b7d4e8a01",
  "variant": {
    "ref": "v_3f9a1c2b7d4e8a01",
    "options": {
      "Color": "White",
      "Size": "M"
    },
    "fields": [
      {
        "name": "catalogVariantId",
        "value": "4012",
        "source": "own"
      }
    ]
  },
  "printshopAsPlaced": {
    "name": "Printful",
    "adapter": "printful"
  },
  "delivery": null,
  "blank": {
    "name": "Classic tee",
    "optionAxes": [
      "Color",
      "Size"
    ],
    "variants": 12
  }
}

Nothing is ordered, and the order is not written, when the prints are not one item: a print committed before its placement was recorded (print_without_placement), prints on different blanks, or some on a blank and some on none (mixed_blanks), or two in one placement (duplicate_placement). The same holds when the printshop cannot make them as one item (printshop_cannot_combine), or when the designs disagree on what it makes one item from, such as Printful’s variant (prints_disagree, naming the key). Each is a 422.

An item with no blank

A sign or a coaster printed on both faces has no blank: commit each face’s design with no blankId or placementId, and order the prints together as above. Prints that are all on no blank are one item, with no placement to compare. The order goes to the printshop the first print’s design was committed with, else the request’s printshopId, else the workspace default; with none it is refused 409 print_needs_printshop. A print whose design was committed with another printshop is refused 422 print_committed_elsewhere, naming it.

order.submitted and every later order.* event carry printIds. Find the order by any of its prints with GET /v1/orders?printId=.

3. Hand each print’s file to the printshop

A partner printshop receives every print as a file of the one item. A printshop you describe yourself sends every print too, once its steps are written to (its setup page in the docs says how). When you fetch the files yourself, name the print: GET /v1/orders/{id}/job/files?printId= and GET /v1/orders/{id}/job/file?printId=. Without printId an order of several prints answers 422 print_id_required, naming its printIds.

Cancelling before it is made

If the customer cancels before the item is made, POST /v1/orders/{id}/cancel asks the printshop to stop the whole item, and the order becomes cancelled once it has. A printshop that has begun it answers 409 order_at_printshop. Refunding the customer stays yours.

Questions? Write to [email protected].

Status · Terms of service · Privacy policy · Subprocessors