Calculate tax
POST /v1/tax/calculate is the core of TaxLens. Give it where the stay is and what the stay is; get back an itemized, stacked tax breakdown.
What it does
The engine resolves the jurisdiction, walks its ancestor chain (country → region → city), collects every active rate that matches your booking and stay date, evaluates the rules bound to those rates (exemptions, overrides, caps, surcharges, reductions), and returns one component per surviving tax plus a total. The calculation is read-only and saves nothing — to persist it, see Bookings API. For the conceptual walk-through, read How a calculation works and Additive stacking.
Locating the stay
Provide either a jurisdiction_code or a lat/lng pair. With coordinates, the geocoder resolves the matching jurisdiction for you. If you only have a street address, run it through address validation first and feed the resulting code back in.
| Field | Type | Description |
|---|---|---|
| jurisdiction_code | string | TaxLens jurisdiction code (e.g. US-NY-NYC, ES-CT-BCN, HR-19-DBV). Optional when lat+lng are supplied. |
| lat / lng | float | Latitude and longitude. Provide the pair instead of jurisdiction_code to auto-resolve via the geocoder. |
Describing the stay
These fields define what is being taxed. stay_date, nightly_rate, currency, and nights are required; everything else refines which rules fire.
| Field | Type | Description |
|---|---|---|
| stay_daterequired | date | Check-in date (YYYY-MM-DD). Rates and rules are time-aware — the engine uses what's in force on this date. |
| nightsrequired | integer | Number of nights (≥ 1). Drives per-night taxes and night caps. |
| nightly_raterequired | decimal | Room rate per night, > 0. Overridden when nightly_rates[] (a per-night schedule) is provided. |
| currencyrequired | string | ISO 4217 code (USD, EUR, JPY …). |
| checkout_date | date | Optional; when supplied it must equal stay_date + nights, else 422. |
| number_of_guests | integer | Guest count (default 1). Multiplies per-person taxes. Use adults to exclude minors from per-person levies. |
| property_type | string | Lodging product type — hotel, vacation_rental, str, apartment_hotel, hostel, etc. (default hotel). Inputs are normalized before rule matching. |
| star_rating | integer | 1–5. Used by star-tiered rates (e.g. Florence, Milan, Dubai). |
| guests[] | list | Per-guest detail ({ nationality, age, residency_status, exempt_entity_type }). Overrides the scalar guest_age / guest_nationality / number_of_guests for mixed-guest exemptions. |
| line_items[] | list | Itemized extras (resort_fee, cleaning_fee, commission …) taxed by their own category. Room line items are ignored — nightly_rate × nights is the canonical room base. |
merchant_of_record, customer_type / business_tax_id for B2B reverse charge, price_includes_tax, settlement_currency, geofencing and para-hôtelier flags — is documented field-by-field in Scenario fields. They are all backward compatible: a legacy request without them returns identical output.The request in code
curl -X POST https://api.taxlens.getdynamiq.ai/v1/tax/calculate \
-H "X-API-Key: $TAXLENS_KEY" \
-H "Content-Type: application/json" \
-d '{
"jurisdiction_code": "ES-CT-BCN",
"stay_date": "2026-06-15",
"checkout_date": "2026-06-17",
"nightly_rate": 180,
"currency": "EUR",
"nights": 2,
"number_of_guests": 2,
"property_type": "hotel",
"star_rating": 4
}'Reading the response
The response is an itemized breakdown. The fields you'll use most:
| Field | Type | Description |
|---|---|---|
| tax_breakdown.components[] | list | One entry per tax that fired: name, category_code, jurisdiction_code, jurisdiction_level, rate, rate_type, taxable_amount, and tax_amount. An exempted component carries is_exempt and exemption_reason. |
| tax_breakdown.total_tax | decimal | Sum of all component tax amounts, in the booking currency. |
| tax_breakdown.effective_rate | decimal | total_tax over the room subtotal (nightly rate × nights) — a single headline rate. |
| total_with_tax | decimal | Subtotal plus total_tax — what the guest pays. |
| rules_applied[] | list | A trace of every rule evaluated, each with its result: applied, exempted, skipped. Your audit of why the number is what it is. |
| collection_info | object | Who remits each component (property vs platform), the taxable base, and per-component MoR splits. Driven by merchant_of_record / is_marketplace. See Channels & MoR. |
{
"calculation_id": "calc_c484953024e7b4e04f7e9b05ba1ca866",
"jurisdiction": { "code": "ES-CT-BCN", "name": "Barcelona", "path": "ES.CT.BCN" },
"tax_breakdown": {
"components": [
{
"name": "Occupancy Tax (flat per person per night)",
"category_code": "occ_flat_person_night",
"jurisdiction_code": "ES-CT-BCN",
"jurisdiction_level": "city",
"rate_type": "flat",
"taxable_amount": "360",
"tax_amount": "20.00"
},
{
"name": "Tourism Tax (flat per person per night)",
"category_code": "tourism_flat_person_night",
"jurisdiction_code": "ES-CT-BCN",
"jurisdiction_level": "city",
"rate_type": "tiered",
"taxable_amount": "360",
"tax_amount": "13.60"
},
{
"name": "VAT / Sales Tax (reduced rate)",
"category_code": "vat_reduced",
"jurisdiction_code": "ES",
"jurisdiction_level": "country",
"rate": 0.1,
"rate_type": "percentage",
"taxable_amount": "393.60",
"tax_amount": "39.36"
}
],
"total_tax": "72.96",
"effective_rate": "0.2026666666666666666666666667",
"currency": "EUR",
"subtotal_excluding_tax": "360",
"subtotal_including_tax": "432.96"
},
"total_with_tax": "432.96",
"rules_applied": [
{ "rule_id": 1361, "name": "Barcelona IEET — 7-night cap per continuous stay",
"rule_type": "cap", "result": "applied" }
],
"collection_info": {
"who_collects": "property",
"taxable_base": "room_rate",
"platform_must_collect": false,
"property_collected_components": ["vat_reduced", "occ_flat_person_night", "tourism_flat_person_night"]
}
}taxable_amount (393.60) is larger than the room subtotal (360) on purpose: Spain folds the operator-levied occupancy and tourism taxes into the VAT base, so 10% VAT is charged on room + those taxes (360 + 20.00 + 13.60). Whether a tourist tax sits inside or outside the VAT base is per-jurisdiction — VAT base composition has the full picture.Try it live
This runs the real engine against your session and active organization. Read-only — nothing is saved. Edit the body and run it again.
A 2-night, 4-star Barcelona hotel stay for two guests.
{
"jurisdiction_code": "ES-CT-BCN",
"stay_date": "2026-06-15",
"checkout_date": "2026-06-17",
"nightly_rate": 180,
"currency": "EUR",
"nights": 2,
"number_of_guests": 2,
"property_type": "hotel",
"star_rating": 4
}Sign in to run this against the live API. Read-only — nothing is saved.