API Verificare SAF-T
Integrați verificarea automată SAF-T direct în softul dvs. de contabilitate. Trimiteți un fișier XML și primiți în secunde rezultatul analizei + link către raportul PDF de audit.
Excepție — gratuit permanent, fără abonament: interogarea datelor publice de firmă (
GET /api/v1/firma/:cui — ANAF + ONRC) funcționează pe orice cont cu cheie API, inclusiv după
expirarea trialului, cu limita de o interogare la 2 secunde.
Autentificare
Toate endpointurile se autentifică cu cheia API a contului dvs., transmisă în headerul
X-Api-Key. Cheia o găsiți (sau o generați) în
Contul meu → Integrare API.
Serverul verifică automat dacă cheia aparține unui cont cu abonament activ.
| Header | Valoare | Obligatoriu |
|---|---|---|
X-Api-Key | Cheia API a contului | Da |
Content-Type | application/xml sau text/xml (la verify-saft) | Da |
Verificare SAF-T
Headers
X-Api-Key: cheia_dvs_api Content-Type: application/xml
Body
Conținutul complet al fișierului SAF-T XML (raw body, nu multipart/form-data).
Date firmă (ANAF + ONRC)
Returnează datele publice combinate ale unei firme românești — status fiscal de la ANAF și date de la Registrul Comerțului (ONRC) — printr-o singură interogare după CUI. Ideal pentru verificarea partenerilor direct din softul dvs.
Headers
X-Api-Key: cheia_dvs_api
Parametru
| Parametru | Descriere |
|---|---|
cui (în cale) | CUI-ul firmei, cu sau fără prefixul RO (ex. 9378841 sau RO9378841) |
200 — Date firmă
Răspunsul conține trei blocuri: anaf (status fiscal), onrc (Registrul Comerțului) și financiar (indicatori din bilanțurile publice, când există).
{
"cui": "9378841",
"interogat_la": "2026-07-14",
"anaf": {
"denumire": "MEDIALOGIC SRL",
"adresa": "MUNICIPIUL BUCUREŞTI, SECTOR 4, ...",
"nr_reg_com": "J1997002988401",
"cod_caen": "5829",
"forma_juridica": "SOCIETATE CU RĂSPUNDERE LIMITATĂ",
"platitor_tva": true,
"tva": "DA — din 2019-09-01",
"tva_la_incasare": "NU — Niciodată",
"split_tva": false,
"inactiv": false,
"stare_inactivitate": "NU",
"ro_e_factura": false
},
"onrc": {
"stare_oficiala": "funcţiune",
"activa": true,
"stare_negativa": false,
"nr_inmatriculare": "J1997002988401",
"data_inmatriculare": "18/04/1997",
"adresa": "Str. ..., Sector 1, Bucureşti",
"reprezentanti": [
{ "nume": "ROŞCA LUCIAN", "calitate": "administrator", "domiciliu": "..." }
],
"caen_autorizat": [ { "cod": "5829", "denumire": "Activităţi de editare ..." } ],
"sucursale": [],
"mutari_sediu_intre_judete": 0
},
"financiar": {
"pe_ani": [ { "an": 2024, "cifraAfaceri": ..., "profitNet": ... } ],
"risc": { "scor": ... },
"altman_z": { "scor": ... }
}
}
Blocurile anaf, onrc sau financiar pot fi null dacă sursa respectivă nu are date pentru firma cerută (ex. firmă nou-înființată fără bilanț depus).
404 — Firmă negăsită
{ "error": "Firma cu CUI 12345678 nu a fost găsită la ANAF sau ONRC." }
429 — Prea multe interogări
Limita este de o interogare la 2 secunde per cheie.
{ "error": "Prea multe interogări. Maxim o interogare la 2 secunde." }
Exemplu cURL
curl -H "X-Api-Key: cheia_dvs_api" \
https://analizafiscala.ro/api/v1/firma/9378841
Răspunsuri posibile
200 — Verificare completă
Fișierul a fost procesat cu succes. Primiți sumarul + link-uri.
{
"status": "ok",
"importId": 48,
"links": {
"rezultat": "https://analizafiscala.ro/import/48/verificari",
"raportAudit": "https://analizafiscala.ro/api/public/verify-saft/48/pdf?token=..."
},
"sumar": {
"companie": "EXEMPLU SRL",
"cui": "RO12345678",
"perioada": "1/2025 - 3/2025",
"total": 120,
"erori": 5,
"avertismente": 12,
"ok": 103
}
}
| Câmp | Tip | Descriere |
|---|---|---|
status | string | Întotdeauna "ok" |
importId | number | ID-ul importului creat — folosiți-l pentru referință |
links.rezultat | string | URL direct către pagina de verificări din aplicație (necesită autentificare) |
links.raportAudit | string | URL semnat pentru descărcarea PDF-ului de audit (valid 24h, fără autentificare) |
sumar.total | number | Numărul total de verificări efectuate |
sumar.erori | number | Verificări cu status „eroare" |
sumar.avertismente | number | Verificări cu status „avertisment" |
sumar.ok | number | Verificări trecute cu succes |
202 — Import în lucru
Există deja un import în curs de procesare. Așteptați finalizarea.
{
"status": "in_lucru",
"importId": 47
}
403 — Abonament expirat
Contul nu are un abonament Complet activ.
{
"status": "abonament_expirat"
}
404 — Cont inexistent
Cheia API nu corespunde niciunui cont activ.
{
"status": "cont_inexistent"
}
400 — Eroare validare
Body XML lipsă sau header X-Api-Key absent.
{
"status": "eroare",
"message": "Headerul X-Api-Key este obligatoriu (cheia o găsiți în Contul meu → Integrare API)."
}
Descărcare raport PDF
Link-ul din links.raportAudit este semnat criptografic și nu necesită autentificare.
Este valid 24 de ore de la generare. Returnează un PDF descărcabil.
Exemple complete
cURL
# Trimitere fișier SAF-T pentru verificare
curl -X POST https://analizafiscala.ro/api/public/verify-saft \
-H "X-Api-Key: cheia_dvs_api" \
-H "Content-Type: application/xml" \
--data-binary @fisier-saft.xml
cURL — descărcare PDF
# Descărcați raportul PDF (link din răspunsul anterior)
curl -o raport-audit.pdf \
"https://analizafiscala.ro/api/public/verify-saft/48/pdf?token=..."
PowerShell
# Citire fișier și trimitere $xml = Get-Content -Path "SAF-T_2025.xml" -Raw -Encoding UTF8 $headers = @{ "X-Api-Key" = "cheia_dvs_api" "Content-Type" = "application/xml" } $body = [System.Text.Encoding]::UTF8.GetBytes($xml) $result = Invoke-RestMethod -Uri "https://analizafiscala.ro/api/public/verify-saft" ` -Method POST -Headers $headers -Body $body $result | ConvertTo-Json -Depth 5 # Descărcați PDF-ul Invoke-WebRequest -Uri $result.links.raportAudit -OutFile "raport-audit.pdf"
Python
# pip install requests import requests with open("SAF-T_2025.xml", "rb") as f: xml_data = f.read() response = requests.post( "https://analizafiscala.ro/api/public/verify-saft", headers={ "X-Api-Key": "cheia_dvs_api", "Content-Type": "application/xml", }, data=xml_data, ) result = response.json() print(result) # Descărcați PDF-ul if result["status"] == "ok": pdf = requests.get(result["links"]["raportAudit"]) with open("raport-audit.pdf", "wb") as f: f.write(pdf.content) print("PDF salvat!")
Node.js
// Node.js 18+ (fetch nativ) const fs = require("fs"); const xml = fs.readFileSync("SAF-T_2025.xml"); const res = await fetch("https://analizafiscala.ro/api/public/verify-saft", { method: "POST", headers: { "X-Api-Key": "cheia_dvs_api", "Content-Type": "application/xml", }, body: xml, }); const result = await res.json(); console.log(result); // Descărcați PDF-ul if (result.status === "ok") { const pdf = await fetch(result.links.raportAudit); const buf = Buffer.from(await pdf.arrayBuffer()); fs.writeFileSync("raport-audit.pdf", buf); console.log("PDF salvat!"); }
C# (.NET)
using var client = new HttpClient();
var xml = File.ReadAllBytes("SAF-T_2025.xml");
var request = new HttpRequestMessage(HttpMethod.Post,
"https://analizafiscala.ro/api/public/verify-saft");
request.Headers.Add("X-Api-Key", "cheia_dvs_api");
request.Content = new ByteArrayContent(xml);
request.Content.Headers.ContentType =
new System.Net.Http.Headers.MediaTypeHeaderValue("application/xml");
var response = await client.SendAsync(request);
var json = await response.Content.ReadAsStringAsync();
Console.WriteLine(json);
API cu cheie (avansat)
Pentru integrări avansate, puteți folosi și API-ul cu cheie API (disponibil în contul dvs., secțiunea Integrare API). Acesta oferă acces la toate endpointurile:
| Endpoint | Descriere |
|---|---|
GET /api/v1/imports | Lista importurilor SAF-T |
GET /api/v1/imports/:id | Detalii import |
GET /api/v1/imports/:id/verificari | Rezultatele verificărilor |
GET /api/v1/imports/:id/balanta | Balanța de verificare |
GET /api/v1/imports/:id/report-links | Link-uri semnate (7 zile) către rapoartele PDF |
GET /api/v1/raport-firma?cui=&an=&luna= | Raportul SAF-T al firmei (PDF-ul managerial pentru administrator), întors ca base64 |
GET /api/v1/d394 | Lista importurilor D394/D390 |
GET /api/v1/d394/:id/verificari | Rezultatele verificărilor D394/D390 |
POST /api/v1/onrc/verify-cuis | Verificare ONRC în lot (max 100 CUI-uri) |
POST /api/v1/upload/saft | Upload SAF-T (multipart) |
POST /api/v1/upload/d394 sau /upload/d390 | Upload D394/D390 — același endpoint sub ambele nume; tipul declarației se detectează automat din conținut |
POST /api/v1/upload/declaratii | Upload în lot: SAF-T + D300/D394/D390 (detectare automată a tipului) — asincron, cu job |
GET /api/v1/job/:id | Starea și rezultatul (sumar) al unui job de upload în lot |
GET /api/v1/job/:id/raport | Raportul unic al jobului: toate verificările (SAF-T + D394/D390 + corelări), o singură listă per firmă |
GET /api/v1/comparatii/:id | Detaliile unei corelări declarație ↔ SAF-T (D300/D394/D390) |
GET /api/v1/firme | Lista firmelor gestionate |
GET /api/v1/portofoliu | Portofoliul de clienți: ultima lună SAF-T și D394/D390 per firmă, note contabile, facturi, conturi bancare, salariați, sold casă, email |
GET /api/v1/sinteza-firme?an=&luna= | Sinteză YTD per firmă (cifră de afaceri, profit/pierdere, datorii stat, active nete, împrumut asociați, sold casă, stare ANAF/ONRC); fără parametri = ultimul SAF-T, cu an+luna = fotografia acelei luni (+ fara_date pentru firmele fără declarație) |
GET /api/v1/monitorizare-parteneri | Partenerii monitorizați, cu status ANAF curent (activ/radiat, TVA, TVA la încasare, inactiv) și alerte |
GET /api/v1/firma/:cui | Date publice firmă (ANAF + ONRC) — orice plan, inclusiv free |
Autentificare cu X-Api-Key: cheia_dvs. Cheia o găsiți în Contul meu → API.
Upload în lot (SAF-T + D300/D394/D390)
POST /api/v1/upload/declaratii acceptă până la 10 fișiere într-un singur apel
(câmpul multipart files), XML sau PDF ANAF, în orice combinație: SAF-T (D406), D300, D394, D390.
Tipul fiecărui fișier este detectat automat. Răspunsul este imediat — rezumatul per fișier
(tip, CIF, firmă, perioadă, acceptat/respins cu motiv) și un job_id (GUID). Procesarea
(import + verificări + corelații cu SAF-T) rulează în fundal.
curl -X POST https://analizafiscala.ro/api/v1/upload/declaratii \
-H "X-Api-Key: cheia_dvs" \
-F "files=@saft_ianuarie.xml" \
-F "files=@d300_ianuarie.pdf" \
-F "files=@d394_ianuarie.pdf"
200 — Rezumat imediat
{
"job_id": "867d98dd-1cc9-477a-b75e-1dc24cc49233",
"status": "in_lucru",
"fisiere": [
{ "fisier": "saft_ianuarie.xml", "tip": "SAF-T", "cui": "12345678",
"denumire": "FIRMA DEMO SRL", "perioada": "1/2025", "status": "acceptat" },
{ "fisier": "d300_ianuarie.pdf", "tip": "D300", "cui": "12345678",
"denumire": "FIRMA DEMO SRL", "perioada": "1/2025", "status": "acceptat" },
{ "fisier": "d394_alta.pdf", "tip": "D394", "cui": "99999999",
"denumire": "ALTA FIRMA SRL", "perioada": "1/2025",
"status": "respins", "motiv": "Declarația nu aparține firmei din SAF-T (CIF în lot: 12345678)." }
],
"rezultat_la": "/api/v1/job/867d98dd-1cc9-477a-b75e-1dc24cc49233"
}
Reveniți apoi (recomandat: la 5–10 secunde) pe GET /api/v1/job/:id. Cât timp jobul e în lucru,
răspunsul are "status": "in_lucru"; când e gata, "status": "finalizat" și câmpul
rezultate cu rezultatul per fișier — numărul de verificări (erori/avertismente/ok), id-urile
importurilor, link-urile de detalii și corelarea cu SAF-T:
{
"job_id": "867d98dd-…", "status": "finalizat",
"rezultate": [
{ "cui": "12345678", "denumire": "FIRMA DEMO SRL", "perioada": "1/2025 - 1/2025",
"status": "finalizat",
"verificari": { "total": 114, "erori": 38, "avertismente": 17, "ok": 59 },
"detalii_la": "https://analizafiscala.ro/api/v1/job/867d98dd-…/raport",
"documente": {
"saft": { "fisier": "saft_ianuarie.xml", "status": "finalizat",
"import_id": 100, "declaratie_inlocuita": false },
"d300": { "fisier": "d300_ianuarie.pdf", "status": "finalizat",
"comparison_id": 26, "saft_import_id": 100 }
} }
]
}
Un singur raport per firmă: verificari este sumarul agregat al întregii
verificări (regulile SAF-T + verificările D394/D390 + corelările declarație ↔ SAF-T), iar
detalii_la este unicul link de detalii — un GET pe el (cu același header
X-Api-Key) întoarce toate verificările într-o singură listă, fiecare rând având câmpul
sursa (SAF-T, D394, D300 ↔ SAF-T etc.), cu explicații,
valori așteptate/găsite și referință legală. documente conține doar identificatorii fișierelor
procesate.
# raportul complet al verificării (toate regulile, toate documentele)
curl -H "X-Api-Key: cheia_dvs_api" \
"https://analizafiscala.ro/api/v1/job/867d98dd-…/raport"
Un lot poate conține și declarațiile mai multor firme (ex. SAF-T-urile a 3 clienți într-un singur apel) —
atunci rezultate are câte o intrare per firmă, iar link-urile detalii_la primesc
automat parametrul ?cui= pentru a filtra raportul la firma respectivă. La joburile cu o singură
firmă parametrul nu e necesar și nu apare.
Raportul firmei (PDF managerial) prin API
Întoarce Raportul SAF-T al firmei — PDF-ul managerial pentru administrator (cifra de afaceri, EBITDA, taxe și salarii de plată, împrumuturi, disponibil bancă/casă, clienți de încasat, furnizori de plată, dividende și decontări cu asociații etc.) — pe baza SAF-T-ului deja încărcat care acoperă luna cerută (funcționează și pentru depunerile trimestriale, după luna de închidere a perioadei).
curl -H "X-Api-Key: cheia_dvs_api" \
"https://analizafiscala.ro/api/v1/raport-firma?cui=12345678&an=2026&luna=4"
200 — PDF-ul, ca base64
{
"cui": "12345678", "denumire": "FIRMA DEMO SRL", "perioada": "4/2026 - 4/2026",
"import_id": 100, "fisier": "Raport_SAF-T_12345678_4_2026.pdf",
"pdf_base64": "JVBERi0xLjMKJf////8KMTIgMCBvYmoK…"
}
# salvare directă pe disc:
curl -s -H "X-Api-Key: cheia_dvs_api" \
"https://analizafiscala.ro/api/v1/raport-firma?cui=12345678&an=2026&luna=4" \
| python -c "import json,sys,base64; d=json.load(sys.stdin); open(d['fisier'],'wb').write(base64.b64decode(d['pdf_base64']))"
404 — Nu există SAF-T pentru perioada cerută
{
"error": "Nu există un SAF-T încărcat pentru CUI 12345678, perioada 4/2026. Încărcați declarația (upload/saft sau upload/declaratii) și reîncercați."
}
Reguli utile:
| Situație | Comportament |
|---|---|
| D300 | Nu are verificări proprii — se corelează cu SAF-T-ul din același lot sau cu unul deja încărcat pentru aceeași firmă și lună. Fără SAF-T → respins, cu motiv explicit. |
| D394 / D390 | Au verificări proprii; corelarea cu SAF-T se face în plus, dacă există unul potrivit. |
| Aceeași perioadă reîncărcată (rectificativă) | Înlocuiește importul anterior (declaratie_inlocuita: true) — nu se dublează. |
| CIF diferit de SAF-T-ul din lot | Declarația e respinsă cu motivul „nu aparține firmei". |
| Fișier nerecunoscut | Respins individual; restul lotului se procesează normal. |
| Joburi | Rezultatele se păstrează 7 zile. |
Rapoarte de portofoliu (JSON)
Trei rapoarte centralizate, gata de integrat în dashboard-uri externe. Toate întorc strict datele
contului căruia îi aparține cheia API (aceleași date ca paginile din platformă) și se apelează cu
un simplu GET cu headerul X-Api-Key.
1. Portofoliul de clienți — GET /api/v1/portofoliu
Un rând per client (CUI), cu ultima lună verificată și statisticile din ultimul SAF-T:
{
"clienti": [
{ "cui": "12345678", "client": "FIRMA DEMO SRL",
"judet": "Cluj", "oras": "Cluj-Napoca",
"ultima_luna_saft": "4/2026", "import_id": 100,
"ultima_decl": "4/2026", "ultima_decl_tip": "D394",
"nr_note_contabile": 2964, "nr_facturi_vanzare": 355, "nr_facturi_cumparare": 728,
"nr_conturi_bancare": 2, "are_salariati": true, "sold_casa": 689.71,
"email_saft": "contab@firma.ro", "email": "administrator@firma.ro" }
]
}
| Câmp | Semnificație |
|---|---|
ultima_luna_saft | Ultima lună acoperită de un SAF-T (după perioadă, nu după data încărcării) |
ultima_decl / ultima_decl_tip | Ultima D394 sau D390 (oricare mai recentă) și tipul ei; null dacă nu există |
nr_note_contabile | Tranzacții distincte în jurnalul (GLE) ultimului SAF-T |
nr_conturi_bancare | Analiticele la 5121 și 5124 din planul de conturi |
are_salariati | Există rulaj pe 641 în GLE |
sold_casa | Sold final debitor cumulat pe conturile 5311 |
email / email_saft | email = adresa editată manual (are prioritate la trimiterea rapoartelor); email_saft = propunerea din XML-ul SAF-T |
2. Sinteza sumelor pe firme — GET /api/v1/sinteza-firme?an=…&luna=…
Sinteza YTD per firmă. Fără parametri: ultimul SAF-T al fiecărei firme.
Cu an + luna (obligatoriu împreună): fotografia portofoliului la acea
lună istorică — se folosește SAF-T-ul care acoperă luna cerută (inclusiv depunerile trimestriale, pe luna de
închidere), YTD-ul devine „de la 1 ianuarie până la luna cerută", iar firmele fără declarație pe acea lună
apar separat în fara_date.
{
"sold_casa_legal": 50000,
"an": 2026, "luna": 4,
"firme": [
{ "cui": "12345678", "firma": "FIRMA DEMO SRL", "import_id": 100,
"ultima_luna": "04/2026",
"cifra_afaceri": 346966.84, "profit_pierdere": 17642.11,
"are_salariati": true, "datorii_stat": 83115.20,
"active_nete": 120500.00, "capital_social": 200,
"eligibil_dividende": true, "imprumut_asociati": 0,
"sold_casa": 689.71, "sold_casa_peste_limita": false,
"total_activ": 512340.55, "audit_obligatoriu": "Nu",
"stare_anaf_label": "Activă", "stare_onrc_label": "Funcțiune",
"nr_importuri_ytd": 4 }
],
"fara_date": [ { "cui": "87654321", "denumire": "ALTA FIRMA SRL" } ]
}
| Câmp | Semnificație |
|---|---|
cifra_afaceri | YTD — rulaj creditor 70x, cumulat pe toate declarațiile anului până la luna de referință |
profit_pierdere | Sold 121 (pozitiv = profit, negativ = pierdere) |
datorii_stat | Solduri creditoare clasa 44 (fără 4428) |
active_nete / eligibil_dividende | Capitaluri proprii (cls 1 fără 15x/16x); eligibilitatea pentru dividende interimare |
imprumut_asociati | Sold creditor 455 |
sold_casa_peste_limita | Depășește plafonul legal (sold_casa_legal) |
stare_anaf_label / stare_onrc_label | Starea curentă la ANAF (activă/radiată/inactiv fiscal) și la Registrul Comerțului |
fara_date | Doar cu an+luna: firmele contului fără SAF-T pe luna cerută |
3. Monitorizare parteneri — GET /api/v1/monitorizare-parteneri
Partenerii din lista de monitorizare, cu statusul curent la ANAF (re-verificat automat, zilnic):
{
"parteneri": [
{ "cui": "12345678", "company_name": "PARTENER SRL", "nota": "furnizor principal",
"last_check": "2026-07-21T04:00:12.000Z",
"status_activ": 1, "status_tva": 1, "status_tva_incasare": 0,
"status_split_tva": 0, "status_inactiv": 0,
"alerta": "TVA la încasare", "created_at": "2026-05-02T09:14:00.000Z" }
]
}
Statusurile sunt 1/0 (status_activ poate fi null = necunoscut la ANAF);
alerta e sinteza textuală a problemelor (radiată, inactiv fiscal, neplătitor de TVA etc.),
null când totul e în regulă.
Limite și restricții
| Parametru | Valoare |
|---|---|
| Rate limit (verify-saft) | 10 request-uri / minut per IP |
| Rate limit (API v1 cu cheie) | 60 request-uri / minut per cheie |
| Rate limit (GET /firma/:cui) | 1 request / 2 secunde per cheie |
| Dimensiune maximă fișier | 100 MB |
| Fișiere per lot (upload/declaratii) | 10 |
| Validitate link PDF (verify-saft) | 24 ore |
| Validitate link-uri report-links / joburi | 7 zile |
| Formate acceptate | XML (SAF-T D.406, D300, D394, D390) și PDF ANAF (cu XML încorporat) |
| Abonament necesar | Complet pentru SAF-T; D394 sau Complet pentru loturile doar cu declarații (D300/D394/D390) |