Docs
Endpoints · Designer

POST/v1/sessions

A design link for one shopper, to open on your page.

What it does

Your server asks, with the key, when a shopper presses Design yours; the browser only ever sees the answer. The answer is an ordinary design link that names one size and at most one design (the shopper can reach nothing else), may be shown in a frame by origin and by no other site, and lasts hours: 24 by default when framed, 30 days when not framed (then it is a link to email or open on its own, and may not be framed at all). The store is the key's store; for a key with no store, the connected store named in connection, else the Your website store whose site address has the host of origin. A store key opens only the products and sizes its store offers. A Paused store opens no designers; a Draft store opens them with a test key, or with its preview_key.

Send the key: Authorization: Bearer sk_test_… or sk_live_…. Any method but POST answers 405 method_not_allowed: “POST only.”

curl -X POST "https://printwisp.com/v1/sessions" \
  -H "Authorization: Bearer $PRINTWISP_KEY" \
  -H "Content-Type: application/json" \
  -d '{"profile":"canvas-40x30","origin":"https://shop.example","customer_ref":"cust_8812","qty":1}'

# 201
{
  "session": "dss_3f9c1a7e5b2d8c40",
  "token": "7b1e5c0a9d3f2e8b4c6a1d7e9f0b3c5a2e4d6f8a1b3c5e7d",
  "url": "https://printwisp.com/d/7b1e5c0a9d3f2e8b4c6a1d7e9f0b3c5a2e4d6f8a1b3c5e7d",
  "expires_at": "2026-10-06T06:12:00+00:00",
  "origin": "https://shop.example",
  "product": "canvas",
  "profile": "prf_9a21c4d8e0f17b35",
  "design": null
}
<?php
$ch = curl_init('https://printwisp.com/v1/sessions');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => json_encode([
      'profile' => 'canvas-40x30',
      'origin' => 'https://shop.example',
      'customer_ref' => 'cust_8812',
      'qty' => 1
    ]),
    CURLOPT_HTTPHEADER     => ['Authorization: Bearer ' . getenv('PRINTWISP_KEY'), 'Content-Type: application/json'],
]);
$answer = json_decode(curl_exec($ch), true);
// Node (your server). The key never reaches a browser.
const r = await fetch('https://printwisp.com/v1/sessions', {
  method: 'POST',
  headers: { Authorization: 'Bearer ' + process.env.PRINTWISP_KEY, 'Content-Type': 'application/json' },
  body: JSON.stringify({ profile: 'canvas-40x30', origin: 'https://shop.example', customer_ref: 'cust_8812', qty: 1 }),
});
const answer = await r.json();
import os, requests

r = requests.post(
    "https://printwisp.com/v1/sessions",
    json={
      "profile": "canvas-40x30",
      "origin": "https://shop.example",
      "customer_ref": "cust_8812",
      "qty": 1
    },
    headers={"Authorization": f"Bearer {os.environ['PRINTWISP_KEY']}"},
)
answer = r.json()

Parameters

