API allows customers, especially those with technical capabilities, to:
Insert expenses directly into VAT4U in real time, bypassing manual imports and streamlining your workflows.
Manage companies (for Expert-level customers).
Retrieve company, claim, and expense data for use in reporting tools or CRM systems.
This guide explains how to manage API users so your development team can securely access and interact with the API.
Core API Features
Expenses
Add expenses
List and retrieve expenses
Delete expenses
Specify which actions should be started by VAT4U after receiving the expense (asynchronous processing):
Compliance check
Data verification
Smart AI
Entities
Create entities
List entities
Update entity information (including VAT numbers and local registrations)
Data Requirements
For accurate processing:
Submit expenses under the correct entity. Each expense is assessed in context of the expense owner entity. Example: VAT4U Comply module is checking compliance of the expense in accordance to data that is stored in the Claimant company profile.
Ensure each entity profile contains valid VAT details. VAT4U Calculate module takes into account company business activity as well VAT Registrations in the Claimant company profile, etc.
Use VAT4U provided categories or predefined category mapping for accurate VAT4U Calculate results.
Rate Limits & Processing
Rate Limits
60 API calls per minute
Roughly 1 call per second, or 60 calls simultaneously within one minute.
Peak Processing Capacity
OCR and Compliance: ~300 expenses/minute (≈1.5 pages per expense)
Smart AI: ~60 expenses/minute
Processing Time Estimates Per Tennant
Example 1: Batch of 60 expenses at once:
Low demand: OCR/Compliance/Verification ~1 min, Smart AI ~1.5 min
High demand: OCR/Compliance/Verification ~4 min, Smart AI ~10 min
Example 2: Single expense (1 every 2 seconds):
Low demand: ~17 sec
High demand: ~1.5 min
Status Tracking
You can track the status of each expense processing in two ways:
By pooling expense information by Expense ID returned from Create expense endpoint.
Using webhooks mechanism
Testing
A test entity can be provided for trials.
API Authentication
API authentication is based on the API username and password, exchanged for the short lived Access Token.
Once users are set up, your dev team can refer to our Postman API documentation for details on implementation.
Where to Find It
Go to Company Settings.
Navigate to the API Users tab:
This tab allows you to manage users who need credentials to access the API.
API Users Table Overview
The table lists all API users associated with your company. You’ll see:
API Identifier – Used internally to distinguish users (not used for API authentication).
API Username – The login credential for API access.
Permissions – Choose between:
Read-only: View and list data.
Read & Write: View, create, and modify data.
Creating an API User
Click Add API User.
Enter an API Identifier (e.g.,
api_user_john) - if you create a company, or expense, or modify an object using this API user, API identifier will be displayed in the overview under User name, similar to the user name of a person when they create or modify expense.Select permissions (Read-only or Read & Write).
Click Add.
After creating the user:
A username and password are generated.
⚠️ Important: The password is displayed only once. Be sure to copy it immediately.
Resetting Password
If the password is lost or you want to reset it for security reasons:
Click Reset Password in the user row.
Confirm the warning: the old password becomes invalid.
A new password is generated and shown, copy it right away.
Deactivating and Reactivating Users
You can deactivate and reactivate users at any time:
A deactivated user cannot log in to the API.
Reactivation immediately restores access.
Managing API Users Linked to a Different Company
Each API user is linked to the company where it was initially set up, so all management tasks, such as updating keys or permissions, must be done from that company’s settings:
Service Provider Access (Expert accounts)
If you create an API user under the Service provider (Expert) company, it will have access to any client company under the service provider company account.
💡 Once your API users are set up, pass the credentials and documentation to your development team so they can start building integrations with VAT4U.
If you need more information, refer to the API Documentation.
VAT4U Webhooks
Set up a webhook
Webhooks provide a powerful mechanism allowing you to get notified when object in VAT4U application has been create/updated or deleted.
Webhooks are especially handy to receive notifications about Asynchronous expense processing events, such as VAT4U Comply and VAT4U Enrich modules.
Setting up webhooks is described in a detailed way here: https://intercom-help.eu/vat4u-eu/en/articles/439615-understanding-webhooks-in-vat4u
Tips for efficient use of Webhooks:
Use a highly-available endpoint with HTTPS and a valid certificate.
Return 2xx quickly; offload heavy work to your own queue if needed.
What VAT4U sends
Method: POST
Body: JSON (UTF-8)
Timeouts: connect 1s, overall 10s
Success: any 2xx status code
Retries: automatic (see section below)
Sample request
Headers
Content-Type: application/json
X-Webhook-Event: expense.created
X-Webhook-Id: 12345
X-Webhook-Tenant: 67890
X-Webhook-Timestamp: 1736616552
X-Webhook-Signature: v1=9e4b3...
Idempotency-Key: 12345:1
Body
{ "spec_version": "1.0", "event_type": "expense.created", "occurred_at": "2025-09-09T12:34:56Z", "tenant_id": "67890", "resource": { "type": "expense", "id": "987654" }, "data": { "id": 987654 } }event_type: example values include expense.created, expense.updated, webhook.test
data: minimal including the object ID, fetch full details via VAT4U API if needed
Idempotency-Key: stable per delivery; use it to avoid double-processing
Verify the signature
VAT4U signs each request with HMAC SHA256: HMAC(secret, timestamp + "." + rawBody).
Header: X-Webhook-Signature: v1=
Header: X-Webhook-Timestamp (Unix seconds)
Verify using your saved secret; use constant-time comparison
Node.js example
const crypto = require('crypto')
function verifySignature(secret, rawBody, timestamp, signatureHeader) { const expected = 'v1=' + crypto .createHmac('sha256', secret) .update(`${timestamp}.${rawBody}`).digest('hex')
const safeEq = (a, b) => a.length === b.length && crypto.timingSafeEqual(Buffer.from(a), Buffer.from(b))
const recent = Math.abs(Date.now() / 1000 - Number(timestamp)) < 300
return recent && safeEq(signatureHeader, expected) }Common pitfalls:
Use the exact raw body bytes received in the HTTP request (not re-serialized JSON).
Keep and use the latest rotated secret.
Retries and delivery status
VAT4U retries on any non-2xx response or network error.
Backoff: 30s × 2^(attempts−1), capped at 30 minutes.
Maximum attempts: 8. After that, the delivery is marked failed.
Check the company API -> Webhook “Events” list to track attempts and statuses (delivered, retry, failed).
Use Idempotency-Key to safely handle duplicates.
Best practices for reliability:
Return 2xx as soon as you enqueue the work internally.
Log the Idempotency-Key and ignore duplicates.
Testing
Use the “Send test event” action to send a webhook.test event to your endpoint.
Validate:
Your endpoint receives and logs the request
Signature verification succeeds
You return 2xx and the delivery appears as delivered in the Webhooks UI
Security recommendations
Treat the webhook secret like a password (store securely, rotate periodically).
Verify signature and timestamp on every request.
Only accept HTTPS with a valid certificate.
Rate-limit and log requests; respond with 2xx quickly; avoid returning verbose errors.
VAT4U only checks response code from your webhooks, and does not parse or store response bodies.
Troubleshooting
Not receiving events
Check “Events” modal for status and last attempt error
Verify your endpoint is publicly reachable and TLS is valid
Ensure you respond within 10 seconds
Signature mismatch
Confirm you’re using the most recent secret
Use the raw request body for HMAC
Check for clock drift >5 minutes
Duplicates processed
Enforce idempotency using the Idempotency-Key header
FAQ
Can I have multiple webhooks?
Yes, you can add multiple endpoints per company. All active webhooks receive events.
Can I filter by event type?
Currently, all event types are sent. You can filter or route on your side using event_type.
Can I pause a webhook?
Yes. Use the Actions menu to pause or resume deliveries.
How do I rotate the secret?
Use “Rotate secret” in the Actions menu. Store the new secret and update your receiver.
What about payload sizes?
Payloads are intentionally minimal; use the referenced resource ID to fetch details when needed.




