Scenario → request fields

The calculation request is backward-compatible: a legacy hotel caller needs none of these. Each optional field unlocks a specific real-world scenario. This maps the field to the situation it's for.

Start from the legacy shape

A direct hotel booking needs only location, dates, nightly rate, currency, and (optionally) property type. Everything on this page is additive — omit a field and the calculation behaves exactly as it did before the field existed. Add a field and you opt into a more specific tax treatment. For the request and response anatomy, see Calculate tax (API).

Tip
When in doubt, leave a field out. Defaults are chosen so the legacy behavior is preserved, and the engine returns the rules it evaluated so you can see exactly what fired.

Channel & merchant of record

FieldTypeDescription
merchant_of_record"property" | "platform" | "none"Who is the seller of record. property (agency model, e.g. an OTA that passes the booking to the hotel) surfaces who collects what via collection_info; platform (the OTA / marketplace is the merchant of record) routes all categories to the platform. Drives the booking's channel. See Channels & MoR.
is_marketplacebooleanMarks the booking as marketplace-facilitated. Treated as platform-equivalent when resolving channel-scoped rates.
platform_typestringAn identifier for the booking platform / channel. Feeds channel resolution alongside merchant_of_record and is_marketplace.
Detail
Channel resolution lets a jurisdiction levy a different rate on direct vs platform sales (e.g. Mexico City Art. 162 direct 3.5% vs Art. 162-bis platform 5%). The channel-mutex capability models that as two channel-scoped rates rather than hand-authored mutual exemptions — see rate & rule configuration. It is an engine capability; no live rate currently sets applies_to_channels, so the Mexico City split is illustrative of the mechanism, not the current data config.

B2B, reverse charge & tax identity

