How to Automate VAT Number Checks for Recurring Payments

Business customers enjoy special tax treatment because they are not charged a VAT in the EU. This tutorial attempts to automate VAT number re-validations for your subscription business.

Matthias Hagemann
4 min readOct 30, 2019

If you run an online subscription business, you’ll ultimately end up signing up customers from the European Union.

Tax Treatment for Business Customers

A business customer does not need to pay VAT. In order to verify that your customer is in fact a business customer, you have to ask for their VAT identification number and validate it in real-time.

If you use Stripe to handle subscription charges (there’s no reason why you shouldn’t), then you can simply add your business customer’s VAT number to the customer account. Stripe will initially validate EU VAT numbers for you, but only once.

Upon validation, the reverse-charge mechanism applies. Reverse-charge is a legal term and means that the obligation to report VAT on a transaction has been reversed from the supplier to the customer. The customer is now made responsible to report and pay VAT, but since a business does not need to pay VAT, it’s a zero-sum in B2B.

Here’s the catch for recurring payments such as subscriptions: How do you know that the VAT number of your customer is still valid? You have to regularly re-validate it before every charge.

If you never re-validate a VAT number after the initial sign up and your customer’s VAT number expires (yes, it does happen), you suddenly face an unfortunate situation whereby you owe a VAT amount which you’ve never collected from your customer.

Webhook Events Trigger Re-Validation

Stripe emits webhook events whenever an invoice becomes due for charge. You can listen to the invoice.upcoming event and look up your customer by the customer ID included in the event’s payload. This type of event is emitted when an invoice is due in 7 and 3 days, respectively. I bet other payment aggregators offer similar webhook events.

If you store your customer’s VAT number in Stripe’s records, you can pass the tax ID stored in the customer_tax_ids field to perform a re-validation with a dedicated service. I like to use Vatstack because it stores all validation records securely in the cloud and I have full traceability of my customer’s tax treatment status.

What I do on my backend is to query whether Vatstack has an entry for the same VAT number within the past 28 days (this accounts for shorter months such as February). The invoice.upcoming event is ideal to trigger re-validation. It’s sent twice, 7 and 3 days before a charge by default and I want to re-validate only on one occurrence.

const axios = require('axios')
const moment = require('moment')
// Exportable router module for Express.js
module.exports.stripe = async (req, res, next) => {
// Extract event object from Stripe’s payload.
if (event.type === 'invoice.upcoming') {
// Iterate through stored tax IDs for the Stripe customer.
await Promise.all(event.object.customer_tax_ids.map(taxId => {
var threshold = moment().subtract('28', 'days').format('YYYY-MM-DD')
var { data } = await axios.get('https://api.vatstack.com/v1/validations', {
params: {
key: process.env.VATSTACK_API_KEY,
query: taxId.value,
requested_since: threshold,
}
})
... }))
}
}

The above code uses the axios and moment NPM libraries to check whether Vatstack has any historical records for the VAT number I’m querying. The API key is given to you upon registration and you store it in your environment variables.

If there’s a result from the past 28 days, I obviously want to skip the re-validation process as it’s either the 2nd invoice.upcoming event or could be a recent signup.

Otherwise, I need to proceed:

...// Using "data" variable from the above code.if (data.validations_count === 0) {
var result = await axios.post('https://api.vatstack.com/v1/validations', {
vat_id: taxId
}, {
headers: { Authorization: `Credential ${ process.env.VATSTACK_API_KEY }` }
})
// Further processing if result.data.valid === false.
}
...

This creates a validation request with Vatstack and, in most cases, it will respond with an official result immediately. The response contains a valid boolean which I can use to process further.

Automate Change of Tax Treatment

You can automate the change of tax treatment until there is no human intervention involved on your side. Several approaches come to my mind:

  • You can send your customer an automated email with the message that their VAT number is no longer valid and, as a result, you’re going to cancel the reverse-charge mechanism unless they enter a new VAT number (which will have to be validated of course).
  • A failure to add a new VAT number would result in you collecting a VAT at their local rate in the upcoming invoices. Geolocated price quotes can also be done with Vatstack and the obtained tax rate updated in Stripe.
  • Remove the outdated VAT number from Stripe’s customer field customer_tax_ids.

--

--

No responses yet