Print from code
Beta. The same API the site uses, plus an MCP server for AI agents. No key needed yet; routes may change.
MCP
A remote MCP server for AI assistants and agents: https://mandarin3d.com/mcp (Streamable HTTP, no key). Setup for each app: For AI agents.
get_service_info- prices, limits, colors, where we ship
quote_file- file URL or base64 → price and order link
price_quote- quantity, color, options
create_checkout- payment link, after the buyer accepts the terms
list_catalog- ready-made parts and their parameters
quote_catalog_item- a catalog part with your text and sizes → price and order link
design_part- no file? a link to the AI designer
OpenAPI: /openapi.json. Server card: /.well-known/mcp/server-card.json.
Quote
POST /api/quote with the model as multipart field file. STL, 3MF, STEP or USDZ, up to 100 MB. USDZ scans keep their real-world size and print in one color without textures.
curl -F file=@bracket.stl https://mandarin3d.com/api/quote{
"id": "Xk3…",
"filename": "bracket.stl",
"grams": 6.19,
"seconds": 763.58,
"bbox": [30, 30, 20],
"cached": false,
"example": { "qty": 1, "print": 3.91, "shipping": 5.51, "total": 9.42 }
}Same file again: served from cache in milliseconds. Raw bytes work too: ?filename=part.stl.
Quote in two steps
For a page that should move on before slicing is done (what mandarin3d.com does). Reserve an id, send the file, then read the quote.
# 1. Reserve a quote id (no file yet)
curl https://mandarin3d.com/api/quote/start -H 'content-type: application/json' \
-d '{"filename":"bracket.stl","bytes":22484}'
{ "id": "Xk3…", "url": "/quote/Xk3…" }
# 2. Send the raw file; answers with the quote once it's sliced
curl -X PUT --data-binary @bracket.stl https://mandarin3d.com/api/quote/Xk3…
# 3. Or poll until it's ready
curl https://mandarin3d.com/api/quote/Xk3…
202 { "status": "waiting" | "slicing" | "error", "error": "…" }
200 { "id": "Xk3…", "grams": 6.19, … }An id waits 30 minutes for its file. Same limits as one-step quotes.
Catalog
Ready-made parts (/catalog) priced with your text and sizes, no file needed. GET /api/catalog lists each item's parameters; POST /api/catalog/quote renders the part from its parametric source and returns a normal quote, so price and checkout work the same.
curl https://mandarin3d.com/api/catalog/quote -H 'content-type: application/json' -d '{"slug":"personalized-name-ornament","values":{"name":"Leo","line2":"2026"}}'
{ "id": "Q7v…", "slug": "personalized-name-ornament", "values": { … },
"grams": 11.6, "bbox": [75, 82.5, 3.6], "example": { "total": 9.76 }, "url": "/quote/Q7v…" }Parts with text also print in two colors (items with two_color in the list): send accent, the text color, and color, the rest of the part. The quote is sliced with both filaments, the price includes the multicolor option, and checkout holds the color and options to send to /api/checkout. PLA only.
curl https://mandarin3d.com/api/catalog/quote -H 'content-type: application/json' -d '{"slug":"personalized-luggage-tag","values":{"name":"Sam Rivera"},"color":"BLU","accent":"WHT"}'
{ "id": "T2c…", "filename": "personalized-luggage-tag-Sam-Rivera-Rivera-family.3mf",
"parts": ["Tag", "Text"], "colors": { "note": "Tag: Blue, Text: White" },
"example": { "total": 12.85 }, "checkout": { "color": "BLU", "options": { "extraColors": ["WHT"] } } }Price
POST /api/price for another quantity. No side effects.
curl https://mandarin3d.com/api/price -H 'content-type: application/json' \
-d '{"quoteId":"Xk3…","qty":10}'Or price locally: GET /api/config has the formula, colors and shipping table.
Material: send "material":"petg" to price, quote (GET /api/quote/:id?material=petg) or order in PETG. Grams and time come from a PETG slice of the same file, and the print price is 20% higher. PETG is made to order in BLK or WHT, adds 3 to 5 business days and can't be rushed. Leave it out for PLA. Other materials have no instant price: ask at /design.
curl https://mandarin3d.com/api/price -H 'content-type: application/json' \
-d '{"quoteId":"Xk3…","color":"BLK","material":"petg"}'Order
POST /api/checkout returns a checkout link. Send acceptTerms: true only after the buyer accepts: custom made to order, all sales final (Terms).
curl https://mandarin3d.com/api/checkout -H 'content-type: application/json' \
-d '{"quoteId":"Xk3…","color":"BLK","qty":1,"acceptTerms":true}'{ "checkoutId": "co_…", "invoiceUrl": "https://…", "price": { "total": 9.42 } }Options (per order, optional): rush (+50% of the print price, printed within 1 business day), fileCheck (+$5), cleanup (+$5), and extraColors (+$3 each, up to 3 codes) with a colorNote saying which parts get which color. POST /api/price takes the same object.
curl https://mandarin3d.com/api/checkout -H 'content-type: application/json' \
-d '{"quoteId":"Xk3…","color":"BLK","qty":1,"acceptTerms":true,
"options":{"rush":true,"extraColors":["RED"],"colorNote":"lid in red"}}'The buyer pays at invoiceUrl. Ships by USPS in 3-5 days.
Reference
GET /api/config- formula, options, colors, shipping, limits
POST /api/quote- file → grams, time, size, price
POST /api/quote/start- reserve a quote id
PUT /api/quote/:id- file for that id → the quote
GET /api/quote/:id- a saved quote (
?material=petgfor PETG), or 202 while slicing GET /api/quote/:id/model- mesh for previews
GET /api/catalog- ready-made parts, parameters, from-prices
POST /api/catalog/quote- catalog part + values → the quote
POST /api/price- price for a quantity and options
POST /api/checkout- checkout link
Errors are { "error": "…" } with a plain-English message. Limits: 320 × 320 × 320 mm, 60 quotes per 10 minutes per IP. Questions: orders@mandarin3d.com.