# Showing options at checkout

> When to quote, how to label on-demand and window options for shoppers, and what to keep for the order.

Source: https://docs.delivr.no/guides/checkout-options/

A quote lists what Delivr can offer for one address. This page is about turning it into choices a shopper understands.

## When to call

| Moment in the checkout                       | Call                                                                                                      |
| -------------------------------------------- | --------------------------------------------------------------------------------------------------------- |
| Cart or product page, postal code only       | [`GET /availability`](/api/operations/getavailability/), cached for 60 seconds per store and postal code. |
| The shopper has entered the full address     | [`POST /quotes`](/api/operations/createquote/), once.                                                     |
| The address, the parcels or the store change | `POST /quotes` again.                                                                                     |
| The shopper pays                             | [`POST /orders`](/api/operations/createorder/) with the `quoteId` and the chosen option's `key`.          |

Quote when the address is complete, not on every keystroke. Quotes are made from your server; your storefront gets the options from your backend, never the API key.

## What to show

Keep the options in the order Delivr gives them: `on_demand` first when there is capacity, then windows in time order.

- **On demand.** Show the `eta` band as the arrival time, such as "Today 14:25–14:55". Do not show `supply`: it is a hint for sellers in [assisted checkout](/guides/assisted-checkout/), not a promise to shoppers.
- **Windows.** Show `window` as "Today 17:00–19:00" or "Thursday 5 November 17:00–19:00", grouped by day if there are many. A window can be booked and cancelled free until its `cutoffAt`.
- **Times.** Answers are in UTC. Show them in the quote's `timeZone`, never the server's or the browser's.
- **Price.** `price` is what Delivr bills you. What the shopper pays is yours to set: the same, a flat fee, or free over a basket size.
- **Nothing to offer.** When `options` is empty or the quote answers `422 no_delivery_options`, hide Delivr for this address. `422 invalid_address` means the address is not found: ask the shopper to check it.

```js
// Labels such as "Today 14:25–14:55" in the market's time zone.
export function optionLabel(option, timeZone, now = new Date()) {
  const time = new Intl.DateTimeFormat("en-GB", { timeZone, hour: "2-digit", minute: "2-digit" });
  const date = new Intl.DateTimeFormat("en-CA", { timeZone, year: "numeric", month: "2-digit", day: "2-digit" });
  const start = new Date(option.type === "on_demand" ? option.eta.from : option.window.start);
  const end = new Date(option.type === "on_demand" ? option.eta.to : option.window.end);
  const days = (Date.parse(date.format(start)) - Date.parse(date.format(now))) / 86_400_000;
  const day =
    days === 0
      ? "Today"
      : days === 1
        ? "Tomorrow"
        : new Intl.DateTimeFormat("en-GB", { timeZone, weekday: "long", day: "numeric", month: "long" }).format(start);
  return `${day} ${time.format(start)}–${time.format(end)}`;
}

const nok = new Intl.NumberFormat("nb-NO", { style: "currency", currency: "NOK" });
nok.format(option.price.amountMinor / 100); // "149,00 kr"
```

For the [quickstart's quote](/quickstart/#quote-a-delivery), this gives "Today 14:25–14:55" for `on_demand` and "Today 17:00–19:00" for the window.

## What to keep for the order

Save the `quoteId` and the chosen option's `key` with the cart. You do not need the quote to still be valid when the shopper pays:

- A quote is offered for 5 minutes (`expiresAt`), plus a grace when you place. Later than that, Delivr quotes again and books the same `key` at **no more than the price you showed**.
- If it would cost more now, you get `409 price_changed` with the new price. Show it, or quote again.
- If the option is gone, you get `409 option_unavailable` (or `409 window_full`) with `details.alternatives`. Offer one of them, by its `key`.

See [Placing on an older quote](/guides/quotes-and-orders/#placing-on-an-older-quote).

## After the order

- Show the placement answer's `eta` (on demand) as the promised arrival. It is only in that answer, so store it.
- Put `trackingUrl` in your order confirmation and emails. The recipient also gets it by SMS from Delivr.
- Ask for `delivery.dropoff` details at checkout (door code, floor, entrance, leave at the door) if your shoppers live in flats. They reach the driver only.