How to use the Shippo Estimate API

Send one request with a shipment's origin, destination, parcel details, and planned ship date, and get back a predicted delivery date for every supported carrier and service level, sorted fastest first. The model is trained on real delivery outcomes across the carriers we support, not carrier-published transit times, and responds in well under 200ms. It's the same delivery-date model behind Shippo Estimate in the web app, now callable directly from your own checkout, product page, or fulfillment system.

Instead of vague labels like Standard or Expedited, show shoppers something concrete: “Arrives Nov 18” next to “Arrives Nov 20 for less,” so they can choose based on what actually matters to them.

  Note: You'll need a Shippo account with billing set up before your first live call. If your account doesn't have access yet, contact support.

Endpoint and authentication

Endpoint: POST https://api.goshippo.com/v2/estimates

Authenticate every request with Authorization: ShippoToken <API_TOKEN>.

Official SDKs are available in Python, Ruby, JavaScript/Node.js, and PHP. Prefer working directly against REST? The endpoint above takes the same parameters.

  Security: Keep your API key out of client-side code and out of source control. Use environment variables or a secrets manager instead.

 

Test mode

Use a shippo_test_ key while you build. Test calls return every service level's estimate exactly one day later than your planned_ship_date, so real predictions aren't spent on development traffic. Filtering, sorting, and validation all behave the same as live mode.

Check the test field in the response to confirm which mode a call ran under (true for test keys, false for live), and switch to a shippo_live_ key before you ship to production.


Required parameters

Every request needs all six of these. Miss one and you get a 422 telling you exactly which field is missing.

Parameter Type Notes
origin.zip string US ZIP, 5 numeric characters
destination.zip string US ZIP, 5 numeric characters
parcel.length, .width, .height number In your chosen distance_unit
parcel.distance_unit enum in, cm, mm, m, ft, yd
parcel.weight number In your chosen mass_unit
parcel.mass_unit enum g, kg, lb, oz
planned_ship_date string ISO 8601, timezone-aware, full datetime (not date-only)

 

Two things that cause more 422s than everything else combined

distance_unit and mass_unit are required, not inferred. Sending dimensions and weight without their units is the single most common 422 developers run into.

planned_ship_date needs a full, timezone-aware timestamp. 2026-08-27T17:00:00Z and 2026-08-27T13:00:00-04:00 both work. A naive timestamp like 2026-08-27T17:00:00 returns a 422, and so does a bare date.

We don't model warehouse or carrier cutoff times, so planned_ship_date is where you encode yours. Pass the moment the package realistically enters the carrier network. If an order lands after your daily handoff, bump the date to the next business day and call again.


Optional parameters

Parameter Type What it does
servicelevel_tokens array of strings Restricts the response to the service levels you list. This is inclusion only, so there's no way to exclude a carrier or service level.
latest_delivery_date string, YYYY-MM-DD Excludes any service level whose estimate falls after this date.
confidence_level enum TYPICAL, DEFAULT, or HIGH. See Confidence levels below.

Behavior worth knowing before you build against it:

  • An invalid token in servicelevel_tokens is ignored rather than rejected. If every token you send is invalid, the call returns a 422.
  • If latest_delivery_date filters out every prediction, you still get a 200 with an empty predictions array. That's a success, not an error.
  • We return every supported service level regardless of which carrier accounts you've connected. Filtering to what you actually ship is on you.
  • Predictions are sorted fastest first by delivery date, then alphabetically by service level token to break ties.

Picking parameters for your use case

What you're building Confidence Ship date to send Filters to use
Delivery promise at checkout or on a product page DEFAULT Your next carrier handoff cutoff None, then filter the response to the services you offer
Choosing a service in the warehouse TYPICAL Today's handoff time servicelevel_tokens for your contracted services
Meeting a hard deadline (perishables, regulated goods, dated events) HIGH Your next handoff cutoff latest_delivery_date set to the deadline
Answering “when will it arrive” for a customer DEFAULT The date the order actually ships servicelevel_tokens for the one service being used
Showing options to sellers on a platform DEFAULT Seller's handoff cutoff Filter the response per seller's connected carriers

