Cum obții token-ul OAuth pentru API-urile ANAF (e-Factura, e-Transport, SAF-T)
Ghid pas cu pas: certificat eIDAS, înregistrare aplicație, OAuth2 authorization code, refresh token, troubleshooting și rotație securizată.
Cuprins
Ghid focusat: cum obții token-ul de acces pentru API-urile ANAF (e-Factura, e-Transport, SAF-T) folosind fluxul OAuth2 bazat pe certificat eIDAS. Acoperim prerequizitele, cei patru pași ai flow-ului, refresh-ul programatic, plus erorile cele mai des întâlnite la prima integrare.
Toate API-urile publice ANAF pentru raportare fiscală folosesc același mecanism de autentificare: OAuth2 authorization-code, având constrângerea suplimentară de TLS client certificate la pasul de autorizare. O dată ce ai înțeles flow-ul pentru e-Factura, îl refoloseși identic pentru e-Transport și pentru depunerile SAF-T. Pentru contextul tehnic al fiecărui sistem, vezi entry-urile despre e-Factura și SAF-T.
De ce ai nevoie înainte să obții token-ul ANAF?
Îți trebuie trei lucruri: certificat digital eIDAS calificat, cont activ în SPV și o aplicație înregistrată la ANAF (client_id plus client_secret). Toate trei, înainte de prima cerere către endpoint-ul de autorizare:
- Certificat digital eIDAS calificat, emis de un furnizor acreditat din România (Trans Sped, certSIGN, DigiSign). Tipul potrivit este cel pentru semnătură electronică calificată (QES). Token USB sau soft, ambele funcționează pentru autorizare. Certificatul trebuie să fie asociat cu o persoană fizică autorizată să reprezinte firma (administrator sau împuternicit înregistrat în SPV).
- Cont activ în SPV (Spațiul Privat Virtual) al ANAF, asociat CUI-ului firmei. SPV-ul este locul unde certificatul tău este înregistrat ca dispozitiv autorizat pentru reprezentarea firmei.
- Aplicație înregistrată la ANAF. Prin portalul logout.anaf.ro creezi o aplicație, declari un
redirect_uripublic (URL-ul tău care primește codul de autorizare), și primeșticlient_idșiclient_secret. Stochează ambele ca secrete (vault, env var criptat)1.
Lipsa oricăruia dintre cele trei elemente blochează complet flow-ul. Verifică-le în ordine înainte de a începe codul.
Pasul 1: autorizarea inițială în browser
ANAF nu acceptă autorizare programatică pentru primul token. Trebuie să loghezi efectiv un utilizator (administrator sau împuternicit) având certificatul activ în interfața de autorizare ANAF. Pașii:
- Construiești URL-ul de autorizare:
https://logincert.anaf.ro/anaf-oauth2/v1/authorize, având parametriiresponse_type=code,client_id=<al tău>,redirect_uri=<al tău>,scope=<list permisă>. - Deschizi URL-ul într-un browser care are token-ul USB sau certificatul soft atașat. Selectezi certificatul din lista propusă de browser.
- Confirmi consimțământul în interfața ANAF (apare numele aplicației tale și scope-ul cerut).
- ANAF redirecționează către
redirect_uriavând un parametrucodeîn query string. Endpoint-ul tău preia acest cod și îl trimite imediat spre schimb la pasul următor.
Pentru securitate: redirect_uri trebuie să fie HTTPS în producție și să corespundă exact celei declarate la înregistrare. Variațiile minore (cu sau fără trailing slash) produc respingere.
Pasul 2: schimbul code → token
În handler-ul de pe redirect_uri, faci un POST către endpoint-ul de token trimițând codul primit:
POST https://logincert.anaf.ro/anaf-oauth2/v1/token
Content-Type: application/x-www-form-urlencoded
TLS client certificate atașat
grant_type=authorization_code
&code=<codul primit>
&client_id=<al tău>
&client_secret=<al tău>
&redirect_uri=<al tău>
Răspunsul, în JSON, conține access_token, refresh_token și expires_in (în secunde). Stochezi ambele token-uri securizat.
Cea mai frecventă greșeală aici este absența certificatului client TLS la nivel de transport. În Java cu Apache HttpClient, trebuie să configurezi explicit SSLContext având KeyStore-ul certificatului. În Node.js, biblioteca https nativă acceptă cert și key direct. Fără certificat client, ANAF returnează 401 fără mesaj specific, iar diagnosticul devine dureros.
Pasul 3: refresh-ul programatic
După primul access-token, refresh-ul se face fără browser și fără utilizator. Endpoint-ul:
POST https://logincert.anaf.ro/anaf-oauth2/v1/token
Content-Type: application/x-www-form-urlencoded
TLS client certificate atașat
grant_type=refresh_token
&refresh_token=<al tău>
&client_id=<al tău>
&client_secret=<al tău>
Răspunsul conține un nou access_token (durată ~90 zile) și, în multe cazuri, un nou refresh_token (rotație). Înlocuiește ambele în storage-ul tău.
Strategia practică: planifici un job care rulează zilnic (cron sau scheduled job) și verifică dacă access_token expiră în mai puțin de 7 zile. Dacă da, face refresh proactiv. Asta evită situația în care expirarea cade noaptea, exact când nu monitorizezi.
Pasul 4: folosirea token-ului în apeluri către API
Pentru orice cerere către e-Factura, e-Transport sau SAF-T, atașezi access-token-ul în header-ul Authorization plus certificatul client TLS la nivel de transport:
GET https://api.anaf.ro/prod/FCTEL/rest/stareMesaj?id_incarcare=123456789
Authorization: Bearer <access_token>
TLS client certificate atașat
Atenție: prezența header-ului Authorization NU înlocuiește certificatul client TLS. ANAF cere ambele simultan. Lipsa certificatului produce 401 chiar cu Bearer token valid.
Care sunt erorile comune la obținerea token-ului ANAF?
Cele patru blocaje clasice sunt 400 la autorizare, 401 imediat după un token valid, refresh-token-ul expirat și token-ul valid pentru un API dar invalid pentru altul:
- 400 la autorizare: parametrii
redirect_urisauclient_idnu corespund înregistrării. Verifică în portalul logout.anaf.ro că valorile sunt identice. - 401 imediat după token-ul valid: certificatul client TLS lipsește la nivel de transport. Verifică TLS handshake-ul în log; dacă nu vezi certificatul tău trimis, configurația SSLContext este incorectă.
- Refresh-token expirat: ai trecut peste limita de viață a refresh-token-ului (nu nelimitată, dar lungă). Trebuie să refaci autorizarea inițială manual în browser, ca la prima înregistrare.
- Token valid pentru un API, invalid pentru altul: scope-ul cerut la autorizare nu a inclus serviciul respectiv. Refaci autorizarea având scope-ul corect.
De ce crawlerra pentru OAuth ANAF?
Autentificarea pe API-urile ANAF este partea cel mai puțin documentată din ecosistemul de raportare fiscală RO, iar majoritatea documentațiilor publice nu acoperă cazurile reale: rotație refresh-token, restart-uri de proces care pierd token-ul din memorie, expirări în timpul producției live. La crawlerra construim layer-ul de autentificare ANAF ca un serviciu separat, având stocare securizată în vault, refresh programatic în avans și alertare la eșecuri de refresh2. Aceeași implementare deservește toate API-urile (e-Factura, e-Transport, SAF-T) sub același credential. Pentru cadrul larg al sistemelor pe care le accesezi, vezi e-Factura și SAF-T; pentru semantica generală a tokenilor JWT pe care îi folosesc multe API-uri publice românești, semantica JWT și mecanismul OAuth ajută.
- Documentația oficială ANAF pentru OAuth: logincert.anaf.ro și anaf.ro (secțiunea „Servicii ANAF online" → „API public"). Documentația specifică pentru fiecare API (e-Factura, e-Transport, SAF-T) este publicată la endpoint-urile dedicate. Procedura de înregistrare a aplicației este pas cu pas în portalul logout.anaf.ro.
[seo.anaf_oauth_docs] - Observații pe rotația token-ului în clientul nostru de producție: refresh-ul programatic stabil cere stocare în vault (nu în env var simplu, pentru că restart-urile pierd valoarea actualizată), plus monitoring pe rata de eșec a refresh-urilor. O rată de eșec brusc crescătoare semnalează că refresh-token-ul însuși se apropie de expirare, ceea ce înseamnă că o re-autorizare manuală urmează în zilele următoare.
[crawlerra.anaf_oauth_rotation]
Întrebări frecvente
Pot obține token ANAF doar prin program, fără utilizator în browser?
Nu pentru primul token. Autorizarea inițială cere un utilizator real având certificatul atașat la browser. ANAF urmărește standardul OAuth2 authorization-code, dar adaugă constrângerea de TLS client certificate la pasul de autorizare. După primul token obținut, refresh-ul se poate face programatic, fără browser. Practic, înregistrezi aplicația o dată, faci autorizarea inițială o dată având certificatul activ în browser, apoi sistemul tău se descurcă singur prin refresh.
Cât timp este valabil token-ul?
Access-token-ul are durată de viață scurtă (de regulă 90 de zile); refresh-token-ul, mai mare, dar nu nelimitat. Implementarea recomandată: stochezi refresh-token-ul securizat (vault, env var criptat), planifici un job care reînnoiește access-token-ul în avans, înainte de expirare, și prinzi 401 ca semnal pentru refresh imediat. Refresh-token-ul însuși are limită; dacă fluxul de refresh începe să eșueze, trebuie să refaci autorizarea manuală.
Pot folosi același token pentru e-Factura și e-Transport?
Da, dacă scope-ul autorizării include ambele servicii. ANAF expune mai multe API-uri (e-Factura, e-Transport, SAF-T) sub același mecanism de autorizare; scope-ul cerut la autorizare determină ce poți accesa. Cel mai practic: ceri scope complet la autorizare, refoloseși token-ul pe toate API-urile. Costul este zero suplimentar; complexitatea de gestiune scade.
Cum testez integrarea fără să afectez datele de producție?
ANAF expune un mediu de sandbox separat (api.anaf.ro/test/...) care folosește același mecanism de autorizare ca producția. Înregistrezi aplicația de test separat în portalul ANAF, faci autorizarea cu același certificat, primești token-uri valabile doar pentru endpoint-urile de test. Sandbox-ul acceptă XML-uri și răspunde cu validare, dar nu emite documente fiscale reale. Folosește-l pentru întregul ciclu de dezvoltare și pentru testele automate de regresie.