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 field | Notes |
|---|---|
as | draft 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}), tags | Optional. 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:
| Action | Body | What it does |
|---|---|---|
send | – | Sends the working version to the customer. |
cancel | reason? | Withdraws a quote that isn’t accepted yet. |
reopen | – | Reopens an expired, declined, rejected or cancelled quote. |
convert | mode: invoice (default) or order | Makes 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}. |
notes | body | Adds an internal note. Answers 201 with the note. |
messages | body | Sends 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).
