Home / Blog / Amazon Delivery Date API: the deliveryDate Field on Product Offers

Amazon Delivery Date API: the deliveryDate Field on Product Offers

How the SellerMagnet API's deliveryDate field works on /amazon-product-offers: one normalized YYYY-MM-DD date per offer (or N/A), how a range or a relative term like "tomorrow" gets resolved to that one date, why the address behind it depends on geo_location, and why two offers from the same seller with different delivery dates are not duplicates. A tested Python script that finds the fastest real offer.

October 31, 2026
5 min read
SellerMagnet Team
Share & Bookmark
Terminal running a Python script that finds the fastest real delivery date among Amazon offers

/amazon-product-offers returns deliveryDate on every offer (and on buyBox) as ONE normalized date, YYYY-MM-DD, or the string "N/A" when the page shows no delivery promise for that offer. It is never a range and never a day count: a page showing "Nov 2 - Nov 6" becomes 2026-11-02, and relative text like "tomorrow" is resolved against the current date before the response is built. The address behind that date is the marketplace's default postcode unless you pass geo_location, and two offers from the same seller with two different delivery dates are not duplicates of each other.

Key Takeaways

  • deliveryDate is always one value: YYYY-MM-DD or "N/A", never a range and never a number of days - do the day-count math yourself if you need it.
  • A date range or a relative term on the page ("tomorrow", a weekday) is resolved to a single date before the response is built; there is no separate "earliest/latest" pair.
  • "N/A" means the page showed no delivery promise for that offer, not that the lookup failed.
  • Without geo_location, dates reflect the marketplace's default postcode; a buyer in another region can see different dates.
  • The same seller can legitimately appear twice with two different deliveryDate values: the API's own duplicate check keys on (sellerId, deliveryDate, condition, fulfillmentType).

What does the deliveryDate field actually contain?

One string per offer: YYYY-MM-DD when the API could read and parse a delivery promise, "N/A" when it could not. There is no separate "earliest" and "latest" pair, no day-count field, and no time component - just the one resolved date. Build your own range or urgency label from that single value if your use case needs one.

deliveryDate at a glance.
ItemValue
FielddeliveryDate (per offer, in offers[] and buyBox)
Typestring: YYYY-MM-DD, or N/A
ShapeONE date, never a range, never a day count
Sourcethe page's delivery-promise text, normalized by the API
Default addressthe marketplace's default postcode, unless geo_location is passed
N/A meansthe page showed no delivery promise for that offer - not a lookup error

One offer's deliveryDate (illustrative data)

{
  "sellerId": "A2FASTSELLER",
  "condition": "New",
  "fulfillmentType": "FBA",
  "totalPrice": 29.99,
  "deliveryDate": "2026-11-02"
}

How does a date range or "tomorrow" turn into one date?

The API strips known non-date words (the shipping term, free-shipping phrasing, articles) from the raw promise text, then tries a set of regex date patterns (including a dedicated pattern for the Japanese 月/日 format), falls back to fuzzy date parsing, then to the first date of a hyphenated range, and finally to relative terms such as "today"/"tomorrow"/"day after tomorrow" mapped per marketplace language. Whichever path matches is adjusted to a future date and formatted YYYY-MM-DD. When none of those steps produce a date, the field stays "N/A".

Terminal-theme table of example delivery-promise text resolved to one deliveryDate value
Whatever the page shows, deliveryDate always resolves to one date or N/A.

Why do two offers from the same seller both show a deliveryDate?

Because a different delivery window is not an exact duplicate. The API already drops exact duplicate offer rows on (sellerId, deliveryDate, condition, fulfillmentType); a seller whose page shows two delivery windows for the same condition and fulfilment type differs on that last key field, so both rows survive. Code that assumes "one row per seller" and keeps only the first will silently drop a real, distinct offer - see the offers seller-count script for the full dedupe-vs-count distinction.

Does geo_location change the delivery date?

Yes. Without geo_location, the API reads the page with the marketplace's own default postcode, so deliveryDate reflects that location's shipping promise. Passing geo_location (a ZIP/postcode) asks for another delivery address on a best-effort basis: if every address change attempt is refused or lands elsewhere, the call still runs and returns a billed 200 from whatever location Amazon ended up using, with no field telling you which postcode was actually applied.

Terminal-theme sequence showing deliveryDate resolved against the default postcode or an optional geo_location
No geo_location: the marketplace's own default postcode decides the date shown.

How do I find the fastest real offer in Python?

The script below reads the offers of each ASIN, ignores "N/A" and non-New offers, and finds the New offer with the earliest real deliveryDate, then compares it with the featured offer's own date. It skips anything that is not a 10-character ASIN before paying, because the offers endpoint bills a malformed ASIN like any other request. It uses sellermagnet.py (ApiError, new_session) and retry.py (get_with_retry) from the Python quickstart.

delivery_date.py - the New offer with the earliest real delivery date, per ASIN

"""Amazon offer delivery dates: find the fastest real New offer per ASIN and flag what deliveryDate cannot tell you.

deliveryDate on /amazon-product-offers is ONE normalized date per offer (YYYY-MM-DD), or the string "N/A" when the
page shows no delivery promise for that offer - never a range and never a number of days. The API resolves
whatever text Amazon shows (a weekday, a date range, a relative term like "tomorrow") into that one date before
the page's postcode. Two offers from the SAME seller with two different deliveryDate values are NOT a duplicate:
the API's own exact-duplicate dedupe key is (sellerId, deliveryDate, condition, fulfillmentType), so a seller
quoting two delivery windows (perhaps two listed conditions or warehouses) survives as two rows.
Helpers: sellermagnet.py and retry.py from https://sellermagnet-api.com/blog/amazon-product-api-python
"""
import re
from datetime import date

