Tax calculation and integrations

Solvimon calculates VAT and sales tax on every invoice, either with its own tax category rules or by delegating the calculation (and filing) to a connected tax engine: Avalara AvaTax, Anrok, or Sphere.


Why this matters

Charging the wrong VAT or sales tax rate is a compliance problem, not a cosmetic one. Whether you rely on Solvimon’s built-in tax categories or connect a dedicated tax engine depends on how many jurisdictions you operate in and how much of the rate lookup and filing you want to outsource.

ProviderStatusNotes
Avalara AvaTaxGenerally availableConfigurable via API and Desk. Supports forwarding finalised invoices for tax filing.
AnrokPrivate betaContact your Solvimon representative to enable it for your platform.
SpherePrivate betaContact your Solvimon representative to enable it for your platform.
Anrok and Sphere are in private beta: reach out to your Solvimon contact to get access before configuring either.

How Solvimon and a tax provider divide the work

Once a tax calculation integration is connected, Solvimon is the system of record for the invoice; the provider is the source of truth for tax law, rates, and filing. Solvimon doesn’t determine what you owe on a connected billing entity: it sends invoice data to the provider for every calculation and reflects the result back on the invoice.

Solvimon is responsible for:

AreaDetails
Providing calculation inputsInvoice line items, amounts, and currency; the customer’s address, tax ID, and exemption status; and the tax category configured on each product, product item, or product category.
Presenting tax on the invoiceApplying the tax amounts returned by the provider to the correct lines and totals, and displaying the tax breakdown and the billing entity’s tax ID on the invoice.
Forwarding for filingSending finalised invoices to the provider for filing, when enable_tax_filing is on for that integration.

Your tax provider is responsible for:

AreaDetails
Tax calculationDetermining nexus and jurisdiction obligations, and applying the correct rate per line based on the tax category or code Solvimon sends.
Exemptions and reverse chargeApplying exemption or reverse-charge treatment based on the customer’s tax ID and exemption status.
Filing and remittanceRecording and reporting transactions for per-jurisdiction filing, and maintaining the audit trail tax authorities require.

You are responsible for:

AreaDetails
ConfigurationMapping Solvimon’s tax categories to your provider’s tax codes, and using custom_tax_codes for line types (commitments, fallback products) that don’t map automatically.
Customer data hygieneKeeping customer addresses, tax IDs, and exemption status current, since Solvimon sends whatever is currently on the customer at calculation time.

If no tax calculation integration is connected for a billing entity, Solvimon calculates tax itself with its native rate tables (for example, standard and reduced EU VAT rates per country) against the tax category and both parties’ countries.

What Solvimon sends and receives

Every tax provider expects a different payload shape, but the data Solvimon sends follows the same general pattern:

  • Customer identity and address – the customer’s registered_address (organization) or residential_address (individual), used to determine jurisdiction.
  • Line items – one entry per invoice line, with its amount and the tax category (STANDARD, NO_TAX, or EXEMPT) configured on the product, product item, or product category.
  • Currency – the invoice’s billing currency, used for rate lookups.
  • Tax ID and exemption context – the customer’s tax ID(s) and tax_exempt status, so the provider can apply reverse charge or exemption logic.
  • Billing entity context – the company_code linking the billing entity to your account on the provider’s side.

What comes back is applied straight onto the invoice: a tax amount per line, an invoice-level total, and (where the provider returns it) rate and jurisdiction detail. Solvimon surfaces this as a tax category summary per invoice: base amount, tax amount, percentage, the applicable rates, and any notes (for example, a reverse-charge note). See the invoice header report for the exact fields.

Configuring customers for tax calculation

Address. A customer needs a registered_address (organization) or residential_address (individual) with a country code for Solvimon, or a connected provider, to determine the applicable jurisdiction. Set it via PATCH /v1/customers/{id} or from the customer details page in Desk.

Tax-exempt customers. Mark a customer tax_exempt (with an optional note explaining why) directly on the customer resource; see tax exemption for how this is configured. When a tax calculation integration is connected, the exemption status is sent along with the calculation so the provider can apply the correct treatment; if you use a provider-side exemption certificate, use the same customer identifier in both systems so it matches up.

Customer tax IDs. A customer’s tax ID(s) are sent to the provider at calculation time, so it can determine reverse-charge eligibility for VAT-registered customers. See validating a customer’s VAT number below for checking a tax ID before you save it.

Merchant tax identifiers

A billing entity carries its own tax_id/tax_ids, registration_number, and registered_address, and can hold additional tax_registrations for jurisdictions where you’re registered separately from your main entity address. These are what appear in the invoice’s “sold from” details and on the PDF, and are the seller context passed to a connected provider.

