Taxes API
REST endpoints for taxes in SKUFlow: 10 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 tax rules | GET /organizations/{organizationId}/tax-rules | read |
| Add a tax rule | POST /organizations/{organizationId}/tax-rules | write |
| Get a tax rule | GET /organizations/{organizationId}/tax-rules/{taxRuleId} | read |
| Change a tax rule | PATCH /organizations/{organizationId}/tax-rules/{taxRuleId} | write |
| Delete a tax rule | DELETE /organizations/{organizationId}/tax-rules/{taxRuleId} | sensitive |
| Delete a set of tax rules | POST /organizations/{organizationId}/tax-rules/delete | sensitive |
| Import a tax rate table | POST /organizations/{organizationId}/tax-rules/import | write |
| Check the tax an address pays | GET /organizations/{organizationId}/taxes/lookup | read |
| Get the tax defaults | GET /organizations/{organizationId}/tax-settings | read |
| Change the tax defaults | PATCH /organizations/{organizationId}/tax-settings | write |
List tax rules
GET /organizations/{organizationId}/tax-rules
The business's sales tax rules by country, state and name, paged (rate tables can hold thousands of ZIP codes). search matches the name, city, county or an exact postal code; region a state; source the file a set was imported from. Also answers sources (MANUAL and each imported file, with counts). To know what an address pays use POST /taxes/lookup. Read-only.
| Permission | taxes.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | taxRules_list (toolset settings) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
search | query | string | No | Up to 120 characters. |
region | query | string | No | Up to 60 characters. |
source | query | string | No | Up to 120 characters. |
active | query | boolean | No | |
limit | query | integer | No | 1–200. |
offset | query | integer | No |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-rules" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
items | array of object | |
items[].id | string | |
items[].name | string | |
items[].kind | enum | One of COMPONENT, COMBINED. |
items[].country | string | |
items[].region | string or null | |
items[].county | string or null | |
items[].city | string or null | |
items[].postalCodes | array of string | |
items[].ratePercent | number | |
items[].clothingRatePercent | number or null | |
items[].shippingTaxable | boolean | |
items[].active | boolean | |
items[].notes | string or null | |
items[].source | string | MANUAL, or the file it was imported from ("import:TX.csv"). |
items[].createdAt | string (date-time) | |
items[].updatedAt | string (date-time) | |
total | integer | |
sources | array of object | |
sources[].source | string | |
sources[].count | integer |
Add a tax rule
POST /organizations/{organizationId}/tax-rules
Adds a sales tax rule. New quotes and invoices shipping to an address it matches are taxed with it; existing ones keep their tax until "Update tax" (POST /quotes/{quoteId}/tax, POST /invoices/{invoiceId}/tax). Typical set-up: one COMPONENT rule per state you collect in, plus county / city rules, or COMBINED rules per ZIP code from a rate table (POST /tax-rules/import).
| Permission | taxes.manage (Owner, Admin) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | taxRules_create (toolset settings) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | What it is, e.g. "Texas state", "Travis County", "Austin city". Up to 120 characters. |
kind | enum | No | COMPONENT (default): adds up with the other matching rules (state + county + city + district). COMBINED: the whole rate for the places it names; the most specific matching COMBINED rule wins alone. One of COMPONENT, COMBINED. |
country | string or null | No | ISO country code (US, CA); default US. Up to 60 characters. |
region | string or null | No | State or province ("TX" or "Texas"); empty = the whole country. Up to 120 characters. |
county | string or null | No | County or parish; empty = any. Up to 120 characters. |
city | string or null | No | City; empty = any. Up to 120 characters. |
postalCodes | array of string | No | Exact codes ("78701"), prefixes ("787*") or ranges ("78701-78799"); empty = any. ZIP+4 is matched on its first five digits. Up to 500 items. |
ratePercent | number | Yes | Percent, e.g. 6.25. 0–100. |
clothingRatePercent | number or null | No | Percent on clothing (apparel lines); null = the same as ratePercent. 0 where clothing is exempt. 0–100. |
shippingTaxable | boolean | No | Whether this rate applies to shipping charges (default true). |
active | boolean | No | Inactive rules are kept but never applied. |
notes | string or null | No | Up to 2000 characters. |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-rules" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Dana Whitfield","ratePercent":1}'Response
201: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | |
name | string | |
kind | enum | One of COMPONENT, COMBINED. |
country | string | |
region | string or null | |
county | string or null | |
city | string or null | |
postalCodes | array of string | |
ratePercent | number | |
clothingRatePercent | number or null | |
shippingTaxable | boolean | |
active | boolean | |
notes | string or null | |
source | string | MANUAL, or the file it was imported from ("import:TX.csv"). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Get a tax rule
GET /organizations/{organizationId}/tax-rules/{taxRuleId}
One tax rule: where it applies and its rates. Read-only.
| Permission | taxes.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | taxRules_get (toolset settings) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
taxRuleId | path | string | Yes |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-rules/{taxRuleId}" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | |
name | string | |
kind | enum | One of COMPONENT, COMBINED. |
country | string | |
region | string or null | |
county | string or null | |
city | string or null | |
postalCodes | array of string | |
ratePercent | number | |
clothingRatePercent | number or null | |
shippingTaxable | boolean | |
active | boolean | |
notes | string or null | |
source | string | MANUAL, or the file it was imported from ("import:TX.csv"). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Change a tax rule
PATCH /organizations/{organizationId}/tax-rules/{taxRuleId}
Changes the fields sent (a new rate, places, active: false to stop applying it). Applies to quotes and invoices taxed from now on; existing ones keep their tax until updated.
| Permission | taxes.manage (Owner, Admin) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | taxRules_update (toolset settings) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
taxRuleId | path | string | Yes |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | What it is, e.g. "Texas state", "Travis County", "Austin city". Up to 120 characters. |
kind | enum | No | COMPONENT (default): adds up with the other matching rules (state + county + city + district). COMBINED: the whole rate for the places it names; the most specific matching COMBINED rule wins alone. One of COMPONENT, COMBINED. |
country | string or null | No | ISO country code (US, CA); default US. Up to 60 characters. |
region | string or null | No | State or province ("TX" or "Texas"); empty = the whole country. Up to 120 characters. |
county | string or null | No | County or parish; empty = any. Up to 120 characters. |
city | string or null | No | City; empty = any. Up to 120 characters. |
postalCodes | array of string | No | Exact codes ("78701"), prefixes ("787*") or ranges ("78701-78799"); empty = any. ZIP+4 is matched on its first five digits. Up to 500 items. |
ratePercent | number | No | Percent, e.g. 6.25. 0–100. |
clothingRatePercent | number or null | No | Percent on clothing (apparel lines); null = the same as ratePercent. 0 where clothing is exempt. 0–100. |
shippingTaxable | boolean | No | Whether this rate applies to shipping charges (default true). |
active | boolean | No | Inactive rules are kept but never applied. |
notes | string or null | No | Up to 2000 characters. |
Example
curl -X PATCH "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-rules/{taxRuleId}" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Dana Whitfield","kind":"COMPONENT","country":"string"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
id | string | |
name | string | |
kind | enum | One of COMPONENT, COMBINED. |
country | string | |
region | string or null | |
county | string or null | |
city | string or null | |
postalCodes | array of string | |
ratePercent | number | |
clothingRatePercent | number or null | |
shippingTaxable | boolean | |
active | boolean | |
notes | string or null | |
source | string | MANUAL, or the file it was imported from ("import:TX.csv"). |
createdAt | string (date-time) | |
updatedAt | string (date-time) |
Delete a tax rule
DELETE /organizations/{organizationId}/tax-rules/{taxRuleId}
Destructive: deletes the rule. Quotes and invoices already taxed keep their tax; prefer active: false to keep it on file.
| Permission | taxes.manage (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 | taxRules_delete (toolset settings) |
| Approval | Over MCP, this tool always waits for your approval in SKUFlow. See Approvals. |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
taxRuleId | path | string | Yes |
Example
curl -X DELETE "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-rules/{taxRuleId}" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
ok | true |
Delete a set of tax rules
POST /organizations/{organizationId}/tax-rules/delete
Destructive: deletes every rule imported from one file (source, as listed in GET /tax-rules sources), or every rule with all: true (rules kept by hand included). Documents already taxed keep their tax.
| Permission | taxes.manage (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 | taxRules_deleteMany (toolset settings) |
| 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 |
|---|---|---|---|
source | string | No | Up to 120 characters. |
all | boolean | No |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-rules/delete" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"source":"string","all":true}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
deleted | integer |
Import a tax rate table
POST /organizations/{organizationId}/tax-rules/import
Reads a CSV rate table and adds its rules. Two layouts: Avalara's free rate tables (State, ZipCode, TaxRegionName, EstimatedCombinedRate…; one COMBINED rule per ZIP code), or a sheet with columns name, country, state, county, city, zip (codes separated by spaces or ;), rate (percent), and optionally kind, clothing_rate, shipping_taxable. Rules imported before from a file of the same fileName are replaced (re-import an updated table); rules added by hand are never touched. dryRun: true only checks and previews. Answers how many rules were written, how many replaced and the rows that could not be read.
| Permission | taxes.manage (Owner, Admin) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | taxRules_import (toolset settings) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
content | string | Yes | The CSV file's text. |
fileName | string or null | No | Names the set ("TX.csv"); a later import of the same name replaces it. Up to 120 characters. |
dryRun | boolean | No |
Example
curl -X POST "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-rules/import" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"content":"string"}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
format | enum or null | One of AVALARA, SIMPLE. |
source | string | |
imported | integer | |
replaced | integer | |
problems | array of object | |
problems[].line | integer | |
problems[].message | string | |
preview | array of object | The first rows as read. |
preview[].line | integer | |
preview[].name | string | |
preview[].kind | enum | One of COMPONENT, COMBINED. |
preview[].country | string or null | |
preview[].region | string or null | |
preview[].county | string or null | |
preview[].city | string or null | |
preview[].postalCodes | array of string | |
preview[].ratePercent | number | |
preview[].clothingRatePercent | number or null | |
preview[].shippingTaxable | boolean |
Check the tax an address pays
GET /organizations/{organizationId}/taxes/lookup
What a sale shipped to an address is taxed: give an address (country, state, county, city, zip) or a saved propertyId; with customerId, the customer's exemption and the address's own rate apply too, exactly as on a quote. Answers the rate, the clothing and shipping rates, the source (RULES, ADDRESS, DEFAULT, EXEMPT, NONE) and the rules that applied. Read-only.
| Permission | taxes.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | taxes_lookup (toolset settings) |
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
country | query | string | No | Up to 120 characters. |
state | query | string | No | Up to 120 characters. |
county | query | string | No | Up to 120 characters. |
city | query | string | No | Up to 120 characters. |
zip | query | string | No | Up to 30 characters. |
propertyId | query | string | No | A saved address (GET /properties). |
customerId | query | string | No | Apply the customer's tax exemption. |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/taxes/lookup" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
source | enum | One of EXEMPT, MANUAL, ADDRESS, RULES, UNIT, DEFAULT, NONE. |
rules | array of object | |
rules[].id | string | |
rules[].name | string | |
rules[].kind | enum | One of COMPONENT, COMBINED. |
rules[].ratePercent | number | |
address | object or null | |
address.country | string or null | |
address.state | string or null | |
address.county | string or null | |
address.city | string or null | |
address.zip | string or null | |
ratePercent | number | |
clothingRatePercent | number or null | |
shippingRatePercent | number or null | |
resolvedAt | string |
Get the tax defaults
GET /organizations/{organizationId}/tax-settings
The default rate (where no rule, address rate or unit default applies), whether it taxes shipping, and how many rules are active. Read-only.
| Permission | taxes.read (Owner, Admin, Staff, Member) |
| Risk | read, OAuth scope skuflow.read. Read: reads only. |
| MCP tool | taxes_settings (toolset settings) |
Example
curl "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-settings" \
-H "Authorization: Bearer $SKUFLOW_API_KEY"Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
defaultRatePercent | number or null | Percent where no rule, address rate or unit default applies; null = no tax. |
defaultShippingTaxable | boolean | |
activeRules | integer | How many active tax rules the business has. |
Change the tax defaults
PATCH /organizations/{organizationId}/tax-settings
Sets the default rate (percent, or null for none) used where no tax rule, address rate or unit default applies, and whether it taxes shipping. Applies to quotes and invoices taxed from now on.
| Permission | taxes.manage (Owner, Admin) |
| Risk | write, OAuth scope skuflow.write. Write: creates or changes records inside the business; nothing leaves it. |
| MCP tool | taxes_updateSettings (toolset settings) |
Request body
| Field | Type | Required | Description |
|---|---|---|---|
defaultRatePercent | number or null | No | 0–100. |
defaultShippingTaxable | boolean | No |
Example
curl -X PATCH "https://app.skuflow.ai/api/organizations/$ORGANIZATION_ID/tax-settings" \
-H "Authorization: Bearer $SKUFLOW_API_KEY" \
-H "Content-Type: application/json" \
-d '{"defaultRatePercent":1,"defaultShippingTaxable":true}'Response
200: the answer's fields
| Field | Type | Description |
|---|---|---|
defaultRatePercent | number or null | Percent where no rule, address rate or unit default applies; null = no tax. |
defaultShippingTaxable | boolean | |
activeRules | integer | How many active tax rules the business has. |