Create a shipping quote
Save manufacturing prices and compare shipping options.
Create a quote
Select inspected models, print sizes, quantities and a US destination. Use quotes:write to create and quotes:read to retrieve. Inspection must have completed with current model and support measurements; estimated volume and detected defects are accepted.
Set MODEL_ID, LONGEST_DIMENSION_MM and SHIPPING_ADDRESS_FILE. Save the recipient address below as address.json, replacing it with your destination. Save a QUOTE_REQUEST_KEY before sending; reuse it on retry.
address.json
json
{
"name": "Alex Example",
"line1": "500 Pine St",
"city": "Seattle",
"state": "WA",
"postal_code": "98101",
"country": "US"
}Create and retrieve a quote
#!/usr/bin/env bash
# Bash + curl + jq. Key needs quotes:write and quotes:read.
set -euo pipefail
: "${API_BASE_URL:?Set your API origin}"
: "${OTTOMFG_API_KEY:?Set your server-side key}"
: "${MODEL_ID:?Set an inspected model ID}"
: "${LONGEST_DIMENSION_MM:?Set print size from 30 to 200 mm}"
: "${SHIPPING_ADDRESS_FILE:?Set the path to your recipient address JSON file}"
: "${QUOTE_REQUEST_KEY:?Generate once with uuidgen; save and reuse on retry}"
body=$(jq -n --arg model "$MODEL_ID" --argjson size "$LONGEST_DIMENSION_MM" \
--slurpfile address "$SHIPPING_ADDRESS_FILE" \
'{items:[{model_id:$model,longest_dimension_mm:$size,quantity:2}],shipping_address:$address[0]}')
quote=$(curl --fail-with-body --silent --show-error --max-time 30 \
-X POST "${API_BASE_URL%/}/api/v1/quotes" \
-H "Authorization: Bearer $OTTOMFG_API_KEY" \
-H "Idempotency-Key: $QUOTE_REQUEST_KEY" \
-H 'Content-Type: application/json' --data "$body") || { printf '%s\n' "$quote"; exit 1; }
printf '%s\n' "$quote" | jq .
quote_id=$(printf '%s\n' "$quote" | jq -er .id)
curl --fail-with-body --silent --show-error --max-time 30 \
"${API_BASE_URL%/}/api/v1/quotes/$quote_id" \
-H "Authorization: Bearer $OTTOMFG_API_KEY"
# Review normalized address, shipping options, status and expiry. No order or charge.
# Same-key replay preserves terms and expiry; status is recalculated.
# Use a new key for a new quote.
Compare shipping options
Supply exactly five ZIP digits as a string, preserving leading zeroes. Review the returned shipping_address for any standardized address corrections.
Choose from the returned options. Each has its own ID, service, estimated transit time and total. We offer one service per transit-day option, ordered by price. Transit starts after dispatch; it is not a guaranteed arrival date. Null estimates mean unavailable.
Shipping starts in Minden, Nevada. Quotes support US destinations and one parcel, up to 150 lb including packing. Amounts are USD cents. Total equals manufacturing subtotal plus shipping; tax is not calculated and is excluded.
Expiry and retention
Quotes are valid for 30 minutes. GET preserves commercial terms and recalculates status: open before expires_at, expired at or after it. A keyed POST replay returns the original status; GET for current state. Neither refreshes prices or extends expiry. Changed measurements or rates require a new quote before acceptance. Accepted order prices remain pinned.
Unordered quotes remain available for 30 days after expiry, then are deleted with their recipient and buyer details. Quotes referenced by an order are retained. Save the quote ID; viewing it does not extend retention.
Recovery
shipping_unavailable means the destination, service or basket cannot be quoted. Correct the address or reduce the basket. shipping_rates_unavailable means a temporary provider failure; retry with backoff and the same key. That outcome does not consume your quote-attempt quota.
API v1 preview