FieldTypeDescription
customer_type"consumer" | "business" | "government" | "diplomat" | "ngo" | "exempt_entity"Who the guest is. business unlocks B2B treatment; government / diplomat / ngo / exempt_entity can trigger exemption rules where a jurisdiction provides them.
business_tax_idstringThe guest's VAT / tax ID (e.g. DE…). Combined with customer_type="business" the engine derives has_valid_vat_id and the cross-border flag is_cross_border_b2b. The room is never reverse-charged (it's taxed where the property is); reverse charge applies to the OTA commission line. See Reverse charge.
commission_supplier_countrystring (ISO country)The OTA / intermediary's own country. Gates commission-line reverse charge on the intermediary's cross-border status independent of the guest — so a US OTA acting as MoR for a German hotel reverse-charges its commission even for a non-EU consumer guest. Omitted → falls back to the guest-derived cross-border flag.
commission_withholding_countrystring (ISO country)The country whose income-tax withholding regime applies to the platform→property payout (e.g. India's TDS on e-commerce). Computed on the gross room subtotal and disclosed as total_withholding, but deliberately excluded from the guest bill, the e-invoice, the refund tax delta, and the liability report — it is a payout-side income-tax deduction, not a consumption tax. Pair with commission_withholding_treaty_rate to apply a treaty-reduced rate. Omitted → no withholding (legacy).
payment_method"card" | "cash" | "bank_transfer" | "foreign_card" | "mobile_money" | "unknown"How the booking was paid. Gates payment-conditioned exemptions where a jurisdiction provides them — e.g. the Argentina IVA refund, the Azerbaijan cashless-POS exemption, and the Uruguay foreign-card IVA-cero. Rules test it with in [list]. Defaults to unknown (no payment-gated rule fires).
Heads up
A valid VAT ID alone does not reverse-charge the room. The room is a service connected to immovable property and is taxed with local VAT regardless of the guest's VAT status.

Pricing, inclusivity & currency

FieldTypeDescription
price_includes_taxbooleanSet true when the nightly rate is tax-inclusive (EU consumer-law display, an inclusive OTA tax policy). The engine reverse-derives the base from the gross; the response always populates both subtotal_excluding_tax and subtotal_including_tax. See Inclusive pricing & currency.
settlement_currencystring (ISO 4217)When the booking is priced in one currency but settled in another, the response adds amount_in_settlement_currency and settlement_fx_rate. The tax calculation itself stays in the booking currency.

Tour operator margin scheme (TOMS)

FieldTypeDescription
margin_schemebooleanOpt into the EU Tour Operators' Margin Scheme (Article 306-310). When true, the destination room VAT is replaced by a single EN 16931 category-E line (VATEX-EU-306, with no VAT shown separately); the VAT on the margin is the operator's own liability, surfaced as total_margin_vat and not added to the guest bill. Supply bought_in_cost and operator_country alongside it (and optionally out_of_eu_cost_fraction for the part of the supply enjoyed outside the EU). Absent → standard destination room VAT (legacy).
Detail
Automatic detection of which bookings qualify as TOMS is deferred — you opt in per booking.

Property shape & supply type

FieldTypeDescription
para_hotelierbooleanFrance only: a bare furnished rental is VAT-exempt; the 10% rate applies only to a para-hôtelier supply (≥3 of 4 services: breakfast, cleaning, linen, reception). For STR-class types, true → 10%, false → exempt, absent → legacy 10%. Hotel-class types always get 10% regardless.
property_postal_codestring (ZIP / postal)Gates geofenced rules that apply only inside a postal boundary (e.g. the Chicago Tourism Improvement District). String match only — normalize ZIP+4 to the 5-digit prefix. Absent → the rule fails open to its pre-geofence behavior.
adultsintegerThe number of chargeable adults for per-person taxes (FR taxe de séjour, etc.), so you can exclude minors with a coarse count: adults=2 on a 4-occupant booking charges per-person taxes for 2. Absent → every occupant is charged (legacy). For per-occupant precision, send guests[] instead.
guests[]array of { age, type, nationality, disability_percentage }Per-occupant details. When provided, each guest is evaluated in its own sub-context and charged at its own resulting rate (age band, residency, disability percentage, guest type), and the per-person amounts are summed — so an individually-exempt guest drops out of the total. age drives age-band rules; type is a canonical guest type (resident, disabled, diplomat, student, senior, …); nationality (ISO 3166-1 alpha-2) drives nationality-based rules; disability_percentage drives threshold exemptions. Sending guests[] overrides the scalar guest fields and the guest count. See Tiered & per-person rates.
property_zone_codestringThe property's sub-city tax-overlay zone, for cities whose lodging tax varies by a zone that is neither an admin boundary nor a clean postal set. Zone-specific rates gate on it by string match; when absent, those rules fall back to the city baseline (backward-compatible). Admin-boundary zones (e.g. the Venice islands) resolve from the address instead.
supplier_tax_regimestringThe host's / supplier's own tax regime, for statutes conditioned on the supplier's standing rather than the booking or guest — small-business and franchise schemes such as the French franchise en base, the German Kleinunternehmer rule, the Italian regime forfettario, the Peruvian MYPE regime, and the UK below-threshold rule. A VAT-exempt regime yields an EN 16931 category-E line with a stated exemption reason. Resolved from an explicit request value, then the supplier legal issuer, then the property default. Absent → standard treatment (backward-compatible).

Rate & rule configuration (not request fields)

A few scenarios are driven by how a rate or rule is configured in the data rather than by a field on your request. You don't send these; they shape how the matching rate behaves. They're listed here so the full picture is in one place.

FieldTypeDescription
collection_modelrate configOn a rate, marks it platform-collected vs property-collected. Used by marketplace-facilitator scenarios (e.g. a city-level rate is platform-collected while the state-level rate stays property-collected).
applies_to_channelsrate config (array)Scopes a rate to ['direct'] / ['platform'] / ['marketplace']. The engine fires the rate only for the booking's resolved channel; NULL means all channels. This is the channel-mutex primitive.
target_jurisdiction_codesrule config (array)On a jurisdiction-wide rule (no bound rate), fans the rule out to descendant jurisdictions by code — so a statewide long-stay exemption reaches every city under it without per-city replication.
Note
The first thing your request controls is the channel; collection_model and applies_to_channels then decide which configured rate that channel selects. See Channels & merchant of record for the end-to-end picture and the OTA guide for worked multi-channel examples.