One call returns the correct tax rate and whether to charge VAT, apply the B2B reverse charge, or treat the sale as out of scope — with a ready-to-paste invoice note. Built for multi-vendor platforms on Stripe Connect, where every transaction has a different seller country.
Canonical machine spec: /openapi.json (OpenAPI 3.0)
If you sell your own product, a Merchant of Record will swallow this problem for you — use one. It becomes the legal seller and the VAT stops being your concern.
That model breaks the moment your vendors are the real sellers and you only take a cut. An MoR assumes one seller; a marketplace has hundreds, in different countries, each with their own registration status. The calculation lands back on the platform, per transaction. That is who this is for.
The rate depends on where the buyer is, where that seller is, and whether the buyer is a business. Get it wrong and you eat the tax or fail an audit.
EU-27 + UK VAT · US state-level sales tax · Canada GST/HST/PST · Australia GST. Rates last reviewed 2026-07.
When API_KEYS is configured on the deployment, /rate and /decide require one of:
X-API-Key: <key>Authorization: Bearer <key>?api_key=<key>/health, /openapi.json, and this docs page are always open. RapidAPI proxy may use X-RapidAPI-Proxy-Secret when configured.
/healthLiveness probe. Returns status, version, lastReviewed.
curl "https://checkout-tax-api.pages.dev/health"
/openapi.jsonOpenAPI 3.0 specification for client generation and marketplace import.
/rate| Parameter | Required | Description |
|---|---|---|
country | yes | ISO 3166-1 alpha-2 (DE, GB, US, CA, AU, …) |
region | US: yes | US state or CA province code |
product_type | no | digital (default) or standard |
200 response fields: country, countryName, region, regionName, taxType, rate, productType, taxable, notes[], source
curl "https://checkout-tax-api.pages.dev/rate?country=DE&product_type=digital"
/decide| Field | Required | Description |
|---|---|---|
seller_country | yes | Seller establishment (EU-27 or GB in v1) |
buyer_country | yes | Buyer country |
buyer_vat_id | no | Format-checked VAT ID (not VIES-verified) |
buyer_region | no | US state / CA province when applicable |
product_type | no | digital or standard |
200 response fields: chargeVat, mechanism (standard|reverse_charge|zero_rated|out_of_scope), rate, taxType, buyerType, sellerCountry, buyerCountry, vatId, invoiceNote, legalBasis, notes[], disclaimer
curl -X POST "https://checkout-tax-api.pages.dev/decide" \
-H "Content-Type: application/json" \
-d '{"seller_country":"DE","buyer_country":"FR","buyer_vat_id":"FRXX123456789"}'
OPTIONS on any path returns 204 with Access-Control-Allow-Origin: * for browser clients.
Errors use shape { "error": { "code": "...", "message": "..." } }:
| code | HTTP | When |
|---|---|---|
missing_country | 400 | A `country` (ISO 3166-1 alpha-2) is required. |
unsupported_country | 400 | Country not in coverage set. |
missing_region | 400 | US/CA require a `region` (state or province). |
unsupported_region | 400 | Region not recognized for the country. |
missing_seller | 400 | `seller_country` is required. |
missing_buyer | 400 | `buyer_country` is required. |
unsupported_seller | 400 | Seller must be established in EU-27 or UK (v1). |
invalid_json | 400 | Request body is not valid JSON. |
invalid_product_type | 400 | `product_type` must be "digital" or "standard". |
method_not_allowed | 405 | HTTP method not allowed for this path. |
unauthorized | 401 | Missing or invalid API key. |
not_found | 404 | No route for the requested path. |
JavaScript (fetch)
const res = await fetch("https://checkout-tax-api.pages.dev/decide", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
seller_country: "DE",
buyer_country: "FR",
buyer_vat_id: "FRXX123456789",
}),
});
const decision = await res.json();
Rate lookups + decisions for evaluation and low volume.
Production volume for a single product.
High volume + priority.
Full source, MIT, 75 tests. Runs on your own Worker, so you pay per invocation instead of a slice of every sale.
Download link appears the moment you pay. MIT licensed — no key, nothing phoning home.