View Categories

Launching soon on the Shopify App StoreAbout Request a Quote, Hide PriceJoin the waitlist

REST API reference: Request a Quote

4 min read

The REST API v1 endpoints of SI Request a Quote, Hide Price: list, create, change, send, cancel, reopen and convert quotes, add notes and messages, and download the PDF. The key, limits, pagination and error format are the same as for all our apps: see the API overview. The same operations are in GraphQL: GraphQL API reference: Request a Quote.

Needs the SI Request a Quote, Hide Price app. It works on a store without Rentals & Bookings. Make the key on its API access page; a key made in any of our apps works too, because keys belong to the store. On a store without the app, every endpoint here answers 403 with the code rentals_rest_app_not_installed and data.app: "quotes".

If the store’s Quotes plan doesn’t include API access, these endpoints answer 403 plan_required. See Automation and integrations.

The examples use two shell variables, API="https://YOUR-API-ADDRESS/api/v1" and KEY="sirb_your_secret_key". GET needs a read key; everything else needs a key with Allow changes (write).

Quotes #

{ref} is the quote’s id, its number (Q-1042) or its public id. Statuses: new, in_review, draft, sent, changes_requested, accepted, ordered, expired, declined, rejected, cancelled. Money is in decimal strings. Line properties keep their keys exactly as you send them.

GET /api/v1/quotes #

Quotes, newest first. Paged. Parameters: status (comma-separated), search (a number, the customer’s name or email, a product title or SKU), source (storefront, cart, quick, admin, api, b2b_review, import), customer_id, updated_since (ISO 8601: only quotes changed since then).

curl -s "$API/quotes?status=sent,changes_requested&updated_since=2026-11-01T00:00:00Z" -H "Authorization: Bearer $KEY"
# 200, X-Total: 4
[{"id": 311, "number": "Q-1042", "public_id": "k3h9w2…", "status": "sent", "status_label": "Sent", "source": "storefront",
  "customer": {"id": 555001, "name": "Jordan Lee", "email": "[email protected]", "phone": null},
  "total": "1450.00", "currency": "USD", "owner_user_id": null, "expires_at": "2026-12-15T04:59:59+00:00", "viewed_at": null,
  "created_at": "2026-11-20T10:00:00+00:00", "updated_at": "2026-11-21T09:30:00+00:00",
  "order_id": null, "order_name": null, "draft_order_id": null, "tags": []}]

POST /api/v1/quotes #

Creates a quote. as: "draft" (the default): you prepare it and nothing is emailed until it is sent (send: true sends it at once). as: "request": as if the customer asked (status new; the request emails go out; the customer’s email is required).

Body fieldNotes
asdraft or request.
customer{id?, email, name?, phone?}; id is the Shopify customer.
lines[{variant_id?, product_id?, title, qty, list_price?, unit_price?, requested_price?, discount?: {type: "percent" or "fixed", value}, taxable?, requires_shipping?, properties?, note?}]. Leave out variant_id for a custom item (then unit_price is required).
send, customer_message, terms, expires_at, discount, shipping ({title, price}), tagsOptional. expires_at: Y-m-d (the end of that day, store time) or ISO 8601.
curl -s -X POST "$API/quotes" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{
  "as": "draft",
  "customer": {"email": "[email protected]", "name": "Jordan Lee"},
  "lines": [{"variant_id": 44001, "title": "Party tent 6×12 m", "qty": 1, "unit_price": "1350.00"}],
  "customer_message": "Here is the price for your December event.",
  "send": true
}'
# 201: the quote

A quote answers the summary above plus locale, market_country, shipping_address, reserve_inventory, company, invoice_url, the working, current, sent and request versions (each with its lines and totals), versions, events, notes, files and emails.

GET /api/v1/quotes/{ref} #

One quote.

PUT /api/v1/quotes/{ref} #

Changes the working version: lines (replaces every line), discount, shipping, tax_exempt, expires_at, customer_message, terms, customer, tags, shipping_address, payment_terms, reserve_inventory, company, currency, market_country. A sent version never changes: editing it starts the next version.

POST /api/v1/quotes/{ref}/{action} #

The actions, each answering the quote:

ActionBodyWhat it does
send–Sends the working version to the customer.
cancelreason?Withdraws a quote that isn’t accepted yet.
reopen–Reopens an expired, declined, rejected or cancelled quote.
convertmode: invoice (default) or orderMakes a Shopify draft order from the sent version: invoice gives the customer the payment link; order makes the order now, with payment pending. Answers {quote, draft_order: {id, invoice_url}, order}.
notesbodyAdds an internal note. Answers 201 with the note.
messagesbodySends the customer a message (emailed, and shown on their quote page). Answers 201 with the message.
curl -s -X POST "$API/quotes/Q-1042/convert" -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" -d '{"mode": "invoice"}'

GET /api/v1/quotes/{ref}/pdf #

A link to the quote’s PDF that works for 10 minutes: {url, version, expires_at}. version picks a version number; default the sent version.

Refusals: 400 invalid (data.field, data.errors), 409 invalid_status (the quote’s status doesn’t allow it, such as cancelling an accepted quote), 404 not_found, 403 plan_required, 502 shopify_error (Shopify refused the draft order).