ChartQuery

Valider les numéros de TVA européens

Vérifiez les numéros de TVA européens au moment du paiement pour permettre les exonérations fiscales B2B et prévenir la fraude avec l'API de validation TVA Veille.

Vue d'ensemble

Les entreprises de l'UE sont exonérées de TVA lors d'achats auprès d'autres entreprises de l'UE — mais uniquement avec un numéro de TVA valide. Ce guide montre comment valider un numéro de TVA au moment du paiement et récupérer les informations associées à l'entreprise (nom et adresse) depuis la base VIES.

Prérequis

  • Une clé API Veille — obtenez-en une sur app.veille.io
  • Installez les dépendances pour votre langage :
pip install requests

Aucune dépendance supplémentaire — utilise l'API native fetch (Node 18+).

Extension curl activée (par défaut).

Aucune dépendance supplémentaire — utilise net/http (Go 1.18+).

Aucune dépendance supplémentaire — utilise java.net.http (Java 11+).

Aucune dépendance supplémentaire — utilise System.Net.Http (.NET 6+).

# Cargo.toml
[dependencies]
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde_json = "1"

Étapes

Valider un numéro de TVA

Appelez GET /v1/vat avec le paramètre vat. Le numéro doit inclure le préfixe pays (p. ex. FR12345678901).

import requests

API_KEY  = "YOUR_API_KEY"
response = requests.get(
    "https://api.veille.io/v1/vat",
    headers={"x-api-key": API_KEY},
    params={"vat": "FR12345678901"},
)
result = response.json()
print(result)
const API_KEY = "YOUR_API_KEY";

const params   = new URLSearchParams({ vat: "FR12345678901" });
const response = await fetch(`https://api.veille.io/v1/vat?${params}`, {
  headers: { "x-api-key": API_KEY },
});
const result = await response.json();
console.log(result);
<?php
$apiKey = "YOUR_API_KEY";
$params = http_build_query(["vat" => "FR12345678901"]);

$ch = curl_init("https://api.veille.io/v1/vat?{$params}");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-api-key: {$apiKey}"]);
$result = json_decode(curl_exec($ch), true);
curl_close($ch);
print_r($result);
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

func main() {
    req, _ := http.NewRequest("GET", "https://api.veille.io/v1/vat?vat=FR12345678901", nil)
    req.Header.Set("x-api-key", "YOUR_API_KEY")

    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)

    var result map[string]any
    json.Unmarshal(body, &result)
    fmt.Println(result)
}
import java.net.URI;
import java.net.http.*;

var client  = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder()
    .uri(URI.create("https://api.veille.io/v1/vat?vat=FR12345678901"))
    .header("x-api-key", "YOUR_API_KEY")
    .GET().build();

var response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
using System.Net.Http;

using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", "YOUR_API_KEY");

var body = await client.GetStringAsync("https://api.veille.io/v1/vat?vat=FR12345678901");
Console.WriteLine(body);
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let result = reqwest::Client::new()
        .get("https://api.veille.io/v1/vat")
        .header("x-api-key", "YOUR_API_KEY")
        .query(&[("vat", "FR12345678901")])
        .send().await?.json::<serde_json::Value>().await?;

    println!("{:#?}", result);
    Ok(())
}

Lire les informations de l'entreprise

Un numéro valide retourne is_valid: true, le company_name, company_address et country_code.

if result.get("is_valid"):
    print(f"✅ Numéro de TVA valide")
    print(f"   Entreprise : {result.get('company_name')}")
    print(f"   Adresse    : {result.get('company_address')}")
    print(f"   Pays       : {result.get('country_code')}")
else:
    print(f"❌ Numéro de TVA invalide : {result.get('error', 'Introuvable dans VIES')}")
