{"openapi":"3.1.0","info":{"title":"TPOP API","version":"1.0.0","summary":"Print on demand: catalog, quotes, print files, orders, tracking and signed webhooks.","description":"Connect your store, ERP or tools to TPOP. Read the catalog, quote an order, upload print files, create and pay orders, follow production and shipping, and receive signed webhooks. Version 1 is stable: no breaking change without a new version, and v1 stays available 12 months after v2 is released.","contact":{"name":"TPOP support"}},"servers":[{"url":"https://api.tpop.pro"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Account","description":"The account and API key in use."},{"name":"Catalog","description":"Products you can print on, their variants, print areas and prices."},{"name":"Quotes","description":"Price an order, with shipping and VAT, without creating it."},{"name":"Files","description":"Print files TPOP downloads from your HTTPS link."},{"name":"Orders","description":"Create, pay, cancel, list and track orders."},{"name":"Webhooks","description":"Signed alerts sent to your server when an order changes."}],"paths":{"/v1/me":{"get":{"tags":["Account"],"operationId":"getMe","summary":"Account and API key in use","description":"Any valid key.","responses":{"200":{"description":"The account and key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Me"}}}},"401":{"$ref":"#/components/responses/Unauthorized"}}}},"/v1/catalog/products":{"get":{"tags":["Catalog"],"operationId":"listCatalogProducts","summary":"List catalog products","description":"Permission `catalog:read`. Only products currently offered to your account.","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/lang"},{"name":"category","in":"query","schema":{"type":"string"},"description":"Category code (sub-categories included)."},{"name":"q","in":"query","schema":{"type":"string"},"description":"Search in titles and SKU."},{"name":"tier","in":"query","schema":{"type":"string","enum":["essential","premium","eco"]}},{"name":"gender","in":"query","schema":{"type":"string"}},{"name":"fit","in":"query","schema":{"type":"string"}},{"name":"label","in":"query","schema":{"type":"string"},"description":"Certification code, e.g. `gots`."}],"responses":{"200":{"description":"A page of products","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CatalogProduct"}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/catalog/products/{id}":{"get":{"tags":["Catalog"],"operationId":"getCatalogProduct","summary":"Catalog product with colors, sizes, print areas and techniques","description":"Permission `catalog:read`.","parameters":[{"$ref":"#/components/parameters/id"},{"$ref":"#/components/parameters/lang"}],"responses":{"200":{"description":"The product","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/CatalogProductDetail"}}}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/catalog/products/{id}/variants":{"get":{"tags":["Catalog"],"operationId":"listCatalogVariants","summary":"Variants of a catalog product (color × size, SKU, price, availability)","description":"Permission `catalog:read`. Order a variant by its `sku`.","parameters":[{"$ref":"#/components/parameters/id"},{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"},{"$ref":"#/components/parameters/lang"}],"responses":{"200":{"description":"A page of variants","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/CatalogVariant"}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/countries":{"get":{"tags":["Catalog"],"operationId":"listCountries","summary":"Countries we ship to","description":"Permission `catalog:read`.","parameters":[{"$ref":"#/components/parameters/lang"}],"responses":{"200":{"description":"All countries served","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Country"}}}}]}}}},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"}}}},"/v1/orders/estimate":{"post":{"tags":["Quotes"],"operationId":"estimateOrder","summary":"Quote an order without creating it","description":"Permission `catalog:read` or `orders:write`. Prices are always computed by TPOP from the catalog and your plan.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateRequest"}}}},"responses":{"200":{"description":"The quote","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Estimate"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"401":{"$ref":"#/components/responses/Unauthorized"},"403":{"$ref":"#/components/responses/Forbidden"},"422":{"$ref":"#/components/responses/Unprocessable"}}}},"/v1/shipping/rates":{"post":{"tags":["Quotes"],"operationId":"shippingRates","summary":"Shipping cost of a set of items to a country","description":"Permission `catalog:read` or `orders:write`. Same body as the quote.","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EstimateRequest"}}}},"responses":{"200":{"description":"Shipping cost","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"type":"object","properties":{"shipping_country":{"type":"string"},"shipping_cents":{"type":"integer"},"currency":{"type":"string"}}}}}}}},"422":{"$ref":"#/components/responses/Unprocessable"}}}},"/v1/files":{"post":{"tags":["Files"],"operationId":"createFile","summary":"Upload a print file from an HTTPS link","description":"Permission `files:write`. TPOP downloads the file once: HTTPS only, public address only, no redirect followed, PNG or JPEG. Send `Idempotency-Key` to make retries safe.","parameters":[{"$ref":"#/components/parameters/idempotencyKeyOptional"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["url"],"properties":{"url":{"type":"string","format":"uri","example":"https://example.com/designs/front.png"},"filename":{"type":"string","maxLength":200}}}}}},"responses":{"201":{"description":"The stored file","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/File"}}}}}},"200":{"description":"Replay of the same request (`Idempotent-Replayed: true`)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/File"}}}}}},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"}}}},"/v1/files/{id}":{"get":{"tags":["Files"],"operationId":"getFile","summary":"A file you uploaded","description":"Permission `files:write` or `orders:read`.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"The file","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/File"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/orders":{"get":{"tags":["Orders"],"operationId":"listOrders","summary":"List orders created through the API","description":"Permission `orders:read`. Most recent first.","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"},{"name":"status","in":"query","schema":{"$ref":"#/components/schemas/OrderStatus"}},{"name":"external_id","in":"query","schema":{"type":"string"}},{"name":"created_after","in":"query","schema":{"type":"string","format":"date-time"}},{"name":"created_before","in":"query","schema":{"type":"string","format":"date-time"}}],"responses":{"200":{"description":"A page of orders","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/Order"}}}}]}}}},"400":{"$ref":"#/components/responses/BadRequest"}}},"post":{"tags":["Orders"],"operationId":"createOrder","summary":"Create an order (draft, or paid with `confirm: true`)","description":"Permission `orders:write`; `confirm: true` also needs `orders:confirm`. `Idempotency-Key` is required. A draft costs nothing. Paying debits your TPOP wallet, within the spending limits of the key; if a check fails the order stays a draft and the error says why.","parameters":[{"$ref":"#/components/parameters/idempotencyKey"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderRequest"}}}},"responses":{"201":{"description":"The new order","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"200":{"description":"Replay of the same request (`Idempotent-Replayed: true`)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"400":{"$ref":"#/components/responses/BadRequest"},"402":{"$ref":"#/components/responses/PaymentRefused"},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"}}}},"/v1/orders/{id}":{"get":{"tags":["Orders"],"operationId":"getOrder","summary":"An order, with shipments, tracking and history","description":"Permission `orders:read`.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"The order","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/orders/{id}/confirm":{"post":{"tags":["Orders"],"operationId":"confirmOrder","summary":"Pay a draft order with the wallet","description":"Permission `orders:confirm`. Refused beyond the per-order or 24-hour limit of the key, when payments are frozen, or when the balance is too low: the order stays a draft. Calling it again on a paid order changes nothing.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"The order, now `confirmed` (or `test_confirmed` with a test key)","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"402":{"$ref":"#/components/responses/PaymentRefused"},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/v1/orders/{id}/cancel":{"post":{"tags":["Orders"],"operationId":"cancelOrder","summary":"Cancel an order before production","description":"Permission `orders:write`. What the wallet paid goes back to the wallet. Refused once production has started.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"The cancelled order, with `refunded_cents`","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/Order"}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"409":{"$ref":"#/components/responses/Conflict"}}}},"/v1/webhooks":{"get":{"tags":["Webhooks"],"operationId":"listWebhooks","summary":"List webhook endpoints","description":"Permission `webhooks:manage`.","parameters":[{"$ref":"#/components/parameters/limit"},{"$ref":"#/components/parameters/cursor"}],"responses":{"200":{"description":"A page of endpoints","content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/Page"},{"type":"object","properties":{"data":{"type":"array","items":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}]}}}}}},"post":{"tags":["Webhooks"],"operationId":"createWebhook","summary":"Register an HTTPS endpoint","description":"Permission `webhooks:manage`. HTTPS on port 443 to a public address only; 10 endpoints at most. The response contains the signing `secret`, shown only once.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"required":["url","events"],"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}}}}}}},"responses":{"201":{"description":"The endpoint, with its secret","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"allOf":[{"$ref":"#/components/schemas/WebhookEndpoint"},{"type":"object","properties":{"secret":{"type":"string","example":"tpop_whsec_…"}}}]}}}}}},"409":{"$ref":"#/components/responses/Conflict"},"422":{"$ref":"#/components/responses/Unprocessable"}}}},"/v1/webhooks/{id}":{"get":{"tags":["Webhooks"],"operationId":"getWebhook","summary":"A webhook endpoint","description":"Permission `webhooks:manage`.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"The endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}},"patch":{"tags":["Webhooks"],"operationId":"updateWebhook","summary":"Change the URL, events or status (active or paused)","description":"Permission `webhooks:manage`.","parameters":[{"$ref":"#/components/parameters/id"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","additionalProperties":false,"properties":{"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}},"status":{"type":"string","enum":["active","paused"]}}}}}},"responses":{"200":{"description":"The endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"404":{"$ref":"#/components/responses/NotFound"},"422":{"$ref":"#/components/responses/Unprocessable"}}},"delete":{"tags":["Webhooks"],"operationId":"deleteWebhook","summary":"Stop an endpoint","description":"Permission `webhooks:manage`. Pending deliveries are dropped.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"The stopped endpoint","content":{"application/json":{"schema":{"type":"object","properties":{"data":{"$ref":"#/components/schemas/WebhookEndpoint"}}}}}},"404":{"$ref":"#/components/responses/NotFound"}}}},"/v1/webhooks/{id}/test":{"post":{"tags":["Webhooks"],"operationId":"testWebhook","summary":"Send a signed `ping` now","description":"Permission `webhooks:manage`. One attempt, no retry.","parameters":[{"$ref":"#/components/parameters/id"}],"responses":{"200":{"description":"Result of the attempt","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"$ref":"#/components/responses/NotFound"}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"`Authorization: Bearer tpop_live_…` (or `tpop_test_…`). Create keys in your TPOP account, menu API. Never put a key in a web page: calls from a browser are refused."}},"parameters":{"id":{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},"limit":{"name":"limit","in":"query","schema":{"type":"integer","minimum":1,"maximum":100,"default":20}},"cursor":{"name":"cursor","in":"query","schema":{"type":"string"},"description":"`next_cursor` of the previous page."},"lang":{"name":"lang","in":"query","schema":{"type":"string","enum":["en","fr","it","es","de","nl","pl","pt"],"default":"en"}},"idempotencyKey":{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{8,100}$"},"description":"Unique per order you create. The same key with the same body returns the same order; with a different body it is refused (409)."},"idempotencyKeyOptional":{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","maxLength":255}}},"responses":{"BadRequest":{"description":"Malformed request (unknown field, invalid JSON, bad parameter)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unauthorized":{"description":"Missing, invalid, expired or revoked key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Forbidden":{"description":"The key lacks the permission, the address is not allowed, or the call comes from a browser","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"NotFound":{"description":"Unknown identifier (or not yours)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Conflict":{"description":"Idempotency conflict, duplicate external_id, or the order can no longer change","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"Unprocessable":{"description":"The content is not acceptable (unknown SKU, file too small for its print area, incomplete address…)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"PaymentRefused":{"description":"`spending_limit_reached`, `payments_frozen`, `insufficient_balance`, `wallet_not_allowed` or `wallet_disabled`: the order stays a draft (`error.details.order` when it was just created)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}},"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"object","required":["code","message"],"properties":{"code":{"type":"string","example":"missing_scope"},"message":{"type":"string"},"details":{"type":"object","additionalProperties":true}}}}},"Page":{"type":"object","required":["data","has_more","next_cursor"],"properties":{"data":{"type":"array","items":[]},"has_more":{"type":"boolean"},"next_cursor":{"type":["string","null"]}}},"Me":{"type":"object","properties":{"account":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}}},"api_key":{"type":"object","properties":{"name":{"type":"string"},"prefix":{"type":"string","example":"tpop_live_AbC12345"},"mode":{"type":"string","enum":["live","test"]},"scopes":{"type":"array","items":{"$ref":"#/components/schemas/Scope"}},"spending_limits":{"type":["object","null"],"properties":{"daily_cents":{"type":"integer"},"per_order_cents":{"type":"integer"},"currency":{"type":"string"},"payments_frozen":{"type":"boolean"}}},"expires_at":{"type":["string","null"],"format":"date-time"}}}}},"Scope":{"type":"string","enum":["catalog:read","orders:read","orders:write","orders:confirm","files:write","webhooks:manage"]},"Money":{"type":"integer","description":"Amount in euro cents."},"CatalogProduct":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"sku_prefix":{"type":"string"},"title":{"type":"string"},"subtitle":{"type":["string","null"]},"category":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"}}},"main_image_url":{"type":["string","null"]},"brand":{"type":["string","null"]},"quality_tier":{"type":["string","null"]},"gender":{"type":["string","null"]},"fit":{"type":["string","null"]},"variants_count":{"type":"integer"},"colors_count":{"type":"integer"},"sizes_count":{"type":"integer"},"base_price_from_cents":{"$ref":"#/components/schemas/Money"},"price_from_cents":{"$ref":"#/components/schemas/Money"},"currency":{"type":"string","example":"EUR"},"production_days":{"type":["integer","null"]},"availability":{"type":"string","enum":["available","discontinued"]},"discontinued_at":{"type":["string","null"],"format":"date-time"},"replacement":{"type":["object","null"],"properties":{"id":{"type":"string"},"title":{"type":"string"}}}}},"CatalogProductDetail":{"allOf":[{"$ref":"#/components/schemas/CatalogProduct"},{"type":"object","properties":{"description_html":{"type":["string","null"]},"details":{"type":["string","null"]},"weight_grams":{"type":["integer","null"]},"pricing":{"type":"object","properties":{"currency":{"type":"string"},"tax_included":{"type":"boolean"},"plan":{"type":"string"},"general_discount_bp":{"type":"integer","description":"Plan discount in basis points, applied by the quote (the better of this and the product price rule, line by line)."}}},"lead_time":{"type":"object","properties":{"production_days":{"type":["integer","null"]}}},"attributes":{"type":"object","additionalProperties":true,"description":"Composition, fabric weight, certifications, care codes, origin and print country."},"colors":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"hex":{"type":["string","null"]}}}},"sizes":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"}}}},"print_areas":{"type":"array","items":{"$ref":"#/components/schemas/PrintArea"}},"techniques":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"min_dpi":{"type":"integer"},"max_colors":{"type":["integer","null"]},"max_width_cm":{"type":["number","null"]},"max_height_cm":{"type":["number","null"]},"extra_days":{"type":"integer"},"is_default":{"type":"boolean"}}}},"facts":{"type":"object","additionalProperties":true,"description":"Product facts: specifications, certifications, care, size guide in cm."}}}]},"PrintArea":{"type":"object","properties":{"face":{"type":"string","example":"front","description":"Use this code as key of `files` when ordering."},"name":{"type":"string"},"is_neck_label":{"type":"boolean"},"width_cm":{"type":"number"},"height_cm":{"type":"number"},"zones":{"type":"array","items":{"type":"object","properties":{"code":{"type":["string","null"]},"width_cm":{"type":"number"},"height_cm":{"type":"number"}}}},"min_dpi":{"type":"integer"},"min_pixels":{"type":"object","properties":{"width":{"type":"integer"},"height":{"type":"integer"}}},"techniques":{"type":"array","items":{"type":"string"}},"extra_cost_cents":{"$ref":"#/components/schemas/Money"},"currency":{"type":"string"}}},"CatalogVariant":{"type":"object","properties":{"sku":{"type":"string","example":"TPO-TS-UNI-CHAN-WHI-S"},"product_id":{"type":"string","format":"uuid"},"color":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"},"hex":{"type":["string","null"]}}},"size":{"type":"object","properties":{"code":{"type":"string"},"name":{"type":"string"}}},"availability":{"type":"string","enum":["available","discontinued"]},"discontinued_at":{"type":["string","null"],"format":"date-time"},"replacement":{"type":["object","null"]},"base_price_cents":{"$ref":"#/components/schemas/Money"},"price_cents":{"$ref":"#/components/schemas/Money"},"currency":{"type":"string"},"weight_grams":{"type":["integer","null"]},"image_url":{"type":["string","null"]}}},"Country":{"type":"object","properties":{"code":{"type":"string","example":"FR"},"name":{"type":"string"},"is_eu":{"type":"boolean"},"requires_customs":{"type":"boolean"}}},"Address":{"type":"object","additionalProperties":false,"required":["name","line1","city","country"],"properties":{"name":{"type":"string","maxLength":200},"company":{"type":["string","null"],"maxLength":200},"line1":{"type":"string","maxLength":255},"line2":{"type":["string","null"],"maxLength":255},"postal_code":{"type":["string","null"],"maxLength":20},"city":{"type":"string","maxLength":120},"country":{"type":"string","pattern":"^[A-Z]{2}$","example":"FR"},"phone":{"type":["string","null"],"maxLength":40},"email":{"type":["string","null"],"format":"email"}}},"OrderItemRequest":{"type":"object","additionalProperties":false,"required":["sku","quantity"],"description":"A catalog variant (`sku`) with either one of your products (`product_id`: its print files are used) or uploaded files per print face (`files`: each file is placed on the whole print area, centered horizontally and aligned to the top, at the largest size that fits; its resolution must reach the `min_dpi` of the area).","properties":{"sku":{"type":"string"},"quantity":{"type":"integer","minimum":1,"maximum":1000},"product_id":{"type":"string","format":"uuid"},"files":{"type":"object","additionalProperties":{"type":"string","format":"uuid"},"example":{"front":"3f0b…","back":"9a1c…"}}}},"EstimateRequest":{"type":"object","additionalProperties":false,"required":["items"],"properties":{"items":{"type":"array","minItems":1,"maxItems":100,"items":{"$ref":"#/components/schemas/OrderItemRequest"}},"shipping_address":{"$ref":"#/components/schemas/Address"},"country":{"type":"string","pattern":"^[A-Za-z]{2}$"}}},"OrderRequest":{"type":"object","additionalProperties":false,"required":["shipping_address","items"],"properties":{"external_id":{"type":"string","maxLength":100,"description":"Your reference, unique in your account."},"confirm":{"type":"boolean","default":false,"description":"true = pay now with the wallet (needs `orders:confirm`)."},"shipping_address":{"$ref":"#/components/schemas/Address"},"items":{"type":"array","minItems":1,"maxItems":100,"items":{"$ref":"#/components/schemas/OrderItemRequest"}}}},"Costs":{"type":"object","properties":{"items_cents":{"$ref":"#/components/schemas/Money"},"discount_cents":{"$ref":"#/components/schemas/Money"},"options_cents":{"$ref":"#/components/schemas/Money"},"shipping_cents":{"$ref":"#/components/schemas/Money"},"tax_cents":{"$ref":"#/components/schemas/Money"},"total_cents":{"$ref":"#/components/schemas/Money"},"tax_rate":{"type":"number","example":20},"vat_regime":{"type":"string","enum":["domestic","eu_vat","eu_reverse_charge","export"]},"currency":{"type":"string"}}},"Estimate":{"type":"object","properties":{"items":{"type":"array","items":{"type":"object","properties":{"sku":{"type":"string"},"title":{"type":"string"},"color":{"type":"string"},"size":{"type":"string"},"quantity":{"type":"integer"},"unit_cost_cents":{"type":"integer"},"total_cost_cents":{"type":"integer"},"printed_faces":{"type":"array","items":{"type":"string"}}}}},"options":{"type":"array","items":{"type":"object","properties":{"code":{"type":["string","null"]},"cents":{"type":"integer"}}}},"costs":{"$ref":"#/components/schemas/Costs"},"shipping_country":{"type":"string"}}},"OrderStatus":{"type":"string","enum":["draft","confirmed","test_confirmed","in_production","shipped","delivered","on_hold","cancelled","refunded"]},"Order":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"number":{"type":"string","example":"P261017-E02B86"},"external_id":{"type":["string","null"]},"status":{"$ref":"#/components/schemas/OrderStatus"},"test":{"type":"boolean"},"items":{"type":"array","items":{"type":"object","properties":{"line":{"type":"integer"},"sku":{"type":"string"},"product_id":{"type":["string","null"]},"title":{"type":"string"},"color":{"type":["string","null"]},"size":{"type":["string","null"]},"quantity":{"type":"integer"},"unit_cost_cents":{"type":"integer"},"total_cost_cents":{"type":"integer"},"files":{"type":"array","items":{"type":"object","properties":{"face":{"type":"string"},"url":{"type":"string"}}}}}}},"shipping_address":{"$ref":"#/components/schemas/Address"},"costs":{"$ref":"#/components/schemas/Costs"},"shipments":{"type":"array","items":{"$ref":"#/components/schemas/Shipment"}},"history":{"type":"array","items":{"type":"object","properties":{"event":{"type":"string"},"status":{"type":["string","null"]},"at":{"type":"string","format":"date-time"}}}},"api_key_prefix":{"type":["string","null"]},"refunded_cents":{"type":"integer","description":"Only on the cancel response."},"created_at":{"type":"string","format":"date-time"},"confirmed_at":{"type":["string","null"],"format":"date-time"},"cancelled_at":{"type":["string","null"],"format":"date-time"},"updated_at":{"type":"string","format":"date-time"}}},"Shipment":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"carrier":{"type":"string","example":"Colissimo"},"tracking_number":{"type":"string"},"tracking_url":{"type":["string","null"]},"status":{"type":"string","enum":["label_created","shipped","in_transit","delivered","returned","lost","cancelled"]},"shipped_at":{"type":["string","null"],"format":"date-time"},"delivered_at":{"type":["string","null"],"format":"date-time"}}},"File":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["ready"]},"filename":{"type":["string","null"]},"mime_type":{"type":"string","enum":["image/png","image/jpeg"]},"size_bytes":{"type":"integer"},"width_px":{"type":"integer"},"height_px":{"type":"integer"},"dpi":{"type":["integer","null"],"description":"Resolution declared by the file. The order check compares pixels with the print area, not this value."},"sha256":{"type":["string","null"]},"url":{"type":"string"},"created_at":{"type":"string","format":"date-time"}}},"EventType":{"type":"string","enum":["order.created","order.in_production","order.shipped","order.delivered","order.issue","order.cancelled","catalog.variant_discontinued"]},"WebhookEndpoint":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string"},"events":{"type":"array","items":{"$ref":"#/components/schemas/EventType"}},"status":{"type":"string","enum":["active","paused","disabled"]},"last_delivery":{"type":["object","null"],"properties":{"type":{"type":"string"},"status":{"type":"string"},"http_status":{"type":["integer","null"]},"at":{"type":["string","null"],"format":"date-time"}}},"created_at":{"type":"string","format":"date-time"},"updated_at":{"type":"string","format":"date-time"},"paused_at":{"type":["string","null"],"format":"date-time"},"deleted_at":{"type":["string","null"],"format":"date-time"}}},"Event":{"type":"object","description":"Body of every webhook delivery. Headers: `TPOP-Event-Id`, `TPOP-Event-Type`, `TPOP-Signature: t=<timestamp>,v1=<hex HMAC-SHA256 of \"<timestamp>.<body>\">`.","properties":{"id":{"type":"string","format":"uuid","description":"Same for every endpoint and every retry: use it to ignore repeats."},"type":{"$ref":"#/components/schemas/EventType"},"created_at":{"type":"string","format":"date-time"},"data":{"type":"object","description":"`order` (id, number, external_id, status, test); `shipments` for order.shipped and order.delivered; `issue.code` for order.issue; `variant` for catalog.variant_discontinued.","additionalProperties":true}}}}},"webhooks":{"orderEvent":{"post":{"summary":"Order or catalog event sent to your endpoint","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Event"}}}},"responses":{"200":{"description":"Answer 2xx within 10 seconds."}}}}}}