Tax on credit notes and voids

  • Credit notes follow the normal invoice lifecycle and reach Final, so tax on a credit note is calculated the same way as on the invoice it credits: natively, or via whichever provider is connected to that billing entity.
  • Voids are different: voiding is only possible on Open or Draft invoices, never Final ones. A voided invoice never reaches finalisation, so it never gets forwarded to a connected provider for filing.

See credit notes for how crediting works.

Implementation

Via API

Connect an AvaTax integration to a billing entity:

POST
/v:version/integrations
1curl -X POST https://test.api.solvimon.com/v1/integrations \
2 -H "X-API-KEY: <apiKey>" \
3 -H "Content-Type: application/json" \
4 -d '{
5 "reference": "Stripe-account001",
6 "type": "PAYMENT_GATEWAY",
7 "name": "Stripe account 001",
8 "description": "Stripe connection for account 001",
9 "status": "ACTIVE",
10 "authentication": {
11 "api_key": {
12 "value": "sk_test_0123456789"
13 },
14 "client_credentials": {
15 "client_id": "f47ac10b58cc4372a5670e02b2c3d479",
16 "client_secret": "fkUN60GjzBXp9pcDZPxpBQ"
17 }
18 },
19 "payment_gateway": {
20 "variant": "STRIPE",
21 "stripe": {
22 "public_key": "pk_test_0§123456789",
23 "signing_secret": "whsec_0123456789"
24 }
25 },
26 "e_invoicing": {
27 "mandates": [
28 {
29 "name": "HU_B2B_REPORTING"
30 }
31 ],
32 "processor": "AVALARA"
33 }
34}'
Response
1{
2 "object_type": "string",
3 "id": "string",
4 "reference": "string",
5 "name": "string",
6 "description": "string",
7 "status": "DRAFT",
8 "message": "string",
9 "type": "PAYMENT_GATEWAY",
10 "authentication": {
11 "api_key": {
12 "header": "string",
13 "value": "string"
14 },
15 "client_credentials": {
16 "client_id": "string",
17 "client_secret": "string"
18 },
19 "username_password": {
20 "username": "string",
21 "password": "string"
22 }
23 },
24 "payment_gateway": {
25 "variant": "ADYEN",
26 "adyen": {
27 "company_account": "string",
28 "environment": "LIVE",
29 "live_prefix": "string",
30 "merchant_accounts": [
31 "string"
32 ],
33 "public_key": "string",
34 "signing_secret": "string",
35 "ownership": "PLATFORM",
36 "system_ownership_details": {
37 "account_holder_id": "string",
38 "balance_account_id": "string",
39 "legal_entity_id": "string",
40 "store_id": "string"
41 },
42 "balance_platform_details": {
43 "account": "string",
44 "authentication": {
45 "api_key": {
46 "header": "string",
47 "value": "string"
48 },
49 "client_credentials": {
50 "client_id": "string",
51 "client_secret": "string"
52 },
53 "username_password": {
54 "username": "string",
55 "password": "string"
56 }
57 }
58 },
59 "legal_entity_manager_details": {
60 "authentication": {
61 "api_key": {
62 "header": "string",
63 "value": "string"
64 },
65 "client_credentials": {
66 "client_id": "string",
67 "client_secret": "string"
68 },
69 "username_password": {
70 "username": "string",
71 "password": "string"
72 }
73 }
74 },
75 "enabled_payment_methods": [
76 "string"
77 ]
78 },
79 "stripe": {
80 "public_key": "string",
81 "signing_secret": "string"
82 }
83 },
84 "e_invoicing": {
85 "mandates": [
86 {
87 "name": "string",
88 "country": "string",
89 "mappings": [
90 {
91 "target": "string",
92 "source": "string",
93 "description": "string"
94 }
95 ],
96 "condition_groups": [
97 {
98 "conditions": [
99 {
100 "field": "string",
101 "comparator_type": "EQUALS",
102 "value": "string"
103 }
104 ]
105 }
106 ],
107 "include_pdf_in_einvoice": true,
108 "supported_file_formats": [
109 {
110 "type": "string",
111 "description": "string"
112 }
113 ]
114 }
115 ],
116 "processor": "AVALARA"
117 },
118 "data_export": {
119 "variant": "S3",
120 "s3": {
121 "bucket_name": "string",
122 "bucket_path": "string",
123 "bucket_region": "string",
124 "authentication_type": "ACCESS_KEY_AND_SECRET",
125 "role_arn": "string",
126 "external_id": "string"
127 },
128 "bigquery": {
129 "project_id": "string",
130 "dataset_id": "string",
131 "dataset_location": "string",
132 "gcs_bucket_name": "string",
133 "gcs_hmac_key_access_id": "string",
134 "gcs_hmac_key_secret": "string"
135 },
136 "gcs": {
137 "bucket_region": "string",
138 "bucket_name": "string",
139 "bucket_path": "string",
140 "flattening": true
141 },
142 "snowflake": {
143 "host": "string",
144 "role": "string",
145 "warehouse": "string",
146 "database": "string",
147 "schema": "string"
148 },
149 "transport_type": "string"
150 },
151 "tax_calculation": {
152 "billing_entity_id": "string",
153 "variant": "AVATAX",
154 "ava_tax": {
155 "company_code": "string"
156 },
157 "custom_tax_codes": [
158 {
159 "field": "INVOICE_COMMITMENT",
160 "value": "string"
161 }
162 ],
163 "enable_tax_filing": true
164 },
165 "linked_resources_configurations": [
166 {
167 "resource_type": "string",
168 "link_details": [
169 {
170 "base_url": "string",
171 "custom_field_reference": "string"
172 }
173 ]
174 }
175 ],
176 "email_provider": {
177 "variant": "SYSTEM",
178 "mailgun": {
179 "domain": "string",
180 "region": "US",
181 "plan": "string"
182 },
183 "delivery_window": {
184 "type": "DAY",
185 "value": 1
186 },
187 "use_localized_templates": true
188 }
189}
FieldDescription
typeSet to TAX_CALCULATION.
tax_calculation.variantAVATAX is the only variant currently exposed via the API; Anrok and Sphere are enabled by Solvimon during private beta onboarding.
tax_calculation.ava_tax.company_codeLinks the billing entity to the corresponding company in your AvaTax account.
tax_calculation.enable_tax_filingWhen true, finalised invoices are also sent to AvaTax for tax filing, not just rate calculation.
tax_calculation.custom_tax_codesOptional overrides that map specific line types (INVOICE_COMMITMENT, PRODUCT_FALLBACK) to a tax code, for cases the automatic product mapping doesn’t cover.