if (result.is_valid) {
  console.log("✅ Numéro de TVA valide");
  console.log(`   Entreprise : ${result.company_name}`);
  console.log(`   Adresse    : ${result.company_address}`);
  console.log(`   Pays       : ${result.country_code}`);
} else {
  console.log(`❌ Numéro de TVA invalide : ${result.error ?? "Introuvable dans VIES"}`);
}
if ($result["is_valid"] ?? false) {
    echo "✅ Numéro de TVA valide\n";
    echo "   Entreprise : {$result['company_name']}\n";
    echo "   Adresse    : {$result['company_address']}\n";
    echo "   Pays       : {$result['country_code']}\n";
} else {
    echo "❌ Numéro de TVA invalide : " . ($result["error"] ?? "Introuvable dans VIES") . "\n";
}
if result["is_valid"].(bool) {
    fmt.Printf("✅ Numéro de TVA valide\n   Entreprise : %v\n   Adresse    : %v\n   Pays       : %v\n",
        result["company_name"], result["company_address"], result["country_code"])
} else {
    errMsg := "Introuvable dans VIES"
    if e, ok := result["error"].(string); ok { errMsg = e }
    fmt.Println("❌ Numéro de TVA invalide :", errMsg)
}
import org.json.*;

var r = new JSONObject(response.body());
if (r.getBoolean("is_valid")) {
    System.out.printf("✅ Numéro de TVA valide%n   Entreprise : %s%n   Adresse    : %s%n   Pays       : %s%n",
        r.getString("company_name"), r.getString("company_address"), r.getString("country_code"));
} else {
    System.out.println("❌ Numéro de TVA invalide : " + r.optString("error", "Introuvable dans VIES"));
}
using System.Text.Json;

var r = JsonDocument.Parse(body).RootElement;
if (r.GetProperty("is_valid").GetBoolean())
{
    Console.WriteLine("✅ Numéro de TVA valide");
    Console.WriteLine($"   Entreprise : {r.GetProperty("company_name")}");
    Console.WriteLine($"   Adresse    : {r.GetProperty("company_address")}");
    Console.WriteLine($"   Pays       : {r.GetProperty("country_code")}");
}
else
{
    var error = r.TryGetProperty("error", out var e) ? e.GetString() : "Introuvable dans VIES";
    Console.WriteLine($"❌ Numéro de TVA invalide : {error}");
}
if result["is_valid"].as_bool().unwrap_or(false) {
    println!("✅ Numéro de TVA valide");
    println!("   Entreprise : {}", result["company_name"].as_str().unwrap_or(""));
    println!("   Adresse    : {}", result["company_address"].as_str().unwrap_or(""));
    println!("   Pays       : {}", result["country_code"].as_str().unwrap_or(""));
} else {
    let err = result["error"].as_str().unwrap_or("Introuvable dans VIES");
    println!("❌ Numéro de TVA invalide : {}", err);
}

Construire un gestionnaire de paiement TVA B2B

Supprimez la TVA du total de la commande lorsqu'un numéro de TVA UE vérifié est fourni.

import requests

API_KEY    = "YOUR_API_KEY"
VAT_RATE   = 0.20  # TVA 20%

def lookup_vat(number: str) -> dict:
    r = requests.get("https://api.veille.io/v1/vat",
        headers={"x-api-key": API_KEY}, params={"vat": number})
    return r.json()

def calculate_checkout(subtotal: float, vat_number: str | None = None) -> dict:
    vat_amount = subtotal * VAT_RATE
    vat_info   = None

    if vat_number:
        result = lookup_vat(vat_number)
        if result.get("is_valid"):
            vat_amount = 0  # Autoliquidation B2B — pas de TVA facturée
            vat_info   = {"company": result["company_name"], "country": result["country_code"]}
        else:
            return {"error": "Le numéro de TVA fourni n'est pas valide."}

    total = subtotal + vat_amount
    return {"subtotal": subtotal, "vat": vat_amount, "total": total, "company": vat_info}

print(calculate_checkout(100.00))
print(calculate_checkout(100.00, vat_number="FR12345678901"))
print(calculate_checkout(100.00, vat_number="INVALID123"))
const API_KEY  = "YOUR_API_KEY";
const VAT_RATE = 0.20;

