oneapi
Sign in
Financiar v1 / Validare

EORI validation

Checks an EORI number — the customs identifier used on declarations with third countries — through the European Commission's service.

It has nothing to do with intra-Community operations: there the VAT number is used, checked through VIES. The confusion is easy and costly.

There is no local list of EORI numbers and it cannot be derived from the tax id: the number is obtained through a separate registration with customs, which only those who declare at customs do. So every unknown check is an external call, protected by a rate limit and a circuit breaker.

POST
https://oneapi.ro/api/financiar/v1/validare/eori

Request body

Sent as JSON in the request body (Content-Type: application/json) — not in the query string.

NameTypeDescriptionAccepted values
eorirequired string Required, in the request body. Spaces, dots and hyphens are ignored. max 20 car.
Romanian EORI number Request body
{
    "eori": "RO14399840"
}
Written with a space after the prefix Request body
{
    "eori": "RO 14399840"
}
A German EORI number Request body
{
    "eori": "DE123456789012345"
}
A country prefix that does not exist Request body
{
    "eori": "XX1"
}

Query parameters

This route accepts no query parameters.

How it behaves

  • Validates an EORI number through the European Commission service (DDS2/EOS).
  • EORI is a CUSTOMS identifier, for declarations involving third countries — it has nothing to do with intra-Community transactions. Those use the VAT number, checked through VIES. The confusion is easy and costly: someone searching for "European partner validation" lands here and checks the wrong thing.
  • There is no local list and it cannot be derived from the tax code. The number is obtained through a separate registration with customs, done only by those who file customs declarations — most companies never do. So a valid, active, VAT-registered tax code says nothing about the existence of an EORI. Every unknown check is an external call.
  • The structure for Romania has three forms, depending on the holder (Norms of ANAF Order 1886): a legal entity established in Romania → RO + tax code; a natural person established in Romania → RO + personal numeric code; an operator established in a third country → RO + the ISO code of that state + the number from that state. The national part may be alphanumeric, up to 15 characters.
  • Hence the method is POST: an EORI of a natural person IS a personal numeric code with a prefix, so the number may be personal data and has no place in a query string.
  • Three states, not two. valid and invalid come from the Commission; serviciu_indisponibil means we received no verdict, and valid is null, not false. Treating an outage as "invalid number" would make a client refuse a perfectly legitimate partner.
  • A Commission outage is not a route error. The response stays HTTP 200, with stare: serviciu_indisponibil and motiv says why: timeout, conexiune (connection failed), http_, raspuns_neinteligibil (a 200 without a verdict — usually the maintenance page), circuit_deschis (after repeated failures we stop calling for a while; meta.reia_dupa_s says how long). An outage is never cached, and a 200 from the Commission without a SOAP envelope is not read as a verdict.
  • Name and address are published only if the economic operator has consented. A valid EORI without a name is normal, not an incomplete answer — and the response says so explicitly.
  • provenienta shows whether the answer came from cache, from the local structure check, or from the Commission.

What it is for

  • Checking a partner before filling in a customs declaration.
  • Confirming your own EORI number.

Response structure

FieldTypeDescription
data.eori string
data.valid boolean true/false from the Commission, or null when the service gave no verdict.
data.stare string valid, invalid, structura_invalida, serviciu_indisponibil.
data.detaliu string
data.denumire null The operator name, if they consented to publication. null otherwise.
data.adresa null The address, in the form published by the source.
data.motiv null Why there was no verdict, only on serviciu_indisponibil: timeout, conexiune, http_, raspuns_neinteligibil, circuit_deschis. null otherwise.
data.provenienta string cache, local, extern or circuit (no call: the circuit breaker is open).
meta.sursa string The official source the data comes from, with its licence where one is required.
meta.temei string The legal basis for the values or for the way they are computed.
meta.provenienta string
meta.atentie_denumire string
meta.nota_intracomunitar string A note on how to read the response: a caveat, a convention or a limit of the source.

Response examples

body: {"eori": "RO14399840"}

POSThttps://oneapi.ro/api/financiar/v1/validare/eori
{
    "data": {
        "eori": "RO14399840",
        "valid": true,
        "stare": "valid",
        "detaliu": "Valid",
        "denumire": null,
        "adresa": null,
        "motiv": null,
        "provenienta": "extern"
    },
    "meta": {
        "sursa": "Comisia Europeană — serviciul de validare EORI (DDS2/EOS).",
        "temei": "Numărul EORI e atribuit de autoritatea vamală; pentru România, de Direcţia Generală a Vămilor din ANAF.",
        "provenienta": "Apel la serviciul Comisiei.",
        "atentie_denumire": "Numărul e valid, dar denumirea şi adresa lipsesc: se publică numai dacă operatorul economic şi-a dat consimţământul. Absenţa lor nu e un răspuns incomplet.",
        "nota_intracomunitar": "EORI e identificator VAMAL, pentru operaţiuni cu ţări terţe. Pentru valabilitatea unui cod de TVA în operaţiuni intracomunitare, verificarea se face la VIES."
    }
}

Error codes

CodeSlugWhen it occurs
401neautentificatToken missing, invalid, expired or revoked.
403feature_indisponibilThe current plan does not include the feature the route depends on.
422validareeori missing or of an impossible length. A number that is present but malformed returns 200 with stare: "structura_invalida".
429limita_taYou exceeded your rate for external checks; capacitate_serviciu — the service is at capacity, not a limit on your account. Both with Retry-After.

All errors share the same shape. eroare.cod is stable and is the value you should branch on in code — not the text in mesaj, which may change.

{
    "eroare": {
        "cod": "validare",
        "mesaj": "eori missing or of an impossible length. A number that is present but malformed returns 200 with stare: \"structura_invalida\"."
    }
}