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.

Cerință: Cont activ pe AnalizaFiscala.ro cu abonament Complet (lunar sau anual) pentru verificarea declarațiilor și rapoarte. Puteți crea un cont și activa trial-ul gratuit de 15 zile aici.
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.

HeaderValoareObligatoriu
X-Api-KeyCheia API a contuluiDa
Content-Typeapplication/xml sau text/xml (la verify-saft)Da

Verificare SAF-T

POST https://analizafiscala.ro/api/public/verify-saft

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.

Disponibil pe orice plan, inclusiv gratuit. Necesită doar o cheie API validă (o generați din Contul meu → Integrare API). Din considerente de protecție a datelor personale, nu se returnează data și locul nașterii administratorilor.
GET https://analizafiscala.ro/api/v1/firma/{cui}

Headers

X-Api-Key: cheia_dvs_api

Parametru

ParametruDescriere
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âmpTipDescriere
statusstringÎntotdeauna "ok"
importIdnumberID-ul importului creat — folosiți-l pentru referință
links.rezultatstringURL direct către pagina de verificări din aplicație (necesită autentificare)
links.raportAuditstringURL semnat pentru descărcarea PDF-ului de audit (valid 24h, fără autentificare)
sumar.totalnumberNumărul total de verificări efectuate
sumar.erorinumberVerificări cu status „eroare"
sumar.avertismentenumberVerificări cu status „avertisment"
sumar.oknumberVerifică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)."
}
GET https://analizafiscala.ro/api/public/verify-saft/{id}/pdf?token=...

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.

Atenție: Link-ul PDF este temporar (24h). Dacă aveți nevoie de acces permanent, salvați PDF-ul local sau accesați rezultatele prin interfața web cu contul dvs.

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:

EndpointDescriere
GET /api/v1/importsLista importurilor SAF-T
GET /api/v1/imports/:idDetalii import
GET /api/v1/imports/:id/verificariRezultatele verificărilor
GET /api/v1/imports/:id/balantaBalanța de verificare
GET /api/v1/imports/:id/report-linksLink-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/d394Lista importurilor D394/D390
GET /api/v1/d394/:id/verificariRezultatele verificărilor D394/D390
POST /api/v1/onrc/verify-cuisVerificare ONRC în lot (max 100 CUI-uri)
POST /api/v1/upload/saftUpload SAF-T (multipart)
POST /api/v1/upload/d394 sau /upload/d390Upload D394/D390 — același endpoint sub ambele nume; tipul declarației se detectează automat din conținut
POST /api/v1/upload/declaratiiUpload în lot: SAF-T + D300/D394/D390 (detectare automată a tipului) — asincron, cu job
GET /api/v1/job/:idStarea și rezultatul (sumar) al unui job de upload în lot
GET /api/v1/job/:id/raportRaportul unic al jobului: toate verificările (SAF-T + D394/D390 + corelări), o singură listă per firmă
GET /api/v1/comparatii/:idDetaliile unei corelări declarație ↔ SAF-T (D300/D394/D390)
GET /api/v1/firmeLista firmelor gestionate
GET /api/v1/portofoliuPortofoliul 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-parteneriPartenerii monitorizați, cu status ANAF curent (activ/radiat, TVA, TVA la încasare, inactiv) și alerte
GET /api/v1/firma/:cuiDate 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

GET https://analizafiscala.ro/api/v1/raport-firma?cui=…&an=…&luna=…

Î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țieComportament
D300Nu 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 / D390Au 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 lotDeclarația e respinsă cu motivul „nu aparține firmei".
Fișier nerecunoscutRespins individual; restul lotului se procesează normal.
JoburiRezultatele 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âmpSemnificație
ultima_luna_saftUltima lună acoperită de un SAF-T (după perioadă, nu după data încărcării)
ultima_decl / ultima_decl_tipUltima D394 sau D390 (oricare mai recentă) și tipul ei; null dacă nu există
nr_note_contabileTranzacții distincte în jurnalul (GLE) ultimului SAF-T
nr_conturi_bancareAnaliticele la 5121 și 5124 din planul de conturi
are_salariatiExistă rulaj pe 641 în GLE
sold_casaSold final debitor cumulat pe conturile 5311
email / email_saftemail = 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âmpSemnificație
cifra_afaceriYTD — rulaj creditor 70x, cumulat pe toate declarațiile anului până la luna de referință
profit_pierdereSold 121 (pozitiv = profit, negativ = pierdere)
datorii_statSolduri creditoare clasa 44 (fără 4428)
active_nete / eligibil_dividendeCapitaluri proprii (cls 1 fără 15x/16x); eligibilitatea pentru dividende interimare
imprumut_asociatiSold creditor 455
sold_casa_peste_limitaDepășește plafonul legal (sold_casa_legal)
stare_anaf_label / stare_onrc_labelStarea curentă la ANAF (activă/radiată/inactiv fiscal) și la Registrul Comerțului
fara_dateDoar 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

ParametruValoare
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șier100 MB
Fișiere per lot (upload/declaratii)10
Validitate link PDF (verify-saft)24 ore
Validitate link-uri report-links / joburi7 zile
Formate acceptateXML (SAF-T D.406, D300, D394, D390) și PDF ANAF (cu XML încorporat)
Abonament necesarComplet pentru SAF-T; D394 sau Complet pentru loturile doar cu declarații (D300/D394/D390)
Întrebări? Contactați-ne la office@medialogic.ro sau deschideți un ticket din aplicație.