> ## Documentation Index
> Fetch the complete documentation index at: https://docs.goshippo.com/llms.txt
> Use this file to discover all available pages before exploring further.

> ## Agent Instructions
> Shippo is a multi-carrier shipping API. For agent integrations that execute shipping operations (rates, labels, tracking, address validation, customs), connect the hosted Shippo MCP server at https://mcp.shippo.com (per-user OAuth; setup at /guides/mcp-server). To search and read this documentation from an agent, a docs search MCP is available at https://docs.goshippo.com/mcp. Shipping workflow knowledge (agent skills and a knowledge pack) is published at https://github.com/goshippo/ai. For REST integrations start at /guides/api-quickstart; test mode uses shippo_test_ API keys.

# Rate shop with delivery dates

## Power rate shopping decisions across multiple service levels in a single call

Compare delivery dates across all supported carriers at once, then join with pricing to find the best value. The Estimate API returns predictions for every supported service level in a single request, sorted fastest first. Because it returns no pricing, use it alongside `POST /shipments` — join the two responses on `servicelevel.token` to build a complete picture of both delivery date and cost for each option.

### How it works

Make two calls:

1. `POST /v2/estimates` — returns delivery date predictions for all (or a filtered set of) service levels.
2. `POST /shipments` — returns rates with pricing for all connected carriers.

Join on `servicelevel.token` to assemble a combined rate-shopping view.

To limit Estimate results to specific service levels, pass `servicelevel_tokens`. To limit Shipments results to specific carriers, pass `carrier_accounts`.

Step 1 — Get delivery date predictions

```sh theme={null}
curl --request POST \
  --url https://api.goshippo.com/v2/estimates \
  --header 'Authorization: ShippoToken <API_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
    "origin": {
      "zip": "95122"
    },
    "destination": {
      "zip": "94103"
    },
    "parcel": {
      "length": 10,
      "width": 8,
      "height": 4,
      "distance_unit": "in",
      "weight": 2,
      "mass_unit": "lb"
    },
    "planned_ship_date": "2026-05-01T17:00:00Z"
  }'
```

Step 2 — Get rates and pricing

```sh theme={null}
curl --request POST \
  --url https://api.goshippo.com/shipments/ \
  --header 'Authorization: ShippoToken <API_TOKEN>' \
  --header 'Content-Type: application/json' \
  --data '{
    "address_from": {
      "street1": "1092 Indian Summer Ct",
      "city": "San Jose",
      "state": "CA",
      "zip": "95122",
      "country": "US"
    },
    "address_to": {
      "street1": "965 Mission St",
      "city": "San Francisco",
      "state": "CA",
      "zip": "94103",
      "country": "US"
    },
    "parcels": [{
      "length": "10",
      "width": "8",
      "height": "4",
      "distance_unit": "in",
      "weight": "2",
      "mass_unit": "lb"
    }],
    "async": false
  }'
```

Step 3 — Join on `servicelevel.token`

```js theme={null}
const DESTINATION_TIMEZONE = "America/Los_Angeles";

// Build a lookup map from the Estimate response
const estimatesByToken = {};
for (const prediction of estimatesResponse.predictions) {
  estimatesByToken[prediction.servicelevel.token] = prediction;
}

// Merge with Shipments rates
const combined = shipmentsResponse.rates
  .map(rate => {
    const estimate = estimatesByToken[rate.servicelevel.token];
    if (!estimate) return null; // no Estimate data for this service level

    const localDeliveryDate = new Date(estimate.estimated_delivery_date_utc)
      .toLocaleDateString("en-US", {
        timeZone: DESTINATION_TIMEZONE,
        weekday: "long",
        month: "long",
        day: "numeric"
      });

    return {
      provider: rate.provider,
      service: rate.servicelevel.name,
      token: rate.servicelevel.token,
      price: parseFloat(rate.amount),
      currency: rate.currency,
      deliveryDate: localDeliveryDate,
      transitDays: estimate.estimated_transit_days,
      rateId: rate.object_id,
    };
  })
  .filter(Boolean)
  .sort((a, b) => a.price - b.price); // cheapest first

// Example output:
// { provider: "UPS",   service: "Ground",           price: 5.80, deliveryDate: "Tuesday, May 5",   transitDays: 4 }
// { provider: "FedEx", service: "Ground",            price: 6.20, deliveryDate: "Monday, May 4",    transitDays: 3 }
// { provider: "USPS",  service: "Priority Mail",     price: 8.50, deliveryDate: "Sunday, May 3",    transitDays: 2 }
// { provider: "FedEx", service: "Priority Overnight",price: 26.35,deliveryDate: "Saturday, May 2",  transitDays: 1 }
```

> [!TIP]
>
> Sort by `price` to find the cheapest option, by `transitDays` to find the fastest, or filter on `deliveryDate` to find the cheapest option that meets a target date before presenting options to customers.


## Related topics

- [Display a delivery date](https://docs.goshippo.com/estimate/display-a-delivery-date.md)
- [Filter by required delivery date](https://docs.goshippo.com/estimate/filter-by-delivery-date.md)
- [Rate shopping with carriers](https://docs.goshippo.com/shipments/rate-shopping-with-carriers.md)
