> ## 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.

# Estimate use cases

Jump to a use case:

* [Display a delivery date on a product detail page, cart, and checkout](#display-a-delivery-date-on-a-product-detail-page-cart-and-checkout)
* [Filter carriers or service levels that miss a required delivery date](#filter-carriers-or-service-levels-that-miss-a-required-delivery-date)
* [Power rate shopping decisions across multiple service levels in a single call](#power-rate-shopping-decisions-across-multiple-service-levels-in-a-single-call)
* [Provide conservative commit dates for regulated or time-critical shipments](#provide-conservative-commit-dates-for-regulated-or-time-critical-shipments)
* [Inform warehouse systems of the ideal ship-out date](#inform-warehouse-systems-of-the-ideal-ship-out-date)

## Display a delivery date on a product detail page, cart, and checkout

Show customers exactly when their order will arrive, before they buy.\
Displaying an expected delivery date at every step of the shopping journey reduces uncertainty, builds purchase confidence, and cuts down on "Where's my order?" support tickets. Shippo Estimate returns an ML-powered `estimated_delivery_date_utc` for each service level, so you can surface a real calendar date, not a vague transit window, wherever your customer sees shipping options.

### How it works

The Estimate API is a standalone `POST /v2/estimates` endpoint. It returns ML-powered predicted delivery dates across carriers and service levels. It does **not** return pricing. For use cases that require both delivery dates and rates, call `POST /v2/estimates` and `POST /shipments` separately and join the results on `servicelevel.token`.

Call `POST /v2/estimates` with the origin ZIP, destination ZIP, parcel dimensions, and the planned ship date. The response includes a `predictions` array with one entry per service level, sorted fastest first. Each entry contains `estimated_delivery_date_utc`, which you convert to the destination's local timezone before displaying.

You can call this endpoint at multiple points in the shopping flow:

* **Product detail page** Use the customer's saved or estimated destination ZIP to show an expected delivery range next to each service option.
* **Cart** Re-call the endpoint when the customer confirms their shipping address to refresh the dates.
* **Checkout** Display the selected service level's predicted delivery date in the order summary before the customer confirms payment.

### Request

Create an Estimate with the origin zip and the customer's destination zip. The estimate object is returned.

```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"
  }'
```

### Response

The `predictions` array returns one entry per supported service level, sorted fastest first.

```json theme={null}
{
  "object_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "created_at": "2026-04-29T14:00:00Z",
  "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",
  "confidence_level": "DEFAULT",
  "servicelevel_tokens": [],
  "latest_delivery_date": null,
  "test": false,
  "predictions": [
    {
      "provider": "FedEx",
      "servicelevel": {
        "name": "Priority Overnight",
        "token": "fedex_priority_overnight"
      },
      "estimated_delivery_date_utc": "2026-05-02T20:00:00Z",
      "estimated_transit_days": 1
    },
    {
      "provider": "USPS",
      "servicelevel": {
        "name": "Priority Mail",
        "token": "usps_priority"
      },
      "estimated_delivery_date_utc": "2026-05-03T20:00:00Z",
      "estimated_transit_days": 2
    },
    {
      "provider": "UPS",
      "servicelevel": {
        "name": "Ground",
        "token": "ups_ground"
      },
      "estimated_delivery_date_utc": "2026-05-05T20:00:00Z",
      "estimated_transit_days": 4
    }
  ]
}
```

### Display example

`estimated_delivery_date_utc` is in UTC. Always convert to the destination timezone before displaying.

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

const shippingOptions = estimatesResponse.predictions.map(prediction => {
  const localDate = new Date(prediction.estimated_delivery_date_utc)
    .toLocaleDateString("en-US", {
      timeZone: DESTINATION_TIMEZONE,
      weekday: "long",
      month: "long",
      day: "numeric"
    });

  return {
    service: `${prediction.provider} ${prediction.servicelevel.name}`,
    token: prediction.servicelevel.token,
    deliveryDate: localDate,
  };
});

// Example output:
// { service: "FedEx Priority Overnight", token: "fedex_priority_overnight", deliveryDate: "Saturday, May 2" }
// { service: "USPS Priority Mail",       token: "usps_priority",            deliveryDate: "Sunday, May 3"  }
// { service: "UPS Ground",               token: "ups_ground",               deliveryDate: "Tuesday, May 5" }
```

<Warning>
  **Timezone caution:** A UTC value of `2026-05-03T03:00:00Z` is May 2nd in `America/Los_Angeles`. Do not read the date directly from the UTC string — always convert first.
</Warning>

<Note>
  The Estimate API does not return pricing. To display rates alongside delivery dates, call `POST /shipments`separately and join on `servicelevel.token`. See [Power rate shopping decisions](#power-rate-shopping-decisions-across-multiple-service-levels-in-a-single-call) for a combined flow example.
</Note>

## Filter carriers or service levels that miss a required delivery date

Some orders have hard delivery requirements: same-day gifts, event merchandise, subscription boxes with commit dates. Rather than presenting all available rates and hoping customers pick correctly, you can use `estimated_delivery_date_utc` to filter out any service levels that would miss the required date before displaying options or purchasing a label.

### How it works

Pass `latest_delivery_date` in the request body. The API compares this date against the UTC date component of each prediction's `estimated_delivery_date_utc` and silently omits any service level whose estimate falls after the specified date. Only service levels that can meet the deadline appear in `predictions`.

<Info>
  **Timezone note:** `latest_delivery_date` is compared against the UTC date component of each estimate — not the local delivery date. If your deadline is expressed in a non-UTC timezone, apply the filter client-side after converting `estimated_delivery_date_utc` to the destination timezone. See [Filtering Results](https://docs.goshippo.com/docs/Estimate/Estimate#filtering-results) for full details.
</Info>

### Request — using `latest_delivery_date`

```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",
    "latest_delivery_date": "2026-05-03"
  }'
```

Service levels that cannot deliver by May 3 (UTC) are omitted from the response. Only eligible service levels are returned in `predictions`.

### Response

```json theme={null}
{
  "object_id": "7a1b2c3d-...",
  "planned_ship_date": "2026-05-01T17:00:00Z",
  "confidence_level": "DEFAULT",
  "latest_delivery_date": "2026-05-03",
  "predictions": [
    {
      "provider": "FedEx",
      "servicelevel": {
        "name": "Priority Overnight",
        "token": "fedex_priority_overnight"
      },
      "estimated_delivery_date_utc": "2026-05-02T20:00:00Z",
      "estimated_transit_days": 1
    },
    {
      "provider": "USPS",
      "servicelevel": {
        "name": "Priority Mail",
        "token": "usps_priority"
      },
      "estimated_delivery_date_utc": "2026-05-03T20:00:00Z",
      "estimated_transit_days": 2
    }
  ],
  "test": false
}
```

Service levels that would have arrived after May 3 — such as UPS Ground — are not present in the response.

### Filter by required delivery date

If your deadline is expressed as a local date rather than UTC, filter the `predictions` array yourself after timezone conversion.

```js theme={null}
const REQUIRED_LOCAL_DATE = "2026-05-03";
const DESTINATION_TIMEZONE = "America/Los_Angeles";

const eligiblePredictions = estimatesResponse.predictions.filter(prediction => {
  const localDate = new Date(prediction.estimated_delivery_date_utc)
    .toLocaleDateString("en-CA", { timeZone: DESTINATION_TIMEZONE }); // "YYYY-MM-DD"
  return localDate <= REQUIRED_LOCAL_DATE;
});

if (eligiblePredictions.length === 0) {
  console.warn("No service levels can meet the required delivery date.");
}
```

<Info>
  **Purchasing a label:** The Estimate API returns no pricing. Once you have the eligible `servicelevel.token` values, pass them to `POST /shipments` (optionally with `carrier_accounts`) to retrieve rates, then purchase a label via `POST /transactions`.
</Info>

## 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.
</Tip>

## Provide conservative commit dates for regulated or time-critical shipments

Use `confidence_level: "HIGH"` to get delivery dates that are more reliable — not just most likely.

For regulated shipments (pharmaceuticals, medical devices, age-restricted goods) and time-critical orders (event tickets, perishables, SLA-bound fulfillment), committing to a delivery date that is missed has real consequences. Passing `confidence_level: "HIGH"` returns a more conservative predicted date — one where historically only 5% of shipments have arrived later — so you only surface dates you can reliably stand behind.

### How confidence levels work

Each `confidence_level` corresponds to a percentile of historical delivery performance on the origin-to-destination lane.

| `confidence_level` | Best for | Behavior |
| - | - | - |
| `TYPICAL` | Internal analytics, baseline planning | Most common outcome; roughly half of shipments arrive by this date |
| `DEFAULT` | Customer-facing display at checkout | Balances competitive promise with strong on-time performance |
| `HIGH` | SLA commitments, regulated or time-critical shipments | Conservative; only 5% of shipments have historically arrived later |

### Request

```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",
    "confidence_level": "HIGH"
  }'
```

### Response

The `confidence_level` field in the response echoes back the level used. At GA, `HIGH` will return later, more conservative dates than `DEFAULT` for the same service level on the same lane.

```json theme={null}
{
  "object_id": "9f8e7d6c-...",
  "planned_ship_date": "2026-05-01T17:00:00Z",
  "confidence_level": "HIGH",
  "latest_delivery_date": null,
  "predictions": [
    {
      "provider": "FedEx",
      "servicelevel": {
        "name": "Priority Overnight",
        "token": "fedex_priority_overnight"
      },
      "estimated_delivery_date_utc": "2026-05-02T23:00:00Z",
      "estimated_transit_days": 1
    },
    {
      "provider": "USPS",
      "servicelevel": {
        "name": "Priority Mail",
        "token": "usps_priority"
      },
      "estimated_delivery_date_utc": "2026-05-05T20:00:00Z",
      "estimated_transit_days": 4
    }
  ],
  "test": false
}
```

### Selecting a service level for a commit date

```js theme={null}
const COMMIT_DATE_UTC = "2026-05-06"; // External SLA deadline, expressed as UTC date
const DESTINATION_TIMEZONE = "America/Los_Angeles";

// Filter to service levels that meet the commit date (using UTC date for comparison)
const eligiblePredictions = estimatesResponse.predictions.filter(prediction => {
  const utcDate = prediction.estimated_delivery_date_utc.split("T")[0]; // "YYYY-MM-DD"
  return utcDate <= COMMIT_DATE_UTC;
});

// To commit to a date, convert to destination local time for customer-facing display
const commitOptions = eligiblePredictions.map(prediction => ({
  service: `${prediction.provider} ${prediction.servicelevel.name}`,
  token: prediction.servicelevel.token,
  commitDate: new Date(prediction.estimated_delivery_date_utc)
    .toLocaleDateString("en-US", {
      timeZone: DESTINATION_TIMEZONE,
      weekday: "long",
      month: "long",
      day: "numeric"
    }),
}));
```

<Warning>
  Shippo Estimate dates are ML-powered predictions, not contractual guarantees. For absolute delivery guarantees with carrier backing, use services such as USPS Priority Mail Express or FedEx First Overnight and confirm money-back guarantee terms with the carrier.
</Warning>

## Inform warehouse systems of the ideal ship-out date

Use `planned_ship_date` and `estimated_transit_days` together to schedule warehouse tasks and enforce fulfillment cutoffs.

Knowing a predicted delivery date is only useful if your warehouse knows the latest date an order can be picked, packed, and handed to the carrier to achieve it. The Estimate API's `planned_ship_date` is the ship-out date you are committing to, and `estimated_transit_days` tells you the transit window from that date. Together they enable automated warehouse task creation, pick queue prioritization, and same-day cutoff enforcement.

### How it works

When you call `POST /v2/estimates`, pass the `planned_ship_date` that reflects your intended handoff to the carrier — typically today's date at the warehouse's daily carrier pickup or drop-off cutoff time. The response echoes `planned_ship_date` back in UTC and returns `estimated_transit_days` on each prediction, so you can calculate and display the full fulfillment timeline.

For warehouse scheduling, `planned_ship_date` is the ship-by target. Your system must create and complete the pick/pack task before that datetime.

### Request

Pass the warehouse cutoff time as the `planned_ship_date`. In this example, the warehouse closes carrier handoffs at 3:00 PM PDT (22:00 UTC).

```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-01T22:00:00Z"
  }'
```

### Response

```json theme={null}
{
  "object_id": "2b3c4d5e-...",
  "planned_ship_date": "2026-05-01T22:00:00Z",
  "confidence_level": "DEFAULT",
  "predictions": [
    {
      "provider": "FedEx",
      "servicelevel": {
        "name": "Priority Overnight",
        "token": "fedex_priority_overnight"
      },
      "estimated_delivery_date_utc": "2026-05-02T20:00:00Z",
      "estimated_transit_days": 1
    },
    {
      "provider": "USPS",
      "servicelevel": {
        "name": "Priority Mail",
        "token": "usps_priority"
      },
      "estimated_delivery_date_utc": "2026-05-03T20:00:00Z",
      "estimated_transit_days": 2
    },
    {
      "provider": "UPS",
      "servicelevel": {
        "name": "Ground",
        "token": "ups_ground"
      },
      "estimated_delivery_date_utc": "2026-05-05T20:00:00Z",
      "estimated_transit_days": 4
    }
  ],
  "test": false
}
```

### Push tasks to your warehouse system

Once the customer selects a service level at checkout, extract `planned_ship_date` and `estimated_transit_days` from the matching prediction and send them downstream to your warehouse management system (WMS) or fulfillment queue.

```js theme={null}
const CUSTOMER_SELECTED_TOKEN = "usps_priority";
const WAREHOUSE_TIMEZONE = "America/Los_Angeles";

// Find the prediction matching what the customer chose
const selectedPrediction = estimatesResponse.predictions.find(
  p => p.servicelevel.token === CUSTOMER_SELECTED_TOKEN
);

// A partial response can omit a service level. Check messages[] for the reason.
if (!selectedPrediction) {
  throw new Error(`No prediction for ${CUSTOMER_SELECTED_TOKEN}`);
}

// planned_ship_date is the cutoff the warehouse must meet
const shipByLocal = new Date(estimatesResponse.planned_ship_date)
  .toLocaleString("en-US", {
    timeZone: WAREHOUSE_TIMEZONE,
    dateStyle: "short",
    timeStyle: "short"
  });

const warehouseTask = {
  orderId: order.id,
  carrier: selectedPrediction.provider,
  service: selectedPrediction.servicelevel.name,
  servicelevelToken: selectedPrediction.servicelevel.token,
  shipBy: estimatesResponse.planned_ship_date,     // "2026-05-01T22:00:00Z" — UTC for storage
  shipByLocal: shipByLocal,                        // "5/1/26, 3:00 PM" — local time for display
  estimatedDeliveryUtc: selectedPrediction.estimated_delivery_date_utc,
  transitDays: selectedPrediction.estimated_transit_days,
  priority: isCutoffApproaching(estimatesResponse.planned_ship_date) ? "URGENT" : "STANDARD",
};

// Send to your WMS or fulfillment queue
await warehouseQueue.enqueue(warehouseTask);
```

### Enforce carrier cutoff times

The `planned_ship_date` you pass into the request defines the cutoff. If an order is placed after your warehouse's daily carrier handoff time, bump `planned_ship_date` to the next day's cutoff (skip days your warehouse is closed) and re-call the endpoint — the delivery date predictions will update accordingly.

```js theme={null}
function getNextShipDate(cutoffHourUTC = 22) {
  const now = new Date();
  const cutoff = new Date(now);
  cutoff.setUTCHours(cutoffHourUTC, 0, 0, 0);

  // If we've passed today's cutoff, ship tomorrow
  if (now >= cutoff) {
    cutoff.setUTCDate(cutoff.getUTCDate() + 1);
  }
  return cutoff.toISOString();
}

function isCutoffApproaching(plannedShipDateUtc, warningWindowMinutes = 60) {
  const cutoff = new Date(plannedShipDateUtc);
  const now = new Date();
  const msUntilCutoff = cutoff - now;
  return msUntilCutoff > 0 && msUntilCutoff <= warningWindowMinutes * 60 * 1000;
}

// Use the result as planned_ship_date in your estimates request
const plannedShipDate = getNextShipDate(22); // 22:00 UTC = 3 PM PDT (2 PM PST)
```

<Tip>
  For orders with tight fulfillment windows, consider calling the Estimate API with `confidence_level: "HIGH"`(see [Provide conservative commit dates](#provide-conservative-commit-dates-for-regulated-or-time-critical-shipments)) so the predicted delivery date accounts for real-world variability before you commit it to the customer.
</Tip>


## Related topics

- [Estimate](/estimate/estimate.md)
- [Create Estimates](/api-reference/estimates/create-estimates.md)
- [Choosing Business Cases/User Stories](/partner-integration/choosing-business-cases.md)