import requests

from retry import get_with_retry
from sellermagnet import ApiError, new_session

MARKETPLACE = "ATVPDKIKX0DER"   # amazon.com
ASINS = ["B0CL61F39H", "B0NODATES1", "not-an-asin"]
MAX_FAILED = 3                  # 502/503 are billed on every attempt: stop after 3 calls that keep failing


def earliest_new(offers: list) -> dict | None:
    """The New offer with the earliest real deliveryDate, or None when no New offer has one."""
    dated = [o for o in offers if o.get("condition") == "New" and re.fullmatch(r"\d{4}-\d{2}-\d{2}",
                                                                              str(o.get("deliveryDate")))]
    return min(dated, key=lambda o: o["deliveryDate"]) if dated else None


def report(asin: str, data: dict) -> str:
    offers = data.get("offers") or []
    box = data.get("buyBox") or {}
    if not offers:
        return f"{asin}: no offers"
    fastest = earliest_new(offers)
    no_promise = sum(1 for o in offers if str(o.get("deliveryDate")) == "N/A")
    if not fastest:
        return f"{asin}: no New offer shows a delivery date ({no_promise} of {len(offers)} are N/A)"
    box_date = str(box.get("deliveryDate"))
    if re.fullmatch(r"\d{4}-\d{2}-\d{2}", box_date):
        gap = (date.fromisoformat(box_date) - date.fromisoformat(fastest["deliveryDate"])).days
        vs_box = "is the featured offer" if gap <= 0 else f"beats the featured offer by {gap} day(s)"
    else:
        vs_box = "featured offer has no delivery date to compare"
    return (f"{asin}: fastest {fastest['deliveryDate']} ({fastest.get('sellerId', '?')}), "
           f"{no_promise} of {len(offers)} offers N/A, {vs_box}")


def main():
    session = new_session()
    failed = 0
    for raw in ASINS:
        asin = raw.strip().upper()
        if not re.fullmatch(r"[A-Z0-9]{10}", asin):
            print(f"{raw}: skipped, not an ASIN (offers would bill it)")
            continue
        if failed >= MAX_FAILED:
            print(f"stopped after {MAX_FAILED} failed calls")
            break
        try:
            data = get_with_retry(session, "amazon-product-offers", asin=asin, marketplaceId=MARKETPLACE)
        except ApiError as err:
            if err.status in (401, 403):
                print(f"stopped: {err}")
                break
            label = "not found (billed 404)" if err.status == 404 else f"error {err}"
            print(f"{asin}: {label}")
            failed += err.status >= 500
            continue
        except (requests.ConnectionError, requests.Timeout) as err:
            print(f"{asin}: error {type(err).__name__}")
            failed += 1
            continue
        print(report(asin, data))


if __name__ == "__main__":
    main()

Output (illustrative data: five offers, one N/A, one Used ignored, a same-seller pair)

B0CL61F39H: fastest 2026-11-02 (A2FASTSELLER), 1 of 5 offers N/A, beats the featured offer by 3 day(s)
B0NODATES1: no New offer shows a delivery date (1 of 1 are N/A)
not-an-asin: skipped, not an ASIN (offers would bill it)
  • 1 of 5 offers N/A on B0CL61F39H: the script counts "N/A" offers without treating them as errors or as "no featured offer".
  • beats the featured offer by 3 day(s): a plain date.fromisoformat() subtraction between two YYYY-MM-DD strings - deliveryDate never needs its own range parser on the client side.
  • no New offer shows a delivery date: a real, reportable state for B0NODATES1, not a failed call; the script still prints a result instead of skipping the ASIN.
  • A Used offer in the fixture is excluded from "fastest New offer" by its condition field, not by its deliveryDate.

What does a delivery date check cost?

1 credit per /amazon-product-offers call, the same call that returns price, seller and fulfilment type; deliveryDate is not a separate billed field. A malformed ASIN is billed the same way, since the endpoint does not validate the ASIN format before fetching. For every other offer field, see the offer listing reference; for comparing the featured offer against Amazon's other named factors, see the Buy Box factor check.

Frequently Asked Questions

What format is the deliveryDate field in the Amazon API?

YYYY-MM-DD, a single normalized date, or the string N/A when the page shows no delivery promise for that offer. It is never a range or a day count.

Does deliveryDate account for my own location?

Only if you pass geo_location. Without it, dates reflect the marketplace's default postcode, which may differ from a specific buyer's address.

Why does the same seller appear twice with different deliveryDate values?

They are not duplicates. The API drops exact-duplicate rows on (sellerId, deliveryDate, condition, fulfillmentType), so two real delivery windows both survive.

What does deliveryDate N/A mean?

The page showed no delivery promise for that offer. It is a real listing state, not a lookup error, and does not need a retry.

Does checking deliveryDate cost extra credits?

No. It is part of the standard /amazon-product-offers response, 1 credit per ASIN, the same call used for price and seller fields.

Bottom line: read deliveryDate as one resolved date or N/A, remember it reflects the marketplace's default postcode unless you set geo_location, and never collapse two different delivery dates from the same seller as a duplicate. A free account includes 150 credits to try it, and the product offers endpoint page lists every other field in the response.

Ready to Extract Amazon Data at Scale?

Start building with SellerMagnet API today. Real-time product data, competitive pricing, and review analytics at your fingertips.

150 free API credits • No credit card required • Cancel anytime