API referenceTax rates

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

ScopeGrants access to
read:tax_ratestax_rates.list, tax_rates.get
write:tax_ratestax_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.

body
include_archived

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.

body
id

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.

body
name

Display name for the rate. Max 60 characters. Must be unique among active rates.

body
rate_percentage

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.

body
description

Optional description or notes about this rate. Max 500 characters. Pass null to store an explicit empty value.

body
is_default

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.

body
id

The tax rate to update.

body
name

New name. Max 60 characters. Must remain unique among active rates — a name already in use by another rate is a conflict error.

body
rate_percentage

New rate as a human percentage (e.g. 9.5). Same constraints as tax_rates.create.

body
description

Updated description. Max 500 characters. Pass null to clear.

body
is_default

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.

body
id

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

KindWhat it meansCommon cause
invalid_inputA field failed validationMissing name or rate_percentage, rate_percentage out of range or too many decimal places, attempting to patch rate_decimal or is_active directly
not_foundThe rate does not exist in this tenant or is already archivedStale id, rate was archived before this call
conflictThe name is already in use by another active rateDuplicate name on create or update
insufficient_scopeThe token does not hold the required scopeMissing read:tax_rates or write:tax_rates

For the full error shape and HTTP status codes, see Errors.