Skip to main content
The ShippingService class (accessed via client.shipping) prices delivery for an address, lists a store’s delivery rates and pickup locations, returns live carrier options, and tracks parcels.

How an address is priced

A store’s delivery rates are its delivery zones, its distance rates and its “everywhere else” rate. An address is priced by:
  1. The first zone that contains it — lowest priority first, then the zone created first. A zone is either an area drawn on a map (match_kind: area) or a set of countries, optionally narrowed to postcode prefixes (match_kind: region).
  2. Otherwise, the distance rate whose range contains its distance from the store. A range includes its min_distance_meters and stops just before its max_distance_meters, so 0–10 km and 10–50 km share the 10 km point without overlapping.
  3. Otherwise, the “everywhere else” rate. When the store has zones or distance rates but no “everywhere else” rate, or has chosen not to deliver outside them (everywhere_else.refuse), an address outside them is not delivered to. calculateShipping then returns only the store’s pickup options, or answers 400 shipping_not_deliverable when the store offers no pickup.
A matched rate is free when the order reaches its free-delivery threshold. A store with no delivery rates at all charges nothing through them (applied_rule: none, configured: false). Every amount is in the store’s own currency, returned as currency.

Delivery options and pickup

A matched rate is the order’s standard delivery option. The store can add named options to the same rate — Express, Next day — each with its own fee, estimate and conditions such as an order-total range or a parcel weight range. A store can also offer pickup at any of its locations, each with its own pickup fee, an optional minimum order, and a note on when orders are ready. The store can set rules for product categories: a surcharge per order or per item, delivery only to nearby addresses (the store’s map zones and distance rates, not its country-wide zones or “everywhere else” rate), or collection only. These rules, and options that depend on parcel weight, apply when the basket’s lines are sent to calculateShipping as items.

Methods

getShippingZones

Retrieve the store’s delivery rates and pickup locations: active distance rates, active delivery zones, the “everywhere else” rate, and the locations where shoppers can collect an order. Useful for showing delivery coverage, likely costs, or a “collect in store” option early in the shopping journey.
Response
everywhere_else is null when the store has none. When refuse is true, the store does not deliver outside its zones and distance rates, and both amounts are null. A region zone covers the addresses in its countries; when postcodes is not empty, only postcodes beginning with one of those prefixes. pickup_locations lists the primary location first and is empty when the store does not offer pickup. The response is cached for up to 60 seconds and carries an ETag; calculateShipping and order creation always read the current rates.

calculateShipping

Calculate the ways a shopper can receive an order — the store’s delivery options and pickup locations — priced for their address and basket.
Response
order_total is the order’s merchandise total in the store’s currency (e.g. 50 = $50.00), not a minor-unit (cents) value — the line totals after any discount. It decides whether the order reaches the matched rate’s free-delivery threshold.
Request Fields: Response Fields: Option ids take three forms: place is the standard delivery option, opt:<id> is a named option the store added to the same rate, and pickup:<location id> is collection at that location. An option with available: false does not apply to this basket — usually a pickup location whose minimum_order the order has not reached — and cannot be ordered with. To order with an option, pass its id as shipping_option_id on createOrder, with shipping_amount equal to its fee. For a pickup option, also send fulfillment_method: 'pickup' and the location’s id as pickup_location_id; the order then needs no shipping address. When the store does not deliver to the address but offers pickup, the response is 200 with deliverable: false, fee: null, applied_rule: none and only the pickup options:
Response

Live carrier rates (multi-carrier)

When the store has a carrier account connected, or its own custom shipping extension, send a destination address_to and a parcel to also receive live carrier options in rates[]. Each option carries its source — the store’s carrier account (shippo) or its custom shipping extension (custom).
To request carrier options only, send address_to and parcel with no coordinates or place name. The store’s own rate is then not priced (there is no location to price it from), so fee is null and applied_rule is none. A store with no carrier connected answers that request with 400 provider_not_configured. To order with a carrier option, pass its rate_id as shipping_rate_id and its source as shipping_rate_source on createOrder (with shipping_parcel for a custom-extension option). The option is fetched again from its source and checked before it is charged.
Buying a shipping label is done by the merchant from their admin — it charges the merchant’s carrier account, marks the order shipped, and emits order.shipped — so there is no SDK method for it. From a storefront you quote rates (calculateShipping) and track parcels (trackShipment).

trackShipment

Returns live tracking status for a parcel by carrier and tracking number, for rendering the status timeline inside your own UI. A secret key tracks any parcel on the store’s carrier account; a publishable key tracks only a tracking number that is on one of the store’s own orders, so a storefront can show a shopper their own parcel.
Response
The lightest way to let a shopper track is to link to the carrier’s own tracking page — no API call. When the label is bought, the carrier tracking URL is saved on the order at shipping_metadata.shippo.tracking_url; render it as a “Track your package” link. Use trackShipment only when you want the status shown natively in your storefront.

Response Codes

All three methods accept publishable and secret keys. calculateShipping uses POST purely to carry a structured request body — it is read-only.

getShippingZones (GET /v1/shipping/zones)

calculateShipping (POST /v1/shipping/calculate)

trackShipment (GET /v1/shipping/tracking/{carrier}/{number})