---
title: "Forecast delivery time (beta)"
method: POST
path: "/delivery-estimates"
tags: ["Delivery Estimates"]
---

# Forecast delivery time (beta)

`POST /delivery-estimates`

## Request

- Base URL: `https://parcelsapp.com/api-docs/mock/v4`
- URL: `https://parcelsapp.com/api-docs/mock/v4/delivery-estimates`
- Auth: HTTP bearer
- TypeScript: <https://skmtc.dev/parcelsapp/apis/parcels-api-v4/docs/delivery-estimates/post.ts> (a function with typed inputs; its response is checked against the schema)

Beta endpoint. Returns a statistical delivery-time estimate without starting carrier tracking or consuming tracking quota.

**Minimum input per shipment**

- `carrier_slug` (find it with `GET /carriers`)
- `transport_mode` returned for that carrier
- `origin.country_code`
- `destination.country_code`

Add city/state, a real IATA airport, or an official UN/LOCODE only when known. For a shipment already in transit, supply exactly one of `accepted_at`, `shipped_at`, or `elapsed_days` to receive a remaining-time estimate. Most callers should omit `completion_scope`; the API chooses the normal boundary for the selected mode.

Read `estimate.median_days`, `estimate.typical_days`, and `confidence.level` first. For progress requests also read `estimate.remaining_status`. `estimated` means the right-censored risk set supports a remaining window. `insufficient_censored_data` or `insufficient_tail_data` means the API deliberately withheld an optimistic remaining ETA; the total-duration estimate remains available. If route history itself is insufficient, the item returns `INSUFFICIENT_DATA`. Exact ocean port requests never degrade to a country/global estimate.

## Request body