async function lookupVat(number: string) {
  const params = new URLSearchParams({ vat: number });
  const res    = await fetch(`https://api.veille.io/v1/vat?${params}`, {
    headers: { "x-api-key": API_KEY },
  });
  return res.json();
}

async function calculateCheckout(subtotal: number, vatNumber?: string) {
  let vatAmount = subtotal * VAT_RATE;
  let companyInfo: any = null;

  if (vatNumber) {
    const result = await lookupVat(vatNumber);
    if (result.is_valid) {
      vatAmount   = 0;
      companyInfo = { company: result.company_name, country: result.country_code };
    } else {
      return { error: "Le numéro de TVA fourni n'est pas valide." };
    }
  }

  return { subtotal, vat: vatAmount, total: subtotal + vatAmount, company: companyInfo };
}

console.log(await calculateCheckout(100));
console.log(await calculateCheckout(100, "FR12345678901"));
console.log(await calculateCheckout(100, "INVALID123"));
<?php
const VAT_RATE = 0.20;

function lookupVat(string $apiKey, string $number): array {
    $params = http_build_query(["vat" => $number]);
    $ch = curl_init("https://api.veille.io/v1/vat?{$params}");
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, ["x-api-key: {$apiKey}"]);
    $result = json_decode(curl_exec($ch), true);
    curl_close($ch);
    return $result;
}

function calculateCheckout(string $apiKey, float $subtotal, ?string $vatNumber = null): array {
    $vatAmount = $subtotal * VAT_RATE;
    $company   = null;

    if ($vatNumber) {
        $result = lookupVat($apiKey, $vatNumber);
        if ($result["is_valid"] ?? false) {
            $vatAmount = 0;
            $company   = ["company" => $result["company_name"], "country" => $result["country_code"]];
        } else {
            return ["error" => "Numéro de TVA invalide."];
        }
    }
    return ["subtotal" => $subtotal, "vat" => $vatAmount, "total" => $subtotal + $vatAmount, "company" => $company];
}

print_r(calculateCheckout("YOUR_API_KEY", 100.0));
print_r(calculateCheckout("YOUR_API_KEY", 100.0, "FR12345678901"));
package main

import (
    "encoding/json"
    "fmt"
    "io"
    "net/http"
)

const APIKey  = "YOUR_API_KEY"
const VATRate = 0.20

func lookupVAT(number string) map[string]any {
    req, _ := http.NewRequest("GET", "https://api.veille.io/v1/vat?vat="+number, nil)
    req.Header.Set("x-api-key", APIKey)
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    body, _ := io.ReadAll(resp.Body)
    var r map[string]any
    json.Unmarshal(body, &r)
    return r
}

func calculateCheckout(subtotal float64, vatNumber string) map[string]any {
    vatAmount := subtotal * VATRate
    var company map[string]any

    if vatNumber != "" {
        result := lookupVAT(vatNumber)
        if result["is_valid"].(bool) {
            vatAmount = 0
            company   = map[string]any{"company": result["company_name"], "country": result["country_code"]}
        } else {
            return map[string]any{"error": "Numéro de TVA invalide."}
        }
    }
    return map[string]any{"subtotal": subtotal, "vat": vatAmount, "total": subtotal + vatAmount, "company": company}
}

func main() {
    fmt.Println(calculateCheckout(100, ""))
    fmt.Println(calculateCheckout(100, "FR12345678901"))
    fmt.Println(calculateCheckout(100, "INVALID123"))
}
import java.net.URI;
import java.net.http.*;
import org.json.*;

public class Main {
    static HttpClient client  = HttpClient.newHttpClient();
    static String     API_KEY = "YOUR_API_KEY";
    static double     VAT_RATE = 0.20;

    static JSONObject lookupVat(String number) throws Exception {
        var req  = HttpRequest.newBuilder()
            .uri(URI.create("https://api.veille.io/v1/vat?vat=" + number))
            .header("x-api-key", API_KEY).GET().build();
        var resp = client.send(req, HttpResponse.BodyHandlers.ofString());
        return new JSONObject(resp.body());
    }

