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=petg for 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.