- DeliveryEstimateRequest: Batch request containing 1-100 independent shipments. Use a one-item array for a single estimate.
  - `shipments` DeliveryEstimateInput[], required
    - union: One shipment to estimate. The normal request needs only a carrier, transport mode, and origin/destination countries. Matching route precision, progress time, client_reference, and completion_scope are optional.
      - object
        - `client_reference` string: Optional caller reference echoed in the result.
        - `carrier_slug` string, required: Canonical carrier slug from GET /carriers.
        - `carrier_name` string: Human carrier name or alias. Prefer carrier_slug; ambiguous names are rejected.
        - `transport_mode` 'parcel' | 'postal' | 'express' | 'road_freight' | 'air_cargo' | 'ocean_container', required: Concrete transport mode. Forecast fallback never crosses this boundary.
        - `completion_scope` 'carrier_acceptance_to_delivery' | 'airport_to_airport' | 'airport_to_availability' | 'port_to_port' | 'port_to_availability' | 'port_to_gate_out': Defines what event counts as completion, and therefore which historical durations are compared. It is not a transport phase or route precision setting. Most callers should omit it and use the mode default. In v1 the start is the earliest confirmed physical carrier event, such as acceptance, pickup, RCS, or origin-terminal gate-in. The `airport_*` and `port_*` names describe the route family and completion boundary; they do not guarantee that the first timestamp is a flight departure or vessel departure. | Value | Measured journey | | --- | --- | | `carrier_acceptance_to_delivery` | Physical carrier acceptance or pickup to delivered/POD. Default for `parcel`, `postal`, `express`, and `road_freight`. | | `airport_to_airport` | First confirmed physical air-cargo event (often pickup or RCS) to arrival received at the destination airport (usually RCF). Default for `air_cargo`. | | `airport_to_availability` | First confirmed physical air-cargo event to ready-for-collection/available at the destination airport. | | `port_to_port` | First confirmed physical ocean event, such as origin-terminal gate-in, to arrival/discharge at the destination port. Default for `ocean_container`. | | `port_to_availability` | First confirmed physical ocean event to available/released for pickup at the destination port. | | `port_to_gate_out` | First confirmed physical ocean event to gate-out or terminal handoff at destination; this is not delivery to a final street address. | Fallback never crosses a completion-scope boundary. If the selected scope lacks enough observations, the API returns `INSUFFICIENT_DATA` rather than using a different endpoint meaning.
        - `origin` DeliveryEstimateLocation, required: A route endpoint. Only country_code is required. Add city/admin1 for parcel or road freight, a real IATA code for air cargo, or UN/LOCODE/port_name for ocean cargo when known.
          - `country_code` string, required: ISO 3166-1 alpha-2.
          - `admin1_code` string: ISO 3166-2 state or region code.
          - `city` string
          - `iata` string: Real IATA airport code for air cargo. It must match country_code.
          - `unlocode` string: Official UNECE UN/LOCODE 2025-1 port code. It must match country_code.
          - `port_name` string: Ocean port name when the UN/LOCODE is unavailable. Official unambiguous names are normalized to UN/LOCODE; other names use a country-qualified internal key.
        - `destination` DeliveryEstimateLocation, required: A route endpoint. Only country_code is required. Add city/admin1 for parcel or road freight, a real IATA code for air cargo, or UN/LOCODE/port_name for ocean cargo when known.
          - `country_code` string, required: ISO 3166-1 alpha-2.
          - `admin1_code` string: ISO 3166-2 state or region code.
          - `city` string
          - `iata` string: Real IATA airport code for air cargo. It must match country_code.
          - `unlocode` string: Official UNECE UN/LOCODE 2025-1 port code. It must match country_code.
          - `port_name` string: Ocean port name when the UN/LOCODE is unavailable. Official unambiguous names are normalized to UN/LOCODE; other names use a country-qualified internal key.
        - `accepted_at` string, date-time: Optional progress input: physical carrier acceptance/start time. Use at most one progress input. It must match the selected completion scope's start boundary and cannot be in the future.
        - `shipped_at` string, date-time: Optional progress input when accepted_at is unavailable. Use at most one of shipped_at, accepted_at, or elapsed_days; future values are rejected.
        - `elapsed_days` number: Optional progress input when no start timestamp is known. Number of calendar days already elapsed; do not combine it with a timestamp.
      - object
        - `client_reference` string: Optional caller reference echoed in the result.
        - `carrier_slug` string: Canonical carrier slug from GET /carriers.
        - `carrier_name` string, required: Human carrier name or alias. Prefer carrier_slug; ambiguous names are rejected.
        - `transport_mode` 'parcel' | 'postal' | 'express' | 'road_freight' | 'air_cargo' | 'ocean_container', required: Concrete transport mode. Forecast fallback never crosses this boundary.
        - `completion_scope` 'carrier_acceptance_to_delivery' | 'airport_to_airport' | 'airport_to_availability' | 'port_to_port' | 'port_to_availability' | 'port_to_gate_out': Defines what event counts as completion, and therefore which historical durations are compared. It is not a transport phase or route precision setting. Most callers should omit it and use the mode default. In v1 the start is the earliest confirmed physical carrier event, such as acceptance, pickup, RCS, or origin-terminal gate-in. The `airport_*` and `port_*` names describe the route family and completion boundary; they do not guarantee that the first timestamp is a flight departure or vessel departure. | Value | Measured journey | | --- | --- | | `carrier_acceptance_to_delivery` | Physical carrier acceptance or pickup to delivered/POD. Default for `parcel`, `postal`, `express`, and `road_freight`. | | `airport_to_airport` | First confirmed physical air-cargo event (often pickup or RCS) to arrival received at the destination airport (usually RCF). Default for `air_cargo`. | | `airport_to_availability` | First confirmed physical air-cargo event to ready-for-collection/available at the destination airport. | | `port_to_port` | First confirmed physical ocean event, such as origin-terminal gate-in, to arrival/discharge at the destination port. Default for `ocean_container`. | | `port_to_availability` | First confirmed physical ocean event to available/released for pickup at the destination port. | | `port_to_gate_out` | First confirmed physical ocean event to gate-out or terminal handoff at destination; this is not delivery to a final street address. | Fallback never crosses a completion-scope boundary. If the selected scope lacks enough observations, the API returns `INSUFFICIENT_DATA` rather than using a different endpoint meaning.
        - `origin` DeliveryEstimateLocation, required: A route endpoint. Only country_code is required. Add city/admin1 for parcel or road freight, a real IATA code for air cargo, or UN/LOCODE/port_name for ocean cargo when known.
          - `country_code` string, required: ISO 3166-1 alpha-2.
          - `admin1_code` string: ISO 3166-2 state or region code.
          - `city` string
          - `iata` string: Real IATA airport code for air cargo. It must match country_code.
          - `unlocode` string: Official UNECE UN/LOCODE 2025-1 port code. It must match country_code.
          - `port_name` string: Ocean port name when the UN/LOCODE is unavailable. Official unambiguous names are normalized to UN/LOCODE; other names use a country-qualified internal key.
        - `destination` DeliveryEstimateLocation, required: A route endpoint. Only country_code is required. Add city/admin1 for parcel or road freight, a real IATA code for air cargo, or UN/LOCODE/port_name for ocean cargo when known.
          - `country_code` string, required: ISO 3166-1 alpha-2.
          - `admin1_code` string: ISO 3166-2 state or region code.
          - `city` string
          - `iata` string: Real IATA airport code for air cargo. It must match country_code.
          - `unlocode` string: Official UNECE UN/LOCODE 2025-1 port code. It must match country_code.
          - `port_name` string: Ocean port name when the UN/LOCODE is unavailable. Official unambiguous names are normalized to UN/LOCODE; other names use a country-qualified internal key.
        - `accepted_at` string, date-time: Optional progress input: physical carrier acceptance/start time. Use at most one progress input. It must match the selected completion scope's start boundary and cannot be in the future.
        - `shipped_at` string, date-time: Optional progress input when accepted_at is unavailable. Use at most one of shipped_at, accepted_at, or elapsed_days; future values are rejected.
        - `elapsed_days` number: Optional progress input when no start timestamp is known. Number of calendar days already elapsed; do not combine it with a timestamp.