Once the integration is ACTIVE, invoices for that billing entity are calculated through AvaTax automatically; no per-invoice configuration is needed.

Validating a customer’s VAT number

Validate a tax ID before saving it on a customer, so invalid EU VAT numbers don’t slip through:

Validate an EU VAT number
$curl -X POST https://test.api.solvimon.com/v1/customers/validate-tax-id \
> -H "X-API-KEY: <apiKey>" \
> -H "Content-Type: application/json" \
> -d '{
> "object_type": "CUSTOMER",
> "type": "ORGANIZATION",
> "organization": {
> "legal_name": "SuperStore GmbH",
> "tax_ids": [
> { "id": "NL123456789B01", "type": "ORGANIZATION" }
> ],
> "registered_address": { "country": "NL" }
> }
> }'
Response
1{
2 "data": [
3 {
4 "id": "NL123456789B01",
5 "valid": "VALID",
6 "source": "VIES",
7 "validation_date": "2026-07-24T10:00:00Z"
8 }
9 ]
10}

For EU tax IDs, Solvimon checks validity against VIES, the EU’s VAT Information Exchange System. valid is VALID, NOT_VALID, or UNKNOWNUNKNOWN is returned when VIES is unreachable or the tax ID’s country doesn’t support automated lookup, so treat it as “couldn’t confirm” rather than “invalid”.

To check which tax ID types are accepted for a given country before submitting one, use GET /v1/tax-id-types:

Get allowed tax id types for Canada. Omit the country parameter to get all countries.
$curl -G https://test.api.solvimon.com/v1/tax-id-types \
> -H "X-API-KEY: <apiKey>" \
> --data-urlencode "country=CA"

Via Desk

Configure a tax calculation integration from Settings → Integrations → Add integration, selecting the tax provider and entering its credentials. Tax categories, customer exemptions, and US sales tax percentages are configured as described in the Tax overview.

Edge cases

  • Connecting an external tax engine to a billing entity doesn’t remove the need to set tax categories: providers like AvaTax still expect a product tax code, so map your product categories to the provider’s codes (or use custom_tax_codes for line types with no direct product mapping).
  • Reverse-charge and exemption treatment is applied by the provider, based on the tax ID and exemption status Solvimon sends; Solvimon itself doesn’t decide reverse-charge eligibility once a provider is connected.
  • If a tax ID fails VIES validation, the invoice still generates. Validation is a check you run before saving a tax ID; it doesn’t block invoicing on its own.
  • Voided invoices never reach Final, so they’re never forwarded to a connected provider for filing; credited invoices do reach Final again and are filed the same way as any other finalised invoice.