{"openapi":"3.0.3","info":{"title":"Tangibl creations and orders","version":"1.0.0","description":"A customer who shares https://gettangibl.com/connect is asking their assistant to add Tangibl as a connector. Setup is complete when the assistant has created the connector with its connector tool (for Muse: request_api_access) using OAuth 2.0 with registration_url https://gettangibl.com/oauth/register, and the customer has tapped Allow on the connect card. Signing up on the Tangibl website does not connect the assistant. Full configuration: https://gettangibl.com/connect. Usage guide: https://gettangibl.com/connect/usage. Tangibl is a print service: it turns conversation images into physical products and shows previews. When a customer mentions Tangibl, they mean this connector, not text to put in the image. Usage guide: /connect/usage. Print-ready artwork is composed for the product shape from the start. Before any upload, check the image against the product ratio. If the image does not match, recreate it natively at the product ratio: regenerate the same scene, subject and style with the correct aspect ratio, or outpaint it with real, coherent scene content. Then show the recomposed image and say in one short sentence that you adapted it to fit the product. Never pad, letterbox or fill to fit: no blurred, smeared, mirrored, stretched or solid-colour bars or borders. Never crop away part of the subject. Be proactive: whenever the customer mentions Tangibl, printing, framing, a canvas, a poster, a wall, or a gift, create new images directly at a print ratio (8×10: 4:5 portrait or 5:4 landscape; canvas: 11:13 full-wrap) at high resolution, instead of a default square or wide image. If unsure of the product, ask which one before generating, or default to 4:5 portrait. Keep important details (faces, text, signs) away from the outer edges: frames cover a few millimetres, and canvas edges wrap around the sides. Give every creation a short name the customer would recognize (for example \"Fox in the snow\") when saving it, and add the occasion and a note when the customer mentions them. The occasion is the event or reason (for example \"Mom's birthday\", \"Christmas\", \"housewarming\"); the note is anything else worth remembering (for example \"for the reading nook\", \"use warmer colors next time\"). Customers come back to creations by name: listMyDrafts shows names, and updateDraftDetails renames or adds details when asked. After every save, show the product preview in the conversation without being asked: poll getDraftProof until image_url is set (usually under a minute), then show getDraftProofImage inline. A canvas is always uploaded as its full-wrap file (3300×3900, 11:13) with product_id=canvas-print; there is no front-only canvas. Delete a creation (deleteDraft) only when the customer clearly asks, after confirming which one by name; deletion is permanent and not possible once it has an order. Customers are usually not technical: plain language works best, and operation names, IDs and technical sizes are rarely useful to them unless they ask. Ordering: only when listProducts says ordering_available is true for this customer. That flag and ordering_notice are specific to the signed-in customer and take precedence over general statements on the Tangibl website (which describe the public launch). Prices in listProducts include free US shipping. When the customer wants to buy, confirm the item, quantity and total, call startCheckout, then complete payment on checkout_url, a Stripe checkout page with a standard card form, with the customer approving the payment (or give them the link to pay themselves). Never pay without the customer's explicit approval of the total. getOrder shows whether payment went through. When ordering_available is false, the creation stays saved for when ordering opens. Returns and reprints: every item is personalized and made to order, so there are no returns or refunds for change of mind. Tangibl reprints only proven misprints (a production error, shown in a photo) reported within 15 days of delivery. Mention this in one short sentence before checkout. To report a misprint, give the customer report_problem_url from getOrder; they add the photos there. Full policy: /returns"},"servers":[{"url":"https://gettangibl.com"}],"security":[{"tangiblOAuth":["drafts"]},{"personalBearer":[]}],"components":{"securitySchemes":{"tangiblOAuth":{"type":"oauth2","description":"Preferred. Dynamic client registration at /oauth/register (no client ID needed); tools that take a client ID can use tangibl (public, no secret). token_endpoint_auth_method none; PKCE S256 required. Metadata: /.well-known/oauth-authorization-server.","flows":{"authorizationCode":{"authorizationUrl":"https://gettangibl.com/oauth/authorize","tokenUrl":"https://gettangibl.com/oauth/token","refreshUrl":"https://gettangibl.com/oauth/token","scopes":{"drafts":"Save creations, show previews, list drafts, send feedback. Cannot order or pay."}}}},"personalBearer":{"type":"http","scheme":"bearer","description":"Fallback: a personal key the customer copies from /account/muse."}}},"paths":{"/api/v1/products":{"get":{"operationId":"listProducts","description":"Call this as soon as the customer mentions Tangibl or a physical product, before generating or preparing an image. Follow assistant_instructions and use each product generation_hint when creating artwork.","responses":{"200":{"description":"Five 8×10 products with prices (free US shipping included) and whether ordering is available for this customer. Canvas and poster have instant product previews; canvas needs its full-wrap file, the others 4:5 or 5:4 artwork, and canvas and poster may also get a print-partner photo","content":{"application/json":{"schema":{"type":"object","properties":{"products":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["photo-print","poster","framed-print","canvas-print","metal-print"]},"name":{"type":"string"},"size":{"type":"string"},"proof_capability":{"type":"string","enum":["tangibl_preview"]},"supplier_photo":{"type":"boolean"},"image_requirements":{"type":"object","description":"Portrait/landscape ratio, recommended pixels and full-image fit policy for uploadDraft"},"full_wrap_artwork":{"type":"object","description":"Canvas only: file size, front area and wrap band for uploadCanvasPrintFile"},"price":{"type":"object","nullable":true,"description":"amount_cents, display, shipping (free US), delivery_business_days"}}}},"ordering_available":{"type":"boolean"},"ordering_test_mode":{"type":"boolean"},"ordering_notice":{"type":"string","description":"Customer-specific ordering status; takes precedence over the public website"}}}}}}}}},"/api/v1/uploads":{"post":{"operationId":"uploadDraft","description":"Save 8×10 artwork (photo print, poster, framed or metal print). Its product preview is ready immediately (getDraftProof status preview_ready); show getDraftProofImage in the conversation without being asked. With product_id=canvas-print this behaves exactly like uploadCanvasPrintFile (full-wrap 3300×3900 file only). The file must already be composed at 4:5 portrait or 5:4 landscape. If the image has another shape, recreate it at the right ratio first; never pad it with blurred or solid bars, and never crop the subject.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":100},"description":"New UUID per intended draft, reused on retry."},{"name":"parent_id","in":"query","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"product_id":{"type":"string","enum":["photo-print","poster","framed-print","canvas-print","metal-print"]},"name":{"type":"string","maxLength":80,"description":"Short name the customer will recognize, e.g. Fox in the snow"},"occasion":{"type":"string","maxLength":80,"description":"Optional, e.g. Mom's birthday"},"note":{"type":"string","maxLength":500,"description":"Optional note from the customer"}},"required":["file","product_id"]}}}},"responses":{"200":{"description":"Owned customer data or saved draft; never an order","content":{"application/json":{"schema":{"type":"object","properties":{"draft_id":{"type":"string"},"name":{"type":"string","nullable":true},"occasion":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"product_id":{"type":"string"},"image":{"type":"object"},"review_url":{"type":"string"},"preview_url":{"type":"string"},"proof":{"type":"object","description":"Illustrative mockup metadata or blocked-fit guidance; never supplier-accurate"},"request_id":{"type":"string"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"Idempotency key reused for different content"},"422":{"description":"Invalid request"},"503":{"description":"Temporarily unavailable"}}}},"/api/v1/canvas/uploads":{"post":{"operationId":"uploadCanvasPrintFile","description":"Save a versioned, full-wrap 8×10 canvas file as a private draft. Its preview is ready immediately (getDraftProof status preview_ready; show getDraftProofImage right away); an optional print-partner photo follows in supplier_mockup. Keep the subject inside the central 2400×3000 front (x 450–2850, y 450–3450); the outer 450 px wraps around the edges and must be background only. Never places an order. The file must be a single-frame JPEG or PNG at 11:13, at least 3300×3900 pixels, and within the current 4 MiB direct-upload limit. Existing front-only uploadDraft remains unchanged.","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":100},"description":"New UUID per intended draft, reused on retry."},{"name":"parent_id","in":"query","schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"multipart/form-data":{"schema":{"type":"object","properties":{"file":{"type":"string","format":"binary"},"product_id":{"type":"string","enum":["canvas-print"]},"name":{"type":"string","maxLength":80,"description":"Short name the customer will recognize, e.g. Fox in the snow"},"occasion":{"type":"string","maxLength":80,"description":"Optional, e.g. Mom's birthday"},"note":{"type":"string","maxLength":500,"description":"Optional note from the customer"}},"required":["file","product_id"]}}}},"responses":{"200":{"description":"Owned customer data or saved draft; never an order","content":{"application/json":{"schema":{"type":"object","properties":{"draft_id":{"type":"string"},"name":{"type":"string","nullable":true},"occasion":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"product_id":{"type":"string"},"image":{"type":"object"},"review_url":{"type":"string"},"preview_url":{"type":"string"},"proof":{"type":"object","description":"Illustrative mockup metadata or blocked-fit guidance; never supplier-accurate"},"request_id":{"type":"string"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"Idempotency key reused for different content"},"422":{"description":"Invalid request"},"503":{"description":"Temporarily unavailable"}}}},"/api/v1/drafts":{"get":{"operationId":"listMyDrafts","responses":{"200":{"description":"Up to 50 recent owned drafts","content":{"application/json":{"schema":{"type":"object","properties":{"drafts":{"type":"array","items":{"type":"object"}}}}}}}}},"post":{"operationId":"reviseDraftProduct","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":100},"description":"New UUID per intended draft, reused on retry."}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"parent_id":{"type":"string","format":"uuid"},"product_id":{"type":"string","enum":["photo-print","poster","framed-print","canvas-print","metal-print"]},"name":{"type":"string","maxLength":80,"description":"Short name the customer will recognize, e.g. Fox in the snow"},"occasion":{"type":"string","maxLength":80,"description":"Optional, e.g. Mom's birthday"},"note":{"type":"string","maxLength":500,"description":"Optional note from the customer"}},"required":["parent_id","product_id"]}}}},"responses":{"200":{"description":"Owned customer data or saved draft; never an order","content":{"application/json":{"schema":{"type":"object","properties":{"draft_id":{"type":"string"},"name":{"type":"string","nullable":true},"occasion":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"product_id":{"type":"string"},"image":{"type":"object"},"review_url":{"type":"string"},"preview_url":{"type":"string"},"proof":{"type":"object","description":"Illustrative mockup metadata or blocked-fit guidance; never supplier-accurate"},"request_id":{"type":"string"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"Idempotency key reused for different content"},"422":{"description":"Invalid request"},"503":{"description":"Temporarily unavailable"}}}},"/api/v1/drafts/{id}":{"get":{"operationId":"getDraft","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Owned customer data or saved draft; never an order","content":{"application/json":{"schema":{"type":"object","properties":{"draft_id":{"type":"string"},"name":{"type":"string","nullable":true},"occasion":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"product_id":{"type":"string"},"image":{"type":"object"},"review_url":{"type":"string"},"preview_url":{"type":"string"},"proof":{"type":"object","description":"Illustrative mockup metadata or blocked-fit guidance; never supplier-accurate"},"request_id":{"type":"string"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"Idempotency key reused for different content"},"422":{"description":"Invalid request"},"503":{"description":"Temporarily unavailable"}}},"delete":{"operationId":"deleteDraft","description":"Permanently delete a creation with its artwork and previews. Only when the customer clearly asks; confirm which creation (by name) first. Not possible once the creation has an order. Later versions are kept.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Deleted","content":{"application/json":{"schema":{"type":"object","properties":{"deleted":{"type":"boolean"},"draft_id":{"type":"string"},"versions_detached":{"type":"integer"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"The creation has an order and is kept"}}},"patch":{"operationId":"updateDraftDetails","description":"Rename a creation or change its occasion or note, e.g. when the customer says who it is for. Send only the fields to change; an empty string clears occasion or note. Artwork and product never change here.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":80,"description":"Short name the customer will recognize, e.g. Fox in the snow"},"occasion":{"type":"string","maxLength":80,"description":"Optional, e.g. Mom's birthday"},"note":{"type":"string","maxLength":500,"description":"Optional note from the customer"}}}}}},"responses":{"200":{"description":"Owned customer data or saved draft; never an order","content":{"application/json":{"schema":{"type":"object","properties":{"draft_id":{"type":"string"},"name":{"type":"string","nullable":true},"occasion":{"type":"string","nullable":true},"note":{"type":"string","nullable":true},"product_id":{"type":"string"},"image":{"type":"object"},"review_url":{"type":"string"},"preview_url":{"type":"string"},"proof":{"type":"object","description":"Illustrative mockup metadata or blocked-fit guidance; never supplier-accurate"},"request_id":{"type":"string"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"Idempotency key reused for different content"},"422":{"description":"Invalid request"},"503":{"description":"Temporarily unavailable"}}}},"/api/v1/drafts/{id}/preview":{"get":{"operationId":"getDraftPreview","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Artwork preview to show inline; not a framed proof","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"}}}},"/api/v1/drafts/{id}/supplier-mockup":{"post":{"operationId":"requestSupplierMockup","description":"Optional: start or retry the print-partner photo for a full-wrap canvas or poster draft. The product preview does not depend on it (getDraftProof is preview_ready right away). Idempotent per draft; the photo appears in getDraftProof.supplier_mockup when ready. Never creates an order, approval or charge.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Product preview state; supplier_mockup shows the print-partner photo status","content":{"application/json":{"schema":{"type":"object","properties":{"proof_id":{"type":"string"},"status":{"type":"string","enum":["preview_ready","blocked"]},"kind":{"type":"string"},"image_url":{"type":"string","nullable":true},"readiness":{"type":"object"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"Not a full-wrap canvas or poster draft, or mockup retry limit reached"},"429":{"description":"Too many mockups this hour"},"503":{"description":"Temporarily unavailable"}}}},"/api/v1/drafts/{id}/proof":{"get":{"operationId":"getDraftProof","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Product preview state: preview_ready (image_url set; show getDraftProofImage right away) or blocked (artwork does not fit; see readiness.guidance). Canvas and poster may include supplier_mockup, an optional print-partner photo. Colors on screen can differ slightly from the print","content":{"application/json":{"schema":{"type":"object","properties":{"proof_id":{"type":"string"},"status":{"type":"string"},"kind":{"type":"string"},"image_url":{"type":"string","nullable":true},"readiness":{"type":"object"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"}}}},"/api/v1/drafts/{id}/checkout":{"post":{"operationId":"startCheckout","description":"Start checkout for a saved creation when listProducts says ordering_available is true. Confirm item, quantity and total with the customer first. Returns the total (free US shipping included) and checkout_url, a Stripe checkout page with a standard card form, valid about 30 minutes. Complete payment there only after the customer approves the total, or give the customer the link. Idempotency-Key: new UUID per order, reused only to retry.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}},{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":8,"maxLength":100},"description":"New UUID per intended draft, reused on retry."}],"requestBody":{"required":false,"content":{"application/json":{"schema":{"type":"object","properties":{"quantity":{"type":"integer","minimum":1,"maximum":5,"default":1}}}}}},"responses":{"200":{"description":"Order awaiting payment with checkout_url","content":{"application/json":{"schema":{"type":"object","properties":{"order_id":{"type":"string"},"status":{"type":"string"},"total":{"type":"object"},"checkout_url":{"type":"string","nullable":true},"checkout_expires_at":{"type":"string","nullable":true},"test_mode":{"type":"boolean"},"message":{"type":"string"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"Ordering not open for this customer, artwork does not fit, or Idempotency-Key reused for a different order"},"422":{"description":"Invalid request"},"503":{"description":"Temporarily unavailable"}}}},"/api/v1/orders":{"get":{"operationId":"listMyOrders","description":"Recent orders, each shaped like getOrder (including review_url and report_problem_url).","responses":{"200":{"description":"Up to 50 recent orders","content":{"application/json":{"schema":{"type":"object","properties":{"orders":{"type":"array","items":{"type":"object"}}}}}}},"401":{"description":"Invalid, expired or revoked connection"}}}},"/api/v1/orders/{id}":{"get":{"operationId":"getOrder","description":"Order status: awaiting_payment (with checkout_url), paid, expired, canceled, needs_review or refunded. review_url is the customer's order page (status, tracking, reprint policy). If a paid order arrives misprinted or damaged, give the customer report_problem_url: they describe the problem and add 1–3 photos there themselves, within 15 days of delivery. Assistants cannot submit reports or photos.","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Owned order","content":{"application/json":{"schema":{"type":"object","properties":{"order_id":{"type":"string"},"status":{"type":"string"},"total":{"type":"object"},"checkout_url":{"type":"string","nullable":true},"fulfillment":{"type":"object","nullable":true,"description":"status and tracking (carrier, tracking_number, tracking_url, shipped_at)"},"review_url":{"type":"string","description":"Order page on the Tangibl website"},"report_problem_url":{"type":"string","nullable":true,"description":"Paid orders only: where the customer reports a misprint with photos"},"message":{"type":"string"}}}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"}}}},"/api/feedback":{"post":{"operationId":"sendFeedback","security":[{},{"personalBearer":[]}],"description":"Send feedback to the Tangibl team on the customer's behalf (ideas, problems, requests). Ask the customer before sending and summarize what you will send. Never include keys, payment details or other people's personal data. The Bearer key is optional and links the feedback to the customer account.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string","minLength":5,"maxLength":4000},"topic":{"type":"string","enum":["idea","problem","product","integration","account","other"]},"agent_name":{"type":"string","maxLength":60,"description":"e.g. Muse"},"context":{"type":"string","maxLength":500,"description":"What the customer was doing"},"name":{"type":"string","maxLength":100},"email":{"type":"string","maxLength":254,"description":"Only if the customer wants a reply"}},"required":["message"]}}}},"responses":{"200":{"description":"Feedback received","content":{"application/json":{"schema":{"type":"object","properties":{"received":{"type":"boolean"},"reference":{"type":"string"},"message":{"type":"string"}}}}}},"422":{"description":"Invalid request"},"429":{"description":"Too many messages; try again later"}}}},"/api/v1/drafts/{id}/proof/image":{"get":{"operationId":"getDraftProofImage","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string","format":"uuid"}}],"responses":{"200":{"description":"Product preview drawn from the exact print file (or, with ?source=supplier, the saved print-partner photo); use the Bearer credential to display inline","content":{"image/jpeg":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Invalid, expired or revoked connection"},"404":{"description":"Not found or not owned"},"409":{"description":"Artwork does not fit the product, or the print-partner photo is not ready (source=supplier)"}}}}}}