## Response `200`

One result per input item. Most integrations only need median_days, typical_days, and confidence.level. Insufficient data is a per-item result, so mixed batches remain HTTP 200.

- DeliveryEstimateResponse
  - `results` DeliveryEstimateResult[], required
    - `client_reference` string
    - `carrier_slug` string, required
    - `transport_mode` 'parcel' | 'postal' | 'express' | 'road_freight' | 'air_cargo' | 'ocean_container', required: Concrete transport mode. Forecast fallback never crosses this boundary.
    - `completion_scope` 'carrier_acceptance_to_delivery' | 'airport_to_airport' | 'airport_to_availability' | 'port_to_port' | 'port_to_availability' | 'port_to_gate_out', required: Defines what event counts as completion, and therefore which historical durations are compared. It is not a transport phase or route precision setting. Most callers should omit it and use the mode default. In v1 the start is the earliest confirmed physical carrier event, such as acceptance, pickup, RCS, or origin-terminal gate-in. The `airport_*` and `port_*` names describe the route family and completion boundary; they do not guarantee that the first timestamp is a flight departure or vessel departure. | Value | Measured journey | | --- | --- | | `carrier_acceptance_to_delivery` | Physical carrier acceptance or pickup to delivered/POD. Default for `parcel`, `postal`, `express`, and `road_freight`. | | `airport_to_airport` | First confirmed physical air-cargo event (often pickup or RCS) to arrival received at the destination airport (usually RCF). Default for `air_cargo`. | | `airport_to_availability` | First confirmed physical air-cargo event to ready-for-collection/available at the destination airport. | | `port_to_port` | First confirmed physical ocean event, such as origin-terminal gate-in, to arrival/discharge at the destination port. Default for `ocean_container`. | | `port_to_availability` | First confirmed physical ocean event to available/released for pickup at the destination port. | | `port_to_gate_out` | First confirmed physical ocean event to gate-out or terminal handoff at destination; this is not delivery to a final street address. | Fallback never crosses a completion-scope boundary. If the selected scope lacks enough observations, the API returns `INSUFFICIENT_DATA` rather than using a different endpoint meaning.
    - `route_scope_used` string: Diagnostic name of the selected statistics bucket, including whether it is carrier specific or a mode fallback. Most integrations can ignore it.
    - `route` DeliveryEstimateRoute: Route-selection diagnostics. Most integrations can ignore this object.
      - `origin_dimension` 'city' | 'admin1' | 'country' | 'airport' | 'port', nullable
      - `origin_key` string, nullable
      - `destination_dimension` 'city' | 'admin1' | 'country' | 'airport' | 'port', nullable
      - `destination_key` string, nullable
      - `carrier_specific` boolean
    - `estimate` DeliveryEstimateValues
      - `mean_days` number, required: Arithmetic mean for analytics. Use median_days as the normal point estimate.
      - `median_days` number, required: Primary point estimate.
      - `typical_days` DeliveryEstimateRange, required: Typical P10-P90 range in calendar days.
        - `min` number
        - `max` number
      - `remaining_status` 'not_requested' | 'estimated' | 'insufficient_censored_data' | 'insufficient_tail_data', required: Whether remaining_days was not requested, safely estimated, or withheld. insufficient_censored_data means the right-censored risk set or identifiable tail is too small; insufficient_tail_data is the fail-closed completed-tail fallback used before a survival generation exists.
      - `remaining_days` DeliveryEstimateRemaining, nullable: Estimated days still remaining. The censored model requires at least 100 subjects, 30 completed events, cohort age of 120 days (300 for ocean), at least five journeys and 10% of subjects in the current risk set, and identifiable P10, P50, and P90. Otherwise remaining_status explains why the API withheld it.
        - `mean` number, nullable: Null for Kaplan-Meier output; use median, min, and max.
        - `median` number
        - `min` number
        - `max` number
      - `estimated_delivery_at` DeliveryEstimateWindow, nullable: Estimated UTC delivery window. Present only when the request supplied a start timestamp or usable elapsed duration.
        - `from` string, date-time
        - `to` string, date-time
    - `confidence` DeliveryEstimateConfidence: Quality of statistical support, not the probability of delivery on one promised date.
      - `level` 'low' | 'medium' | 'high', required: Simple evidence-quality label for normal integrations.
      - `score` number, required: Diagnostic evidence-quality score, not an on-time-delivery probability.
      - `sample_count` integer, required
      - `effective_sample_count` number, required
      - `remaining_effective_sample_count` number: For Kaplan-Meier, the right-censored risk-set size at elapsed time; for the completed-tail fallback, time-decayed completed-tail support. Present only for a progress request.
      - `minimum_remaining_effective_sample_count` number: Safety floor applied by the active remaining-time method. Kaplan-Meier requires at least five journeys and 10% of subjects in the risk set, in addition to the per-mode subject floor and identifiable P10-P90 tail.
      - `survival_subject_count` integer
      - `survival_completed_count` integer
      - `survival_censored_count` integer
      - `survival_risk_set` integer
      - `survival_minimum_subject_count` integer
      - `survival_minimum_completed_count` integer
      - `survival_cohort_age_days` number
      - `survival_minimum_maturation_days` integer
      - `lookback_days` integer, required
      - `last_observation_at` string, date-time, nullable
      - `freshness_days` number
      - `fallback_level` integer, required
    - `model` object: Model diagnostics for reproducibility. Most integrations can ignore this object.
      - `version` string
      - `unit` 'calendar_days'
      - `histogram_bucket_hours` integer
      - `remaining_method` 'kaplan_meier_right_censored_v1' | 'completed_tail_guard_v1': Kaplan-Meier uses active right-censored journeys and delayed entry. The completed-tail guard remains a fail-closed fallback when no survival generation is published.
    - `error` DeliveryEstimateInsufficientData
      - `code` 'INSUFFICIENT_DATA', required
      - `message` string, required
      - `available_sample_count` integer, required
      - `minimum_sample_count` integer, required
  - `generated_at` string, date-time, required
  - `model_version` string, required

## Other responses

- `400`: Invalid carrier, mode, scope, location code, date, or batch.
- `401`: Missing or invalid API key.
- `402`: Subscription is inactive.
- `403`: Account or subscription cannot use the endpoint.
- `404`: Beta endpoint is disabled by the production feature flag.
- `429`: Too many requests.
- `500`: Unexpected server error.

## Changes

- **2026-11-06** `dd6315a8bc4e`: 1 breaking, 19 warning, 9 info
  - the response property `results/items/estimate/remaining_days/mean` became nullable for the status `200`
  - removed the request property `shipments/items/destination/icao`
  - removed the request property `shipments/items/destination/postal_code`
  - removed the request property `shipments/items/origin/icao`
  - …25 more
- **2026-07-19** `f8d02f819394`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/parcelsapp/apis/parcels-api-v4/changes/delivery-estimates/post.md)

---

[API](https://skmtc.dev/parcelsapp/apis/parcels-api-v4.md) - [All operations](https://skmtc.dev/parcelsapp/apis/parcels-api-v4/llms.txt) - [OpenAPI document](https://skmtc.dev/parcelsapp/apis/parcels-api-v4/revisions/dd6315a8bc4e?raw)