ParameterTypeDescription
profilestringThe size to design on: its code (canvas-40x30) or its id (prf_…). Give profile or product; when both are given they must agree.
productstringThe product's code (or id). Enough on its own when the product has one size or a default size; otherwise the answer is 422 invalid_session listing the sizes to choose from.
originstringThe web address of the page that shows the designer: scheme and host, no path (https://shop.example). The link may be framed there only, for 24 hours by default. Without it the link cannot be framed and lasts 30 days.
customer_refstring ≤ 190Your own id for the shopper. Lets the same shopper reopen the design later with design. A signed-in customer's designs are listed under it (GET /v1/projects).
signed_inbooleanIs customer_ref a signed-in customer (true) or a guest (false)? Read from the ref when not sent: wp-user-, shopify-customer- are signed in. A guest gets the designer's ✕ "Keep this design?" sheet; a signed-in shopper is never asked (it is in My designs).
customer_emailstringA signed-in customer's VERIFIED email. With link: answers link_email_is_customers, and when it is the link's address the design joins their account (proof by mailbox).
linkstringAn emailed link's token (64 hex), which your page read from #pw_link= (embed.js link()): opens the design that link names. A browser that did not make it is offered "Make my own copy"; a signed-in customer under another address, "Add to My designs" (a copy). 404 link_not_found, or 410 link_gone once it was replaced, ordered or deleted.
pagestringYour product page showing the designer (on origin). A link emailed from this design then opens there, with #pw_link=<token>, rather than on PrintWisp's own designer page.
customer_namestring ≤ 190The shopper's name, kept with the session.
qtyinteger 1–100000The quantity the designer starts with.
hoursinteger 1–720How long the link lasts. Default 24 when framed, 30 days when not.
designstringReopen a design (dsn_…): it must have been made under the same customer_ref, on the same size, and not yet ordered (an ordered design is frozen as printed). Or a Design's code from GET /v1/designs: the designer opens with every page already set, as this store offers that Design on the product; a code it does not offer is ignored.
connectionstringFor a key with no store: the connected store (int_…) the designer's Add to cart should go to. A store's own key needs none.
pricenumber | stringThe unit price your page shows, a number like 89.00. When the store's prices come from both your page and PrintWisp and must agree, the designer refuses Add to cart while PrintWisp's price differs from it.
preview_keystringWhile the store is a Draft: the store's preview key, for a live key (a test key needs none). A Paused store opens no designers.
metadataobjectAnything your server wants back with Add to cart: up to 20 keys (letters, digits, _; up to 40 characters), each a string (up to 500 characters), number, true/false or null. Kept with the session and sent in the Add-to-cart JSON as {{metadata.<key>}}. A Custom Website passes its own cart id here ({"cart": "c_8f3c41"}), so PrintWisp's server-to-server Add to cart knows whose cart it is.
Example bodiesCopy
{"product":"canvas"}   // one-size product, a link to email, 30 days
{"profile":"canvas-40x30","origin":"https://shop.example"}   // framed on your page, 24 hours
{"profile":"canvas-40x30","origin":"https://shop.example","customer_ref":"cust_8812","design":"dsn_5c2a9e01b7d4f638"}   // the same shopper reopens a design
{"link":"9f2c…64 hex…e01b","origin":"https://shop.example","customer_ref":"wp-user-12","signed_in":true,"customer_email":"sarah.t@gmail.com"}   // an emailed link, opened on your page (answers link_email_is_customers)

Response

201 application/json. The link and what it names. Give your page the url; keep session to tie the design to your own records. profile is the size's id and product the product's code; design is the reopened design or null.

{
  "session": "dss_3f9c1a7e5b2d8c40",
  "token": "7b1e5c0a9d3f2e8b4c6a1d7e9f0b3c5a2e4d6f8a1b3c5e7d",
  "url": "https://printwisp.com/d/7b1e5c0a9d3f2e8b4c6a1d7e9f0b3c5a2e4d6f8a1b3c5e7d",
  "expires_at": "2026-10-06T06:12:00+00:00",
  "origin": "https://shop.example",
  "product": "canvas",
  "profile": "prf_9a21c4d8e0f17b35",
  "design": null
}

Errors

HTTPerrormessage
401unauthorizedSend Authorization: Bearer <secret key>. Keys are made in PrintWisp, on your store's Overview → API keys.
403store_draftThis store is a Draft: send its preview_key to open designers until it is Open.
404product_not_foundNo product with that code.
404profile_not_foundNo size with that id.
404design_not_foundNo design with that id.
404design_not_foundNo design with that id for this customer.
404link_not_foundNo such link here.
405method_not_allowedPOST only.
410link_goneA newer link was sent for this design.
409store_pausedThis store is paused: it opens no designers until it is set to Open or Draft.
409account_pausedThis PrintWisp account is paused: the free trial ended. Add a card under Organisation → Plan & billing to switch it back on. Nothing was deleted.
422invalid_sessionThat size is not one of that product's.
422invalid_sessionThis product comes in 2 sizes. Say which with profile: prf_9a21c4d8e0f17b35, prf_0b3e7f2a9c4d5618.
422invalid_sessionThis product has no size to design on yet.
422invalid_sessionSay which product (its code) or which size (profile).
422invalid_sessionorigin must be the web address of the page that shows the designer, like https://shop.example -- scheme and host, no path.
422invalid_sessionqty must be a whole number, 1 or more.
422invalid_sessionhours must be a whole number from 1 to 720.
422invalid_sessionThat design was made on another size.
422invalid_sessionThat design has been ordered and cannot be changed. Start a new one.
422invalid_sessionprice is the unit price your page shows, a number like 89.00.
422invalid_sessionNo such connection: int_2b7c9e0d4a1f6835.
422product_not_offeredThe store web-au does not offer that product. Add it on the Products tab of that store.
422size_not_offeredThe store web-au does not offer that size. Offer it on the Products tab of that store.
422ready_productThat product is ready to ship: it has no designer. Quote it with POST /v1/quote {sku, qty} and order it with lines [{sku, qty}].
{ "error": "invalid_session", "message": "That size is not one of that product's." }

← Every routeQuickstart →