{
  "openapi": "3.1.0",
  "info": {
    "title": "VAT Validation API",
    "version": "1",
    "summary": "Check a VAT number's form and its registration with the national VAT registry; returns the registered name and address.",
    "description": "Part of the VAT Suite service of IBAN.com. One request checks a VAT number: first its form (country prefix,\nlength, structure and check digits), then its registration with the national VAT registry of the country,\nand returns whether the number is currently registered together with the registered name and address.\nAll EU member states, Northern Ireland (`XI`), the United Kingdom and Norway.\n\nFull documentation with recorded examples and the supported countries: https://developer.iban.com/vat-api\n\nResponses are JSON only (no `format` parameter). The HTTP status tells the kind of outcome: **200** the\nnumber is well-formed and the registry answered (`active` is the result); **422** the number failed a\nformat check (same body, result code 601–604); **400** a parameter is missing (306, 307); **403** an\naccount problem (301–305); **429** above 20 requests per second; **503** when the national registry does not\nanswer. Every 200 and 422 uses one query from the VAT Suite balance; 400, 403 and 429 use none.\n",
    "termsOfService": "https://www.iban.com/terms",
    "license": {
      "name": "Proprietary — IBAN.com Terms & Conditions",
      "url": "https://www.iban.com/terms"
    },
    "contact": {
      "name": "IBAN.com support",
      "url": "https://clients.iban.com/support"
    }
  },
  "servers": [
    {
      "url": "https://api.bav.com",
      "description": "Production. There is no separate sandbox; test requests use queries like any other request."
    }
  ],
  "tags": [
    {
      "name": "VAT",
      "description": "VAT number validation against the national registries."
    }
  ],
  "paths": {
    "/validate/": {
      "post": {
        "tags": [
          "VAT"
        ],
        "operationId": "validateVat",
        "summary": "Validate a VAT number (POST)",
        "description": "Parameters as an `application/x-www-form-urlencoded` body, the key included. JSON request bodies are\nnot read (result code 306). Preferred in production: the key travels in the request body instead of the\nURL. Allow at least 30 s before timing out: some national registries are slow.\n",
        "security": [],
        "requestBody": {
          "required": true,
          "content": {
            "application/x-www-form-urlencoded": {
              "schema": {
                "$ref": "#/components/schemas/VatRequest"
              },
              "examples": {
                "france": {
                  "summary": "Google France (recorded 9 Oct 2026)",
                  "value": {
                    "api_key": "YOUR_API_KEY",
                    "vat": "FR64443061841"
                  }
                },
                "belgium_formatted": {
                  "summary": "Separators are removed before the check",
                  "value": {
                    "api_key": "YOUR_API_KEY",
                    "vat": "BE 0567.647.463"
                  }
                }
              }
            }
          }
        },
        "responses": {
          "200": {
            "$ref": "#/components/responses/Checked"
          },
          "400": {
            "$ref": "#/components/responses/MissingParameter"
          },
          "403": {
            "$ref": "#/components/responses/AccountError"
          },
          "422": {
            "$ref": "#/components/responses/FormatFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/RegistryDown"
          }
        }
      },
      "get": {
        "tags": [
          "VAT"
        ],
        "operationId": "validateVatGet",
        "summary": "Validate a VAT number (GET)",
        "description": "The same parameters in the query string, the key included (`api_key`). With GET the key is part of the\nURL and ends up in proxy and web-server access logs: use POST in production.\n",
        "security": [
          {
            "ApiKeyQuery": []
          }
        ],
        "parameters": [
          {
            "$ref": "#/components/parameters/vat"
          }
        ],
        "responses": {
          "200": {
            "$ref": "#/components/responses/Checked"
          },
          "400": {
            "$ref": "#/components/responses/MissingParameter"
          },
          "403": {
            "$ref": "#/components/responses/AccountError"
          },
          "422": {
            "$ref": "#/components/responses/FormatFailed"
          },
          "429": {
            "$ref": "#/components/responses/RateLimited"
          },
          "500": {
            "$ref": "#/components/responses/ServerError"
          },
          "503": {
            "$ref": "#/components/responses/RegistryDown"
          }
        }
      }
    }
  },
  "components": {
    "securitySchemes": {
      "ApiKeyQuery": {
        "type": "apiKey",
        "in": "query",
        "name": "api_key",
        "description": "Your personal key, shown under *API Access* in the client area, as the `api_key` parameter. On a POST\nrequest it is a field of the form body instead. Missing: HTTP 400, result code 306. Wrong or empty:\nHTTP 403, result code 301.\n"
      }
    },
    "parameters": {
      "vat": {
        "name": "vat",
        "in": "query",
        "required": true,
        "description": "The VAT number to check, **with its country prefix** (`FR64443061841`). Upper or lower case; spaces,\nfull stops and hyphens are removed before the check (`BE 0567.647.463` → `BE0567647463`). Any other\ncharacter gives result code 601. Missing: HTTP 400, code 307; empty or shorter than 4 characters: HTTP\n422, code 603. Greece is sent as `EL` (the ISO code `GR` is refused with 602), Northern Ireland as `XI`.\n",
        "schema": {
          "type": "string"
        },
        "example": "FR64443061841"
      }
    },
    "responses": {
      "Checked": {
        "description": "The number is well-formed and the registry answered. `active` is the result: `true` with the\nregistration in `registration_data`, `false` with an empty object. `valid` is always `true` here and\n`error` an empty object.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/VatResponse"
            },
            "examples": {
              "registered": {
                "summary": "FR64443061841 — registered (recorded 9 Oct 2026)",
                "value": {
                  "query": {
                    "vat": "FR64443061841",
                    "status": "completed",
                    "request_time": "2026-10-09 07:46:39"
                  },
                  "valid": true,
                  "active": true,
                  "registration_data": {
                    "name": "EURL GOOGLE FRANCE",
                    "address": "8 RUE DE LONDRES",
                    "city": "PARIS",
                    "zip": "75009",
                    "country_iso": "FR",
                    "country_name": "France"
                  },
                  "error": {}
                }
              },
              "not_registered": {
                "summary": "FR14999999999 — well-formed, not listed by the registry (recorded 9 Oct 2026)",
                "value": {
                  "query": {
                    "vat": "FR14999999999",
                    "status": "completed",
                    "request_time": "2026-10-09 07:59:46"
                  },
                  "valid": true,
                  "active": false,
                  "registration_data": {},
                  "error": {}
                }
              },
              "northern_ireland": {
                "summary": "XI220430231 — the registry delivers the whole address in `zip`; `country_iso` is GB (recorded 9 Oct 2026)",
                "value": {
                  "query": {
                    "vat": "XI220430231",
                    "status": "completed",
                    "request_time": "2026-10-09 07:47:15"
                  },
                  "valid": true,
                  "active": true,
                  "registration_data": {
                    "name": "TESCO PLC",
                    "address": "",
                    "city": "",
                    "zip": "CIRRUS A SHIRE PARK KESTREL WAY WELWYN GARDEN CITY   AL7 1GA",
                    "country_iso": "GB",
                    "country_name": "United Kingdom"
                  },
                  "error": {}
                }
              }
            }
          }
        }
      },
      "FormatFailed": {
        "description": "The number failed a check that needs no registry; the query is charged. `valid` and `active` are\n`false`, `error.code` is a **number**: 601 invalid characters · 602 country code not supported (also a\nnumber sent without its prefix, or Greece as `GR`) · 603 shorter than 4 characters · 604 wrong format,\nlength, structure or check digit.\n",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/VatResponse"
            },
            "examples": {
              "check_digit": {
                "summary": "FR64443061842 — code 604 (recorded 9 Oct 2026)",
                "value": {
                  "query": {
                    "vat": "FR64443061842",
                    "status": "completed",
                    "request_time": "2026-10-09 07:46:32"
                  },
                  "valid": false,
                  "active": false,
                  "registration_data": {},
                  "error": {
                    "code": 604,
                    "text": "Invalid VAT format, length, structure or check digit."
                  }
                }
              },
              "unsupported_country": {
                "summary": "US123456789 — code 602 (recorded 9 Oct 2026)",
                "value": {
                  "query": {
                    "vat": "US123456789",
                    "status": "completed",
                    "request_time": "2026-10-09 07:46:31"
                  },
                  "valid": false,
                  "active": false,
                  "registration_data": {},
                  "error": {
                    "code": 602,
                    "text": "Country code not supported."
                  }
                }
              },
              "too_short": {
                "summary": "FR1 — code 603 (recorded 9 Oct 2026)",
                "value": {
                  "query": {
                    "vat": "FR1",
                    "status": "completed",
                    "request_time": "2026-10-09 07:46:30"
                  },
                  "valid": false,
                  "active": false,
                  "registration_data": {},
                  "error": {
                    "code": 603,
                    "text": "VAT number cannot be shorter than 4 characters."
                  }
                }
              },
              "invalid_characters": {
                "summary": "FR64443061841! — code 601 (recorded 9 Oct 2026)",
                "value": {
                  "query": {
                    "vat": "FR64443061841!",
                    "status": "completed",
                    "request_time": "2026-10-09 07:46:30"
                  },
                  "valid": false,
                  "active": false,
                  "registration_data": {},
                  "error": {
                    "code": 601,
                    "text": "Invalid characters in VAT number."
                  }
                }
              }
            }
          }
        }
      },
      "MissingParameter": {
        "description": "A required parameter is missing: 306 `api_key` (also the answer to a JSON request body), 307 `vat`. Only `error` is in the body; `code` is a three-digit string. Not charged.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RequestError"
            },
            "examples": {
              "missing_vat": {
                "summary": "vat missing (recorded 9 Oct 2026)",
                "value": {
                  "error": {
                    "code": "307",
                    "message": "Bad Request: Missing 'vat' parameter value"
                  }
                }
              },
              "missing_key": {
                "summary": "api_key missing (recorded 9 Oct 2026)",
                "value": {
                  "error": {
                    "code": "306",
                    "message": "Bad Request: Missing 'api_key' parameter value"
                  }
                }
              }
            }
          }
        }
      },
      "AccountError": {
        "description": "301 key invalid · 302 subscription expired · 303 no queries available · 304 no access to this API · 305 IP address not allowed. Only `error` in the body; not charged. 301 recorded, the others follow the same path.",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RequestError"
            },
            "examples": {
              "wrong_key": {
                "summary": "Wrong key (recorded 9 Oct 2026)",
                "value": {
                  "error": {
                    "code": "301",
                    "message": "API Key is invalid"
                  }
                }
              }
            }
          }
        }
      },
      "RateLimited": {
        "description": "More than 20 requests per second. Rejected by the web server before reaching the API: not processed,\nnot charged; the body is a small HTML page, there is no `Retry-After` header. Wait a moment and resend.\n",
        "content": {
          "text/html": {
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "ServerError": {
        "description": "Empty `text/html` body. Recorded for a parameter sent in a form the API cannot read (`vat[]`); for anything else a temporary problem — retry with increasing delays. A request that got no answer may still have been processed and charged.",
        "content": {
          "text/html": {
            "schema": {
              "type": "string"
            }
          }
        }
      },
      "RegistryDown": {
        "description": "The national registry of the country did not answer; result code 503, *National registry not responding. Try again later.* Not charged. Retry later with increasing delays — national registries have maintenance windows. Not observed in the recorded calls (shape from the API description).",
        "content": {
          "application/json": {
            "schema": {
              "$ref": "#/components/schemas/RequestError"
            }
          }
        }
      }
    },
    "schemas": {
      "VatRequest": {
        "type": "object",
        "required": [
          "api_key",
          "vat"
        ],
        "properties": {
          "api_key": {
            "type": "string",
            "description": "Your personal key, shown under *API Access* in the client area.",
            "examples": [
              "YOUR_API_KEY"
            ]
          },
          "vat": {
            "type": "string",
            "description": "The VAT number with its country prefix; spaces, full stops and hyphens are removed, letters upper-cased.",
            "examples": [
              "FR64443061841",
              "BE 0567.647.463",
              "EL094014201",
              "XI220430231"
            ]
          }
        }
      },
      "VatResponse": {
        "type": "object",
        "required": [
          "query",
          "valid",
          "active",
          "registration_data",
          "error"
        ],
        "properties": {
          "query": {
            "type": "object",
            "required": [
              "vat",
              "status",
              "request_time"
            ],
            "properties": {
              "vat": {
                "type": "string",
                "description": "The number as it was checked — upper case, spaces, full stops and hyphens removed. Empty when an empty value was sent."
              },
              "status": {
                "type": "string",
                "enum": [
                  "completed",
                  "processing"
                ],
                "description": "`completed` in every recorded response; `processing` is defined for a national registry that does not answer."
              },
              "request_time": {
                "type": "string",
                "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}$",
                "description": "Time the check was completed, UTC, `YYYY-MM-DD HH:MM:SS` (equals the `Date` header of the response)."
              }
            }
          },
          "valid": {
            "type": "boolean",
            "description": "`true` when the number passed the checks that need no registry (prefix, length, structure, check digits); `false` only in a 422."
          },
          "active": {
            "type": "boolean",
            "description": "`true` when the national registry lists the number as a current VAT registration; `false` for a well-formed number the registry does not list, and in every 422."
          },
          "registration_data": {
            "description": "The registration as the registry delivers it (six string fields), or an empty object when `active` is `false`.",
            "oneOf": [
              {
                "$ref": "#/components/schemas/RegistrationData"
              },
              {
                "type": "object",
                "additionalProperties": false,
                "description": "Empty — not registered or format check failed."
              }
            ]
          },
          "error": {
            "description": "An empty object in a 200; in a 422 the result code (a number) and its text.",
            "oneOf": [
              {
                "type": "object",
                "additionalProperties": false,
                "description": "Empty — the number was checked against the registry."
              },
              {
                "$ref": "#/components/schemas/FormatError"
              }
            ]
          }
        }
      },
      "RegistrationData": {
        "type": "object",
        "required": [
          "name",
          "address",
          "city",
          "zip",
          "country_iso",
          "country_name"
        ],
        "properties": {
          "name": {
            "type": "string",
            "description": "Registered name of the business, in the script and case the registry uses (non-ASCII characters are escaped as `\\uXXXX` in the JSON text)."
          },
          "address": {
            "type": "string",
            "description": "Street address; may be empty or the literal `N/A`. Some registries deliver the whole address in one field (Romania in `city`, Northern Ireland in `zip`) — store the three fields together."
          },
          "city": {
            "type": "string"
          },
          "zip": {
            "type": "string"
          },
          "country_iso": {
            "type": "string",
            "description": "ISO 3166-1 alpha-2 of the registering country — `GR` for a number sent with the `EL` prefix, `GB` for `XI`."
          },
          "country_name": {
            "type": "string",
            "description": "Country name in English."
          }
        }
      },
      "FormatError": {
        "type": "object",
        "required": [
          "code",
          "text"
        ],
        "additionalProperties": false,
        "properties": {
          "code": {
            "type": "integer",
            "enum": [
              601,
              602,
              603,
              604
            ],
            "description": "601 invalid characters · 602 country code not supported · 603 shorter than 4 characters · 604 invalid format, length, structure or check digit."
          },
          "text": {
            "type": "string",
            "examples": [
              "Invalid characters in VAT number.",
              "Country code not supported.",
              "VAT number cannot be shorter than 4 characters.",
              "Invalid VAT format, length, structure or check digit."
            ]
          }
        }
      },
      "RequestError": {
        "type": "object",
        "required": [
          "error"
        ],
        "additionalProperties": false,
        "description": "The only member of a 400, 403 or 503 body.",
        "properties": {
          "error": {
            "type": "object",
            "required": [
              "code",
              "message"
            ],
            "additionalProperties": false,
            "properties": {
              "code": {
                "type": "string",
                "enum": [
                  "301",
                  "302",
                  "303",
                  "304",
                  "305",
                  "306",
                  "307",
                  "503"
                ],
                "description": "A three-digit **string** (unlike the 422 codes)."
              },
              "message": {
                "type": "string",
                "examples": [
                  "API Key is invalid",
                  "Bad Request: Missing 'api_key' parameter value",
                  "Bad Request: Missing 'vat' parameter value",
                  "National registry not responding. Try again later."
                ]
              }
            }
          }
        }
      }
    }
  }
}