Skip to main content
POST
/
api
/
v1
/
ship
/
quote
Get shipping quote
curl --request POST \
  --url https://api.example.com/api/v1/ship/quote \
  --header 'Content-Type: application/json' \
  --data '
{
  "item_ids": [
    "<string>"
  ],
  "destination": {}
}
'
{
  "session_id": "quote_01HF8X2YJK9PMQ4ZRT7NVCB6WD",
  "expires_at": "2026-04-18T19:30:00.000Z",
  "quotes": [
    {
      "id": "quote_01HF8X2YJK9PMQ4ZRT7NVCB6WD_rate_standard",
      "carrier": "USPS",
      "service": "Ground Advantage",
      "amount": 5.95,
      "estimated_days_min": 3,
      "estimated_days_max": 5,
      "insured": false
    },
    {
      "id": "quote_01HF8X2YJK9PMQ4ZRT7NVCB6WD_rate_priority",
      "carrier": "USPS",
      "service": "Priority Mail",
      "amount": 9.75,
      "estimated_days_min": 1,
      "estimated_days_max": 3,
      "insured": true
    },
    {
      "id": "quote_01HF8X2YJK9PMQ4ZRT7NVCB6WD_rate_express",
      "carrier": "FedEx",
      "service": "2Day",
      "amount": 18.50,
      "estimated_days_min": 2,
      "estimated_days_max": 2,
      "insured": true
    }
  ]
}
Returns carrier rates and ETAs for shipping one or more items to a destination. Use this to display shipping options before the user commits.
No payment is required. Quotes are informational and shipping fees are settled B2B with the partner.

Request body

item_ids
string[]
required
Item identifiers from /api/v1/vm/buy/status (nfts[].id) or /api/v1/inventory/:user_id (items[].id).
destination
object
required
Shipping address.

Example request

POST /api/v1/ship/quote
X-API-Key: <your_api_key>
Content-Type: application/json

{
  "item_ids": ["item_id_1", "item_id_2"],
  "destination": {
    "name": "Jane Doe",
    "line1": "123 Main St",
    "line2": "Apt 4B",
    "city": "Austin",
    "state": "TX",
    "postal_code": "78701",
    "country": "US",
    "phone": "+15125551234",
    "email": "jane@example.com"
  }
}

Response

{
  "session_id": "quote_01HF8X2YJK9PMQ4ZRT7NVCB6WD",
  "expires_at": "2026-04-18T19:30:00.000Z",
  "quotes": [
    {
      "id": "quote_01HF8X2YJK9PMQ4ZRT7NVCB6WD_rate_standard",
      "carrier": "USPS",
      "service": "Ground Advantage",
      "amount": 5.95,
      "estimated_days_min": 3,
      "estimated_days_max": 5,
      "insured": false
    },
    {
      "id": "quote_01HF8X2YJK9PMQ4ZRT7NVCB6WD_rate_priority",
      "carrier": "USPS",
      "service": "Priority Mail",
      "amount": 9.75,
      "estimated_days_min": 1,
      "estimated_days_max": 3,
      "insured": true
    },
    {
      "id": "quote_01HF8X2YJK9PMQ4ZRT7NVCB6WD_rate_express",
      "carrier": "FedEx",
      "service": "2Day",
      "amount": 18.50,
      "estimated_days_min": 2,
      "estimated_days_max": 2,
      "insured": true
    }
  ]
}
session_id
string
Quote session identifier (groups the returned quotes[]).
expires_at
string
ISO timestamp after which all quotes in this session are no longer valid.
quotes[].id
string
Rate identifier. Pass as quote_id in /api/v1/ship/request.
quotes[].carrier
string
Shipping carrier (for example USPS, FedEx).
quotes[].service
string
Carrier service level (for example Priority Mail, 2Day).
quotes[].amount
number
Shipping cost in USD. Billed B2B to the partner.
quotes[].estimated_days_min
number
ETA in business days (lower bound).
quotes[].estimated_days_max
number
ETA in business days (upper bound).
quotes[].insured
boolean
Whether the rate includes carrier insurance.

Errors

StatusBodyCause
400{ "error": "item_ids is required" }Missing or empty item_ids
400{ "error": "Invalid destination address", "details": "...", "suggested": { ... } }Address validation failed. The body includes a human-readable details string and, when available, a suggested normalized address object (Google’s correction). See Address validation below.
400{ "error": "Item not found" }One or more item_ids are unknown or not owned by this partner’s user
400{ "error": "No shippable items in request" }All items are non-shippable
422{ "error": "Country not supported" }Production: destination country is not currently serviced. Sandbox: the country field is not a 2-character string. The sandbox does not check against an actual country allow-list, so any 2-character value (including "ZZ") is accepted.
500{ "error": "Failed to fetch shipping rates" }Carrier rate lookup failed

Address validation

Destinations submitted to /ship/quote are validated server-side via the Google Address Validation API before any rate lookup runs. The validator runs against both production and sandbox. Pass criteria:
  • Required fields are present and non-empty: name, line1, city, country.
  • country is exactly 2 characters (ISO 3166-1 alpha-2).
  • Google returns validationGranularity of PREMISE or SUB_PREMISE. PREMISE_PROXIMITY is rejected — it indicates Google is uncertain about the exact location, which carriers misroute or refuse for graded-card-grade shipments.
  • No address components are flagged as unconfirmed.
Failure response shape:
400
{
  "error": "Invalid destination address",
  "details": "Address contains unconfirmed components",
  "suggested": {
    "name": "Jane Doe",
    "line1": "123 Main Street",
    "line2": "Apt 4B",
    "city": "Austin",
    "state": "TX",
    "postal_code": "78701-1234",
    "country": "US"
  }
}
When Google can suggest a corrected address, it’s returned under suggested so the partner can prompt the end user to confirm. suggested may be absent when validation fails on a structural check (e.g. missing name). Outage behavior: if the Google API is unreachable or returns a non-2xx response, /ship/quote fails closed with 400 { "error": "Invalid destination address", "details": "Validation failed: internal error" }. Same behavior applies if GOOGLE_MAPS_API_KEY is not configured server-side. Address validation is a hard dependency of /ship/quote — partners should retry with backoff on this specific details value rather than treat the address as invalid.

Sandbox notes

In sandbox, every ship/quote call returns exactly three rates in this order:
ServiceCarrierInsuredDaysAmount formula (USD)
Ground AdvantageUSPSno3–55.95 + (n − 1) × 1.50
Priority MailUSPSyes1–39.75 + (n − 1) × 2.00
2DayFedExyes2–218.50 + (n − 1) × 3.00
Where n = item_ids.length. Quotes expire 15 minutes after issuance. Sandbox session_id format: quote_<16-char uppercase base64url>. Quote IDs follow ${session_id}_rate_${"standard"|"priority"|"express"}.