There's also no way to request Saturday delivery. We do respect each service level's normal delivery days when we calculate the date, so a service that runs weekends gets treated differently from one that doesn't. You just can't elect it as an option the way you can on a shipment.


Timezone of the estimates

We return estimated_delivery_date_utc in UTC, always. Convert it before you show it to anyone.

This matters more than it sounds. 2026-04-12T03:00:00Z is April 12th in UTC but April 11th in America/Los_Angeles. Slice the date off the UTC string and display it as-is, and you'll be a day off for a meaningful share of your West Coast buyers.

The same boundary applies to filtering. latest_delivery_date compares against the UTC date, so a package arriving on the 11th local time can still get filtered out by a latest_delivery_date of 2026-04-11. If your use case needs local-date filtering, convert estimated_delivery_date_utc to your target timezone and filter client-side. Timezone-aware filtering is on our roadmap.

estimated_transit_days is the gap between planned_ship_date and the predicted delivery date, returned as a float. We calculate the delivery date first, adjusting for each service level's business days and carrier holidays, then take the difference. Adding estimated_transit_days back onto your ship date won't always land exactly on estimated_delivery_date_utc, so treat the date itself as the source of truth.


Confidence levels

Pass confidence_level to control how conservative the estimate is. Omit it, or send null, and you get DEFAULT. The response echoes back whichever level was applied.

Think of each level as a percentile of historical delivery performance on that lane. TYPICAL sits near the median, DEFAULT sits higher for a safer customer-facing promise, and HIGH sits highest for commitments that can't slip.

Value What it means Use it for
TYPICAL The most common outcome on this lane. The majority of deliveries arrive on or before this date. Internal planning, picking between services
DEFAULT Calibrated for showing to buyers. The majority of deliveries arrive by this date. Checkout, product pages, order confirmation
HIGH A conservative date. Historically, only outlier shipments have arrived later. Commitments and promises that can't slip

Values are uppercase. All three come from the same underlying prediction, so switching levels doesn't cost you an extra call.

Across every confidence level, dates are calibrated against real delivery outcomes so shipments arrive within the predicted window at least 90% of the time. That's a window figure, not a promise about the exact day, so build any customer-facing message around a date or a short range instead of a single guaranteed day.

  Note: None of these are guarantees. They're predictions trained on real delivery outcomes, and carrier performance varies. Only certain services carry a carrier money-back guarantee, at the carrier's discretion. Learn more here: Shipping Delays & Carrier Money-Back Guarantees.

Supported service levels

We support 29 service levels across USPS, UPS, FedEx, and regional carriers, for US domestic, single-piece shipments.

International, cross-border, and multi-piece shipments aren't supported yet.

Errors

Status What happened
401 API key is missing, invalid, or revoked
422 A required field is missing or malformed, the ZIP isn't supported, the ship date is naive or in the past, or every service level token was invalid
429 You hit a rate limit. Retry with exponential backoff, or contact support if you need a higher limit.
503 Prediction service is temporarily unavailable. Retry with exponential backoff. If it persists, check the status page or contact support.

When a single service level can't produce a prediction, it's simply left out of the predictions array. The rest of the response returns normally.


What the API doesn't do yet

No batch endpoint yet, no international or cross-border estimates, and no multi-piece shipments.

object_id is a correlation ID for support, not something you can fetch later. There's no way to retrieve a past estimate once the response comes back, so save anything you need from it on your end.


Frequently asked questions

Q: What do I need before I can call this API?

A: A Shippo account with billing set up. If your account doesn't have access yet, contact support.

Q: How accurate are these estimates?

A: Across every confidence level, shipments arrive within the predicted window at least 90% of the time, measured against real delivery outcomes. Treat the date as a well-calibrated promise, not a guarantee of the exact day.

Q: Is this a guarantee?

A: No. Estimates are data-driven predictions, not guarantees.

Q: Do I need to call the endpoint once per service level?

A: No. One call returns predictions for every supported service level, sorted fastest first.

Q: Can I filter the response by carrier account?

A: Not server-side. We return every supported service level regardless of which carriers you've connected. Filter to what you actually ship on your end.

Q: Are test calls billed?

A: No. Test key calls also return every estimate one day later than your planned_ship_date, so treat them as directional while you build, not exact.


Related articles

Was this article helpful?

Related articles