MwSt.-Nummer beim B2B-Checkout validieren
Überprüfen Sie europäische MwSt.-Nummern in Echtzeit beim Checkout, um B2B-Steuerbefreiungen korrekt anzuwenden und Betrug zu verhindern.
Übersicht
Dieses Playbook zeigt, wie Sie die MwSt.-Nummer eines Unternehmens beim Checkout validieren. Ein gültiges MwSt.-Ergebnis enthält den offiziellen Firmennamen und die Adresse, sodass Sie Benutzerformulare automatisch ausfüllen und die Rechnung korrekt ausstellen können.
Voraussetzungen
- Einen Veille-API-Schlüssel — erhalten Sie einen auf app.veille.io
- Installieren Sie die Abhängigkeiten für Ihre Sprache:
pip install requestsKeine zusätzlichen Abhängigkeiten — verwendet die native fetch-API (Node 18+).
curl-Erweiterung aktiviert (standardmäßig).
Keine zusätzlichen Abhängigkeiten — verwendet net/http (Go 1.18+).
Keine zusätzlichen Abhängigkeiten — verwendet java.net.http (Java 11+).
Keine zusätzlichen Abhängigkeiten — verwendet System.Net.Http (.NET 6+).
# Cargo.toml
[dependencies]
reqwest = { version = "0.12", features = ["json"] }
tokio = { version = "1", features = ["full"] }
serde_json = "1"Schritte
MwSt.-Nummer validieren
Rufen Sie GET /v1/vat mit dem Parameter vat_number auf. Das Format ist Ländercode + Nummer (z.B. 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_number": "FR12345678901"},
)
result = response.json()
print(result)const API_KEY = "YOUR_API_KEY";
const params = new URLSearchParams({ vat_number: "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_number" => "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"
"net/url"
)
func main() {
params := url.Values{"vat_number": {"FR12345678901"}}
req, _ := http.NewRequest("GET", "https://api.veille.io/v1/vat?"+params.Encode(), 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_number=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_number=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_number", "FR12345678901")])
.send().await?.json::<serde_json::Value>().await?;
println!("{:#?}", result);
Ok(())
}Firmendaten auslesen
Die Antwort enthält is_valid, company_name, address und country_code. Verwenden Sie diese Daten, um das Checkout-Formular automatisch auszufüllen.
if result.get("is_valid"):
print(f"✓ Gültige MwSt.-Nummer")
print(f" Unternehmen : {result.get('company_name')}")
print(f" Adresse : {result.get('address')}")
print(f" Land : {result.get('country_code')}")
else:
print("✗ Ungültige oder inaktive MwSt.-Nummer")if (result.is_valid) {
console.log("✓ Gültige MwSt.-Nummer");
console.log(` Unternehmen : ${result.company_name}`);
console.log(` Adresse : ${result.address}`);
console.log(` Land : ${result.country_code}`);
} else {
console.log("✗ Ungültige oder inaktive MwSt.-Nummer");
}if ($result["is_valid"] ?? false) {
echo "✓ Gültige MwSt.-Nummer\n";
echo " Unternehmen : {$result['company_name']}\n";
echo " Adresse : {$result['address']}\n";
echo " Land : {$result['country_code']}\n";
} else {
echo "✗ Ungültige oder inaktive MwSt.-Nummer\n";
}if isValid, ok := result["is_valid"].(bool); ok && isValid {
fmt.Printf("✓ Gültige MwSt.-Nummer\n Unternehmen : %v\n Adresse : %v\n Land : %v\n",
result["company_name"], result["address"], result["country_code"])
} else {
fmt.Println("✗ Ungültige oder inaktive MwSt.-Nummer")
}import org.json.*;
var r = new JSONObject(response.body());
if (r.getBoolean("is_valid")) {
System.out.printf("✓ Gültige MwSt.-Nummer%n Unternehmen : %s%n Adresse : %s%n Land : %s%n",
r.getString("company_name"), r.getString("address"), r.getString("country_code"));
} else {
System.out.println("✗ Ungültige oder inaktive MwSt.-Nummer");
}using System.Text.Json;
var r = JsonDocument.Parse(body).RootElement;
if (r.GetProperty("is_valid").GetBoolean()) {
Console.WriteLine("✓ Gültige MwSt.-Nummer");
Console.WriteLine($" Unternehmen : {r.GetProperty("company_name")}");
Console.WriteLine($" Adresse : {r.GetProperty("address")}");
Console.WriteLine($" Land : {r.GetProperty("country_code")}");
} else {
Console.WriteLine("✗ Ungültige oder inaktive MwSt.-Nummer");
}if result["is_valid"].as_bool().unwrap_or(false) {
println!("✓ Gültige MwSt.-Nummer");
println!(" Unternehmen : {}", result["company_name"].as_str().unwrap_or(""));
println!(" Adresse : {}", result["address"].as_str().unwrap_or(""));
println!(" Land : {}", result["country_code"].as_str().unwrap_or(""));
} else {
println!("✗ Ungültige oder inaktive MwSt.-Nummer");
}B2B-Checkout-Ablauf mit MwSt.-Steuerbefreiung
Prüfen Sie, ob eine MwSt.-Nummer gültig ist, und wenden Sie die entsprechende steuerliche Behandlung an (Reverse-Charge-Mechanismus innerhalb der EU).
import requests
API_KEY = "YOUR_API_KEY"
SELLER_COUNTRY = "FR"
PRODUCT_PRICE_EUR = 1000.00
VAT_RATE = 0.20
def validate_vat(vat_number: str) -> dict:
r = requests.get("https://api.veille.io/v1/vat",
headers={"x-api-key": API_KEY}, params={"vat_number": vat_number})
return r.json()
def calculate_checkout(vat_number: str | None) -> dict:
if not vat_number:
return {"price": PRODUCT_PRICE_EUR, "vat": PRODUCT_PRICE_EUR * VAT_RATE,
"total": PRODUCT_PRICE_EUR * (1 + VAT_RATE), "type": "B2C"}
v = validate_vat(vat_number)
if not v.get("is_valid"):
return {"error": "Ungültige MwSt.-Nummer. Bitte erneut prüfen."}
buyer_country = v.get("country_code")
# Innergemeinschaftlicher Reverse-Charge: MwSt.-befreit wenn Käufer ≠ Verkäufer-Land
if buyer_country and buyer_country != SELLER_COUNTRY:
return {"price": PRODUCT_PRICE_EUR, "vat": 0.0, "total": PRODUCT_PRICE_EUR,
"type": "B2B (innergemeinschaftlich, Reverse-Charge)",
"company": v.get("company_name"), "address": v.get("address")}
vat_amount = PRODUCT_PRICE_EUR * VAT_RATE
return {"price": PRODUCT_PRICE_EUR, "vat": vat_amount,
"total": PRODUCT_PRICE_EUR + vat_amount, "type": "B2B (Inland)",
"company": v.get("company_name"), "address": v.get("address")}
# Testfälle
for vat in [None, "INVALID_VAT", "DE123456789", "FR12345678901"]:
print(f"MwSt.: {vat!r} → {calculate_checkout(vat)}")const API_KEY = "YOUR_API_KEY";
const SELLER_COUNTRY = "FR";
const PRODUCT_PRICE_EUR = 1000;
const VAT_RATE = 0.2;
async function validateVat(vatNumber: string) {
const params = new URLSearchParams({ vat_number: vatNumber });
return (await fetch(`https://api.veille.io/v1/vat?${params}`, { headers: { "x-api-key": API_KEY } })).json();
}
async function calculateCheckout(vatNumber?: string) {
if (!vatNumber) {
return { price: PRODUCT_PRICE_EUR, vat: PRODUCT_PRICE_EUR * VAT_RATE,
total: PRODUCT_PRICE_EUR * (1 + VAT_RATE), type: "B2C" };
}
const v = await validateVat(vatNumber);
if (!v.is_valid) return { error: "Ungültige MwSt.-Nummer." };
if (v.country_code && v.country_code !== SELLER_COUNTRY) {
return { price: PRODUCT_PRICE_EUR, vat: 0, total: PRODUCT_PRICE_EUR,
type: "B2B (Reverse-Charge)", company: v.company_name, address: v.address };
}
return { price: PRODUCT_PRICE_EUR, vat: PRODUCT_PRICE_EUR * VAT_RATE,
total: PRODUCT_PRICE_EUR * (1 + VAT_RATE), type: "B2B (Inland)",
company: v.company_name, address: v.address };
}
for (const vat of [undefined, "INVALID", "DE123456789", "FR12345678901"]) {
console.log(`MwSt.: ${vat} →`, await calculateCheckout(vat));
}<?php
const SELLER_COUNTRY = "FR";
const PRODUCT_PRICE_EUR = 1000.0;
const VAT_RATE = 0.20;
function validateVat(string $apiKey, string $vatNumber): array {
$params = http_build_query(["vat_number" => $vatNumber]);
$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}"]);
$r = json_decode(curl_exec($ch), true);
curl_close($ch);
return $r;
}
function calculateCheckout(string $apiKey, ?string $vatNumber): array {
if (!$vatNumber) {
return ["price" => PRODUCT_PRICE_EUR, "vat" => PRODUCT_PRICE_EUR * VAT_RATE,
"total" => PRODUCT_PRICE_EUR * (1 + VAT_RATE), "type" => "B2C"];
}
$v = validateVat($apiKey, $vatNumber);
if (!($v["is_valid"] ?? false)) return ["error" => "Ungültige MwSt.-Nummer."];
$buyerCountry = $v["country_code"] ?? "";
if ($buyerCountry && $buyerCountry !== SELLER_COUNTRY) {
return ["price" => PRODUCT_PRICE_EUR, "vat" => 0, "total" => PRODUCT_PRICE_EUR,
"type" => "B2B (Reverse-Charge)", "company" => $v["company_name"]];
}
return ["price" => PRODUCT_PRICE_EUR, "vat" => PRODUCT_PRICE_EUR * VAT_RATE,
"total" => PRODUCT_PRICE_EUR * (1 + VAT_RATE), "type" => "B2B (Inland)", "company" => $v["company_name"]];
}
foreach ([null, "INVALID_VAT", "DE123456789"] as $vat) {
print_r(calculateCheckout("YOUR_API_KEY", $vat));
}package main
import (
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
)
const (
APIKey = "YOUR_API_KEY"
SellerCountry = "FR"
Price = 1000.0
VATRate = 0.20
)
func validateVAT(vat string) map[string]any {
params := url.Values{"vat_number": {vat}}
req, _ := http.NewRequest("GET", "https://api.veille.io/v1/vat?"+params.Encode(), nil)
req.Header.Set("x-api-key", APIKey)
resp, _ := http.DefaultClient.Do(req)
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var v map[string]any
json.Unmarshal(body, &v)
return v
}
func checkout(vat string) string {
if vat == "" { return fmt.Sprintf("B2C: Total=%.2f€ (MwSt.=%.2f€)", Price*(1+VATRate), Price*VATRate) }
v := validateVAT(vat)
if !(v["is_valid"].(bool)) { return "❌ Ungültige MwSt.-Nummer." }
country, _ := v["country_code"].(string)
if country != "" && country != SellerCountry {
return fmt.Sprintf("B2B Reverse-Charge: Total=%.2f€ (MwSt.=0€) — %v", Price, v["company_name"])
}
return fmt.Sprintf("B2B Inland: Total=%.2f€ (MwSt.=%.2f€) — %v", Price*(1+VATRate), Price*VATRate, v["company_name"])
}
func main() {
for _, vat := range []string{"", "INVALID", "DE123456789"} {
fmt.Printf("MwSt.:%q → %s\n", vat, checkout(vat))
}
}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 String SELLER = "FR";
static double PRICE = 1000.0;
static double VAT_RATE = 0.20;
static JSONObject validate(String vat) throws Exception {
var req = HttpRequest.newBuilder()
.uri(URI.create("https://api.veille.io/v1/vat?vat_number=" + vat))
.header("x-api-key", API_KEY).GET().build();
return new JSONObject(client.send(req, HttpResponse.BodyHandlers.ofString()).body());
}
static String checkout(String vat) throws Exception {
if (vat == null || vat.isEmpty())
return String.format("B2C: Total=%.2f€ (MwSt.=%.2f€)", PRICE*(1+VAT_RATE), PRICE*VAT_RATE);
var v = validate(vat);
if (!v.getBoolean("is_valid")) return "❌ Ungültige MwSt.-Nummer.";
var country = v.optString("country_code","");
if (!country.isEmpty() && !country.equals(SELLER))
return String.format("B2B Reverse-Charge: %.2f€ (keine MwSt.) — %s", PRICE, v.getString("company_name"));
return String.format("B2B Inland: %.2f€ (MwSt.=%.2f€) — %s", PRICE*(1+VAT_RATE), PRICE*VAT_RATE, v.getString("company_name"));
}
public static void main(String[] args) throws Exception {
for (var vat : new String[]{"", "INVALID", "DE123456789"})
System.out.printf("MwSt.:%s → %s%n", vat, checkout(vat));
}
}using System.Net.Http;
using System.Text.Json;
const string apiKey = "YOUR_API_KEY";
const string seller = "FR";
const double price = 1000.0;
const double vatRate = 0.20;
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("x-api-key", apiKey);
async Task<JsonElement?> ValidateVat(string vatNumber)
{
var resp = await client.GetAsync($"https://api.veille.io/v1/vat?vat_number={vatNumber}");
if (!resp.IsSuccessStatusCode) return null;
return JsonDocument.Parse(await resp.Content.ReadAsStringAsync()).RootElement;
}
async Task<string> Checkout(string? vatNumber)
{
if (string.IsNullOrEmpty(vatNumber))
return $"B2C: Total={(price*(1+vatRate)):F2}€ (MwSt.={(price*vatRate):F2}€)";
var v = await ValidateVat(vatNumber);
if (v == null || !v.Value.GetProperty("is_valid").GetBoolean()) return "❌ Ungültige MwSt.-Nummer.";
var country = v.Value.TryGetProperty("country_code", out var c) ? c.GetString() : "";
if (!string.IsNullOrEmpty(country) && country != seller)
return $"B2B Reverse-Charge: {price:F2}€ (keine MwSt.) — {v.Value.GetProperty("company_name")}";
return $"B2B Inland: {price*(1+vatRate):F2}€ (MwSt.={(price*vatRate):F2}€)";
}
foreach (var vat in new string?[] { null, "INVALID", "DE123456789" })
Console.WriteLine($"MwSt.:{vat} → {await Checkout(vat)}");use reqwest::Client;
use serde_json::Value;
const API_KEY: &str = "YOUR_API_KEY";
const SELLER: &str = "FR";
const PRICE: f64 = 1000.0;
const VAT_RATE: f64 = 0.20;
async fn validate_vat(client: &Client, vat: &str) -> Value {
client.get("https://api.veille.io/v1/vat")
.header("x-api-key", API_KEY)
.query(&[("vat_number", vat)])
.send().await.unwrap().json::<Value>().await.unwrap()
}
async fn checkout(client: &Client, vat: Option<&str>) -> String {
let Some(vat) = vat else {
return format!("B2C: Total={:.2}€ (MwSt.={:.2}€)", PRICE*(1.0+VAT_RATE), PRICE*VAT_RATE);
};
let v = validate_vat(client, vat).await;
if !v["is_valid"].as_bool().unwrap_or(false) { return "❌ Ungültige MwSt.-Nummer.".to_string(); }
let country = v["country_code"].as_str().unwrap_or("");
if !country.is_empty() && country != SELLER {
return format!("B2B Reverse-Charge: {:.2}€ (keine MwSt.) — {}", PRICE, v["company_name"].as_str().unwrap_or(""));
}
format!("B2B Inland: {:.2}€ (MwSt.={:.2}€)", PRICE*(1.0+VAT_RATE), PRICE*VAT_RATE)
}
#[tokio::main]
async fn main() -> Result<(), reqwest::Error> {
let client = Client::new();
for vat in [None, Some("INVALID"), Some("DE123456789")] {
println!("MwSt.:{:?} → {}", vat, checkout(&client, vat).await);
}
Ok(())
}Speichern Sie validierte MwSt.-Nummern und den entsprechenden Firmennamen in Ihrer Datenbank und vermeiden Sie unnötige erneute Validierungen. MwSt.-Nummern ändern sich selten — eine Neuvalidierung wöchentlich oder bei Kontoaktualisierung ist ausreichend.