Utile v1 / Email
Check an email address
Signals about an email address: whether the form is correct, whether the domain has MX records, whether it is a disposable provider, whether it is a plus alias. It sends no verification message.
POST
https://oneapi.ro/api/utile/v1/email/valideaza
Request body
Sent as JSON in the request body (Content-Type: application/json) — not in the query string.
NameTypeDescriptionAccepted values
adresarequired
string
REQUIRED. The address to check, at most 320 characters.
max 320 car.
mxoptional
boolean | null
0 skips the DNS lookup and checks syntax only. Checked by default.
An ordinary address
Request body
{
"adresa": "ion.popescu@example.com"
}
Disposable domain
Request body
{
"adresa": "test@mailinator.com"
}
Syntax only, no DNS
Request body
{
"adresa": "ion@exemplu.ro",
"mx": false
}
Query parameters
This route accepts no query parameters.
How it behaves
- POST, with the address in the body (JSON):
adresa(required, at most 320 characters) andmx(falseskips the DNS lookup and checks syntax only; checked by default). An e-mail address is personal data: in a URL it would end up in access logs and in the referrer — so aGETgets405 metoda_nepotrivita. - This is not a verdict. The only check that proves an address exists is sending a message with a confirmation link. Everything this route returns are SIGNALS — an address can pass every check and not exist, while one rejected by the list can be perfectly functional.
- The address is deliberately NOT validated at the gate with the usual email rule: that is precisely what the route is meant to report. Rejected on entry, a malformed address would never reach the analysis.
- Missing MX records do not automatically mean the domain cannot receive mail. RFC 5321 says a domain with no MX but with A or AAAA is a valid recipient — hence
staredistinguishesfara_mx_dar_cu_afromfara_mx_si_fara_a. - Internationalised domains are converted to Punycode before any check, because both the syntax filter and DNS work on the ASCII form. The
domeniuin the response is the converted form. - The DNS lookup is rate-limited on two levels (per user and global) and cached for 10 minutes per DOMAIN. When the rate is exceeded or the DNS server does not answer,
mx.verificatisfalsewith the reason andpoate_primi_mailisnull— a DNS outage is never turned into “the domain cannot receive mail” and is not cached. The lookup has a 2-second timeout and a single attempt, and after 5 failures in a row the MX check pauses for 2 minutes (the reason says so) — a request no longer hangs 10 seconds on a dead DNS. - Zero retention: the address is never written anywhere, not to logs, not to the database. The only thing cached is the DNS answer for the domain, which says nothing about the person in front of the
@.
What it is for
- Catch typos at sign-up, before the confirmation mail is lost.
- Filter disposable addresses out of a newsletter sign-up form.
- Separate role accounts (
office@) from personal addresses in a contact database.
Response structure
All fields below live inside data.
FieldTypeDescription
adresa
string
The address, in the form published by the source.
normalizata
string
The address with the local part lower-cased and the domain in ASCII form.
local
string
The part before the
@.
domeniu
string
The domain, in ASCII form (Punycode if it was internationalised).
eticheta
null
The
+tag suffix, which some providers ignore on delivery. Useful for de-duplication.
semnale.sintaxa_valida
boolean
Whether the address passes RFC 5322 and the length limits.
semnale.domeniu_temporar
boolean
Whether the domain is on the disposable list.
semnale.cutie_de_rol
boolean
Whether it is a role account (
office@, info@) rather than a person's.
semnale.poate_primi_mail
boolean
Whether the domain has MX or A records.
null if the check was not performed.
probleme
array
What exactly is wrong with the syntax, in words.
mx.verificat
boolean
Whether the DNS lookup actually got an answer. On
false, mx.motiv says why (rate exceeded or a DNS server that did not answer).
mx.stare
string
are_mx, fara_mx_dar_cu_a or fara_mx_si_fara_a; absent when verificat: false.
mx.poate_primi
boolean
mx.servere[]
array
The mail servers, ordered by priority.
mx.servere[].server
string
mx.servere[].prioritate
integer
scor
integer
A 0–100 figure composed from the signals above, for callers who want a single number. It is derived, not measured.
observatie
string
A note on how to read the response: a computation convention or a limit of the data.
sursa.domenii_temporare
string
sursa.mx
string
sursa.sintaxa
string
mx.motiv
Why there was no check; present only when
verificat: false.
Response examples
corp: {"adresa": "ion.popescu@example.com"}
POSThttps://oneapi.ro/api/utile/v1/email/valideaza
{
"data": {
"adresa": "ion.popescu@example.com",
"normalizata": "ion.popescu@example.com",
"local": "ion.popescu",
"domeniu": "example.com",
"eticheta": null,
"semnale": {
"sintaxa_valida": true,
"domeniu_temporar": false,
"cutie_de_rol": false,
"poate_primi_mail": true
},
"probleme": [],
"mx": {
"verificat": true,
"stare": "are_mx",
"poate_primi": true,
"servere": [
{
"server": "",
"prioritate": 0
}
]
},
"scor": 90,
"observatie": "Semnalele NU sunt un verdict. O adresă poate trece toate verificările și să nu existe; una respinsă de listă poate fi perfect funcțională. Singura dovadă că o adresă e reală e un mesaj de confirmare livrat.",
"sursa": {
"domenii_temporare": "disposable-email-domains — CC0 1.0",
"mx": "interogare DNS live, cu cache de o oră pe domeniu",
"sintaxa": "RFC 5322 (prin filtrul PHP) plus limitele de lungime din RFC 5321"
}
}
}
corp: {"adresa": "test@mailinator.com"}
POSThttps://oneapi.ro/api/utile/v1/email/valideaza
{
"data": {
"adresa": "test@mailinator.com",
"normalizata": "test@mailinator.com",
"local": "test",
"domeniu": "mailinator.com",
"eticheta": null,
"semnale": {
"sintaxa_valida": true,
"domeniu_temporar": true,
"cutie_de_rol": false,
"poate_primi_mail": true
},
"probleme": [],
"mx": {
"verificat": true,
"stare": "are_mx",
"poate_primi": true,
"servere": [
{
"server": "mail.mailinator.com",
"prioritate": 1
}
]
},
"scor": 50,
"observatie": "Semnalele NU sunt un verdict. O adresă poate trece toate verificările și să nu existe; una respinsă de listă poate fi perfect funcțională. Singura dovadă că o adresă e reală e un mesaj de confirmare livrat.",
"sursa": {
"domenii_temporare": "disposable-email-domains — CC0 1.0",
"mx": "interogare DNS live, cu cache de o oră pe domeniu",
"sintaxa": "RFC 5322 (prin filtrul PHP) plus limitele de lungime din RFC 5321"
}
}
}
corp: {"adresa": "ion@exemplu.ro", "mx": false}
POSThttps://oneapi.ro/api/utile/v1/email/valideaza
{
"data": {
"adresa": "ion@exemplu.ro",
"normalizata": "ion@exemplu.ro",
"local": "ion",
"domeniu": "exemplu.ro",
"eticheta": null,
"semnale": {
"sintaxa_valida": true,
"domeniu_temporar": false,
"cutie_de_rol": false,
"poate_primi_mail": null
},
"probleme": [],
"mx": null,
"scor": 60,
"observatie": "Semnalele NU sunt un verdict. O adresă poate trece toate verificările și să nu existe; una respinsă de listă poate fi perfect funcțională. Singura dovadă că o adresă e reală e un mesaj de confirmare livrat.",
"sursa": {
"domenii_temporare": "disposable-email-domains — CC0 1.0",
"mx": "interogare DNS live, cu cache de o oră pe domeniu",
"sintaxa": "RFC 5322 (prin filtrul PHP) plus limitele de lungime din RFC 5321"
}
}
}
Error codes
| Code | Slug | When it occurs |
|---|---|---|
| 401 | neautentificat | Token missing, invalid, expired or revoked. |
| 403 | feature_indisponibil | The current plan does not include the feature the route depends on. |
| 405 | eroare | metoda_nepotrivita: the route only accepts POST, with the address in the body. |
| 422 | validare | adresa is missing or longer than 320 characters. |
| 429 | cota_depasita | The plan's monthly quota has been exceeded (see 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": "adresa is missing or longer than 320 characters."
}
}