Estimate Quote Shipping
POST/api/quotes/:quote/shipping-estimates
Rates the quote's selected product lines with the account's own EasyPost connection, to the quote's shipping address (shipping_address_id), and records the run. Nothing on the quote changes until a rate is applied.
orders:writeGrant this scope to your token under Settings → Developer → Personal Access Tokens.
Request body (all optional — send {} to rate the order as it stands):
origin_warehouse_id(integer, nullable): rate every item from this warehouse instead of each line's own warehouse.parcels(array, max 50, nullable): override the parcels built from product weights and dimensions. Each parcel:weight_oz(number, required, > 0, max 2400 = 150 lb),length_in/width_in/height_in(number, optional, > 0, max 108).refresh(boolean): bypass the 15-minute rate cache.
Response (data):
status:ok,not_connected(no EasyPost connection),key_rejected(the EasyPost API key was refused),missing_package_data(some products have no weight — listed inmissing_weight_products),no_origin_address(the shipping warehouse has no complete address),no_destination(no ship-to address),no_items(no product lines),no_rates(no carrier returned a rate) orrating_failed(EasyPost could not rate the shipment; try again). Onlyokcarriesoptions; every status comes back as 200 with a human-readablemessage.mode:productionortest— the mode of the EasyPost key that rated the shipment (test keys return list rates).currency: the order's currency; everyamountis converted to it.original_amount/original_currencyare what the carrier quoted.options[]: one per carrier service, cheapest first —key(<carrier>|<service>, pass it asoption_keywhen applying),carrier,service,carrier_account_id,amount,currency,original_amount,original_currency,delivery_days, andorigins[](the per-warehouse share when the order ships from several warehouses:warehouse_id,warehouse_name,amount,currency,parcels). A service is offered only when every origin warehouse can use it.warnings[]: notes such as products rated on a default weight or a missing exchange rate.missing_weight_products[]:{id, sku, name}of products with no weight.shipments[]: what was rated per origin warehouse —warehouse_id,warehouse_name,fromaddress,parcels[](weight_oz,length_in,width_in,height_in) andtotal_weight_oz.quoted_at,request_hash,estimate_id: when it was rated, a fingerprint of the rated request, and the recorded estimate's id (use it in the apply endpoint).defaults: the account's default markup (markup_typepercentorflat,markup_value) used when applying without an explicit markup.subject: the current Shipping lines that a rate would replace (existing_shipping_lines[]:id,description,quantity,amount,tax_rate), the currenttotal,currency, thenew_line_tax_ratea new Shipping line would carry andis_tax_included.
Identical requests within 15 minutes reuse the cached rates; send refresh: true to re-rate.
A quote that is no longer editable (sent, accepted, declined, expired, converted) is refused with 422 — revise it first.
Authentication: Requires Bearer token.
Requires permission: quotes.update
Request
Responses
- 200
- 401
- 403
- 404
- 422
- 429
OK
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Not found — no record with the given identifier (or the route does not exist). Verify the ID before retrying.
Unprocessable Content
Response Headers
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.