Limits and errors
How rate and quota limits apply, which headers you get, what a response looks like (envelope, pagination, intervals) and the format errors come in — common to every module.
Rate and quota limits
Each plan includes a rate limit (requests per second) and a monthly request volume, published on the pricing page. Limits apply per account, shared across all tokens.
When the rate limit is exceeded, the request gets status 429 and a Retry-After header (seconds until you can retry). Exceeding the monthly volume does not stop the account abruptly: you get warnings, and once depleted requests also get 429, with no unannounced charges.
Quota headers
Every response carries self-monitoring headers, so you know where you stand without a separate call:
Response format
Every successful response has only data and, when relevant, meta at the top level. data holds only the data you asked for; everything that describes it — freshness (actualizat), the source, the attribution a licence requires, pagination — lives in meta.
{
"data": [
"…"
],
"meta": {
"paginare": {
"pagina": 2,
"per_pagina": 50,
"total": 137,
"pagini": 3
},
"actualizat": {
"administrativ": "2026-08-15T16:39:14+00:00"
}
}
}Paginated lists take ?pagina= (from 1) and ?per_pagina=, and the position comes back in meta.paginare: {pagina, per_pagina, total, pagini}. There is no offset and no counters inside data.
"The first N" — rankings, nearest results, the suggestions of a semantic match, the recent end of a series — is requested with ?limita=. That is not pagination: a ranking has no second page.
Intervals are requested with ?de_la= and ?pana_la=, both inclusive, on every route. They accept YYYY, YYYY-MM, YYYY-Tn (a quarter) or YYYY-MM-DD, and the route brings them to its own granularity: on a daily series pana_la=2024 means up to and including 31 December 2024, on a yearly one de_la=2024-03-01 means the year 2024.
Where a route links two points rather than an interval — the distance between two localities, the path between two companies, a street segment — the pair is ?de= and ?la=.
Error format
Errors share the same envelope across the whole platform: an eroare object with a stable code (for code), a human-readable message and, on validation, per-field details. The anaf module adds two fields to that same object — camp (the offending field) and request_id (quote it when reporting an error) — and on document validation it also carries errors and warnings alongside. A client that reads eroare.cod works the same on every module.
{
"eroare": {
"cod": "validare",
"mesaj": "Datele trimise nu sunt valide.",
"detalii": {
"q": [
"Trebuie să aibă minim 2 caractere."
]
}
}
}Maintenance (API unavailable)
This is very rare and always scheduled — usually at night, when we reindex or ingest large volumes of data — and typically lasts only a few minutes. During these windows, all routes respond with status 503 and a Retry-After header, in the same error envelope, with the mentenanta code. You can build your client to retry automatically after the Retry-After interval:
{
"eroare": {
"cod": "mentenanta",
"mesaj": "API-ul este temporar indisponibil."
}
}Status codes
What the codes mean, common to all routes:
| Status | Meaning |
|---|---|
| 200 | Successful request. |
| 400 | Malformed request. |
| 401 | Missing or invalid token. |
| 403 | Token without access to the requested module or resource. |
| 404 | The requested resource does not exist. |
| 422 | Invalid parameters — see detalii for fields. |
| 429 | Too many requests — respect Retry-After. |
| 503 | API in maintenance (mentenanta) or data being rebuilt right then (baza_ocupata, a few seconds) — retry after Retry-After. |
| 5xx | Temporary server error — retry later. |