> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://docs.zip.tax/v-6-0/guides/merchant-compliance-solutions/cart/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.zip.tax/_mcp/server. # Cart Tax Calculation Calculate the tax due on a cart of items for one of your [TaxCloud-connected merchants](taxcloud-connected-merchants). Use this before you record an order so you can display an accurate tax total at checkout. The calculation reflects the merchant's own compliance configuration (registrations, product rules, and exemptions). > **Info** > > This is the **merchant-scoped** cart calculation at `/merchant/cart/calculate`. > It is different from the general-purpose `/calculate/cart` rate-lookup endpoint, > which is not tied to a merchant. ## One endpoint, two engines `/merchant/cart/calculate` serves both [compliance models](merchant-management). The request body is the same for both, and Ziptax picks the engine from the `merchantId` you send — you never branch on merchant type when building a request. | | TaxCloud-connected merchant | Self-managed merchant | | ---------------------------------------------- | ----------------------------------------------------------------------- | -------------------------------------------------------------- | | **Engine** | Forwarded to TaxCloud using the merchant's stored credentials | Calculated by Ziptax's own rate engine, no TaxCloud call | | **Documented on** | This page | [Self-Managed Cart Calculation](self-managed-cart-calculation) | | **Plan** | Enterprise | Pro and Enterprise | | **Discounts, exemptions, `deliveredBySeller`** | Supported | Rejected with `400` | | **`tic` vocabulary** | TaxCloud codes, e.g. `11010` for shipping | Ziptax codes, e.g. `10001` for shipping | | **Result can become an order** | Yes, via [`order/create-from-cart`](orders#create-an-order-from-a-cart) | No — the calculation is stateless | > **Warning** > > If you serve both merchant types, read > [Self-Managed Cart Calculation](self-managed-cart-calculation) before you reuse > this page's payloads. Taxability codes mean different things on the two paths, > and a TaxCloud shipping code sent for a self-managed merchant is taxed as an > ordinary product rather than as freight. The rest of this page describes the TaxCloud-connected path. A connected merchant with no valid credentials returns `404` (`credentials not found`) — Ziptax does not fall back to its own engine, because the resulting tax would not match what the merchant's TaxCloud account files. ## Endpoint ```http POST https://api.zip-tax.com/merchant/cart/calculate ``` ## Request body | Field | Type | Required | Description | | ----------------- | ----------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------- | | `merchantId` | string (UUID) | Yes | The connected merchant whose TaxCloud connection is used. Must be owned by the calling account. Consumed for routing and not forwarded. | | `items` | array of [Cart](#cart-object) | Yes | The carts to calculate tax for (1–100). Most integrations send a single cart. | | `transactionDate` | string (RFC3339 date-time) | No | The datetime the carts are calculated for, e.g. `2026-07-13T14:00:00Z`. Defaults to the current time. | ### Cart object | Field | Type | Required | Description | | ------------------- | --------------------------------------- | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `cartId` | string (1–50 chars) | No | Your identifier for this cart. If omitted, one is generated and returned; either way, pass it to [`order/create-from-cart`](orders#create-an-order-from-a-cart) to record the sale. | | `customerId` | string (1–50 chars) | Yes | Your identifier for the customer in your own system. Used to match exemption certificates and order history. | | `origin` | [Address](#address-object) | Yes | The ship-from address of the sale. Used with `destination` to determine sourcing and the applicable jurisdictions. | | `destination` | [Address](#address-object) | Yes | The ship-to address of the sale. Tax is generally calculated for this address in destination-sourced states. | | `currency` | object | Yes | `{ "currencyCode": "USD" }`. The `currency` object itself is required; the inner `currencyCode` (ISO 4217 code the prices are denominated in, `USD` or `CAD`) defaults to `USD` when omitted. | | `lineItems` | array of [Line item](#line-item-object) | Yes | The line items in the cart. Tax is calculated and returned per item. | | `deliveredBySeller` | boolean | No | Whether the seller delivers the order directly (own vehicles) rather than via common carrier. Affects taxability of delivery charges in some states. | | `discounts` | [Discounts](#discounts-object) | No | Optional line-item and order-level discounts. If omitted, prices are used as is. | | `exemption` | object | No | `{ "exemptionId": "...", "isExempt": true }`. Reference an [exemption certificate](exemption-certificates) by id (`isExempt` is then assumed true), or set `isExempt` directly. | ### Address object | Field | Type | Required | Description | | ------------- | ---------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------- | | `line1` | string (1–128 chars) | Yes | First line of the address: street number and name, PO Box, or building. Values longer than 50 characters are truncated. | | `line2` | string (max 128 chars) | No | Second line, if any (apartment, suite, unit). Values longer than 50 characters are truncated. | | `city` | string (1–50 chars) | Yes | City or post-town. | | `state` | string | Yes | Two-letter state or province abbreviation, e.g. `MN`, `CA`, `ON`. | | `zip` | string (1–16 chars) | Yes | Postal or ZIP code. Five-digit (`55401`) and ZIP+4 (`55401-2427`) formats are accepted. | | `countryCode` | string | No | ISO 3166-1 alpha-2 country code: `US` or `CA`. Defaults to `US`. | ### Line item object | Field | Type | Required | Description | | ----------- | --------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | `index` | integer (0–500) | Yes | Zero-based position of the item within the cart. Each item must have a unique index. | | `itemId` | string (1–50 chars) | Yes | Your unique identifier for the line item (e.g. SKU or line reference). Used to match items in later order, refund, and discount operations. | | `price` | number (≥ 0) | Yes | Unit price of the item in the cart's currency. When discounts are provided, this must be the **pre-discount** (original) price. | | `quantity` | number (0–99999.9999) | Yes | Quantity of the item. Fractional quantities are allowed. For larger quantities, send a single line with quantity `1` and the extended (total) amount as the price. | | `tic` | integer (0–100000) | No | Taxability Information Code classifying the product for product-specific tax rules (e.g. `11010` for shipping). Defaults to `0` (general tangible goods). | | `productId` | string | No | ID of the product in the merchant's TaxCloud product catalog. Must match an existing catalog product when provided. | ### Discounts object | Field | Type | Required | Description | | ------------------- | ------ | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | `lineItemDiscounts` | array | No | Discounts applied to specific line items, before any order-level discount. Each entry is `{ "itemId": "...", "type": "percentage" \| "amount", "value": 0.1 }` and must reference a valid `itemId` from `lineItems`. | | `orderDiscount` | object | No | `{ "type": "percentage" \| "amount", "value": 0.1 }`. Applied to the whole order after line-item discounts. Shipping items (TICs 11010–11015) and Colorado retail delivery fees (TIC 11098) are excluded. | For `percentage` discounts, `value` is a decimal fraction between 0 and 1 (`0.1` = 10% off); for `amount` discounts it is a fixed currency amount. When you provide discounts, line-item prices must be pre-discount originals — if your prices are already discounted, omit the `discounts` field. ## Example #### cURL ```bash curl -X POST "https://api.zip-tax.com/merchant/cart/calculate" \ -H "X-API-KEY: YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "merchantId": "6b3c1f5e-2a8d-4c9b-9f2e-1d7a4b6c8e10", "transactionDate": "2026-07-13T14:00:00Z", "items": [ { "cartId": "cart-2026-000123", "customerId": "customer-453", "currency": { "currencyCode": "USD" }, "origin": { "line1": "1 Market St", "city": "San Francisco", "state": "CA", "zip": "94105" }, "destination": { "line1": "200 Spectrum Center Dr", "city": "Irvine", "state": "CA", "zip": "92618" }, "lineItems": [ { "index": 0, "itemId": "sku-1001", "price": 49.99, "quantity": 2, "tic": 0 } ] } ] }' ``` #### Python ```python import requests res = requests.post( "https://api.zip-tax.com/merchant/cart/calculate", headers={"X-API-KEY": "YOUR_API_KEY"}, json={ "merchantId": "6b3c1f5e-2a8d-4c9b-9f2e-1d7a4b6c8e10", "transactionDate": "2026-07-13T14:00:00Z", "items": [ { "cartId": "cart-2026-000123", "customerId": "customer-453", "currency": {"currencyCode": "USD"}, "origin": {"line1": "1 Market St", "city": "San Francisco", "state": "CA", "zip": "94105"}, "destination": {"line1": "200 Spectrum Center Dr", "city": "Irvine", "state": "CA", "zip": "92618"}, "lineItems": [ {"index": 0, "itemId": "sku-1001", "price": 49.99, "quantity": 2, "tic": 0}, ], } ], }, ) res.raise_for_status() cart = res.json() ``` #### Node.js ```javascript const res = await fetch("https://api.zip-tax.com/merchant/cart/calculate", { method: "POST", headers: { "X-API-KEY": "YOUR_API_KEY", "Content-Type": "application/json", }, body: JSON.stringify({ merchantId: "6b3c1f5e-2a8d-4c9b-9f2e-1d7a4b6c8e10", transactionDate: "2026-07-13T14:00:00Z", items: [ { cartId: "cart-2026-000123", customerId: "customer-453", currency: { currencyCode: "USD" }, origin: { line1: "1 Market St", city: "San Francisco", state: "CA", zip: "94105" }, destination: { line1: "200 Spectrum Center Dr", city: "Irvine", state: "CA", zip: "92618" }, lineItems: [ { index: 0, itemId: "sku-1001", price: 49.99, quantity: 2, tic: 0 }, ], }, ], }), }); const cart = await res.json(); ``` ## Response Returns the calculated carts with tax computed per line item. | Field | Type | Description | | ---------------------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------- | | `connectionId` | string | The TaxCloud connection the calculation ran under. | | `transactionDate` | string (RFC3339 date-time) | The datetime the carts were calculated for. | | `items` | array | One calculated cart per submitted cart, in the same order. | | `items[].cartId` | string | Identifier of the calculated cart. Pass it to [`order/create-from-cart`](orders#create-an-order-from-a-cart). | | `items[].customerId` | string | Your customer identifier, as submitted. | | `items[].deliveredBySeller` | boolean | Whether the seller delivers the order directly, as submitted. | | `items[].origin` / `items[].destination` | [Address](#address-object) | The addresses, as submitted. | | `items[].exemption` | object | The exemption information applied to the calculation. | | `items[].currency` | object | The currency the prices and tax amounts are denominated in. | | `items[].lineItems[].index` | integer | Zero-based position of the item within the cart. | | `items[].lineItems[].itemId` | string | Your line item identifier, as submitted. | | `items[].lineItems[].tic` | integer or null | The TIC the item was calculated under. | | `items[].lineItems[].price` | number | The unit price tax was calculated on (discounted, when discounts applied). | | `items[].lineItems[].originalPrice` | number | The original pre-discount unit price, as submitted. | | `items[].lineItems[].quantity` | number | Quantity of the item. | | `items[].lineItems[].tax.rate` | number | The combined tax rate applied, as a decimal fraction (e.g. `0.08125` = 8.125%). | | `items[].lineItems[].tax.amount` | number | The calculated tax amount for the line item. | ```json { "connectionId": "25eb9b97-5acb-492d-b720-c03e79cf715a", "transactionDate": "2026-07-13T14:00:00Z", "items": [ { "cartId": "cart-2026-000123", "customerId": "customer-453", "deliveredBySeller": false, "origin": { "line1": "1 Market St", "city": "San Francisco", "state": "CA", "zip": "94105", "countryCode": "US" }, "destination": { "line1": "200 Spectrum Center Dr", "city": "Irvine", "state": "CA", "zip": "92618", "countryCode": "US" }, "exemption": { "exemptionId": null, "isExempt": null }, "currency": { "currencyCode": "USD" }, "lineItems": [ { "index": 0, "itemId": "sku-1001", "tic": 0, "price": 49.99, "originalPrice": 49.99, "quantity": 2, "tax": { "rate": 0.0775, "amount": 7.75 } } ] } ] } ``` > **Warning** > > If you do not receive a response, it is safe to call `cart/calculate` again: > calculation has no lasting side effect. Do **not**, however, retry > [order](orders) or [refund](refunds) writes blindly. See > [Retries and idempotency](transactions#retries-and-idempotency). ## Related #### [Self-Managed Cart Calculation](self-managed-cart-calculation) The same endpoint for a self-managed merchant, calculated by Ziptax. #### [Orders](orders) Turn a calculated cart into a recorded order. #### [Merchant Transactions](transactions) Shared conventions, errors, and usage. > Calculate sales tax for a cart of items on behalf of a TaxCloud-connected merchant.