Create a quote
POST/api/v1/quotes
Overview
Create a quote for inspected models, sizes, quantities and a US address. Returns manufacturing prices and USPS/UPS shipping options, without tax, valid for 30 minutes. No order, payment or repair job is created. Unordered quotes are kept for 30 days after expiry. A retry with the same Idempotency-Key returns the original quote for 24 hours.
Requires quotes:write.
Parameters
Idempotency-Key header · optional
Account, method and path scoped retry key, retained for 24 hours from first use. Same body replays the original successful status and body. A changed body returns 409 idempotency_key_reused; an in-flight request returns 409 idempotency_request_in_progress with Retry-After. Retry transient failures with the same key and body.
string
Request body
application/json
items array · required
1–50 inspected model items, up to 1,000 prints in total. Matching model/size entries merge; combined quantity cannot exceed 500 per model and size.
items item fields
model_id string · required
Immutable model ID: MD- followed by eight uppercase Crockford Base32 characters. Use this same ID in the website, URLs and API; pass it unchanged.
Min length: 11 · Max length: 11
quantity integer · required
Minimum: 1 · Maximum: 500
longest_dimension_mm number · required
Longest bounding-box dimension in millimeters, 30–200 inclusive. Fractional values are accepted. Uniformly scale all axes. At model creation this is the default and inspection reference size; each pricing/quote item explicitly selects its own size. Callers convert other units to millimeters.
Minimum: 30 · Maximum: 200
shipping_address object · required
US recipient address. Supply a five-digit ZIP code as a string, preserving leading zeroes; ZIP+4 and other lengths are rejected. Text must be nonblank and contain no Unicode category C characters. Postal verification may standardize the address. No client parcel weight, dimensions or origin.
shipping_address fields
name string · required
Delivery recipient; may differ from the buyer.
Min length: 1 · Max length: 255
company string · optional
Optional recipient company.
Min length: 1 · Max length: 255
line1 string · required
Street address.
Min length: 1 · Max length: 200
line2 string · optional
Optional apartment, suite, or additional address line.
Min length: 1 · Max length: 200
city string · required
Destination city/locality.
Min length: 1 · Max length: 100
state string · required
Supported two-letter US state or territory code, or AA/AE/AP military region.
Min length: 1 · Max length: 2
postal_code string · required
Exactly five digits, for example 02108. ZIP+4 is not accepted.
Min length: 5 · Max length: 5
country string · required
Literal US.
Always: "US"
Min length: 1 · Max length: 2
phone string · optional
Recipient contact; required where the selected carrier/service requires it.
Min length: 1 · Max length: 50
email string (email) · optional
Min length: 1 · Max length: 254
buyer object · optional
Optional buyer details, separate from the delivery recipient. The authenticated account owns the quote and order.
buyer fields
name string · optional
Buyer name.
Min length: 1 · Max length: 255
company string · optional
Buyer company.
Min length: 1 · Max length: 255
email string (email) · optional
Min length: 1 · Max length: 254
Responses
Saved quote with manufacturing and shipping totals in USD cents. Tax excluded; no charge is made. Shipping prices in this example are illustrative.
200 response
JSON
{
"id": "quote_6c82bd3e319b4bb099310d54a761879e",
"created_at": "2026-09-17T18:00:00.000000Z",
"expires_at": "2026-09-17T18:30:00.000000Z",
"currency": "usd",
"items": [
{
"model_id": "MD-739YQ549",
"longest_dimension_mm": 100,
"quantity": 2,
"dimensions_mm": {
"x": 100,
"y": 50,
"z": 20
},
"unit_price": 2460,
"subtotal": 4920,
"repair": {
"required": false,
"applied": false,
"reason": null,
"status": "not_applied",
"fee": 0,
"covered_by_order_id": null
}
}
],
"shipping_address": {
"name": "Test Recipient",
"line1": "123 EXAMPLE ST",
"city": "SEATTLE",
"state": "WA",
"postal_code": "98101",
"country": "US"
},
"buyer": {
"company": "Example Store",
"email": "orders@example.com"
},
"estimated_production_business_days": null,
"shipping_options": [
{
"id": "shipopt_6c82bd3e319b4bb099310d54a761879e",
"name": "UPS Ground",
"totals": {
"subtotal": 4920,
"shipping": 1000,
"total": 5920
},
"estimated_transit_business_days": {
"min": 3,
"max": 3
},
"estimated_delivery": null,
"carrier": "UPS"
},
{
"id": "shipopt_8c1f25d94e3142f8b9a70635d42c81e0",
"name": "USPS Priority Mail Express",
"totals": {
"subtotal": 4920,
"shipping": 2000,
"total": 6920
},
"estimated_transit_business_days": {
"min": 1,
"max": 1
},
"estimated_delivery": null,
"carrier": "USPS"
}
],
"pricing_version": "pv_20261001_model_repair_01",
"status": "open"
}Returns the Quote object.
Response headers
X-Request-IDRequest identifier for support. Send X-Request-ID with 8–64 ASCII letters, digits or hyphens to reuse that value; otherwise the server generates a UUID4 hex value. Include the returned X-Request-ID in support requests. Do not put secrets or account IDs in this value.
Idempotent-ReplayedPresent when the original successful response is replayed.
Errors
| HTTP | Code | What to do |
|---|---|---|
| 400 Bad Request | invalid_argument | A field, query parameter or header is invalid. Fix the field named in details, then send the request again. |
| 400 Bad Request | model_not_found | No model with this ID exists in the account, or it was deleted. Check the ID. |
| 400 Bad Request | pricing_unavailable | The model cannot be priced, usually because processing failed. Read the model's status_reasons; repeating the request does not rerun inspection. |
| 400 Bad Request | shipping_unavailable | No shipping service accepts this destination or basket. Check the address, or split an oversized basket. |
| 401 Unauthorized | unauthenticated | The API key is missing, invalid or revoked. Send a valid business API key in Authorization: Bearer. |
| 403 Forbidden | permission_denied | The key lacks the endpoint's scope, or payments lack spending consent. Check the scope listed on the endpoint. |
| 409 Conflict | idempotency_key_reused | This Idempotency-Key was already used with a different body. Retry the original body, or use a new key for a new operation. |
| 409 Conflict | idempotency_request_in_progress | A request with this Idempotency-Key is still running. Wait Retry-After seconds, then retry the same key and body. |
| 409 Conflict | model_not_ready | The model is still processing. Wait until its status is ready, then retry. |
| 409 Conflict | model_repair_estimate_pending | The repair fee is still being estimated. Wait until the model status is ready, then retry. |
| 413 Content Too Large | request_too_large | The JSON body is over this endpoint's size limit. Send a smaller body. |
| 415 Unsupported Media Type | unsupported_media_type | The body is not JSON. Send Content-Type: application/json. |
| 429 Too Many Requests | resource_exhausted | A rate or account limit was reached. Wait at least Retry-After seconds, then retry. |
| 500 Internal Server Error | internal | The server failed unexpectedly. Retry with backoff; contact support with X-Request-ID if it persists. |
| 503 Service Unavailable | shipping_rates_unavailable | Shipping rates could not be fetched. Retry with backoff and the same Idempotency-Key. |
| 503 Service Unavailable | unavailable | A required service is briefly unavailable. Retry with backoff, reusing the same Idempotency-Key. |
API v1 preview