Home / Use cases / Next.js

Next.js

Next.js server action for VAT validation

Use Next.js 14 Server Actions to validate EU VAT numbers server-side in a React form. No API route needed — validation runs securely on the server with full TypeScript types.

Next.js 14 Server Actions allow you to call server-side code directly from a React component without writing a separate API route. For VAT validation, this means the TaxID API key never leaves the server, the fetch call runs in the Node.js runtime where you have access to environment variables, and the result is streamed back to the client as a serialised server response. The form component uses useTransition to track the pending state and provide optimistic UI feedback while the validation runs.

The Server Action calls GET /api/v1/validate/:country/:vat with the Authorization header populated from process.env.TAXID_API_KEY, parses the JSON response into a typed VATResult object, and returns it to the client. The 'use server' directive marks the function as a Server Action, and calling it from the client triggers a POST to Next.js's internal actions endpoint — the network request is handled by the framework, not by your code.

Using useTransition alongside the Server Action provides two benefits: isPending is true while the action is running, which drives the loading spinner, and the transition does not block the React render pipeline, so the rest of the page remains interactive. Combine this with React's useOptimistic hook if you want to speculatively show a 'validating' state before the server confirms, giving instant visual feedback to users on high-latency connections.

Implementation steps

  1. 1

    Create Server Action for VAT validation

    Define an async function in a file with 'use server' at the top (or inline with the directive). The function signature should be: async function validateVAT(country: string, vat: string): Promise<VATResult>. Inside, call fetch(`https://api.taxid.pro/v1/validate/${country}/${vat}`, { headers: { Authorization: `Bearer ${process.env.TAXID_API_KEY}` }, next: { revalidate: 3600 } }) and return the typed response. The next.revalidate option enables Next.js data cache for repeated lookups.

  2. 2

    Add optimistic UI with useTransition

    In your client component, call const [isPending, startTransition] = useTransition() and wrap the Server Action call in startTransition(() => { validateVAT(country, vat).then(setResult) }). Set isPending to true immediately while the transition is in flight, which triggers your loading indicator without blocking the rest of the page. This pattern is idiomatic Next.js 14 and avoids the complexity of manual loading state management.

  3. 3

    Display company name confirmation

    When the Server Action resolves with status: 'active', update component state with the result and render the company_name from the VATResult in a highlighted confirmation block. For status: 'invalid', show an inline validation error adjacent to the VAT input field. For status: 'service_unavailable', display a non-blocking warning ('VAT verification is temporarily unavailable — your number will be validated shortly') and allow the form to proceed so users are not blocked by a VIES outage.

  4. 4

    Handle pending and error states

    Use isPending from useTransition to show a spinner on the submit button and disable the VAT input during validation, preventing double-submissions. Wrap the startTransition call in a try/catch to handle network errors and surface them as a user-facing error state rather than a silent failure. For the error state, distinguish between a TaxID API error (HTTP 4xx/5xx) and a VIES service_unavailable response (HTTP 200 with status: 'service_unavailable') — they require different UX responses.

Code example

Node.js

const res = await fetch(
  'http://localhost:3000/api/v1/validate/DE/DE123456789',
  { headers: { 'Authorization': 'Bearer YOUR_API_KEY' } }
);
const { valid, status, company_name, company_address } = await res.json();

if (valid) {
  console.log(`Valid EU business: ${company_name}`);
} else if (status === 'service_unavailable') {
  // VIES is temporarily down — retry or allow with manual check
  console.log('VIES unavailable — check back in a few minutes');
} else {
  console.log('Invalid VAT number — charge local tax rate');
}

Python

import requests

res = requests.get(
    "http://localhost:3000/api/v1/validate/DE/DE123456789",
    headers={"Authorization": "Bearer YOUR_API_KEY"}
)
data = res.json()

if data["valid"]:
    print(f"Valid: {data['company_name']}")
elif data["status"] == "service_unavailable":
    print("VIES temporarily unavailable")
else:
    print("Invalid VAT number")

API response

The TaxID API returns a consistent JSON response for every validation request:

200 OK (active)valid
{
  "valid": true,
  "status": "active",
  "country_code": "DE",
  "vat_number": "123456789",
  "company_name": "Example GmbH",
  "company_address": "Musterstraße 1, 10115 Berlin",
  "request_date": "2026-05-10T00:00:00.000Z",
  "cached": false,
  "request_id": "req_01j..."
}

Error handling

The API uses a consistent Stripe-style error format. Always handle service_unavailable separately — VIES has occasional downtime and you should not reject valid customers during outages.

active

VAT number is valid and the business is registered

invalid

VAT number format is wrong or not registered in VIES

service_unavailable

VIES or the national system is temporarily down — retry later

Further reading

Evaluating EU VAT APIs? Compare TaxID with:

Ready to implement?

Get your free API key and start validating EU VAT numbers today.

Get free API key

Related use cases

Stripe EU VAT: Validate Tax IDs Before Charging Customers

Stripe EU VAT integration guide: validate EU VAT numbers server-side before applying zero-rate B2B e...

UK VAT validation in Shopify B2B

Validate UK VAT numbers for B2B customers in Shopify. Required under UK Making Tax Digital rules for...

WooCommerce Spain NIF/CIF validation

Validate Spanish NIF and CIF numbers in WooCommerce checkout. Automatically apply B2B tax exemptions...