Tax rates
Manage tax rates and the tenant default via the Zoop MCP tool layer.
Use these tools to create and manage tax rates for your Zoop tenant (your account's isolated workspace). Each rate has a name and a percentage value. One rate can be marked as the tenant default — the rate Zoop applies automatically when creating new invoices, unless you override it.
All tools in this group require read:tax_rates or write:tax_rates. There is no umbrella scope that expands to cover these — the pair stands alone. See Scopes for the full catalog.
New to the Zoop MCP tool layer? Start at MCP overview to learn how to connect and authenticate before calling any tools on this page.
Scopes
| Scope | Grants access to |
|---|---|
read:tax_rates | tax_rates.list, tax_rates.get |
write:tax_rates | tax_rates.create, tax_rates.update, tax_rates.archive |
write:tax_rates does not imply read:tax_rates. If your integration needs to both read and write, request both scopes.
Unlike most write tools, the tax rate tools do not require a user actor. A tenant-key token — a token issued to your app directly, without an associated user ID — can call all five tools. This is because tax rates have no created_by field to attribute.
How rates are stored
Zoop stores rates as a decimal internally — for example, 0.0825 represents 8.25%. You will see this in rate_decimal in get and list responses.
When you create or update a rate, send the human-readable percentage in rate_percentage (e.g. 8.25). Zoop does the conversion for you. Do not send rate_decimal directly — attempting to patch it returns invalid_input.
Valid range for rate_percentage: 0 to 99.9999, with at most 4 decimal places. A value of 99.99999 or higher would round to a stored decimal of 1.0, which is not allowed.
Tools
tax_rates.list
Returns all active tax rates for your tenant, most recent first. The response also includes default_tax_rate_id — the id of the rate currently set as the tenant default, or null if no default is set.
Archived (soft-deleted) rates are excluded by default. Pass include_archived: true to include them.
When true, returns archived (soft-deleted) rates alongside active ones. Defaults to false.
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "tax_rates.list",
"arguments": {}
}
}
{
"jsonrpc": "2.0",
"id": 1,
"result": {
"content": [
{
"type": "text",
"text": "{"rates":[{"id":"d4e5f6a7-...","name":"CA sales tax","rate_decimal":0.0825,"description":null,"is_active":true,"created_at":"2026-01-10T09:00:00.000Z"}],"default_tax_rate_id":"d4e5f6a7-..."}"
}
]
}
}
tax_rates.get
Fetch a single tax rate by its id. Returns not_found if the rate does not exist in your tenant or has been archived.
The tax rate's id. Get this from tax_rates.list.
Example
{
"jsonrpc": "2.0",
"id": 1,
"method": "tools/call",
"params": {
"name": "tax_rates.get",
"arguments": {
"id": "d4e5f6a7-..."
}
}
}
tax_rates.create
Create a new tax rate. The name must be unique among active rates in your tenant — a duplicate name returns a conflict error.
Display name for the rate. Max 60 characters. Must be unique among active rates.
The tax rate as a human percentage: 8.25 means 8.25%. Stored internally as 0.0825. Must be between 0 and 99.9999 with at most 4 decimal places.
Optional description or notes about this rate. Max 500 characters. Pass null to store an explicit empty value.
Set to true to make this the tenant default. If another rate is already the default, it is automatically demoted. Defaults to false.
Example — create a rate and set it as the default
{
"jsonrpc": "2.0",
"id": 2,
"method": "tools/call",
"params": {
"name": "tax_rates.create",
"arguments": {
"name": "CA sales tax",
"rate_percentage": 8.25,
"description": "California statewide base rate",
"is_default": true
}
}
}
{
"jsonrpc": "2.0",
"id": 2,
"result": {
"content": [
{
"type": "text",
"text": "{"id":"d4e5f6a7-...","name":"CA sales tax","rate_decimal":0.0825,"description":"California statewide base rate","is_active":true,"created_at":"2026-06-13T18:00:00.000Z"}"
}
]
}
}
tax_rates.update
Update a tax rate's fields. This is a partial patch — only the fields you send are changed; fields you omit stay as they are.
Two fields cannot be patched directly: rate_decimal (use rate_percentage instead) and is_active (use tax_rates.archive to deactivate a rate). Attempting either returns invalid_input.
The tax rate to update.
New name. Max 60 characters. Must remain unique among active rates — a name already in use by another rate is a conflict error.
New rate as a human percentage (e.g. 9.5). Same constraints as tax_rates.create.
Updated description. Max 500 characters. Pass null to clear.
Pass true to make this the tenant default — any existing default is automatically demoted. Pass false to clear the default when this rate is currently the default (the tenant default becomes null). Has no effect if this rate is not currently the default.
Example — change the rate percentage
{
"jsonrpc": "2.0",
"id": 3,
"method": "tools/call",
"params": {
"name": "tax_rates.update",
"arguments": {
"id": "d4e5f6a7-...",
"rate_percentage": 9.0
}
}
}
tax_rates.archive
Archive (soft-delete) a tax rate. Archiving hides the rate from default list results without deleting the underlying record — any invoices or quotes that used the rate keep their correct totals.
If the archived rate is the tenant default, the default is automatically cleared (set to null). Zoop will not apply any tax rate automatically until you set a new default.
Archiving a rate that is already archived (or does not exist) returns not_found. There is no restore tool in the current MCP version.
The tax rate to archive.
If you archive the current default rate, the tenant default is cleared. New invoices and quotes will have no tax rate pre-applied until you set a new default with tax_rates.update or tax_rates.create.
Example
{
"jsonrpc": "2.0",
"id": 4,
"method": "tools/call",
"params": {
"name": "tax_rates.archive",
"arguments": {
"id": "d4e5f6a7-..."
}
}
}
{
"jsonrpc": "2.0",
"id": 4,
"result": {
"content": [
{
"type": "text",
"text": "{"archived":true,"id":"d4e5f6a7-..."}"
}
]
}
}
Managing the tenant default
The tenant default is a single pointer: at most one rate is marked as the default at any time. Here is the typical lifecycle.
Create the rate
Call tax_rates.create with is_default: true. If a default already exists, it is automatically demoted.
Change the default
Call tax_rates.update on the new rate with is_default: true. The previous default is demoted automatically.
Clear the default
Call tax_rates.update on the current default with is_default: false. The default becomes null. No tax rate will be pre-applied to new documents until you set another.
Archive the default rate
Call tax_rates.archive. The rate is hidden and the default is cleared automatically — same outcome as clearing it explicitly.
To read the current default at any time, call tax_rates.list and read default_tax_rate_id from the response.
Error reference
| Kind | What it means | Common cause |
|---|---|---|
invalid_input | A field failed validation | Missing name or rate_percentage, rate_percentage out of range or too many decimal places, attempting to patch rate_decimal or is_active directly |
not_found | The rate does not exist in this tenant or is already archived | Stale id, rate was archived before this call |
conflict | The name is already in use by another active rate | Duplicate name on create or update |
insufficient_scope | The token does not hold the required scope | Missing read:tax_rates or write:tax_rates |
For the full error shape and HTTP status codes, see Errors.