Server-side REST reference for hand-built sites: resolve store SKUs to 3D products, read saved configurations back, and create / track orders from your backend.
PwaiEmbed.onAddToCart(fn) payload)? That is covered in the Custom site — full integration guide. This page documents the HTTP endpoints behind it.
https://printwearai.com/api
Content-Type: application/json).{ "error": "message" }.Your workspace (Integration page) exposes two keys:
| Key | Prefix | Usage |
|---|---|---|
| Public embed key | fk_… | Identifies your workspace. Safe to expose in HTML. Sent as the X-Embed-Key header (recommended) or the embed_key query parameter. |
| API secret | sk_… | Confidential — keep it server-side only, never ship it to a browser. Rotate it anytime from your workspace settings. It is not required by the endpoints below, which authenticate with the embed key and end-customer session tokens. |
X-Embed-Key header over the query string: keys in query strings leak into Referer headers, proxy logs and browser history. When you use the query parameter, the API adds an X-Embed-Key-Warning response header to remind you.The /configs and /customer/orders endpoints act on behalf of a logged-in end customer of your workspace. A session is created by:
POST /api/auth/register — body { "email", "password", "name" } (password: 8+ chars with letters and digits). Requires the tenant context, so send your X-Embed-Key header. Rate-limited to 5 requests / 10 min / IP.POST /api/auth/login — body { "email", "password" }. Rate-limited to 10 requests / 5 min / IP.Both set a pwai_session cookie. From a server, keep the cookie jar, or replay the session token as a bearer header:
Authorization: Bearer <session-token> # the pwai_session cookie value
Maps an external identifier (your store's SKU, product id or product page URL) to the linked 3D product. This is the endpoint embed.js and the SDK call during auto-detection; you can call it from your server too.
| Query parameter | Role |
|---|---|
embed_key | Required. Your fk_… key |
external_sku | External SKU / reference |
external_id | External product id |
external_url | Product page URL (fallback, matched on the URL path) |
Lookup order: imported external products by SKU → by external id → the 3D product's own SKU / reference field → external product URL. Provide at least one identifier.
curl "https://printwearai.com/api/resolve?embed_key=fk_YOUR_KEY&external_sku=JERSEY-001"
{
"product_slug": "home-jersey",
"product_name": "Home jersey",
"glb_path": "/models/home-jersey.glb",
"thumbnail": "https://…/thumb.jpg",
"price_base": 29.9,
"zones_config": { … },
"sizes": ["S","M","L","XL"],
"external_sku": "JERSEY-001",
"external_id": "123456"
}
Errors: 400 missing embed_key · 403 invalid key · 404 no linked product found.
Auth: end-customer session. A config_id received in the widget's add_to_cart payload refers to one of these records.
| Endpoint | Role |
|---|---|
GET /api/configs | List the customer's configs (most recent first), each with product_name and product_slug. Heavy fields (config_json, patron_svg) are omitted from the list. |
GET /api/configs/{id} | Full record, including the decoded config_json. |
POST /api/configs | Create. Body: product_id + config_json (required), optional name, patron_svg, thumbnail_b64. Returns { "id": … } and fires the config.saved webhook. |
PUT /api/configs/{id} | Update any of name, config_json, patron_svg, thumbnail_b64. Returns { "ok": true }. |
DELETE /api/configs/{id} | Delete. Returns { "ok": true }. |
curl -X POST "https://printwearai.com/api/configs" \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "product_id": 12, "name": "Home kit v2",
"config_json": { "zones": { "front": { "color": "#0044AA" } } } }'
# → { "id": 341 }
Auth: end-customer session plus tenant context (X-Embed-Key header).
| Body field | Role |
|---|---|
items | Required, non-empty array. Each item: product_id (required), quantity, and optional config_id, sizes_breakdown (e.g. {"M":3,"L":2}), patron_svg, config_snapshot |
shipping_addr | Object (free-form address) |
billing_addr | Object — defaults to shipping_addr |
notes | Free text |
Prices are computed server-side from the product's base price and quantity tiers — any client-sent price is ignored. Totals (total_ht, total_ttc) use the workspace VAT rate. The response is the full order row; the order.created webhook fires for your backend.
Initial status depends on the merchant's payment setup:
pending_payment and the response includes a checkout_url to redirect the customer to Stripe Checkout. The order becomes paid after payment.confirmed immediately; the production job is created and the confirmation email is sent.Errors: 400 no items · 402 monthly order quota of the workspace plan reached.
curl -X POST "https://printwearai.com/api/customer/orders" \
-H "Authorization: Bearer $SESSION_TOKEN" \
-H "X-Embed-Key: fk_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{
"items": [
{ "product_id": 12, "quantity": 14, "config_id": 341,
"sizes_breakdown": { "S": 2, "M": 6, "L": 4, "XL": 2 } }
],
"shipping_addr": { "name": "FC Example", "line1": "1 Stadium Rd", "city": "Lyon", "zip": "69000", "country": "FR" },
"notes": "Deliver before the 15th"
}'
# → full order row; includes "checkout_url" when status is "pending_payment"
Returns the customer's orders, most recent first, each with an nb_items count.
curl "https://printwearai.com/api/customer/orders" \
-H "Authorization: Bearer $SESSION_TOKEN"
Creates a Stripe Checkout session on the merchant's connected account for an unpaid order and returns { "url": "https://checkout.stripe.com/…" }. Errors: 404 order not found · 400 order already paid / cancelled / refunded, or empty · 503 the merchant has not enabled online payments.
PwaiEmbed.onAddToCart(fn) handler stores m.config_id on your cart line.POST /api/customer/orders with the customer's session, passing config_id per item — that is the thread linking the design to production.order.created / config.saved webhooks, and the order appears in your workspace → Orders with the production-ready pattern export.See also: Custom site — full guide (front-end) · JavaScript SDK · Webhooks