    static JSONObject calculateCheckout(double subtotal, String vatNumber) throws Exception {
        double vatAmount = subtotal * VAT_RATE;
        JSONObject company = null;

        if (vatNumber != null && !vatNumber.isEmpty()) {
            var result = lookupVat(vatNumber);
            if (result.getBoolean("is_valid")) {
                vatAmount = 0;
                company   = new JSONObject().put("company", result.getString("company_name"))
                    .put("country", result.getString("country_code"));
            } else {
                return new JSONObject().put("error", "Numéro de TVA invalide.");
            }
        }
        return new JSONObject().put("subtotal", subtotal).put("vat", vatAmount)
            .put("total", subtotal + vatAmount).put("company", company);
    }

    public static void main(String[] args) throws Exception {
        System.out.println(calculateCheckout(100, null));
        System.out.println(calculateCheckout(100, "FR12345678901"));
        System.out.println(calculateCheckout(100, "INVALID123"));
    }
}
using System.Net.Http;
using System.Text.Json;

const double VAT_RATE = 0.20;
var apiKey = "YOUR_API_KEY";
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);

async Task<JsonElement> LookupVat(string number)
{
    var body = await client.GetStringAsync($"https://api.veille.io/v1/vat?vat={number}");
    return JsonDocument.Parse(body).RootElement;
}

async Task<string> CalculateCheckout(double subtotal, string? vatNumber = null)
{
    double vatAmount  = subtotal * VAT_RATE;
    string? company   = null;

    if (vatNumber != null)
    {
        var result = await LookupVat(vatNumber);
        if (result.GetProperty("is_valid").GetBoolean())
        { vatAmount = 0; company = result.GetProperty("company_name").GetString(); }
        else return """{"error":"Numéro de TVA invalide."}""";
    }
    return $"""{{ "subtotal": {subtotal}, "vat": {vatAmount}, "total": {subtotal + vatAmount}, "company": "{company}" }}""";
}

Console.WriteLine(await CalculateCheckout(100));
Console.WriteLine(await CalculateCheckout(100, "FR12345678901"));
Console.WriteLine(await CalculateCheckout(100, "INVALID123"));
use reqwest::Client;
use serde_json::{json, Value};

const VAT_RATE: f64 = 0.20;
const API_KEY: &str = "YOUR_API_KEY";

async fn lookup_vat(client: &Client, number: &str) -> Value {
    client.get("https://api.veille.io/v1/vat")
        .header("x-api-key", API_KEY)
        .query(&[("vat", number)])
        .send().await.unwrap().json::<Value>().await.unwrap()
}

async fn calculate_checkout(client: &Client, subtotal: f64, vat_number: Option<&str>) -> Value {
    let mut vat_amount = subtotal * VAT_RATE;
    let mut company    = json!(null);

    if let Some(number) = vat_number {
        let result = lookup_vat(client, number).await;
        if result["is_valid"].as_bool().unwrap_or(false) {
            vat_amount = 0.0;
            company    = json!({"company": result["company_name"], "country": result["country_code"]});
        } else {
            return json!({ "error": "Numéro de TVA invalide." });
        }
    }
    json!({ "subtotal": subtotal, "vat": vat_amount, "total": subtotal + vat_amount, "company": company })
}

#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
    let client = Client::new();
    println!("{}", calculate_checkout(&client, 100.0, None).await);
    println!("{}", calculate_checkout(&client, 100.0, Some("FR12345678901")).await);
    println!("{}", calculate_checkout(&client, 100.0, Some("INVALID123")).await);
    Ok(())
}

Conservez toujours le nom et l'adresse de l'entreprise validée avec l'enregistrement de la commande. Les autorités fiscales de l'UE exigent la preuve que le mécanisme d'autoliquidation a été correctement appliqué.

Sur cette page