Taxes
A tax rule decides the rate applied to an invoice line. Kontier picks the rule at billing time from three things: where the customer is, what kind of customer they are, and what is being sold.
Rules are versioned and dated, because a VAT rate that changed on 1 January must not retroactively change last year's invoices.
What a rule matches on
Four fields are required: jurisdiction_country, tax_type, rate and
valid_from. Everything else narrows when the rule applies.
| Field | Narrows by |
|---|---|
jurisdiction_country | Country. Required |
jurisdiction_region | State or province, where country is not enough |
applies_to_customer_types | BUSINESS, CONSUMER, UNKNOWN |
applies_to_supply_types | DOMESTIC, INTRA_EU_B2B, INTRA_EU_B2C, EXPORT |
applies_to_product_categories | The product's tax category |
rate is a decimal string, so "19" or "0.19" depending on your
convention, never a float.
Supply type
Supply type is derived from where you are, where the customer is, and whether they are a business. It is what makes cross-border VAT work.
| Supply type | Situation |
|---|---|
DOMESTIC | Same country. Normal local rate |
INTRA_EU_B2B | EU business in another member state. Reverse charge: you charge 0% and they account for it |
INTRA_EU_B2C | EU consumer in another member state. Charged at their country's rate |
EXPORT | Outside the EU. Usually zero-rated |
This is why customer type matters so much. A business with a
validated VAT number in another EU state is INTRA_EU_B2B and pays no VAT to
you. The same company recorded as CONSUMER is charged full local VAT, and the
invoice is wrong.
Reverse charge depends on a validated VAT number
INTRA_EU_B2B requires the customer to actually be a business with a valid VAT
identification number. Validate it rather than trusting what was typed into a
signup form.
Stacking and order
Two fields handle jurisdictions that apply more than one tax.
apply_order sets the sequence. is_compound decides whether a rule is
calculated on the subtotal, or on the subtotal plus the taxes already applied
before it. Compound tax is how some Canadian provinces work, and getting the
order wrong produces a number that is close enough to look right.
inclusive says whether the price already contains the tax. An inclusive
CHF 100 at 19% is CHF 84.03 net plus CHF 15.97 tax, not CHF 119.
Versioning and coverage
Tax rules are versioned like plans: edits stage a new version, and
publishing puts it in force. valid_from is required precisely so a rate change
takes effect on the right day rather than the day somebody remembered.
requires_continuous_coverage refuses to publish a version that leaves a gap in
the timeline, which is worth enabling: a gap means an invoice lands on a date
with no applicable rule.
Dashboard and API names
| In the dashboard | In the API |
|---|---|
| Organization → Billing & Money → Taxes | /v1/tax-rules |
| Rate | rate, a decimal string |
| Country / Region | jurisdiction_country / jurisdiction_region |
| Applies to | the three applies_to_* arrays |
| Tax category on a product | matched by applies_to_product_categories |
| the org's own tax identity | /v1/organization/tax-profile |
Where taxes go next
- Every invoice line carries its rate and the decision behind it, pinned at finalisation so it never drifts.
- Verifications validate a VAT number, which is what unlocks reverse charge.
- Credit notes reverse tax at the rate the original line used, not today's rate.
Reference
| Topic | When you need it |
|---|---|
| Customers | Type and address, the inputs to supply type |
| Invoices | Where the chosen rate is recorded |
| Exchange rates | The other thing pinned at finalisation |
| Tax rules API | Every field, plus versions and timeline |