Quotes

A quote is a short-lived, binding price — orders are always placed against one, so the amount is fixed before you commit.

A quote locks a binding price for one purchase. Orders are always placed against a quote — never against a product directly — so the amount your wallet is debited is fixed before you commit. Quoting requires the quotes.create scope.

Create a quote

POST /api/v1/quotes
{
  "productId": "0198d72d-99d6-75a6-9f12-971050ba7a5f",
  "variantId": "0198d72d-a15b-7cbf-ab69-b95410e98636",
  "value": null,
  "quantity": 1,
  "currency": "USD"
}
FieldRules
productIdRequired. A product from your catalog.
variantIdRequired iff the product has variants.
valueRequired iff the product is a value-range product; must land on the product's minimumValue/maximumValue/valueStep grid.
quantity1–20.
currencyMust equal the product's sell currency.

A valid request returns 200 OK:

{
  "id": "0198d72d-a6ce-77c6-9586-fc36708731d0",
  "productId": "0198d72d-99d6-75a6-9f12-971050ba7a5f",
  "variantId": "0198d72d-a15b-7cbf-ab69-b95410e98636",
  "quantity": 1,
  "total": 52.50,
  "currency": "USD",
  "expiresAtUtc": "2026-09-05T12:05:00Z"
}

There is no quote-retrieval endpoint — persist the id and total from this response if you need them later. (That is also why the response is 200 and not 201 with a Location: there is nothing to dereference.)

The rules that keep pricing honest

  • total is final. It is the exact amount order creation will reserve and, on fulfillment, debit from your wallet. No fees are added later.
  • Quotes expire. expiresAtUtc is typically a few minutes out. An order against an expired quote is rejected — quote at the moment of purchase, not at page-render time.
  • One quote, one order. Reusing a quote for a second order is rejected; idempotent retries of the same order are handled by the Idempotency-Key, not by re-quoting.
  • Quotes are workspace-bound. A quote created by one workspace's key can never be ordered by another.

Displaying prices without quoting

For catalog display, use the variant price fields from the catalog — they are your live sell prices. Reserve quoting for the checkout step. If you cache display prices, keep the cache short-lived: catalog prices move with the market, and the quote at checkout is the only price that binds.

Common rejections

StatuscodeWhy
400invalid_requestQuantity outside 1–20, missing/contradictory variantId/value, off-grid value, wrong currency.
404not_foundThe product is not in your catalog.
409(conflict code)The product or variant became unavailable between display and quote.

Handle quote rejection as a normal user-facing event ("this item just became unavailable") rather than an exceptional error — availability is re-verified at every step by design.


Did this page help you?