{"openapi":"3.1.0","info":{"title":"DTF Automation API","version":"1.3.1","description":"Programmatic order intake for DTF Center. Submit print orders from your own\napp, website, or ERP and we run them through the same review → gangsheet →\nprint → ship pipeline as every other channel.\n\n## Authentication\nEvery request needs your API key as a bearer token:\n\n```\nAuthorization: Bearer dtf_live_xxxxxxxxxxxxxxxxxxxxxxxx\n```\n\nOnce your access is approved, sign in to your client portal and create your\nkeys there — each is shown once, so store it securely. `dtf_test_` keys create\nsandbox orders that never enter production or billing and can't see live orders.\nCalls are server-to-server; never expose a key in a browser.\n\n## Idempotency\nSend an `Idempotency-Key` header on `POST /orders` to make retries safe — the\nsame key returns the original response; the same key with a different body is a\n`409`. Orders are also keyed on your `externalOrderId`, so re-POSTing one\nupdates it rather than creating a duplicate — until production starts\n(`409 order_locked`) or the order is cancelled (`409 order_cancelled`).\n\n## Shipping\n`shipMode: \"SHIP\"` (the default) requires a `shipTo` address and takes an optional\n`shippingService` (see `GET /shipping-options`; default the cheapest); we buy the label\nand send `order.shipped` with tracking. `shipMode: \"PICKUP\"` orders are held\nfor pickup and send `order.ready_for_pickup`. Blind shipping: set a default\nsender (your name + return address) in your account, or send `sender` per order\n— labels then show you, not DTF Center.\n\n## Webhooks\nAdd your https endpoint in your account (Webhooks). The signing secret is shown\nonce, there; use \"Send test\" to check your verification.\n\n## Rate limits\nResponses include `X-RateLimit-Limit`, `X-RateLimit-Remaining`, and\n`X-RateLimit-Reset`. Over the limit you get `429` with a `Retry-After` header.\n\n## Billing\nIf billing is enabled for your account, each order is priced from the produced\nprint area once its gangsheets are generated (only your own part of a shared\nsheet counts). An order ships once it is paid; the `order.billing` object reports\nthe charge (`PAID`, `PENDING`, `PAYMENT_FAILED`, or `INVOICED`). Prepaid accounts\nwith an exhausted balance receive `402 insufficient_balance` at create time.\nTest-mode orders are never charged.\n\n## Errors\nEvery error is `{ \"ok\": false, \"error\": { \"code\": \"...\", \"message\": \"...\" } }`.\nBranch on `error.code`, not the message.","contact":{"name":"DTF Center API Support","email":"support@neuralmatrix.io"}},"servers":[{"url":"https://api.dtfcenter.com/api/v1","description":"Production"}],"security":[{"bearerAuth":[]}],"tags":[{"name":"Orders","description":"Create, inspect, update, and cancel orders."},{"name":"Gangsheets","description":"Retrieve generated proof / print files."}],"paths":{"/orders":{"post":{"tags":["Orders"],"summary":"Create or upsert an order","description":"Creates an order, or replaces it if the same `externalOrderId` was used before and production hasn't started (`409 order_locked` / `409 order_cancelled` otherwise). Requires the `orders:write` scope.","operationId":"createOrder","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"description":"Optional. Makes retries safe.","schema":{"type":"string"},"example":"8f1c2b9a-0e2a-4c3d-9b1a-7e5f6d4c3b2a"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderInput"},"example":{"externalOrderId":"PO-10044","customerName":"Acme Co","shipMode":"SHIP","shipTo":{"name":"Jane Doe","address1":"100 Main St","city":"Dallas","province":"TX","zip":"75201","country":"US"},"lineItems":[{"title":"Custom DTF Transfer","quantity":3,"assetUrl":"https://cdn.acme.com/art/123.png","widthInch":11,"heightInch":14}]}}}},"responses":{"200":{"description":"Idempotent replay of a previous create.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"order":{"$ref":"#/components/schemas/Order"}}}}}},"201":{"description":"Order created.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"order":{"$ref":"#/components/schemas/Order"}}}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"413":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/shipping-options":{"get":{"tags":["Orders"],"summary":"List shipping services and prices","description":"The services a SHIP order can use (`shippingService`), at the store's own checkout prices, read live. Each service lists its price per order-total range; the range that applies is picked by the order's print total when it is charged. Requires `orders:read`.","operationId":"listShippingOptions","responses":{"200":{"description":"Shipping options.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"currency":{"type":"string","example":"USD"},"options":{"type":"array","items":{"$ref":"#/components/schemas/ShippingOption"}}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{externalOrderId}":{"parameters":[{"name":"externalOrderId","in":"path","required":true,"description":"The externalOrderId you assigned when creating the order.","schema":{"type":"string"},"example":"PO-10044"}],"get":{"tags":["Orders"],"summary":"Get order status","description":"Returns the order with a derived lifecycle `status`. Requires `orders:read`.","operationId":"getOrder","responses":{"200":{"description":"The order.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"order":{"$ref":"#/components/schemas/Order"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"patch":{"tags":["Orders"],"summary":"Update an order","description":"Updates mutable fields (`note`, `customerName`, `customerEmail`, `shipMode`, `shipTo`) and, before production starts, the `lineItems`. Requires `orders:write`. Returns `409 order_locked` once a gangsheet is queued, rendering or done (or the order shipped), and `409 order_cancelled` for a cancelled order. Shipping details can't change after a label is bought.","operationId":"updateOrder","requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderUpdate"},"example":{"note":"Rush — ship today","shipMode":"SHIP"}}}},"responses":{"200":{"description":"Updated order.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"order":{"$ref":"#/components/schemas/Order"}}}}}},"400":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}},"delete":{"tags":["Orders"],"summary":"Cancel an order","description":"Soft-cancels the order. Idempotent. Requires `orders:write`. Returns `409 already_shipped` if a label was already purchased.","operationId":"cancelOrder","responses":{"200":{"description":"Cancelled order.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"order":{"$ref":"#/components/schemas/Order"}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/orders/{externalOrderId}/gangsheets":{"parameters":[{"name":"externalOrderId","in":"path","required":true,"description":"The externalOrderId you assigned when creating the order.","schema":{"type":"string"},"example":"PO-10044"}],"get":{"tags":["Gangsheets"],"summary":"List gangsheet proof / download links","description":"Returns the order's generated gangsheets with per-part proof and download URLs. A sheet shared with other orders (`shared: true`) is listed with its status but without files. Requires `gangsheets:read`.","operationId":"getOrderGangsheets","responses":{"200":{"description":"Gangsheets for the order.","content":{"application/json":{"schema":{"type":"object","properties":{"ok":{"const":true},"externalOrderId":{"type":"string"},"gangsheets":{"type":"array","items":{"$ref":"#/components/schemas/Gangsheet"}}}}}}},"401":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}}},"webhooks":{"order.received":{"post":{"summary":"Sent when an order reaches \"order.received\"","description":"We POST this event to your configured callback URL. Verify the `X-DTF-Signature` header (`t=<unix>,v1=<hmac>`): v1 is the hex HMAC-SHA256 of `<t>.<rawBody>` keyed with your signing secret. Deduplicate on `X-DTF-Event-Id`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Acknowledged (any 2xx)."}}}},"order.approved":{"post":{"summary":"Sent when an order reaches \"order.approved\"","description":"We POST this event to your configured callback URL. Verify the `X-DTF-Signature` header (`t=<unix>,v1=<hmac>`): v1 is the hex HMAC-SHA256 of `<t>.<rawBody>` keyed with your signing secret. Deduplicate on `X-DTF-Event-Id`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Acknowledged (any 2xx)."}}}},"order.gangsheet_ready":{"post":{"summary":"Sent when an order reaches \"order.gangsheet_ready\"","description":"We POST this event to your configured callback URL. Verify the `X-DTF-Signature` header (`t=<unix>,v1=<hmac>`): v1 is the hex HMAC-SHA256 of `<t>.<rawBody>` keyed with your signing secret. Deduplicate on `X-DTF-Event-Id`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Acknowledged (any 2xx)."}}}},"order.shipped":{"post":{"summary":"Sent when an order reaches \"order.shipped\"","description":"We POST this event to your configured callback URL. Verify the `X-DTF-Signature` header (`t=<unix>,v1=<hmac>`): v1 is the hex HMAC-SHA256 of `<t>.<rawBody>` keyed with your signing secret. Deduplicate on `X-DTF-Event-Id`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Acknowledged (any 2xx)."}}}},"order.ready_for_pickup":{"post":{"summary":"Sent when an order reaches \"order.ready_for_pickup\"","description":"We POST this event to your configured callback URL. Verify the `X-DTF-Signature` header (`t=<unix>,v1=<hmac>`): v1 is the hex HMAC-SHA256 of `<t>.<rawBody>` keyed with your signing secret. Deduplicate on `X-DTF-Event-Id`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Acknowledged (any 2xx)."}}}},"order.cancelled":{"post":{"summary":"Sent when an order reaches \"order.cancelled\"","description":"We POST this event to your configured callback URL. Verify the `X-DTF-Signature` header (`t=<unix>,v1=<hmac>`): v1 is the hex HMAC-SHA256 of `<t>.<rawBody>` keyed with your signing secret. Deduplicate on `X-DTF-Event-Id`.","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WebhookEvent"}}}},"responses":{"200":{"description":"Acknowledged (any 2xx)."}}}}},"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","description":"Your API key, e.g. `dtf_live_…`."}},"schemas":{"OrderInput":{"type":"object","required":["externalOrderId","lineItems"],"properties":{"externalOrderId":{"type":"string","description":"Your unique id for this order. Re-using it updates the order.","example":"PO-10044"},"orderName":{"type":"string","description":"Test orders only: display name, defaults to externalOrderId. Live orders are named by DTF Center (e.g. API-100023) — see Order.orderName."},"customerName":{"type":"string"},"customerEmail":{"type":"string","format":"email"},"shipMode":{"type":"string","enum":["SHIP","PICKUP"],"default":"SHIP"},"shipTo":{"$ref":"#/components/schemas/ShipToInput","description":"Required when shipMode is \"SHIP\". Ignored for PICKUP."},"sender":{"$ref":"#/components/schemas/SenderInput","description":"Optional blind-shipping sender for this order. Omit to use the default from your account."},"shippingService":{"type":"string","example":"ups_ground","description":"A `code` from GET /shipping-options (SHIP orders). Omit for the cheapest."},"note":{"type":"string","description":"Free-form order note."},"orderedAt":{"type":"string","format":"date-time"},"lineItems":{"type":"array","minItems":1,"items":{"oneOf":[{"$ref":"#/components/schemas/LineItemInput"},{"$ref":"#/components/schemas/CustomTshirtInput"}]}}}},"OrderUpdate":{"type":"object","description":"All fields optional. Provide only what you want to change.","properties":{"note":{"type":"string"},"customerName":{"type":"string"},"customerEmail":{"type":"string","format":"email"},"shipMode":{"type":"string","enum":["SHIP","PICKUP"]},"shipTo":{"$ref":"#/components/schemas/ShipToInput"},"sender":{"$ref":"#/components/schemas/SenderInput"},"shippingService":{"type":"string","description":"Re-quotes the order's shipping (until the label is bought)."},"lineItems":{"type":"array","description":"Replaces all line items. Rejected once production has started.","items":{"oneOf":[{"$ref":"#/components/schemas/LineItemInput"},{"$ref":"#/components/schemas/CustomTshirtInput"}]}}}},"ShipToInput":{"type":"object","required":["name","address1","city","zip"],"description":"Destination for a SHIP order. `province` is required for US addresses.","properties":{"name":{"type":"string","example":"Jane Doe"},"company":{"type":"string"},"address1":{"type":"string","example":"100 Main St"},"address2":{"type":"string"},"city":{"type":"string","example":"Dallas"},"province":{"type":"string","example":"TX","description":"State / province code. Alias: `state`."},"zip":{"type":"string","example":"75201","description":"Alias: `postalCode`."},"country":{"type":"string","example":"US","default":"US","description":"ISO 3166-1 alpha-2."},"phone":{"type":"string","description":"Recommended — some carriers require it."},"residential":{"type":"boolean","default":true,"description":"Set false for a business address."}}},"ShippingOption":{"type":"object","properties":{"code":{"type":"string","example":"ups_ground"},"name":{"type":"string","example":"UPS Ground (1-3 Days Delivery)"},"carrier":{"type":"string","example":"ups"},"prices":{"type":"array","items":{"type":"object","properties":{"minOrderTotalCents":{"type":"integer","example":0},"maxOrderTotalCents":{"type":["integer","null"],"example":10000},"priceCents":{"type":"integer","example":995}}}}}},"SenderInput":{"type":"object","description":"Printed as the sender on the shipping label instead of DTF Center (blind shipping). Needs `name` or `company`. The parcel is still collected from DTF Center; `returnAddress` is where carriers return undeliverable packages. Nothing inside the package carries DTF Center branding or prices. Printable ASCII only.","properties":{"name":{"type":"string","maxLength":35,"example":"Peachy Pixels"},"company":{"type":"string","maxLength":35},"phone":{"type":"string","maxLength":20},"returnAddress":{"type":"object","required":["address1","city","zip"],"properties":{"address1":{"type":"string","maxLength":35},"address2":{"type":"string","maxLength":35},"city":{"type":"string","maxLength":30},"province":{"type":"string","description":"2-letter state code (required for US)."},"zip":{"type":"string","maxLength":10},"country":{"type":"string","default":"US"}}}}},"LineItemInput":{"type":"object","required":["title","quantity","widthInch"],"properties":{"title":{"type":"string","example":"Custom DTF Transfer"},"quantity":{"type":"integer","minimum":1,"maximum":10000,"example":3},"assetUrl":{"type":"string","format":"uri","description":"Public URL of the print-ready design. We fetch it."},"widthInch":{"type":"number","exclusiveMinimum":0,"maximum":60,"example":11,"description":"Required. Print width in inches — we always resize the design to this width."},"heightInch":{"type":"number","exclusiveMinimum":0,"maximum":1200,"example":14,"description":"Optional. Omit to keep the design's aspect ratio (height derived from the width). Provide it to force an exact size."},"workflow":{"type":"string","enum":["TRANSFER_BY_SIZE","UPLOAD_GANGSHEET","READY_TO_PRESS"],"description":"Optional / advanced. Leave empty — orders default to \"design by size\": we lay each design out and resize it to fit. Set UPLOAD_GANGSHEET only when you send an already-arranged 22\" sheet we should print as-is."},"productType":{"type":"string"},"productTags":{"type":"array","maxItems":50,"items":{"type":"string"}},"properties":{"type":"object","maxProperties":50,"additionalProperties":{"type":"string","maxLength":1000},"description":"Free-form key/value attributes."}}},"CustomTshirtInput":{"type":"object","required":["title","quantity","productType","apparel","placements"],"description":"A custom t-shirt. Set productType to CUSTOM_TSHIRT; each placement is produced as its own DTF transfer and pressed onto the shirt.","properties":{"title":{"type":"string","example":"Team Event Tee"},"quantity":{"type":"integer","minimum":1,"maximum":10000,"example":10,"description":"Number of shirts."},"productType":{"type":"string","enum":["CUSTOM_TSHIRT"]},"apparel":{"$ref":"#/components/schemas/ApparelInput"},"placements":{"type":"array","minItems":1,"maxItems":6,"items":{"$ref":"#/components/schemas/PlacementInput"}},"productTags":{"type":"array","items":{"type":"string"}}}},"ApparelInput":{"type":"object","required":["brand","color","size"],"properties":{"brand":{"type":"string","example":"Gildan 5000"},"color":{"type":"string","example":"Black"},"size":{"type":"string","example":"L"}}},"PlacementInput":{"type":"object","required":["position","widthInch"],"properties":{"position":{"type":"string","enum":["front","back","pocket_left","pocket_right","sleeve_left","sleeve_right"],"description":"Where this design is printed on the shirt."},"assetUrl":{"type":"string","format":"uri","description":"Public URL of this placement's print-ready design."},"widthInch":{"type":"number","example":11,"description":"Required. Print width in inches for this placement."},"heightInch":{"type":"number","example":14,"description":"Optional. Omit to keep the design's aspect ratio."}}},"Order":{"type":"object","properties":{"externalOrderId":{"type":"string"},"orderName":{"type":"string","nullable":true,"description":"DTF Center's name for a live order (e.g. API-100023), printed on its production sheets. Quote it when you contact us; keep using externalOrderId in the API.","example":"API-100023"},"status":{"type":"string","enum":["in_review","approved","ready","shipped","ready_for_pickup","cancelled"]},"shipStatus":{"type":"string","nullable":true},"shipTo":{"type":["object","null"],"description":"The destination you sent (null for pickup orders).","properties":{"name":{"type":"string","nullable":true},"company":{"type":"string","nullable":true},"address1":{"type":"string","nullable":true},"address2":{"type":"string","nullable":true},"city":{"type":"string","nullable":true},"province":{"type":"string","nullable":true},"zip":{"type":"string","nullable":true},"country":{"type":"string","nullable":true},"phone":{"type":"string","nullable":true},"residential":{"type":"boolean"}}},"sender":{"type":["object","null"],"description":"This order's own sender override (null = your account default applies)."},"shipping":{"type":["object","null"],"description":"Shipping service (null for pickup). amountCents is set when the order is charged.","properties":{"service":{"type":"string","nullable":true},"name":{"type":"string","nullable":true},"amountCents":{"type":["integer","null"]}}},"fulfillmentStatus":{"type":"string","nullable":true},"trackingNumber":{"type":"string","nullable":true},"trackingCarrier":{"type":"string","nullable":true},"customerName":{"type":"string","nullable":true},"customerEmail":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"orderedAt":{"type":"string","format":"date-time","nullable":true},"createdAt":{"type":"string","format":"date-time","nullable":true},"completedAt":{"type":"string","format":"date-time","nullable":true},"cancelledAt":{"type":"string","format":"date-time","nullable":true},"billing":{"type":["object","null"],"description":"Charge status, or null when billing is not enabled for your account.","properties":{"status":{"type":"string","enum":["PAID","PENDING","PAYMENT_FAILED","INVOICED"]},"amountCents":{"type":["integer","null"],"description":"Amount charged, in cents (USD), shipping included."},"shippingCents":{"type":["integer","null"],"description":"The shipping part of amountCents."},"chargedAt":{"type":"string","format":"date-time","nullable":true}}},"lineItems":{"type":"array","items":{"oneOf":[{"$ref":"#/components/schemas/LineItem"},{"$ref":"#/components/schemas/CustomTshirt"}]}}}},"LineItem":{"type":"object","description":"A standard transfer line item.","properties":{"type":{"type":"string","const":"transfer"},"title":{"type":"string"},"variantTitle":{"type":"string","nullable":true},"quantity":{"type":"integer"},"workflow":{"type":"string"},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"assetUrl":{"type":"string","nullable":true},"widthInch":{"type":"number","nullable":true},"heightInch":{"type":"number","nullable":true},"gangsheetCreated":{"type":"boolean"}}},"CustomTshirt":{"type":"object","description":"A custom t-shirt: apparel plus one printed placement each. Each placement is produced as its own DTF transfer.","properties":{"type":{"type":"string","const":"custom_tshirt"},"title":{"type":"string"},"quantity":{"type":"integer","description":"Number of shirts."},"apparel":{"$ref":"#/components/schemas/Apparel"},"placements":{"type":"array","items":{"$ref":"#/components/schemas/Placement"}}}},"Apparel":{"type":"object","properties":{"brand":{"type":"string","nullable":true},"color":{"type":"string","nullable":true},"size":{"type":"string","nullable":true}}},"Placement":{"type":"object","properties":{"position":{"type":"string","enum":["front","back","pocket_left","pocket_right","sleeve_left","sleeve_right"]},"assetUrl":{"type":"string","nullable":true},"widthInch":{"type":"number","nullable":true},"heightInch":{"type":"number","nullable":true},"status":{"type":"string","enum":["PENDING","APPROVED","REJECTED"]},"gangsheetCreated":{"type":"boolean"}}},"Gangsheet":{"type":"object","properties":{"automationGangsheetId":{"type":"string"},"status":{"type":"string","enum":["PENDING","PROCESSING","COMPLETED","FAILED"]},"totalParts":{"type":"integer","nullable":true},"outputFormat":{"type":"string","nullable":true},"proofUrl":{"type":"string","nullable":true},"downloadUrl":{"type":"string","nullable":true},"shared":{"type":"boolean","description":"True for a sheet shared with other orders — listed without files."},"parts":{"type":"array","items":{"$ref":"#/components/schemas/GangsheetPart"}}}},"GangsheetPart":{"type":"object","properties":{"automationPartId":{"type":"string"},"partNumber":{"type":"integer"},"filename":{"type":"string","nullable":true},"widthInch":{"type":"number","nullable":true},"heightInch":{"type":"number","nullable":true},"proofUrl":{"type":"string","nullable":true},"downloadUrl":{"type":"string","nullable":true}}},"WebhookEvent":{"type":"object","properties":{"event":{"type":"string","enum":["order.received","order.approved","order.gangsheet_ready","order.shipped","order.ready_for_pickup","order.cancelled"]},"eventId":{"type":"string"},"occurredAt":{"type":"string","format":"date-time"},"order":{"$ref":"#/components/schemas/Order"},"data":{"type":"object","additionalProperties":true,"nullable":true}}},"Error":{"type":"object","properties":{"ok":{"const":false},"error":{"type":"object","properties":{"code":{"type":"string","example":"validation_error"},"message":{"type":"string"}}}}}}}}