Tax Calculation
Tax Calculation
Calculate the tax for a transaction, including support for multiple line items, product-specific taxability rules, and seller registration validation.
Endpoint
POST /v1/calculateRequest Body
| Field | Type | Required | Description |
|---|---|---|---|
line_items | array | Yes | Array of items in the transaction (1-100 items) |
line_items[].amount | integer | Yes | Price in cents (e.g., 9999 = $99.99) |
line_items[].product_type | string | Yes | Product category (see below) |
line_items[].quantity | integer | No | Quantity (default: 1) |
line_items[].description | string | No | Item description |
customer.address.country | string | Yes | 2-letter ISO country code |
customer.address.region | string | No | State/province code (required for US/CA) |
customer.address.postal_code | string | No | Postal/ZIP code |
seller.registered_in | array | No | Jurisdictions where seller collects tax |
currency | string | Yes | 3-letter ISO currency code |
transaction_date | string | No | Date in YYYY-MM-DD format (default: today) |
Product Types
| Type | Description |
|---|---|
physical_goods | Tangible products |
digital_goods | Downloadable products (ebooks, software) |
saas | Software as a Service subscriptions |
services | Professional services |
streaming | Streaming media services |
Example Request
curl -X POST "https://api.shipvat.com/v1/calculate" \ -H "Authorization: Bearer sk_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "line_items": [ { "amount": 9999, "product_type": "saas", "quantity": 1, "description": "Pro plan - monthly" } ], "customer": { "address": { "country": "DE", "postal_code": "10115" } }, "seller": { "registered_in": ["US", "DE", "GB"] }, "currency": "USD" }'Response
{ "subtotal": 9999, "tax_amount": 1899, "total": 11898, "tax_rate": 19, "tax_breakdown": [ { "jurisdiction": "DE", "jurisdiction_name": "Germany", "tax_type": "VAT", "rate": 19, "taxable_amount": 9999, "tax_amount": 1899 } ], "line_items": [ { "amount": 9999, "product_type": "saas", "quantity": 1, "description": "Pro plan - monthly", "taxable": true, "tax_rate": 19, "tax_amount": 1899 } ], "seller_registered": true, "warnings": [], "queried_at": "2024-01-15T10:30:00.000Z"}Response Fields
| Field | Type | Description |
|---|---|---|
subtotal | integer | Sum of all line item amounts (cents) |
tax_amount | integer | Total tax to collect (cents) |
total | integer | subtotal + tax_amount (cents) |
tax_rate | number | Effective tax rate as percentage |
tax_breakdown | array | Tax grouped by jurisdiction and type |
line_items | array | Per-item tax calculation results |
seller_registered | boolean | Whether seller is registered in destination |
warnings | array | Non-fatal warnings about the calculation |
queried_at | string | ISO timestamp of the calculation |
Seller Registration
The seller.registered_in array determines whether tax should be calculated:
- Registered: Tax is calculated based on destination rules
- Not registered: Returns
tax_amount: 0with a warning
{ "seller": { "registered_in": ["US", "DE", "GB"] }}For US and Canada, you can specify:
- Federal level:
"US"or"CA"(covers all states/provinces) - State/province level:
"US-CA","US-TX","CA-ON", etc.
Taxability Rules
Different product types have different tax rules per jurisdiction:
| Jurisdiction | SaaS | Digital Goods | Physical Goods |
|---|---|---|---|
| EU countries | Taxable (VAT) | Taxable (VAT) | Taxable (VAT) |
| US-CA | Exempt | Exempt | Taxable |
| US-TX | Taxable | Taxable | Taxable |
| US-OR | No sales tax | No sales tax | No sales tax |
When a product is exempt, the response includes:
{ "line_items": [ { "taxable": false, "tax_rate": 0, "tax_amount": 0, "taxability_reason": "SaaS is exempt in California" } ]}Multiple Line Items
Calculate tax for multiple items in one request:
curl -X POST "https://api.shipvat.com/v1/calculate" \ -H "Authorization: Bearer sk_your_api_key" \ -H "Content-Type: application/json" \ -d '{ "line_items": [ {"amount": 4999, "product_type": "saas", "quantity": 1}, {"amount": 1999, "product_type": "services", "quantity": 2} ], "customer": {"address": {"country": "GB"}}, "seller": {"registered_in": ["GB"]}, "currency": "GBP" }'Response aggregates tax across all items:
{ "subtotal": 8997, "tax_amount": 1799, "total": 10796, "tax_rate": 20, "tax_breakdown": [ { "jurisdiction": "GB", "jurisdiction_name": "United Kingdom", "tax_type": "VAT", "rate": 20, "taxable_amount": 8997, "tax_amount": 1799 } ]}US State Sales Tax
For US destinations, always include the region field:
{ "customer": { "address": { "country": "US", "region": "CA", "postal_code": "94102" } }}Warnings
The API may return warnings for:
- Seller not registered in destination jurisdiction
- No specific taxability rule found (using standard rate)
- No rate found for the specified category
{ "warnings": [ "Seller is not registered to collect tax in Germany. Registration may be required based on sales thresholds. Use /v1/decision/collect to check." ]}Error Responses
400 Bad Request
{ "error": "Invalid request body", "details": { "errors": { "line_items": ["At least one line item is required"], "customer.address.country": ["Country must be a 2-letter ISO code"] } }}404 Not Found
{ "error": "Jurisdiction not found", "jurisdiction": "XX"}Integration Example
// Calculate tax before checkoutconst response = await fetch('https://api.shipvat.com/v1/calculate', { method: 'POST', headers: { 'Authorization': 'Bearer sk_your_api_key', 'Content-Type': 'application/json' }, body: JSON.stringify({ line_items: cart.items.map(item => ({ amount: Math.round(item.price * 100), // Convert to cents product_type: item.taxCategory, quantity: item.quantity, description: item.name })), customer: { address: { country: customer.country, region: customer.state, postal_code: customer.postalCode } }, seller: { registered_in: ['US', 'DE', 'GB', 'CA'] }, currency: 'USD' })});
const tax = await response.json();
// Display to customerconsole.log(`Subtotal: $${(tax.subtotal / 100).toFixed(2)}`);console.log(`Tax: $${(tax.tax_amount / 100).toFixed(2)}`);console.log(`Total: $${(tax.total / 100).toFixed(2)}`);