Workflows API
REST endpoints for workflows in SKUFlow: 4 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 |
|---|---|---|
| Draft a quote from a description of the work | POST /organizations/{organizationId}/workflows/quote-from-description | write |
| Invoice an approved quote and send it to the customer | POST /organizations/{organizationId}/workflows/invoice-quote-and-send | sensitive |
| Everything about a customer (360 and open items) | GET /organizations/{organizationId}/workflows/customer-overview | read |
| Create a draft store for a customer | POST /organizations/{organizationId}/workflows/store-for-customer | write |
Draft a quote from a description of the work
POST /organizations/{organizationId}/workflows/quote-from-description
Turns a description of the work ("150 navy tees, 2-colour front print, 1-colour back") into a DRAFT quote (Q-n) for a customer: lines you give are used as they are (a line may be a product line); without them, each phrase of the description (split on commas, 'and', new lines) is matched first to the product catalog (GET /products search: garments, promo items, large format with a size like 72x36) and the decoration phrases after it ("2-colour front print", "embroidered left chest", "DTF back") become a design (POST /designs: method from the decoration matrix, the product's area, ink colours or stitches) priced from the matrix; anything else is matched to the pricebook. What was assumed (sizes, colour, stitch count) is listed in assumptions — set the size breakdown before sending. Phrases with no match are listed in unmatched. Nothing is sent: review it, then quotes.send. Returns the quote, the lines, the designs made, the assumptions, the unmatched phrases and the quote's url.
| 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 | quote_from_description (toolset sales, in the default set) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | The customer (GET /customers). |
propertyId | string | No | |
requestId | string | No | The request this answers. |
description | string | Yes | The work, in plain words. Up to 5000 characters. |
title | string | No | Default: the description's first phrase. Up to 200 characters. |
lines | array of object | No | Up to 100 items. |
lines[].product | object | No | A product line (sizes × colours and a design, or a large-format size), priced by the server; the other fields are ignored. |
lines[].product.productId | string | Yes | The product (GET /products). |
lines[].product.designId | string or null | No | Its design (GET /designs?productId=): placements and methods priced. |
lines[].product.sizes | array of object | No | Garments and promo goods: the quantity per variant (the size × colour grid). Up to 300 items. |
lines[].product.largeFormat | object or null | No | |
lines[].product.waivedFees | array of string | No | One-time fees to leave off, by key ("left-chest:digitizing"). Up to 50 items. |
lines[].product.label | string or null | No | Text before the sizes; default: the product's name. Up to 200 characters. |
lines[].pricebookItemId | string | No | A pricebook item (GET /pricebook/items). |
lines[].description | string | No | The line's text (required without an item). Up to 1000 characters. |
lines[].quantity | number | No | 0.01–100000. Default 1. |
lines[].unitPriceCents | integer | No | Overrides the item's price; required without an item. |
validUntil | 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/workflows/quote-from-description" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customerId":"customer_id","description":"string"}'Response
201: the answer's fields
| Field | Type | Description |
|---|---|---|
quote | object | The DRAFT quote (Q-n), as POST /quotes returns it. |
quote.id | string | |
lines | array of object | |
lines[].description | string | |
lines[].quantity | number | |
lines[].unitPriceCents | integer | |
lines[].pricebookItemId | string or null | |
lines[].productId | string or null | |
lines[].designId | string or null | |
lines[].matchedFrom | string or null | The phrase it was matched from. |
designs | array of object | Designs made for decorated products (add artwork to them: PATCH /designs/{designId}). |
designs[].id | string | |
designs[].name | string | |
assumptions | array of string | What the workflow assumed (sizes, colour, stitches): confirm or fix before sending. |
unmatched | array of string | Phrases with no product or pricebook match: add them or ask. |
url | string | The SKUFlow screen for the result (open it in the web app to see or change it). |
Invoice an approved quote and send it to the customer
POST /organizations/{organizationId}/workflows/invoice-quote-and-send
Customer-facing: invoices an approved quote and sends the invoice in one step: reuses the invoice the quote was already converted to, or converts it (quotes.convertToInvoice: the approved lines, deposits applied), then sends it by email (default) or text with the business's invoice message (messages.previewSend → messages.send), which issues it (SENT) and gives the customer the pay link. Consent applies (no text without OK-to-text). If sending is impossible (no address, consent) the invoice is still made and the answer says why. Returns the invoice, the message and the invoice's url.
| Permission | invoices.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 | invoice_quote_and_send (toolset invoices, 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. |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
quoteId | string | Yes | The APPROVED quote to bill (GET /quotes). |
channel | enum | No | One of EMAIL, SMS. Default EMAIL. |
message | string | No | Replaces the message body (default: the business's invoice template). Up to 5000 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/workflows/invoice-quote-and-send" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"quoteId":"quote_id"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
invoice | object | The invoice (INV-n). |
invoice.id | string | |
invoiceCreated | boolean | |
sent | boolean | |
message | object or null | The message as sent (status, channel, recipient). |
notSentReason | string or null | |
url | string | The SKUFlow screen for the result (open it in the web app to see or change it). |
Everything about a customer (360 and open items)
GET /organizations/{organizationId}/workflows/customer-overview
One customer at a glance: the record, the Customer 360 summary (lifetime value, health, behaviours, predictions), and their open items: open quotes, unpaid invoices with the balance and new requests. Give customerId, or query (name, email or phone) when it matches one customer. Parts your role cannot see are left out and named in hidden. Read-only.
| Permission | customers.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | customer_overview (toolset customers, in the default set) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
customerId | query | string | No | |
query | query | string | No | Name, email or phone. Up to 200 characters. |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/workflows/customer-overview" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
customer | object | |
customer.id | string | |
insight | object or null | Customer 360 (GET /customers/{customerId}/insights). |
openQuotes | array of object | |
unpaidInvoices | array of object | |
balanceDueCents | integer | Sum of the unpaid invoices' balances, in cents. |
openRequests | array of object | |
hidden | array of string | Sections left out because the role cannot read them. |
url | string | The SKUFlow screen for the result (open it in the web app to see or change it). |
Create a draft store for a customer
POST /organizations/{organizationId}/workflows/store-for-customer
A company (or team, fundraiser) store for one customer in one call: drafts the banner and categories (POST /stores/draft: Claude when configured, else a template; invents nothing), creates the DRAFT store for the customer with those categories and the products given (GET /products; each lands in its suggested category) and the pricing, checkout, access and dates given, then answers the store with what still blocks opening (readiness). Nothing is public: review it, then POST /stores/{storeId}/publish.
| Permission | stores.manage (Owner, Admin, Staff) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | workflows_storeForCustomer (toolset stores) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
customerId | string | Yes | The customer the store is for (GET /customers). |
productIds | array of string | Yes | Catalog products to sell (GET /products). Up to 300 items. |
kind | enum | No | One of COMPANY, TEAM, FUNDRAISER, RETAIL. Default COMPANY. |
name | string | No | Default: from the customer's name. Up to 200 characters. |
checkoutMode | enum | No | Default PAY_ONLINE; INVOICE_ACCOUNT and FREE bill the customer. One of PAY_ONLINE, INVOICE_ACCOUNT, FREE. |
priceMode | enum | No | One of CATALOG, MARKUP, FIXED. |
markupPercent | number | No | 0–1000. |
allowanceCents | integer | No | 0–100000000. |
opensOn | string | No | A calendar date in the business's own calendar, YYYY-MM-DD. |
closesOn | string | No | The order deadline. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/workflows/store-for-customer" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"customerId":"customer_id","productIds":["product_id"]}'Response
201: the answer's fields
| Field | Type | Description |
|---|---|---|
store | object | |
store.id | string | |
store.readiness | array of string | |
draftSource | enum | One of AI, TEMPLATE. |
url | string | The SKUFlow screen for the result (open it in the web app to see or change it). |