{"openapi":"3.1.0","info":{"title":"CartWright (demo) API","version":"1.0.0","description":"Demo store for CartWright, the CW-100 Lab autonomous mobile robot for controlled spaces, an AIPhoundry test product. Not for sale. Prices are whole cents. No sign-in is needed for anything here. Every unit sold is built from a revision a named engineer signed off. Start at https://cartwright.aiphoundry.com/llms.txt."},"servers":[{"url":"https://cartwright.aiphoundry.com"}],"paths":{"/api/store":{"get":{"operationId":"getStore","summary":"This site and every product it lists","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Store"}}}}}}},"/api/store/products/{id}":{"get":{"operationId":"getProduct","summary":"One product","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object","properties":{"product":{"$ref":"#/components/schemas/Product"}}}}}},"404":{"description":"No such product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/store/orders":{"post":{"operationId":"placeOrder","summary":"Check an order (dry_run) or place it, as an AI agent","description":"Pay with a Stripe shared payment token (payment.token, spt_...) your user granted you for this seller: the order is paid at once with no page to visit, and packaged from the engineer-signed revision for manufacture. Without a token the response carries payment.checkout_url for a person to pay. Send an Idempotency-Key: a retry with the same key returns the same order (header Idempotent-Replayed: true). Each store caps what agents may order at once and per day; dry_run reports the caps and anything that stops the order, and writes nothing.","parameters":[{"name":"Idempotency-Key","in":"header","required":false,"schema":{"type":"string","pattern":"^[A-Za-z0-9_.:-]{8,100}$"}}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OrderRequest"}}}},"responses":{"200":{"description":"A dry run, or the same order again for a repeated Idempotency-Key","content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/DryRun"},{"$ref":"#/components/schemas/Order"}]}}}},"201":{"description":"Placed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Order"}}}},"400":{"description":"A field is missing or not valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"402":{"description":"The payment was declined; nothing is owed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"403":{"description":"This store does not take orders from agents","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"404":{"description":"No such product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"409":{"description":"Not orderable: a demo, not sellable now, or over the per-order limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"429":{"description":"Agents have reached this store's daily limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}},"503":{"description":"Payments are not switched on yet","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/store/orders/{id}":{"get":{"operationId":"getOrder","summary":"An order, with the token returned when it was placed","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"token","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"No such order","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/store/products/{id}/media/{sha256}":{"get":{"operationId":"getProductMedia","summary":"A product's image or 3D model (GLB), by its hash","parameters":[{"name":"id","in":"path","required":true,"schema":{"type":"string"}},{"name":"sha256","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"The file"},"404":{"description":"No such file","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/store/cell":{"post":{"operationId":"checkCell","summary":"Check a robot cell layout for a product the site shows in its 3D cell","description":"Send product_id and any of the layout the 3D cell page posts (cell_m, robot_xy_m, robot_turn_deg, pick_xy_m, place_xy_m in metres, x right and y back from the cell centre; speed_pct). The engine fills the rest with the robot's defaults and returns whether both stands are in reach, the cycle time and picks a minute at its catalogue speeds (a DEMO estimate), and the guard sides the arm can sweep over. When the robot has a frame template, `frames` is the cell's mount, stands and guard as cut pieces of 80/20's 40 series, laid out for this layout: the cut list as 80/20's cart takes it, an estimate at list prices (placeholders until real quotes), the machined plates and hardware priced on the quote, and whether it reprices at JLCMC as drawn. Frames are DEMO until an engineer signs them. A quote request may carry the same layout as `cell`; its message then carries the cell's line and the frames' line.","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","required":["product_id"],"properties":{"product_id":{"type":"string"}}}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"400":{"description":"Not a layout, or no 3D cell for this product","content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error"}}}}}}},"/api/mcp":{"post":{"operationId":"mcp","summary":"The same store as an MCP server (Streamable HTTP, JSON-RPC)","description":"Tools: get_store, get_product, preview_order, place_order, get_order (and submit_idea where the site takes ideas).","requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object"}}}},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}}}}}},"components":{"schemas":{"Error":{"type":"object","required":["error"],"properties":{"error":{"type":"string"}}},"Media":{"type":"object","properties":{"kind":{"type":"string"},"type":{"enum":["model","image"]},"alt":{"type":"string"},"url":{"type":"string"}}},"Product":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"description":{"type":"string"},"price":{"type":"integer","description":"Cents"},"currency":{"type":"string"},"demo":{"type":"boolean","description":"Shown, never sold"},"media":{"type":"array","items":{"$ref":"#/components/schemas/Media"}}}},"Store":{"type":"object","properties":{"site":{"type":"object"},"products":{"type":"array","items":{"$ref":"#/components/schemas/Product"}}}},"ShipTo":{"type":"object","required":["name","line1","city","postal_code","country"],"properties":{"name":{"type":"string"},"line1":{"type":"string"},"line2":{"type":"string"},"city":{"type":"string"},"region":{"type":"string"},"postal_code":{"type":"string"},"country":{"type":"string","description":"ISO 3166-1 alpha-2"}}},"OrderRequest":{"type":"object","required":["product_id"],"properties":{"product_id":{"type":"string"},"quantity":{"type":"integer","minimum":1,"maximum":20,"default":1},"email":{"type":"string","format":"email","description":"Required unless dry_run"},"ship_to":{"$ref":"#/components/schemas/ShipTo"},"payment":{"type":"object","properties":{"token":{"type":"string","description":"Stripe shared payment token (spt_...)"}}},"agent":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"}}},"dry_run":{"type":"boolean","default":false}}},"DryRun":{"type":"object","properties":{"dry_run":{"const":true},"orderable":{"type":"boolean"},"problems":{"type":"array","items":{"type":"string"}},"amount":{"type":"integer"},"currency":{"type":"string"},"limits":{"type":"object","properties":{"ordering":{"type":"boolean"},"max_order":{"type":"integer","description":"Cents per order"},"max_daily":{"type":"integer","description":"Cents a day, all agents"}}}}},"Order":{"type":"object","properties":{"order_id":{"type":"string"},"token":{"type":"string","description":"The key to this order: keep it"},"status":{"enum":["pending","paid","packaged","in_production","shipped","cancelled"]},"amount":{"type":"integer"},"currency":{"type":"string"},"revision":{"type":["string","null"],"description":"The signed revision it is built from"},"payment":{"type":"object","properties":{"method":{"enum":["shared_payment_token","checkout"]},"status":{"enum":["paid","pending","failed"]},"checkout_url":{"type":"string"}}},"order_url":{"type":"string"},"next":{"type":"string"}}}}}}