> For the complete documentation index, see [llms.txt](https://docs.parcellab.com/docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.parcellab.com/docs/developers/promise/api.md).

# Promise Dates

Use the Promise API to get an estimated delivery date to display during conversion and checkout to reduce uncertainty that leads to cart abandonment and improve customer delivery satisfaction.

## Overview

parcelLab provides an API you can call to get forecasted delivery dates. This date can be used to display a delivery date promise on the product details page or at checkout. It can be shown in a format you want on your website so customers can see when a product should arrive before buying it.

{% hint style="info" %}
For more information on the scope and requirements of this feature, please contact your parcelLab representative.
{% endhint %}

For an embeddable storefront widget, see [Promise UI Plugin](/docs/developers/promise/ui-plugin.md).

## Get Promise Date

You can retrieve the forecasted delivery date of an order using the `v4/promise/prediction/predict` endpoint.

## Generate prediction

> If IP lookup fails or no delivery methods match, Backend uses fallback\_country\_iso3 when supplied. Matching IP methods take priority, even in another country. An empty prediction list after method selection does not trigger a fallback.\
> \
> IP requests are limited to 60 per minute per caller IP. Excess requests return HTTP 429 with Retry-After. Country and postal code requests do not use this limit.

```json
{"openapi":"3.1.0","info":{"title":"parcelLab API","version":"v4"},"security":[{"HeaderToken":[]},{"OAuth2Authentication":[]},{}],"components":{"securitySchemes":{"HeaderToken":{"type":"apiKey","in":"header","name":"Authorization","description":"Send `Authorization: Parcellab-API-Token <encoded-token>`.\n\n`<encoded-token>` = `base64(account_id:token)` as provided in the portal."},"OAuth2Authentication":{"type":"http","scheme":"bearer","bearerFormat":"JWT","description":"Unbound access tokens use Authorization: Bearer <token>. DPoP-bound tokens use Authorization: DPoP <token> and a DPoP proof header signed with the bound key for each request. Supported proof algorithms: ES256 and RS256."}},"schemas":{"PredictionResponse":{"properties":{"request_id":{"title":"Request Id","type":"string"},"success":{"title":"Success","type":"boolean"},"prediction":{"items":{"$ref":"#/components/schemas/Prediction"},"title":"Prediction","type":"array"},"location":{"anyOf":[{"$ref":"#/components/schemas/PredictionLocation"},{"type":"null"}],"default":null,"description":"Location selected by Backend for prediction, including an IP fallback country when used. Retained when no predictions are generated. Null if resolution failed or an older Backend response omits the location."}},"required":["request_id","success","prediction"],"title":"PredictionResponse","type":"object"},"Prediction":{"properties":{"id":{"description":"Delivery Method ID","title":"Id","type":"string"},"warehouse":{"description":"Warehouse ID","title":"Warehouse","type":"string"},"courier":{"description":"parcelLab courier code, e.g. ups","title":"Courier","type":"string"},"courier_name":{"description":"Pretty courier name","title":"Courier Name","type":"string"},"courier_alias":{"description":"Retailer internal courier code","items":{"type":"string"},"title":"Courier Alias","type":"array"},"courier_service_level":{"description":"All specified aliases for the service level","items":{"type":"string"},"title":"Courier Service Level","type":"array"},"global_courier_service_level":{"$ref":"#/components/schemas/CourierServiceLevelEnum","description":"parcelLab global courier service level for the delivery method. Unrecognized Backend values are returned as unknown."},"prediction":{"$ref":"#/components/schemas/PredictionDetails","description":"The prediction details"}},"required":["id","warehouse","courier","courier_name","courier_alias","courier_service_level","global_courier_service_level","prediction"],"title":"Prediction","type":"object"},"CourierServiceLevelEnum":{"enum":["standard","unused","express","expedited","unknown"],"title":"CourierServiceLevelEnum","type":"string"},"PredictionDetails":{"properties":{"min":{"description":"The minimum number of expected courier working days until delivery. Note: The value for minimum and maximum can be equal.","title":"Min","type":"integer"},"max":{"description":"The maximum number of expected courier working days until delivery. Note: The value for minimum and maximum can be equal.","title":"Max","type":"integer"},"likely":{"description":"The most likely number of expected courier working days until delivery.","title":"Likely","type":"integer"},"send_date":{"description":"The date of dispatch as per warehouse configuration.","format":"date","title":"Send Date","type":"string"},"earliest_date":{"description":"The earliest expected delivery date taking into consideration working days of the courier, holidays in the destination, and warehouse cut-off and handling times.","format":"date","title":"Earliest Date","type":"string"},"latest_date":{"description":"The latest expected delivery date taking into consideration working days of the courier, holidays in the destination, and warehouse cut-off and handling times.","format":"date","title":"Latest Date","type":"string"},"most_likely_date":{"description":"The most likely individual date of delivery.","format":"date","title":"Most Likely Date","type":"string"},"earliest_locale":{"description":"Localized representations of the earliest expected delivery date in the specified format.","title":"Earliest Locale","type":"string"},"latest_locale":{"description":"Localized representations of the latest expected delivery date in the specified format.","title":"Latest Locale","type":"string"},"most_likely_locale":{"description":"Localized representations of the most likely delivery date in the specified format.","title":"Most Likely Locale","type":"string"},"cutoff":{"description":"The time in minutes until cut-off for the estimated delivery dates.","title":"Cutoff","type":"integer"},"cutoff_locale":{"description":"Localized representation of the cut-off time.","title":"Cutoff Locale","type":"string"}},"required":["min","max","likely","send_date","earliest_date","latest_date","most_likely_date","earliest_locale","latest_locale","most_likely_locale","cutoff","cutoff_locale"],"title":"PredictionDetails","type":"object"},"PredictionLocation":{"properties":{"country":{"description":"Country code returned by Backend for prediction.","title":"Country","type":"string"},"region":{"description":"Resolved region, or the ISO2 country for a country-level location.","title":"Region","type":"string"},"zip":{"anyOf":[{"type":"string"},{"type":"null"}],"description":"Postal code used for prediction. Can be null, or \"0\" for the existing country-level fallback.","title":"Zip"}},"required":["country","region","zip"],"title":"PredictionLocation","type":"object"},"Error400Response":{"type":"object","properties":{"type":{"type":"string"},"errors":{"type":"array","items":{"$ref":"#/components/schemas/GenericErrorItem"}}},"required":["errors","type"]},"GenericErrorItem":{"type":"object","properties":{"code":{"type":"string"},"detail":{"type":"string"},"attr":{"type":["string","null"]}},"required":["code","detail"]},"ErrorResponse404":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ClientErrorEnum"},"errors":{"type":"array","items":{"$ref":"#/components/schemas/Error404"}}},"required":["errors","type"]},"ClientErrorEnum":{"enum":["client_error"],"type":"string","description":"* `client_error` - Client Error"},"Error404":{"type":"object","properties":{"code":{"$ref":"#/components/schemas/ErrorCode404Enum"},"detail":{"type":"string"},"attr":{"type":["string","null"]}},"required":["attr","code","detail"]},"ErrorCode404Enum":{"enum":["not_found"],"type":"string","description":"* `not_found` - Not Found"},"ErrorResponse429":{"type":"object","properties":{"type":{"$ref":"#/components/schemas/ClientErrorEnum"},"errors":{"type":"array","items":{"$ref":"#/components/schemas/Error429"}}},"required":["errors","type"]},"Error429":{"type":"object","properties":{"code":{"$ref":"#/components/schemas/ErrorCode429Enum"},"detail":{"type":"string"},"attr":{"type":["string","null"]}},"required":["attr","code","detail"]},"ErrorCode429Enum":{"enum":["throttled"],"type":"string","description":"* `throttled` - Throttled"}}},"paths":{"/v4/promise/prediction/predict/":{"get":{"operationId":"promise_prediction_predict_retrieve","description":"If IP lookup fails or no delivery methods match, Backend uses fallback_country_iso3 when supplied. Matching IP methods take priority, even in another country. An empty prediction list after method selection does not trigger a fallback.\n\nIP requests are limited to 60 per minute per caller IP. Excess requests return HTTP 429 with Retry-After. Country and postal code requests do not use this limit.","summary":"Generate prediction","parameters":[{"in":"query","name":"account","schema":{"type":"integer","title":"Account ID"},"description":"Account ID","required":true},{"in":"query","name":"calibration","schema":{"enum":["conservative","balanced","aggressive",null],"type":["string","null"]},"description":"Set to true, to indicate that the prediction should be done based on the current, not yet published, promise configuration\n\n* `conservative` - conservative\n* `balanced` - balanced\n* `aggressive` - aggressive"},{"in":"query","name":"courier","schema":{"type":["string","null"],"minLength":1,"maxLength":40},"description":"The logistics courier to be used. Defaults to returning all configured couriers."},{"in":"query","name":"destination_country_iso3","schema":{"type":["string","null"]},"description":"ISO 3166-1 alpha-3 code of the destination country. Supply either this field or destination_ip_address."},{"in":"query","name":"destination_ip_address","schema":{"type":["string","null"],"minLength":1},"description":"Shopper IPv4 or IPv6 address for an estimated delivery location. Do not combine with destination_country_iso3 or destination_postal_code. IP lookup does not confirm a delivery address."},{"in":"query","name":"destination_postal_code","schema":{"type":["string","null"],"minLength":1,"maxLength":10},"description":"Postal code of the destination. Requires destination_country_iso3."},{"in":"query","name":"dispatch_now","schema":{"type":"boolean","default":false},"description":"Forces the forecasted delivery date to skip any warehouse calculation and generate a prediction if the parcel is shipped at the moment of the API call, if set to 'true'"},{"in":"query","name":"draft","schema":{"type":["boolean","null"],"title":"Draft Mode"},"description":"Set to true, to indicate that the prediction should be done based on the current, not yet published, promise configuration"},{"in":"query","name":"fallback_country_iso3","schema":{"type":["string","null"]},"description":"Optional ISO 3166-1 alpha-3 country for IP destinations. Used when IP lookup fails or no delivery methods match. Matching IP delivery methods take priority. The fallback uses no IP postal code or region."},{"in":"query","name":"language_iso2","schema":{"type":["string","null"],"minLength":2,"title":"Language","maxLength":5,"pattern":"^[a-zA-Z]{2}(?:[-_][a-zA-Z]{2})?$"},"description":"Language code to use for localization. Plain language codes such as en or es are supported. Locale codes with country suffixes such as es_US or es-US are also accepted."},{"in":"query","name":"now_override","schema":{"type":["string","null"],"format":"date-time","title":"Now"},"description":"Locks the prediction for a specified request date as a ISO 8601 date and time in UTC format like 2022-06-10T06:42:00Z. Defaults now to the current time if omitted, which is required for production usage. "},{"in":"query","name":"service_level","schema":{"type":["string","null"],"minLength":1,"maxLength":40},"description":"The courier service level mapped in your Promise configuration (for example: express delivery). Defaults to returning all courier service levels."},{"in":"query","name":"tag","schema":{"type":["string","null"],"minLength":1,"maxLength":40},"description":"Tag to target prediction adjustment rule"},{"in":"query","name":"warehouse","schema":{"type":["string","null"],"minLength":1,"maxLength":40},"description":"The warehouse the delivery shipped from (input field: key). Defaults to the default warehouse for the destination."}],"tags":["Promise"],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PredictionResponse"}}},"description":""},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/Error400Response"}}},"description":""},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse404"}}},"description":""},"429":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse429"}}},"description":""}}}}}}
```

### Integration Flow: Send, Read, and Save

Use the confirmed checkout address first. Before checkout, use a shopper's saved country and postal code when available; otherwise, use an IP estimate with a country fallback. A saved country-only choice should also take priority over a new IP lookup.

| Stage                                   | Send or read                                                                                                                                                                                         | What your integration does                                                                                                                                                                |
| --------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Estimate before an address is known     | Send `account`, `destination_ip_address`, and optionally `fallback_country_iso3`.                                                                                                                    | Read `location.country` and `location.zip` to label an approximate destination. Keep it separate from the delivery address.                                                               |
| Shopper enters or changes a destination | Send `destination_country_iso3` and, if available, `destination_postal_code`. Remove `destination_ip_address` and `fallback_country_iso3`.                                                           | Save the shopper's country and postal code together if you want to reuse their choice. Clear the old postal code when the country changes. Request a new prediction.                      |
| Select the shipping option              | Read a matching entry from `prediction[]`, using its `id`, `warehouse`, `courier`, and service-level fields.                                                                                         | Select the method offered at checkout. Do not assume the first entry is the right method.                                                                                                 |
| Display the date                        | Read the selected entry's `prediction.earliest_date`, `latest_date`, or `most_likely_date`.                                                                                                          | For "delivery by", use `latest_date`; for a range, use `earliest_date` and `latest_date` from the same entry. Check the HTTP status, `success`, and a nonempty matching prediction first. |
| Shopper places the order                | Save the displayed ISO date or range, selected method, confirmed destination, and top-level `request_id` with the order in your system.                                                              | Keep the promise shown at checkout. A later prediction must not silently replace that saved promise.                                                                                      |
| Send the order or tracking to parcelLab | Send a saved single date in `mutations[].tracking.announced_delivery_date`. For a range, send `announced_delivery_date_min` and `announced_delivery_date_max` at the top level of the order payload. | Put the saved request ID in `mutations[].tracking.additional_fields.requestID` if this custom field is configured for your integration.                                                   |

The Promise GET request does not save the shopper's selection or attach a promise to an order. Your integration must do this. See [Create Orders/Trackings](/docs/developers/orders/create-orders-trackings.md) for the authenticated write request and [the product flow](https://docs.parcellab.com/docs/convert/promise#using-promise-dates-in-communications-from-parcellab) for a complete field example.

Keep automatic IP locations in temporary page state. Save manual destination choices separately from order data, with an expiry that fits your storefront. A raw API integration does not get the reference widget's automatic 30-day storage. Treat `location.zip` values of `null` or `"0"` as no postal code, and do not infer a confirmed address from `location`.

Request a new prediction when the destination or selected shipping method changes and before the order is placed. Save ISO dates, not localized display text or the cutoff duration. If no matching prediction is available, let the shopper correct the destination and omit the delivery date.

### Choose a Destination

Supply your `account` ID and exactly one destination: a country with an optional postal code, or the shopper's IPv4 or IPv6 address.

| Parameter                  | Use                                                                                                          |
| -------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `account`                  | Required. Your parcelLab account ID. The account must have Promise enabled.                                  |
| `destination_country_iso3` | ISO 3166-1 alpha-3 country code, such as `DEU`. Required unless you supply `destination_ip_address`.         |
| `destination_postal_code`  | Optional postal code. Requires `destination_country_iso3`. Keep leading zeros.                               |
| `destination_ip_address`   | Shopper's IPv4 or IPv6 address. Do not combine with `destination_country_iso3` or `destination_postal_code`. |
| `fallback_country_iso3`    | Optional ISO 3166-1 alpha-3 country code, such as `USA`. Only valid with `destination_ip_address`.           |

The existing `courier`, `service_level`, `warehouse`, `tag`, `draft`, `language_iso2`, `calibration`, `dispatch_now`, and `now_override` parameters also apply to IP requests.

#### Use an IP Address

Before the shopper supplies a delivery address, send their IP address in `destination_ip_address`. The API does not use request headers to select the destination IP.

```
https://api.parcellab.com/v4/promise/prediction/predict/?account=YOUR_ACCOUNT_ID&destination_ip_address=8.8.8.8
```

For IPv6, use your HTTP client's query-parameter encoder. For example:

```
https://api.parcellab.com/v4/promise/prediction/predict/?account=YOUR_ACCOUNT_ID&destination_ip_address=2001%3A4860%3A4860%3A%3A8888
```

Replace `YOUR_ACCOUNT_ID` with your Promise-enabled account ID and the example IP with the shopper's IP address. Supply an IP address without a hostname, network prefix, or IPv6 scope ID.

IP lookup estimates a location. It does not confirm the delivery address. When the shopper supplies an address, use its country and postal code for the next request and remove the IP and fallback parameters.

#### Set a Fallback Country

Add `fallback_country_iso3` to use a country-level location when the IP cannot resolve or has no matching delivery methods:

```
https://api.parcellab.com/v4/promise/prediction/predict/?account=YOUR_ACCOUNT_ID&destination_ip_address=8.8.8.8&fallback_country_iso3=USA
```

The API selects the location as follows:

1. If the IP location has matching delivery methods, the API uses that location, even when its country differs from the fallback country.
2. If IP lookup fails or no delivery methods match, the API tries the fallback country. It does not use the IP location's postal code or region for the fallback.
3. The API generates predictions for the selected methods. If they produce no predictions, the API keeps the selected location and returns an empty `prediction` array. This does not trigger another fallback.

Account access checks and delivery method filters also apply to the fallback. A fallback country does not guarantee a prediction.

#### Rate Limits for IP Requests

IP requests have two limits: 60 requests per minute per caller IP, and 60 requests per minute per account and caller IP combination. The caller IP is the address that sends the API request, which can differ from `destination_ip_address`. Requests from your server can share the same caller limit.

If either limit is exceeded, the API returns HTTP `429` with a `Retry-After` header. Wait for the specified number of seconds before retrying. Changing the destination IP or account does not bypass the caller-IP limit. Country and postal code requests do not use these IP-specific limits.

### Result Structure

For HTTP `200` responses, `prediction` contains the applicable predictions and `location` identifies the destination used. The `request_id` is for tracing and troubleshooting.

For example, if a US fallback location has no matching delivery methods:

```json
{
  "request_id": "abcd1234",
  "success": true,
  "prediction": [],
  "location": {
    "country": "USA",
    "region": "US",
    "zip": null
  }
}
```

#### Selected Location

The `location` object applies to both IP and explicit destinations. When the API uses a fallback country, this object contains the country-level fallback location. A selected location can remain present when `prediction` is empty, including when `success` is `false`.

| Field     | Description                                                                                                   |
| --------- | ------------------------------------------------------------------------------------------------------------- |
| `country` | Three-letter country code used for prediction. Kosovo uses `XKX`.                                             |
| `region`  | Resolved region, such as `DE-BY`, or the two-letter country code, such as `US`, for a country-level location. |
| `zip`     | Postal code as a string. Can be `null` or `"0"` for a country-level location.                                 |

`location` is `null` if no location is available. Clients must accept `null`.

#### Predictions

Each entry in the prediction array represents one delivery method, including a delivery prediction like the following structure:

```json
{ 
  "id": "Delivery Method ID", 
  "warehouse": "Warehouse ID", 
  "courier": "parcelLab courier code, e.g. ups", 
  "courier_name": "Pretty courier name", 
  "courier_alias": [ "Retailer internal courier code" ],
  "courier_service_level": [ "all specified aliases for the service level" ], 
  "global_courier_service_level": "Global service level of the delivery method",
  "prediction": { 
    "min": 1, 
    "max": 2, 
    "likely": 2,
    "send_date": "2022-06-11", 
    "earliest_date": "2022-06-12",
    "latest_date": "2022-06-13",
    "most_likely_date": "2022-06-13",
    "earliest_locale": "Thursday, Jun 12th, 2022",
    "latest_locale": "Friday, Jun 13th, 2022",
    "most_likely_locale": "Friday, Jun 13th, 2022",
    "cutoff": 747,
    "cutoff_locale": "12 hours"
  } 
} 
```

#### Delivery Prediction Details

The details included in a delivery prediction are described in the following table.

<table data-full-width="false"><thead><tr><th width="182">Key</th><th width="216.53846153846155">Type</th><th>Description</th></tr></thead><tbody><tr><td>min</td><td>Integer</td><td>The minimum number of expected courier working days until delivery.<br><strong>Note:</strong> The value for minimum and maximum can be equal.</td></tr><tr><td>max</td><td>Integer</td><td><p>The maximum number of expected courier working days until delivery.</p><p><strong>Note:</strong> The value for minimum and maximum can be equal.</p></td></tr><tr><td>likely</td><td>Integer</td><td>The most likely number of expected courier working days until delivery.</td></tr><tr><td>send_date</td><td><a href="https://www.iso.org/iso-8601-date-and-time-format.html">ISO 8601 date format</a>: YYYY-MM-DD</td><td>The date of dispatch as per warehouse configuration.</td></tr><tr><td>earliest_date</td><td><a href="https://www.iso.org/iso-8601-date-and-time-format.html">ISO 8601 date format</a>: YYYY-MM-DD</td><td>The earliest expected delivery date taking into consideration working days of the courier, holidays in the destination, and warehouse cut-off and handling times.</td></tr><tr><td>latest_date</td><td><a href="https://www.iso.org/iso-8601-date-and-time-format.html">ISO 8601 date format</a>: YYYY-MM-DD</td><td>The latest expected delivery date taking into consideration working days of the courier, holidays in the destination, and warehouse cut-off and handling times.</td></tr><tr><td>most_likely_date</td><td><a href="https://www.iso.org/iso-8601-date-and-time-format.html">ISO 8601 date format</a>: YYYY-MM-DD</td><td>The most likely individual date of delivery.</td></tr><tr><td>earliest_locale</td><td>Defaults to <code>dddd, MMM DDD, YYYY</code></td><td>Localized representations of the earliest expected delivery date in the specified format.</td></tr><tr><td>latest_locale</td><td>Defaults to <code>dddd, MMM DDD, YYYY</code></td><td>Localized representations of the latest expected delivery date in the specified format.</td></tr><tr><td>most_likely_locale</td><td>Defaults to <code>dddd, MMM DDD, YYYY</code></td><td>Localized representations of the most likely delivery date in the specified format.</td></tr><tr><td>cutoff</td><td>Integer</td><td>The time in minutes until cut-off for the estimated delivery dates.</td></tr><tr><td>cutoff_locale</td><td>String</td><td>Localized representations of the cut-off. Can be used within a sentence like "Order within <em>[2 hours | an hour | 20 minutes]</em> to receive your order by <em>[Saturday, Mar 23rd, 2022]</em>".</td></tr></tbody></table>

### Sample Calls

The sample API calls below show different information in the request (for example: home delivery as the courier service type) for the delivery prediction.

{% tabs %}
{% tab title="Country" %}
Request: `GET https://api.parcellab.com/v4/promise/prediction/predict/?account=1612197&destination_country_iso3=DEU`

Example response:

```json
{ 
    "request_id": "wLy6ThLp",
    "success": true, 
    "location": { "country": "DEU", "region": "DE", "zip": null },
    "prediction": [{ 
        "id": "DHL Standard", 
        "warehouse": "Europe Warehouse",  
        "courier": "dhl-germany", 
        "courier_name": "DHL", 
        "courier_alias": [],
        "courier_service_level": ["home-delivery","pick-from-store"],
        "global_courier_service_level": "standard",
        "prediction": { 
            "min": 1, 
            "max": 3, 
            "likely": 2,
            "send_date": "2023-11-23", 
            "earliest_date": "2023-11-24", 
            "latest_date": "2023-11-27", 
            "most_likely_date": "2023-11-25",
            "earliest_locale": "Friday, Nov 24th, 2023", 
            "latest_locale": "Monday, Nov 27th, 2023", 
            "most_likely_locale": "Saturday, Nov 25th, 2023", 
            "cutoff": 104, 
            "cutoff_locale": "1 hour, 44 minutes"}},
        { 
         "id": "UPS Express",
         "warehouse": "Europe Warehouse",  
         "courier": "ups", 
         "courier_name": "UPS", 
         "courier_alias": [],
         "courier_service_level": ["home-delivery","express","overnight"],
         "global_courier_service_level": "express",
         "prediction": { 
             "min": 1, 
             "max": 1, 
             "likely": 1,
             "send_date": "2023-11-23", 
             "earliest_date": "2023-11-24", 
             "latest_date": "2023-11-24",
             "most_likely_date": "2023-11-24", 
             "earliest_locale": "Friday, Nov 24th, 2023", 
             "latest_locale": "Friday, Nov 24th, 2023",
             "most_likely_locale": "Friday, Nov 24th, 2023", 
             "cutoff": 76, 
             "cutoff_locale": "1 hour, 16 minutes"
      }
  }]
}
```

{% endtab %}

{% tab title="Country and Zip Code" %}
Request: `GET https://api.parcellab.com/v4/promise/prediction/predict/?account=1612197&destination_country_iso3=DEU&destination_postal_code=80469`

Example response:

```json
{ 
    "request_id": "Zgr8YN3w",
    "success": true, 
    "location": { "country": "DEU", "region": "DE-BY", "zip": "80469" },
    "prediction": [{ 
        "id": "DHL Standard", 
        "warehouse": "Europe Warehouse",  
        "courier": "dhl-germany", 
        "courier_name": "DHL", 
        "courier_alias": [],
        "courier_service_level": ["home-delivery","pick-from-store"],
        "global_courier_service_level": "standard",
        "prediction": { 
            "min": 1, 
            "max": 3, 
            "likely": 2,
            "send_date": "2023-11-23",
            "earliest_date": "2023-11-24",
            "latest_date": "2023-11-27",
            "most_likely_date": "2023-11-25",
            "earliest_locale": "Friday, Nov 24th, 2023",
            "latest_locale": "Monday, Nov 27th, 2023",
            "most_likely_locale": "Saturday, Nov 25th, 2023",
            "cutoff": 104, 
            "cutoff_locale": "1 hour, 44 minutes"}},
        { 
         "id": "UPS Express",
         "warehouse": "Europe Warehouse",  
         "courier": "ups", 
         "courier_name": "UPS", 
         "courier_alias": [],
         "courier_service_level": ["home-delivery","express","overnight"],
         "global_courier_service_level": "express",
         "prediction": { 
             "min": 1, 
             "max": 1, 
             "likely": 1,
             "send_date": "2023-11-23",
             "earliest_date": "2023-11-24",
             "latest_date": "2023-11-24",
             "most_likely_date": "2023-11-24",
             "earliest_locale": "Friday, Nov 24th, 2023",
             "latest_locale": "Friday, Nov 24th, 2023",
             "most_likely_locale": "Friday, Nov 24th, 2023",
             "cutoff": 76, 
             "cutoff_locale": "1 hour, 16 minutes"
       }    
  }]
}
```

{% endtab %}

{% tab title="Specific Service Types" %}
Request: `GET https://api.parcellab.com/v4/promise/prediction/predict/?account=1612197&destination_country_iso3=USA&service_level=home-delivery`

Example response:

```json
{ 
    "request_id": "gxFAiZfP",
    "success": true, 
    "location": { "country": "USA", "region": "US", "zip": null },
    "prediction": [{ 
        "id": "USPS Standard", 
        "warehouse": "US East Coast Warehouse",  
        "courier": "usps", 
        "courier_name": "USPS", 
        "courier_alias": [],
        "courier_service_level": ["home-delivery","pick-from-store"],
        "global_courier_service_level": "standard",
        "prediction": { 
            "min": 3, 
            "max": 5, 
            "likely": 4, 
            "send_date": "2022-08-19", 
            "earliest_date": "2022-08-24", 
            "latest_date": "2022-08-26", 
            "most_likely_date": "2022-08-25",
            "earliest_locale": "Wednesday, Aug 24th, 2022", 
            "latest_locale": "Friday, Aug 26th, 2022", 
            "most_likely_locale": "Thursday, Aug 25th, 2022", 
            "cutoff": 1236, 
            "cutoff_locale": "21 hours" 
      } 
  }]
}
```

{% endtab %}
{% endtabs %}

### Errors and Empty Results

| HTTP status                            | Meaning                                                                                                                                                                                                      |
| -------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `400`                                  | Invalid request. Examples include a missing or invalid destination, both country and IP destinations, a postal code without a country, an invalid fallback country, or a fallback without an IP destination. |
| `404`                                  | IP lookup could not resolve a valid location and no fallback country was supplied.                                                                                                                           |
| `429`                                  | An IP request rate limit was exceeded. Follow the `Retry-After` header.                                                                                                                                      |
| `200` with an empty `prediction` array | A location was selected, but no delivery methods matched or the selected methods produced no predictions. Do not display a delivery date.                                                                    |

Validation and rate-limit errors use the v4 `errors` array. Errors from the prediction service retain their original HTTP status and JSON fields. These responses can use `requestId` instead of `request_id`. For example, an unresolved IP request can return HTTP `404` with:

```json
{
  "requestId": "failed-prediction",
  "success": false,
  "location": null,
  "error": "Could not resolve destination"
}
```

### Calculating Delivery Dates for Orders with Known Dispatch Date

For orders where you know the actual dispatch date, you can calculate accurate delivery dates based on when the order will ship. This is useful for scenarios where:

* An order's dispatch date is confirmed after placement
* You need to provide customers with updated delivery expectations based on actual shipment dates
* Customer service agents need to communicate accurate timelines for existing orders

**How It Works**

To calculate a delivery date for an already placed order when you know the dispatch date, use these two parameters together:

1. `now_override=<date>` - set this to the known dispatch date/time in ISO 8601 UTC format (for example: `2025-07-01T16:00:00.000Z`)
2. `dispatch_now=true` - this forces the API to skip warehouse cutoff calculations and calculate the delivery date as if the parcel ships at the exact time specified in `now_override`

{% hint style="warning" %}
The `now_override` timestamp must be in UTC (Zulu time), not local time. Always include the `Z` suffix or `.000Z` to indicate UTC.
{% endhint %}

{% hint style="info" %}
When using `dispatch_now=true` with a specific `now_override` value for already placed orders, the `cutoff` will be 0 as you're bypassing warehouse calculations and calculating delivery based on the known dispatch time.
{% endhint %}

### Testing Your Promise Configuration

To preview saved but unpublished changes to your Promise configuration in a staging environment:

1. Integrate the Promise API call to your staging environment.
2. Add the query parameter `&draft=true` to your Promise API call.

This will generate a promise date based on your unpublished Promise configuration, that can be used to review the effect of any configuration updates on the frontend of your staging environment.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.parcellab.com/docs/developers/promise/api.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
