Zum Inhalt springen

The quote object

Read time: 10 minutes. Who it's for: Developers mapping QuotWay quotes into another system.

GET /v1/quotes, GET /v1/quotes/{id}, POST /v1/quotes and POST /v1/quotes/{id}/send-proposal all return quotes in this shape. It's the merchant's view of the quote: it includes lines the buyer can't see (flagged as such) and never includes internal notes.

Conventions

  • Keys are snake_case; enum values are lowercase (proposal_sent, b2b).
  • Money is a decimal string with exactly two places ("1250.00"), always next to an ISO 4217 currency code. Parse it with a decimal type, not a float.
  • Timestamps are ISO-8601 in UTC ("2026-09-29T14:12:00.000Z").
  • Shopify references are Shopify GIDs (gid://shopify/Customer/7012345678).
  • New fields may be added to this object at any time; your code should ignore fields it doesn't know. See Versioning.

Example

A wholesale quote where the buyer accepted one line, declined one and left one open:

{
  "object": "quote",
  "id": "clz8k2x9f0001qw7h3m4n5p6r",
  "number": "QW-1042",
  "status": "partially_accepted",
  "mode": "wholesale",
  "source": "product_page",
  "currency": "USD",
  "version_number": 2,
  "negotiation_round": 1,
  "po_number": "PO-88213",
  "requested_delivery_date": "2026-11-01T00:00:00.000Z",
  "expires_at": "2026-10-14T00:00:00.000Z",
  "created_at": "2026-09-22T09:31:05.412Z",
  "updated_at": "2026-09-29T14:12:00.000Z",
  "first_accepted_at": "2026-09-29T14:12:00.000Z",
  "fully_converted_at": null,
  "invoice_sent_at": null,
  "totals": {
    "currency": "USD",
    "subtotal": "2300.00",
    "discount_total": "115.00",
    "shipping_total": "40.00",
    "tax_estimate": "0.00",
    "total": "2225.00",
    "accepted_total": "1187.50",
    "still_open_total": "450.00",
    "headline": "1187.50",
    "headline_mode": "open",
    "base_currency": {
      "currency": "USD",
      "total": null,
      "accepted_total": null,
      "exchange_rate": null
    }
  },
  "lines": [
    {
      "id": "clz8m0v1a0010qw7hk2l3m4n5",
      "quote_line_item_id": "clz8k2xa00002qw7h9a8b7c6d",
      "position": 0,
      "product_id": "gid://shopify/Product/8123456789",
      "variant_id": "gid://shopify/ProductVariant/4455667788",
      "sku": "NW-CUP-12OZ",
      "title": "Compostable cup, 12 oz",
      "variant_title": "Case of 50",
      "quantity": 100,
      "catalog_price": "14.00",
      "requested_price": "11.50",
      "unit_price": "12.50",
      "line_total": "1250.00",
      "is_custom": false,
      "requires_shipping": true,
      "taxable": true,
      "buyer_visibility": "show",
      "kit": null,
      "decision": "accept",
      "accepted": true,
      "still_open": false
    },
    {
      "id": "clz8m0v1a0011qw7hp6q7r8s9",
      "quote_line_item_id": "clz8k2xa00003qw7hd5e4f3g2",
      "position": 1,
      "product_id": "gid://shopify/Product/8123456790",
      "variant_id": "gid://shopify/ProductVariant/4455667790",
      "sku": "NW-LID-12OZ",
      "title": "Lid, 12 oz",
      "variant_title": null,
      "quantity": 20,
      "catalog_price": "32.00",
      "requested_price": null,
      "unit_price": "30.00",
      "line_total": "600.00",
      "is_custom": false,
      "requires_shipping": true,
      "taxable": true,
      "buyer_visibility": "show",
      "kit": null,
      "decision": "reject",
      "accepted": false,
      "still_open": false
    },
    {
      "id": "clz8m0v1a0012qw7ht1u2v3w4",
      "quote_line_item_id": "clz8k2xa00004qw7hh1i2j3k4",
      "position": 2,
      "product_id": null,
      "variant_id": null,
      "sku": null,
      "title": "Custom logo print setup",
      "variant_title": null,
      "quantity": 10,
      "catalog_price": null,
      "requested_price": null,
      "unit_price": "45.00",
      "line_total": "450.00",
      "is_custom": true,
      "requires_shipping": false,
      "taxable": true,
      "buyer_visibility": "show",
      "kit": null,
      "decision": "defer",
      "accepted": false,
      "still_open": true
    }
  ],
  "proposal": {
    "version_number": 2,
    "sent_by": "merchant",
    "created_at": "2026-09-24T16:02:44.108Z",
    "shipping_status": "final",
    "shipping_label": "UPS Ground",
    "payment_terms": "Net 30",
    "deposit_percentage": null,
    "expires_at": "2026-10-14T00:00:00.000Z"
  },
  "approval": { "active": false, "pending_domain": null },
  "shopify": {
    "customer_id": "gid://shopify/Customer/7012345678",
    "company_id": null,
    "company_location_id": null,
    "company_contact_id": null,
    "draft_order_ids": [],
    "order_ids": []
  },
  "assigned_staff": { "id": "clx3q9r8s0000ab12cd34ef56", "email": "sam@northwind-supply.com" },
  "kit_conversion_mode": "collapse",
  "based_on_quote_id": null,
  "links": {
    "admin_url": "https://admin.shopify.com/store/northwind-supply/apps/<app-client-id>/app/quotes/clz8k2x9f0001qw7h3m4n5p6r"
  }
}

With the read_customer_data scope, the quote also carries a customer object and each line a buyer_note - see Buyer personal data.

Top-level fields

Field Type Description
object "quote" Always quote.
id string The quote's id. Use it in API paths.
number string The human reference buyers and staff see, e.g. QW-1042 (the prefix is the store's setting). Not usable in API paths.
status string Where the quote is in its life cycle - see Status.
mode string wholesale (a standard quote) or b2b (a company-aware quote tied to a Shopify B2B company location).
source string Where the request came from: product_page, cart, buyer_portal, admin (created by staff), guest, customer_account (buyer quick order in the Shopify customer account) or api.
currency string ISO currency of the quote's money.
version_number integer The current proposal version (0 before any proposal exists).
negotiation_round integer How many negotiation rounds the quote has been through.
po_number string | null The buyer's purchase-order number.
requested_delivery_date timestamp | null The delivery date the buyer asked for.
expires_at timestamp | null When the current offer expires.
created_at / updated_at timestamp Created / last changed. updated_at is the field to sync on.
first_accepted_at timestamp | null When the buyer first accepted any part of the quote.
fully_converted_at timestamp | null When every accepted line had become a Shopify draft order.
invoice_sent_at timestamp | null When the draft-order invoice was sent.
totals object See Totals.
lines array See Lines.
proposal object | null The current proposal version; null before the first proposal. See Proposal.
approval object active - an approval chain is in progress; pending_domain - merchant (your team's approval) or buyer (the buyer's internal approval), or null.
shopify object Shopify ids: customer_id, company_id, company_location_id, company_contact_id (each may be null), plus draft_order_ids and order_ids (arrays of GIDs). These are identifiers, not personal data.
assigned_staff object | null The staff member the quote is assigned to (id, email).
kit_conversion_mode string How kits become draft-order lines: collapse (one line at the kit price) or expand (the components).
based_on_quote_id string | null Set when staff created the quote with Duplicate quote; the id of the original. (A buyer's reorder is a fresh request and doesn't set it.)
links.admin_url string Opens the quote in the QuotWay admin inside Shopify. Staff need to be logged in to Shopify.
customer object Only with read_customer_data. See Buyer personal data.

Status

status is one of:

Value Meaning
submitted A new request, not yet opened. Quotes created with POST /v1/quotes start here.
in_review Your team has opened the quote and is working on it.
awaiting_info Waiting for information from the buyer.
awaiting_merchant_approval A proposal is waiting for your team's internal approval before it goes out.
proposal_sent A proposal is with the buyer.
awaiting_buyer_approval The buyer's own internal approval chain is reviewing the proposal.
countered The buyer made a counter-offer.
partially_accepted The buyer accepted some lines.
fully_accepted The buyer accepted the whole proposal.
partially_converted Some accepted lines have become a Shopify draft order.
fully_converted Every accepted line has become a Shopify draft order.
invoice_sent The draft-order invoice has been sent to the buyer.
order_completed The buyer paid and the order was placed.
order_cancelled The resulting order was cancelled.
order_refunded The resulting order was refunded.
declined The quote was declined.
expired The offer passed its expiry date.
closed The quote was closed.

New statuses may be added in future; treat an unknown value as "in progress" rather than failing.

Totals

totals answers two different questions - what was offered and what was agreed - and gives you one field, headline, that is always the right figure to act on.

Field Description
currency ISO currency of every amount in totals (except base_currency).
subtotal Sum of the current proposal's lines, before discount.
discount_total The quote-level discount.
shipping_total Shipping on the proposal.
tax_estimate Estimated tax. Shopify computes the final tax on the draft order.
total What was offered on the current version: subtotal − discount + shipping + tax estimate. Never rewritten by acceptance.
accepted_total What the buyer committed to on a mixed acceptance - the accepted lines, net of their share of the quote discount, excluding shipping and tax. null when nothing has been accepted, and also null on a full acceptance (use total).
still_open_total The value of the lines the buyer left undecided (the sum of their line totals, before any discount share). null unless some lines are still open.
headline The figure to act on. See headline_mode. Always present.
headline_mode Why headline is what it is - see below.
base_currency The store's base currency view: currency, total, accepted_total and the exchange_rate captured when the quote was requested. The amounts are null when no exchange-rate snapshot was captured - fall back to totals.total when the quote's currency equals the base currency.

headline_mode

Value Situation headline equals
none Nothing accepted yet. total
full Accepted in full. total
decided Every line was either accepted or declined - nothing is pending. accepted_total
open Some lines accepted, some still undecided. accepted_total (what's agreed so far); still_open_total is what's still in play

If you only store one number, store headline. Reconstructing it yourself from total and the lines is how quote values end up wrong in a CRM: on a partial acceptance total still shows the whole original offer.

Lines

Before the first proposal, lines are the buyer's requested lines. Once a proposal exists, they are the current proposal version's lines, and quote_line_item_id links each one back to the request line it came from.

Field Description
id The line's id (a proposal-version line once a proposal exists).
quote_line_item_id The request line this proposal line came from; null before a proposal.
position Sort order, starting at 0.
product_id / variant_id Shopify GIDs; null for custom lines.
sku, title, variant_title As captured from Shopify. A kit's parent line shows the kit's name.
quantity Integer.
catalog_price The Shopify price when the line was captured.
requested_price The unit price the buyer asked for, if any.
unit_price The price you offered; null until priced.
line_total unit_price × quantity; null until priced.
is_custom true for a custom line (not a Shopify product).
requires_shipping, taxable How the line converts to the draft order.
buyer_visibility What the buyer sees: show, price_hidden (shown as "Included", no price) or hidden (not shown to the buyer at all).
kit For kit lines: key (groups a kit's lines), role (parent or component) and title. null otherwise.
decision The buyer's per-line decision on a mixed acceptance: accept, reject (declined) or defer (decide later). null when there's nothing to mark - not yet accepted, or accepted in full.
accepted true when the line is part of an accepted set.
still_open true when the line is undecided and still negotiable.
buyer_note The buyer's note on this line. Only with read_customer_data.

still_open is not !accepted

A declined line is neither accepted nor still open. Use the pair like this:

accepted still_open The line is…
false true not yet decided - before acceptance, or deferred by the buyer
true false accepted
false false declined

Kits

A kit is sold as one line at one price. Its parent line carries the price; its component lines are 0.00 and exist so stock and fulfilment see what's in the box. All of a kit's lines share the same kit.key. To total a quote yourself, sum parents and ordinary lines - the components add nothing. Component lines are often buyer_visibility: "hidden"; they're included here because this is the merchant's view.

Proposal

proposal describes the current version, or is null before the first one.

Field Description
version_number The version this describes.
sent_by Who created it: merchant, buyer (a counter-offer) or system (automation).
created_at When the version was created.
shipping_status pending (shipping still to be confirmed) or final.
shipping_label The shipping method label, if set.
payment_terms Payment-terms name, e.g. Net 30, if set.
deposit_percentage The deposit asked for, e.g. "50.00", or null.
expires_at When this version's offer expires.

Buyer personal data

With the read_customer_data scope, quotes include:

"customer": {
  "email": "buyer@example.com",
  "name": "Dana Ortiz",
  "phone": "+1 303 555 0142",
  "company_name": "Acme Restaurant Group",
  "shipping_address": {
    "firstName": "Dana",
    "lastName": "Ortiz",
    "name": null,
    "company": "Acme Restaurant Group",
    "address1": "1200 Larimer St",
    "address2": null,
    "city": "Denver",
    "province": null,
    "provinceCode": "CO",
    "countryCode": "US",
    "zip": "80204",
    "phone": null
  },
  "billing_address": null,
  "custom_fields": { "industry": "Hospitality", "weekly_volume": "500+" },
  "notes": "Delivery to our Denver kitchen, please."
}
  • shipping_address / billing_address are the stored address objects - note their keys are camelCase (address1, provinceCode, countryCode), unlike the rest of the API - or null.
  • custom_fields holds the answers to the store's custom quote-form fields, keyed by field key.
  • notes is the buyer's note on the request.

Without the scope, customer and every buyer_note are absent (not null). Nothing else changes, so the same code can handle both.

Internal notes your team writes are never returned by the API.

Brauchen Sie noch Hilfe? Das Team hilft gern weiter.

Wir möchten Analyse-Cookies setzen, um zu verstehen, wie die Website genutzt wird. Sie sind nicht erforderlich – eine Ablehnung ändert nichts an der Funktion der Website, und Sie können Ihre Entscheidung jederzeit ändern auf unserer Datenschutzseite.