Get Customer Quote
GET/api/public/quotes/:token
Returns what the customer link shows the buyer: the offer, who it is from and for, where it stands and the conversation.
This endpoint currently requires session authentication; Personal Access Token scope support is in progress.
Opening the link marks a sent quote as viewed by the customer. Pass preview=1 to read the quote without marking it viewed (for the seller's own preview).
No login. The 64-character quote token in the URL is the only credential — send no bearer token. The request must go to the seller's own workspace domain (e.g. https://acme.sku.io): the workspace is identified from the request's domain, and any other domain answers 404. Returns 503 while the workspace is briefly under maintenance.
Every refusal is JSON {message, reason}: message is written for the buyer and reason is a stable code — not_found (404: unknown token, a quote that was never sent, or a quote answered on a sales channel), being_updated (422: the seller is revising the quote; also carries quote_number and seller_name), expired, already_answered, closed, invalid_selection (all 422).
Limited to 60 requests per minute per IP address.
Response fields
status—sent,viewed,accepted,declined,expiredorordered. A quote past its valid-until date readsexpiredeven before the hourly expiry run reaches it.valid_until(date),days_until_expiry(whole days left; null once the quote is answered or has no date).seller—nameandlogo_urlof the store the quote is from (an uploaded logo is returned inline as adata:URI; null when none or too large).customer—name,company.- Money:
subtotal,line_discount_total,order_discount_total,discount_total,tax_total,total,deposit_type(none,percent,fixed),deposit_value,deposit_amount. lines[]—id(used inselected_line_idswhen accepting),sku,description,quantity,unit_price,discount_type,discount_value,line_type(standard= always included,optional= the buyer may add it,single_select= choose exactly one perselect_group),select_group,is_selected,subtotal,line_total(after the line discount).acceptance—signer_nameandaccepted_atof the latest signature, or null.declined_reason— only whenstatusisdeclined.comments[]— the conversation:id,author_type(customerorseller),author_name,body,created_at.actions—can_accept,can_decline(true while the quote awaits an answer),can_comment(false once the quote is declined or ordered).
Cost, margin, warehouses, internal notes and the sales rep are never returned.
Authentication: none (quote token in the URL).
Procurement details — shipping_terms (Incoterm and named place, or null), tax_exemption ({summary, is_expired} when the buyer's account is tax exempt, else null), documents (files the seller shared with the buyer: {id, name, size, mime}; download each with Download Customer Quote Document) and per-line lead_time_days (calendar days from order, or null).
Request
Responses
- 200
- 401
- 403
- 404
- 422
- 429
OK
Response Headers
Unauthenticated — the bearer token is missing, revoked, expired, or malformed. Never retry automatically; fix the credential. See the Errors guide.
Forbidden — the token lacks a required scope, the endpoint is not available to API tokens, or the user behind the token lacks the permission. A human must adjust the token scopes or user permissions; do not retry.
Not Found
Response Headers
Unprocessable Entity
Response Headers
Rate limited — platform limit is 1,000 requests/min; individual tokens may carry lower limits. Honor the Retry-After header before retrying. See the Rate Limits guide.