Quotes API
REST endpoints for quotes in SKUFlow: 16 operations with parameters, request and response fields, permissions and curl examples.
Base URL: https://app.skuflow.ai/api. Every call needs Authorization: Bearer skf_… (Authentication); {organizationId} ($ORGANIZATION_ID in the examples) is your business's id.
| Operation | Endpoint | Risk |
|---|---|---|
| List quotes | GET /organizations/{organizationId}/quotes | read |
| Create a draft quote | POST /organizations/{organizationId}/quotes | write |
| Get a quote with options, lines and totals | GET /organizations/{organizationId}/quotes/{quoteId} | read |
| Update a quote | PATCH /organizations/{organizationId}/quotes/{quoteId} | write |
| Delete a quote | DELETE /organizations/{organizationId}/quotes/{quoteId} | sensitive |
| Update a quote's tax | POST /organizations/{organizationId}/quotes/{quoteId}/tax | write |
| Mark a quote as sent | POST /organizations/{organizationId}/quotes/{quoteId}/send | sensitive |
| Approve on the customer's behalf | POST /organizations/{organizationId}/quotes/{quoteId}/approve | sensitive |
| Archive a quote | POST /organizations/{organizationId}/quotes/{quoteId}/archive | write |
| Duplicate a quote as a new draft | POST /organizations/{organizationId}/quotes/{quoteId}/duplicate | write |
| Replace the customer link | POST /organizations/{organizationId}/quotes/{quoteId}/link | sensitive |
| Convert an approved quote to an invoice | POST /organizations/{organizationId}/quotes/{quoteId}/invoice | write |
| Price a product line before adding it to a quote | GET /organizations/{organizationId}/quotes/price-line | read |
| List a quote's proofs | GET /organizations/{organizationId}/quotes/{quoteId}/proofs | read |
| Send a new proof of a design | POST /organizations/{organizationId}/quotes/{quoteId}/proofs | sensitive |
| Reply on a proof | POST /organizations/{organizationId}/quotes/{quoteId}/proofs/{proofId}/comments | sensitive |
List quotes
GET /organizations/{organizationId}/quotes
Quotes (Q-n) newest first, filtered by text, status, customer or request; paged with a total. totalCents is the approved total, else the lowest option's total. Sent quotes past validUntil read as EXPIRED. Read-only.
| Permission | quotes.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | quotes_list (toolset sales, in the default set) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
query | query | string | No | Free-text search over the list's names, numbers and contact details. Up to 200 characters. |
status | query | enum | No | One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
customerId | query | string | No | |
requestId | query | string | No | |
businessUnitId | query | string | No | Only this business unit (GET /business-units), or "none" for records without one. Up to 100 characters. |
today | query | string | No | A calendar date in the business's own calendar, YYYY-MM-DD. |
limit | query | integer | No | Page size, 1–200. Default 50. |
offset | query | integer | No | Rows to skip; the answer's total counts every match. Default 0. |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
items | array of object | |
items[].id | string | Quote id. |
items[].organizationId | string | |
items[].identifier | string | Q-n, unique per organization. |
items[].customerId | string | |
items[].propertyId | string or null | |
items[].requestId | string or null | The request it was made from. |
items[].title | string | |
items[].message | string or null | Shown to the customer. |
items[].validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
items[].status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
items[].taxRate | number | Tax rate in percent. |
items[].taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
items[].taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
items[].taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
items[].depositPercent | number or null | Deposit asked, as a percent of the total. |
items[].depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
items[].internalNotes | string or null | |
items[].publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
items[].sentAt | string (date-time) or null | |
items[].approvedAt | string (date-time) or null | |
items[].approvedOptionId | string or null | |
items[].approvedLineIds | array of string | The optional lines the customer kept. |
items[].approvedTotalCents | integer or null | Approved total in cents, with tax. |
items[].approvedDepositCents | integer or null | Approved deposit in cents. |
items[].signatureName | string or null | |
items[].approvedByStaff | boolean | Staff recorded the approval for the customer. |
items[].changesRequestedAt | string (date-time) or null | |
items[].changesRequestedNote | string or null | |
items[].declinedAt | string (date-time) or null | |
items[].declineReason | string or null | |
items[].invoiceId | string or null | The invoice it was converted to. |
items[].convertedAt | string (date-time) or null | |
items[].soldByUserId | string or null | The team member who sold it. |
items[].financingDisabled | boolean | |
items[].businessUnitId | string or null | |
items[].customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
items[].createdAt | string (date-time) | |
items[].updatedAt | string (date-time) | |
items[].customer | object | |
items[].customer.id | string | |
items[].customer.name | string | |
items[].businessUnit | object or null | The business unit. |
items[].businessUnit.id | string | |
items[].businessUnit.name | string | |
items[].property | object or null | |
items[].property.id | string | Property id. |
items[].property.name | string or null | |
items[].property.address | string or null | |
items[].property.city | string or null | |
items[].optionCount | integer | |
items[].totalCents | integer | The approved total, else the lowest option's total (with tax), in integer cents. |
total | integer | How many match the filters, across all pages. |
Create a draft quote
POST /organizations/{organizationId}/quotes
Creates a DRAFT quote (Q-n) for a customer with options and lines. Tax is 0 for tax-exempt customers, else taxRate, else decided for the ship-to address propertyId (its own rate, else the business's tax rules, else the unit's or the business default; taxDetails says how). Apparel lines take the clothing rate. Without options, one empty option is made. Nothing is sent: POST /quotes/{quoteId}/send marks it sent and the customer opens /q/{token}.
| Permission | quotes.write (Owner, Admin, Staff) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | quotes_create (toolset sales, in the default set) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | |
customFields | object | No | Quote custom field values (GET /custom-fields?entity=QUOTE); those marked visibleToCustomer print on the quote. Required ones are checked when the quote is created here. |
propertyId | string or null | No | |
requestId | string or null | No | |
title | string or null | No | Up to 500 characters. |
message | string or null | No | |
validUntil | empty string or string or null | No | |
taxRate | number | No | Percent typed instead of the tax rules; omitted = decided for the ship-to address. -1000–1000. |
depositPercent | number or null | No | 0–100. |
depositCents | integer or null | No | 0–100000000. |
internalNotes | string or null | No | |
options | array of object | No | Up to 10 items. |
options[].name | string or null | No | Up to 200 characters. |
options[].description | string or null | No | Up to 5000 characters. |
options[].imageUrl | string or null | No | A picture of this option (e.g. a mockup), shown to the customer; else its first pricebook item's image. Up to 2000 characters. |
options[].highlights | array of string | No | Feature bullets compared side by side across options on the customer's page. Up to 12 items. |
options[].warranty | string or null | No | A guarantee or note shown with this option. Up to 500 characters. |
options[].recommended | boolean | No | Mark as the recommended option. |
options[].lines | array of object | Yes | Up to 200 items. |
options[].lines[].description | string | No | Required on a typed or pricebook line; written by the server for a product line. |
options[].lines[].quantity | number | No | -1000000–1000000. |
options[].lines[].unitPriceCents | integer | No | Money in integer cents; negative for a discount or credit line. -100000000–100000000. |
options[].lines[].optional | boolean | No | |
options[].lines[].defaultSelected | boolean | No | |
options[].lines[].pricebookItemId | string or null | No | The pricebook item the line was picked from (GET /pricebook/items): the server snapshots its cost; later pricebook edits never change this quote. |
options[].lines[].product | object or null | No | A product with sizes × colours and a design (or a large-format size): priced by the server from the catalog and the decoration matrix and written as one line per set of sizes priced alike plus one per one-time fee. Send one product per decorated line; leave out the lines it wrote (same groupKey) when sending the quote back. |
financingDisabled | boolean | No | Exposes to customers: true hides Affirm and Klarna ("or about $X/mo", pay the deposit over time) on this quote even when the business offers financing. |
businessUnitId | string or null | No | Business unit (GET /business-units): its branding shows on the quote. Omitted on create: the request's unit. Up to 100 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customerId":"customer_id"}'Response
201: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Get a quote with options, lines and totals
GET /organizations/{organizationId}/quotes/{quoteId}
One quote with its options, lines, totals, deposit, approval details and the customer link token (publicToken, for /q/{token}). Read-only.
| Permission | quotes.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | quotes_get (toolset sales, in the default set) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes | |
today | query | string | No | A calendar date in the business's own calendar, YYYY-MM-DD. |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) | |
customer | object | |
customer.id | string | |
customer.name | string | |
customer.email | string or null | |
customer.phone | string or null | |
customer.address | string or null | |
customer.city | string or null | |
customer.state | string or null | |
customer.zip | string or null | |
customer.taxExempt | boolean | |
property | object or null | |
property.id | string | Property id. |
property.name | string or null | |
property.address | string or null | |
property.city | string or null | |
property.state | string or null | |
property.zip | string or null | |
property.taxRate | number or null | |
request | object or null | |
request.id | string | |
request.identifier | string | REQ-n |
request.status | enum | NEW → QUOTED → CONVERTED (its quote was invoiced), or ARCHIVED. One of NEW, QUOTED, CONVERTED, ARCHIVED. |
invoice | object or null | |
invoice.id | string | |
invoice.identifier | string | INV-n |
invoice.status | enum | DRAFT (not issued), SENT (issued, money due), PAID, OVERDUE (past dueDate) or CANCELLED. One of DRAFT, SENT, PAID, OVERDUE, CANCELLED. |
invoice.totalCents | integer | |
options | array of object | |
options[].id | string | Quote option id (for optionId). |
options[].quoteId | string | |
options[].name | string | |
options[].description | string or null | |
options[].sortOrder | integer | |
options[].imageUrl | string or null | |
options[].highlights | array of string | |
options[].warranty | string or null | |
options[].recommended | boolean | |
options[].lines | array of object | |
options[].lines[].id | string | Quote line id (for selectedLineIds). |
options[].lines[].optionId | string | |
options[].lines[].description | string | |
options[].lines[].quantity | number | |
options[].lines[].unitPriceCents | integer | Unit price, in integer cents. |
options[].lines[].optional | boolean | The customer may leave it out. |
options[].lines[].defaultSelected | boolean | An optional line's default. |
options[].lines[].sortOrder | integer | |
options[].lines[].pricebookItemId | string or null | |
options[].lines[].costCents | integer or null | Our unit cost in cents (costing.read only). |
options[].lines[].kind | enum | STANDARD (typed or pricebook), PRODUCT (sizes priced alike of a product line), LARGE_FORMAT or DECORATION_FEE (a one-time fee of a decorated line). One of STANDARD, PRODUCT, LARGE_FORMAT, DECORATION_FEE. |
options[].lines[].groupKey | string or null | A decorated line's lines share it; send the line's product input once instead of them. |
options[].lines[].productId | string or null | |
options[].lines[].productVariantId | string or null | |
options[].lines[].designId | string or null | |
options[].lines[].pricing | any | The pricing snapshot: on the first line of a group, input (the product line to send back to keep or change it) and result (sizes, decoration per location, fees). |
options[].lines[].taxClass | enum | Which rate taxes the line: STANDARD, CLOTHING (apparel), SHIPPING or EXEMPT (set by the server). One of STANDARD, CLOTHING, SHIPPING, EXEMPT. |
options[].totals | object | The option's totals in cents with its default lines. |
options[].totals.lineTotals | array of integer | |
options[].totals.included | array of boolean | |
options[].totals.subtotalCents | integer | |
options[].totals.taxCents | integer | |
options[].totals.totalCents | integer | |
options[].totals.depositCents | integer | |
designs | any | The designs on the quote's lines with their current mockups (signed links); proofs: GET /quotes/{quoteId}/proofs. |
approvalSnapshot | any | What the customer approved (option, lines, totals), frozen at approval; null before. |
Update a quote
PATCH /organizations/{organizationId}/quotes/{quoteId}
Changes the fields sent, until the customer decides. options replaces every option and line (send them all). Moving an expired quote's date forward re-opens it.
| Permission | quotes.write (Owner, Admin, Staff) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | quotes_update (toolset sales, in the default set) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
customerId | string | No | |
customFields | object | No | Quote custom field values (GET /custom-fields?entity=QUOTE); those marked visibleToCustomer print on the quote. Required ones are checked when the quote is created here. |
propertyId | string or null | No | |
requestId | string or null | No | |
title | string or null | No | Up to 500 characters. |
message | string or null | No | |
validUntil | empty string or string or null | No | |
taxRate | number | No | Percent typed instead of the tax rules; omitted = decided for the ship-to address. -1000–1000. |
depositPercent | number or null | No | 0–100. |
depositCents | integer or null | No | 0–100000000. |
internalNotes | string or null | No | |
options | array of object | No | Up to 10 items. |
options[].name | string or null | No | Up to 200 characters. |
options[].description | string or null | No | Up to 5000 characters. |
options[].imageUrl | string or null | No | A picture of this option (e.g. a mockup), shown to the customer; else its first pricebook item's image. Up to 2000 characters. |
options[].highlights | array of string | No | Feature bullets compared side by side across options on the customer's page. Up to 12 items. |
options[].warranty | string or null | No | A guarantee or note shown with this option. Up to 500 characters. |
options[].recommended | boolean | No | Mark as the recommended option. |
options[].lines | array of object | Yes | Up to 200 items. |
options[].lines[].description | string | No | Required on a typed or pricebook line; written by the server for a product line. |
options[].lines[].quantity | number | No | -1000000–1000000. |
options[].lines[].unitPriceCents | integer | No | Money in integer cents; negative for a discount or credit line. -100000000–100000000. |
options[].lines[].optional | boolean | No | |
options[].lines[].defaultSelected | boolean | No | |
options[].lines[].pricebookItemId | string or null | No | The pricebook item the line was picked from (GET /pricebook/items): the server snapshots its cost; later pricebook edits never change this quote. |
options[].lines[].product | object or null | No | A product with sizes × colours and a design (or a large-format size): priced by the server from the catalog and the decoration matrix and written as one line per set of sizes priced alike plus one per one-time fee. Send one product per decorated line; leave out the lines it wrote (same groupKey) when sending the quote back. |
financingDisabled | boolean | No | Exposes to customers: true hides Affirm and Klarna ("or about $X/mo", pay the deposit over time) on this quote even when the business offers financing. |
businessUnitId | string or null | No | Business unit (GET /business-units): its branding shows on the quote. Omitted on create: the request's unit. Up to 100 characters. |
today | string | No | A calendar date in the business's own calendar, YYYY-MM-DD. |
Example
curl -X PATCH "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customerId":"customer_id","customFields":{},"propertyId":"property_id"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Delete a quote
DELETE /organizations/{organizationId}/quotes/{quoteId}
Destructive: deletes the quote with its options and lines; its customer link stops working. Deposits taken on it stay as payments, no longer linked to a quote. Prefer archiving (POST /quotes/{quoteId}/archive).
| Permission | quotes.delete (Owner, Admin) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | quotes_delete (toolset sales) |
| Approval | Over MCP, this tool always waits for your approval in SKUFlow. See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Example
curl -X DELETE "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
ok | true |
Update a quote's tax
POST /organizations/{organizationId}/quotes/{quoteId}/tax
Taxes a quote the customer has not decided on again: for its ship-to address under the business's current tax rules, or at taxRate when given. Changes its totals (the customer sees them on /q/{token} if it was sent); 409 once approved, declined or converted. Answers the quote with taxDetails.
| Permission | quotes.write (Owner, Admin, Staff) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | quotes_refreshTax (toolset sales) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
taxRate | number | No | Percent typed instead of the tax rules. 0–100. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/tax" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"taxRate":1}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) | |
customer | object | |
customer.id | string | |
customer.name | string | |
customer.email | string or null | |
customer.phone | string or null | |
customer.address | string or null | |
customer.city | string or null | |
customer.state | string or null | |
customer.zip | string or null | |
customer.taxExempt | boolean | |
property | object or null | |
property.id | string | Property id. |
property.name | string or null | |
property.address | string or null | |
property.city | string or null | |
property.state | string or null | |
property.zip | string or null | |
property.taxRate | number or null | |
request | object or null | |
request.id | string | |
request.identifier | string | REQ-n |
request.status | enum | NEW → QUOTED → CONVERTED (its quote was invoiced), or ARCHIVED. One of NEW, QUOTED, CONVERTED, ARCHIVED. |
invoice | object or null | |
invoice.id | string | |
invoice.identifier | string | INV-n |
invoice.status | enum | DRAFT (not issued), SENT (issued, money due), PAID, OVERDUE (past dueDate) or CANCELLED. One of DRAFT, SENT, PAID, OVERDUE, CANCELLED. |
invoice.totalCents | integer | |
options | array of object | |
options[].id | string | Quote option id (for optionId). |
options[].quoteId | string | |
options[].name | string | |
options[].description | string or null | |
options[].sortOrder | integer | |
options[].imageUrl | string or null | |
options[].highlights | array of string | |
options[].warranty | string or null | |
options[].recommended | boolean | |
options[].lines | array of object | |
options[].lines[].id | string | Quote line id (for selectedLineIds). |
options[].lines[].optionId | string | |
options[].lines[].description | string | |
options[].lines[].quantity | number | |
options[].lines[].unitPriceCents | integer | Unit price, in integer cents. |
options[].lines[].optional | boolean | The customer may leave it out. |
options[].lines[].defaultSelected | boolean | An optional line's default. |
options[].lines[].sortOrder | integer | |
options[].lines[].pricebookItemId | string or null | |
options[].lines[].costCents | integer or null | Our unit cost in cents (costing.read only). |
options[].lines[].kind | enum | STANDARD (typed or pricebook), PRODUCT (sizes priced alike of a product line), LARGE_FORMAT or DECORATION_FEE (a one-time fee of a decorated line). One of STANDARD, PRODUCT, LARGE_FORMAT, DECORATION_FEE. |
options[].lines[].groupKey | string or null | A decorated line's lines share it; send the line's product input once instead of them. |
options[].lines[].productId | string or null | |
options[].lines[].productVariantId | string or null | |
options[].lines[].designId | string or null | |
options[].lines[].pricing | any | The pricing snapshot: on the first line of a group, input (the product line to send back to keep or change it) and result (sizes, decoration per location, fees). |
options[].lines[].taxClass | enum | Which rate taxes the line: STANDARD, CLOTHING (apparel), SHIPPING or EXEMPT (set by the server). One of STANDARD, CLOTHING, SHIPPING, EXEMPT. |
options[].totals | object | The option's totals in cents with its default lines. |
options[].totals.lineTotals | array of integer | |
options[].totals.included | array of boolean | |
options[].totals.subtotalCents | integer | |
options[].totals.taxCents | integer | |
options[].totals.totalCents | integer | |
options[].totals.depositCents | integer | |
designs | any | The designs on the quote's lines with their current mockups (signed links); proofs: GET /quotes/{quoteId}/proofs. |
approvalSnapshot | any | What the customer approved (option, lines, totals), frozen at approval; null before. |
Mark a quote as sent
POST /organizations/{organizationId}/quotes/{quoteId}/send
Sends to the customer: marks the quote SENT (records sentAt), which opens its customer page /q/{token} for approval. Nothing is emailed; share the link from GET /quotes/{quoteId}.
| Permission | quotes.send (Owner, Admin, Staff) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | quotes_send (toolset sales, in the default set) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
today | string | No | A calendar date in the business's own calendar, YYYY-MM-DD. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/send" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"today":"2026-11-03"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Approve on the customer's behalf
POST /organizations/{organizationId}/quotes/{quoteId}/approve
Acts for the customer: records the customer's approval (e.g. given by phone) of one option; the quote becomes APPROVED and can be converted to an invoice and take deposits. selectedLineIds are the optional lines kept; omitted means their defaults. Stores the terms the customer was shown (terms, else the business's current quote terms) and, when they signed on the device, signatureDataUrl. Get option and line ids from GET /quotes/{quoteId}.
| Permission | quotes.approve (Owner, Admin, Staff) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | quotes_approve (toolset sales) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
optionId | string | No | |
selectedLineIds | array of string | No | Up to 200 items. |
signatureName | string or null | No | Up to 200 characters. |
terms | string or null | No | The terms shown to the customer (GET /signing-terms resolved.quoteTerms); omitted: the business's current ones. Up to 5000 characters. |
signatureDataUrl | string or null | No | The customer's signature drawn on the device: a data:image/png;base64 URL. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/approve" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"optionId":"option_id","selectedLineIds":["selectedLine_id"],"signatureName":"string"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Archive a quote
POST /organizations/{organizationId}/quotes/{quoteId}/archive
Moves the quote to ARCHIVED: out of the open lists, kept for the record. Its customer link stops accepting answers.
| Permission | quotes.write (Owner, Admin, Staff) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | quotes_archive (toolset sales) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/archive" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Duplicate a quote as a new draft
POST /organizations/{organizationId}/quotes/{quoteId}/duplicate
Copies the quote's options and lines into a new DRAFT quote (new Q-n, new link) for the same customer. Returns the new quote.
| Permission | quotes.write (Owner, Admin, Staff) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | quotes_duplicate (toolset sales) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/duplicate" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
201: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Replace the customer link
POST /organizations/{organizationId}/quotes/{quoteId}/link
REVOKES / EXPOSES: issues a new customer link token; the previous /q/{token} link stops working at once. Returns the quote.
| Permission | quotes.send (Owner, Admin, Staff) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | quotes_regenerateLink (toolset sales) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/link" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Quote id. |
organizationId | string | |
identifier | string | Q-n, unique per organization. |
customerId | string | |
propertyId | string or null | |
requestId | string or null | The request it was made from. |
title | string | |
message | string or null | Shown to the customer. |
validUntil | string or null | YYYY-MM-DD; a sent quote expires after it. |
status | enum | DRAFT → SENT (customer can answer at /q/{publicToken}) → APPROVED / CHANGES_REQUESTED / DECLINED; APPROVED → CONVERTED (invoice made). SENT past validUntil becomes EXPIRED. One of DRAFT, SENT, APPROVED, CHANGES_REQUESTED, DECLINED, CONVERTED, EXPIRED, ARCHIVED. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
depositPercent | number or null | Deposit asked, as a percent of the total. |
depositCents | integer or null | Deposit asked, as a fixed amount in cents. |
internalNotes | string or null | |
publicToken | string | The customer link token: the quote page is /q/{publicToken}. |
sentAt | string (date-time) or null | |
approvedAt | string (date-time) or null | |
approvedOptionId | string or null | |
approvedLineIds | array of string | The optional lines the customer kept. |
approvedTotalCents | integer or null | Approved total in cents, with tax. |
approvedDepositCents | integer or null | Approved deposit in cents. |
signatureName | string or null | |
approvedByStaff | boolean | Staff recorded the approval for the customer. |
changesRequestedAt | string (date-time) or null | |
changesRequestedNote | string or null | |
declinedAt | string (date-time) or null | |
declineReason | string or null | |
invoiceId | string or null | The invoice it was converted to. |
convertedAt | string (date-time) or null | |
soldByUserId | string or null | The team member who sold it. |
financingDisabled | boolean | |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=QUOTE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Convert an approved quote to an invoice
POST /organizations/{organizationId}/quotes/{quoteId}/invoice
Creates a DRAFT invoice with the approved lines, through the normal invoice rules; the quote becomes CONVERTED (and its request too); deposits paid on the quote move onto it and count as paid. Nothing is sent. Returns the invoice.
| Permission | invoices.write (Owner, Admin, Staff) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | quotes_convertToInvoice (toolset sales, in the default set) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/invoice" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
201: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | Invoice id. |
organizationId | string | |
identifier | string | INV-n, unique per organization. |
customerId | string | |
status | enum | DRAFT (not issued), SENT (issued, money due), PAID, OVERDUE (past dueDate) or CANCELLED. One of DRAFT, SENT, PAID, OVERDUE, CANCELLED. |
subtotalCents | integer | Lines total before tax, in integer cents. |
taxRate | number | Tax rate in percent. |
taxClothingRate | number or null | Percent on CLOTHING lines; null = taxRate (some states tax apparel less). |
taxShippingRate | number or null | Percent on SHIPPING lines; null = taxRate (0 where shipping is not taxed). |
taxDetails | any | How the rate was decided: source EXEMPT (tax-exempt customer), MANUAL (typed), ADDRESS (the address's own rate), RULES (the business's tax rules for the ship-to address; rules lists them), UNIT, DEFAULT or NONE. Null on older records. |
taxCents | integer | Tax, in integer cents. |
totalCents | integer | Total with tax, in integer cents. |
propertyId | string or null | The ship-to address (a property of the customer); its tax rules decide the rate. |
notes | string or null | |
dueDate | string or null | YYYY-MM-DD |
paidDate | string or null | YYYY-MM-DD |
amountPaidCents | integer | Paid so far, net of refunds, tips excluded, in integer cents. |
financingDisabled | boolean | |
importLocked | boolean | Imported paid history: read-only, its amounts never change. |
businessUnitId | string or null | |
customFields | any | Custom field values by key (definitions: GET /custom-fields?entity=INVOICE). |
createdAt | string (date-time) | |
updatedAt | string (date-time) | |
customer | object | |
customer.id | string | |
customer.name | string | |
businessUnit | object or null | The business unit. |
businessUnit.id | string | |
businessUnit.name | string | |
property | object or null | The ship-to address. |
property.id | string | Property id. |
property.name | string or null | |
property.address | string or null | |
property.city | string or null | |
property.county | string or null | |
property.state | string or null | |
property.zip | string or null | |
property.country | string or null | |
balanceDueCents | integer | Still due, in integer cents. |
partiallyPaid | boolean |
Price a product line before adding it to a quote
GET /organizations/{organizationId}/quotes/price-line
What a product line would cost (the quote builder's live price): the quote lines it becomes (sizes priced alike, fees), per-location decoration and the totals; ok: false with problems when the matrix can't price it as asked. breakQuantity reads the matrix at a larger quantity (the design's total on the option). Read-only: add it to a quote with options[].lines[].product.
| Permission | quotes.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | quotes_priceLine (toolset sales) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
product | query | object | Yes | A product line: the server prices blanks + decoration from the matrix and writes a line per set of sizes priced alike, then one line per one-time fee. |
breakQuantity | query | integer | No | 0–1000000. |
includeFees | query | boolean or enum | No |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/price-line?product=%5Bobject%20Object%5D" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
ok | boolean | False when the decoration matrix can't price it (see problems); lines is then empty. |
problems | array of string | Why it can't be priced as asked (e.g. more colours than the table prices). |
lines | any | The quote lines it becomes: description, quantity, unit price, kind (PRODUCT, LARGE_FORMAT, DECORATION_FEE) and (with costing.read) unit cost. |
result | any | The priced result: groups, placements, fees (or the large-format breakdown) and totals. |
List a quote's proofs
GET /organizations/{organizationId}/quotes/{quoteId}/proofs
Every proof version of the quote's designs (newest first per design) with mockups, status, comments and the customer's decision (name, time and, for staff, address and browser). Read-only.
| Permission | quotes.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | proofs_list (toolset sales) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/proofs" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
An array of objects:
| Field | Type | Description |
|---|---|---|
id | string | |
quoteId | string | |
designId | string or null | |
version | integer | |
status | enum | One of PENDING, APPROVED, CHANGES_REQUESTED, SUPERSEDED. |
designName | string | |
designRevision | integer | |
mockups | array of object | |
mockups[].view | enum | One of FRONT, BACK, SIDE, DETAIL, OTHER. |
mockups[].colorName | string or null | |
mockups[].widthPx | integer | |
mockups[].heightPx | integer | |
mockups[].url | string or null | The flattened PNG (signed, 1 hour). |
summary | any | Product, colours and placements (method, size, artwork) as proofed. |
note | string or null | |
decidedAt | string (date-time) or null | |
decidedByName | string or null | |
comments | array of object | |
comments[].id | string | |
comments[].author | enum | One of STAFF, CUSTOMER. |
comments[].authorName | string | |
comments[].body | string | |
comments[].requestsChanges | boolean | |
comments[].createdAt | string (date-time) | |
createdAt | string (date-time) |
Send a new proof of a design
POST /organizations/{organizationId}/quotes/{quoteId}/proofs
Exposes to the customer: a new proof version of a design on the quote (current mockups, rendered when stale), shown on the quote page at once; earlier open versions are superseded. Sending the quote does this for designs that need it.
| Permission | quotes.send (Owner, Admin, Staff) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | proofs_create (toolset sales) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
designId | string | Yes | |
note | string or null | No | Up to 2000 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/proofs" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"designId":"design_id"}'Response
201: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | |
version | integer | |
status | string |
Reply on a proof
POST /organizations/{organizationId}/quotes/{quoteId}/proofs/{proofId}/comments
Exposes to the customer: adds a comment from the team under the proof on the quote page. Returns the quote's proofs.
| Permission | quotes.send (Owner, Admin, Staff) |
| Risk | sensitive, OAuth scope skuflow.sensitive. Sensitive: moves money, deletes, sends or shows something to a customer, or grants or revokes access. |
| MCP tool | proofs_comment (toolset sales) |
| Approval | Over MCP, this tool asks for your OK first (in the AI app when it supports it, otherwise in SKUFlow). See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
quoteId | path | string | Yes | |
proofId | path | string | Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
body | string | Yes | Up to 5000 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/quotes/{quoteId}/proofs/{proofId}/comments" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"body":"string"}'Response
201: the answer's fields
An array of objects:
| Field | Type | Description |
|---|---|---|
id | string | |
quoteId | string | |
designId | string or null | |
version | integer | |
status | enum | One of PENDING, APPROVED, CHANGES_REQUESTED, SUPERSEDED. |
designName | string | |
designRevision | integer | |
mockups | array of object | |
mockups[].view | enum | One of FRONT, BACK, SIDE, DETAIL, OTHER. |
mockups[].colorName | string or null | |
mockups[].widthPx | integer | |
mockups[].heightPx | integer | |
mockups[].url | string or null | The flattened PNG (signed, 1 hour). |
summary | any | Product, colours and placements (method, size, artwork) as proofed. |
note | string or null | |
decidedAt | string (date-time) or null | |
decidedByName | string or null | |
comments | array of object | |
comments[].id | string | |
comments[].author | enum | One of STAFF, CUSTOMER. |
comments[].authorName | string | |
comments[].body | string | |
comments[].requestsChanges | boolean | |
comments[].createdAt | string (date-time) | |
createdAt | string (date-time) |