API v1 / schema 1.0.0

Quickstart

Three calls, one evidence trail.

Keep your API key on your server. Begin with published country coverage, discover authoritative jurisdiction records, then inspect rules or resolve supported defaults.

  1. Obtain a scoped key from your TouristTaxTools operator.
  2. Read country coverage and its explicit gaps.
  3. Confirm the property's authoritative jurisdiction before applying any defaults.
1. Inspect published countries
curl 'https://api.touristtaxtools.com/v1/countries' \
  -H "Authorization: Bearer $TOURISTTAXTOOLS_API_KEY"
2. Discover jurisdictions
curl 'https://api.touristtaxtools.com/v1/jurisdictions?country=IT&q=Rome&limit=20&offset=0' \
  -H "Authorization: Bearer $TOURISTTAXTOOLS_API_KEY"
3. Check an address — may return unknown
curl 'https://api.touristtaxtools.com/v1/resolve' \
  -H "Authorization: Bearer $TOURISTTAXTOOLS_API_KEY" \
  -H 'Content-Type: application/json' \
  --data '{
    "countryCode": "IT",
    "address": {
      "street": "Piazza della Rotonda",
      "city": "Roma",
      "postalCode": "00186"
    },
    "on": "2026-10-26",
    "accommodationType": "hotel"
  }'

Handle uncertainty as a result.

A successful HTTP response can carry unknown, ambiguous, manual_review or stale. These are meaningful states. Do not turn them into a zero tax.

Server-side JavaScript · Node 24
// Run on your server. Never bundle this key into a browser.
const response = await fetch(
  'https://api.touristtaxtools.com/v1/resolve',
  {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.TOURISTTAXTOOLS_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      countryCode: 'IT',
      // Use identifiers from authoritative property records.
      // Discovery by a place name does not prove applicability.
      officialCodes: [{ scheme: 'IT:ISTAT', value: '058091' }],
      on: '2026-10-26',
      accommodationType: 'hotel',
    }),
    signal: AbortSignal.timeout(8000),
    redirect: 'error',
  },
);
if (!response.ok) throw new Error(`API status ${response.status}`);
const result = await response.json();
if (result.status === 'resolved' && Array.isArray(result.defaults)) {
  // Offer supported defaults for review before saving.
  // Preserve manual settings and historical reservation amounts.
} else {
  // Keep existing settings. Show result.reasons for manual review.
}

Review a policy before requesting a stay quote.

POST /v2/resolve provides a separate policy-review and quote contract for exact official addresses with qualified local coverage. A published v1 rule does not establish that a v2 policy or automatic quote is available.