e-Factura ANAF prin API

Preflight CIUS-RO, depunere în SPV, stare normalizată, răspuns semnat și inbox de facturi primite.

Preflight CIUS-RO, depunere în SPV, stare normalizată, răspuns semnat și inbox de facturi primite.

← Înapoi la documentația API

Prima factură în 6 pași

  1. Rulează POST /v1/invoices/{id}/efactura/validate. Preflight-ul CIUS-RO nu trimite nimic la ANAF și îți spune exact ce ar fi respins.
  2. Depune cu POST /v1/invoices/{id}/efactura/submit, obligatoriu cu Idempotency-Key. Primești submission_id și status.
  3. Urmărește GET /v1/efactura/submissions/{id} până ajunge în accepted sau rejected.
  4. Forțează o interogare la ANAF cu POST /v1/efactura/submissions/{id}/refresh — intră în bucketul de 10 pe minut.
  5. Descarcă arhiva cu răspunsul semnat de la ANAF prin GET /v1/efactura/submissions/{id}/download.

Toate endpoint-urile

MetodăEndpointScopeIdempotency-KeyCereri / minut
GET/invoices/{invoice_id}/xml
Descarcă XML-ul UBL / CIUS-RO
invoices:read—120
POST/invoices/{invoice_id}/efactura/validate
Preflight CIUS-RO — validează fără trimitere
efactura:read—120
POST/invoices/{invoice_id}/efactura/submit
Trimite factura la ANAF (SPV)
efactura:submitobligatoriu10
GET/efactura/submissions
Listează transmiterile către ANAF
efactura:read—120
GET/efactura/submissions/{submission_id}
Returnează o transmitere
efactura:read—120
POST/efactura/submissions/{submission_id}/refresh
Întreabă ANAF starea curentă
efactura:read—10
GET/efactura/submissions/{submission_id}/download
Descarcă arhiva răspunsului semnat
efactura:read—120
GET/efactura/inbox
Facturile primite de la furnizori prin SPV
efactura:read—120
GET/efactura/inbox/{inbound_id}
Returnează o factură primită
efactura:read—120
GET/efactura/inbox/{inbound_id}/download
Descarcă arhiva facturii primite
efactura:read—120
POST/efactura/inbox/sync
Trage mesajele noi din SPV în inbox
efactura:read—10

Ce este API-ul 4invoices

bash
# CIUS-RO preflight. Sends NOTHING to ANAF.
curl -sS -X POST "https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/validate?include_xml=true" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# → {"invoice_id":"inv_01J7ABC","valid":false,
#    "errors":["buyer.county is required for RO buyers"],
#    "xml_base64":"PD94bWwg..."}
bash
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/submit \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Idempotency-Key: efactura-inv_01J7ABC-1'

# → {"submission_id":"sub_01J7XYZ","status":"queued"}
python
import time, requests

BASE = "https://api.4invoices.net/v1"
TERMINAL = {"accepted", "rejected"}
H = {"Authorization": f"Bearer {token}"}

def wait_for_anaf(submission_id, timeout=900):
    deadline = time.time() + timeout
    delay = 15
    while time.time() < deadline:
        r = requests.get(f"{BASE}/efactura/submissions/{submission_id}", headers=H, timeout=30)
        r.raise_for_status()
        status = r.json()["status"]
        if status in TERMINAL:
            return r.json()
        # /refresh asks ANAF directly and shares the 10/min submit bucket.
        requests.post(f"{BASE}/efactura/submissions/{submission_id}/refresh", headers=H, timeout=30)
        time.sleep(delay)
        delay = min(delay * 2, 120)
    raise TimeoutError(submission_id)
bash
# Pull new SPV messages, then read the inbound supplier invoices.
curl -sS -X POST https://api.4invoices.net/v1/efactura/inbox/sync \
  -H "Authorization: Bearer $ACCESS_TOKEN"

curl -sS "https://api.4invoices.net/v1/efactura/inbox?limit=50" \
  -H "Authorization: Bearer $ACCESS_TOKEN"

# ANAF allows roughly ONE message-list call per minute per CIF,
# deci /inbox/sync consumă din cota de 10/min. Programează-l cu cron, nu-l interoga.

https://api.4invoices.net/v1 · https://api.4invoices.net/v1/openapi.json

Circuitul ANAF e-Factura

not_sentvalidatingqueuedsentprocessingacceptedrejectederror

Erori

StatusTipCod
422invalid_request_errorcius_ro_incomplete

Greșeli frecvente

  • Ciclul de viață normalizat: not_sent → validating → queued → sent → processing → accepted | rejected | error.
  • accepted înseamnă transmis legal. rejected înseamnă că ANAF a refuzat: corectezi și depui din nou. error este o problemă de transport la noi și se poate reîncerca.
  • Depunerea este ireversibilă: o a doua copie a aceleiași facturi nu se poate retrage din SPV. De aceea Idempotency-Key este obligatoriu.
  • GET /v1/invoices/{id}/xml îți dă XML-ul UBL / CIUS-RO fără nicio depunere — pentru arhivă proprie sau audit.
  • Inbox: POST /v1/efactura/inbox/sync trage mesajele noi, GET /v1/efactura/inbox le listează, iar /download aduce arhiva fiecărei facturi primite.
  • Endpoint-urile e-Factura funcționează doar pentru tenanți români; altfel primești 404.

Întrebări frecvente de la dezvoltatori

Cât durează până ANAF acceptă o factură?

Variabil, de la secunde la ore. Nu bloca procesul de vânzare: depune asincron și tratează accepted și rejected ca evenimente.

Pot lua XML-ul CIUS-RO fără să trimit la ANAF?

Da. GET /v1/invoices/{id}/xml generează documentul fără depunere, iar /efactura/validate cu include_xml=true îl întoarce în base64.

Cât de des pot rula inbox/sync?

Maximum 10 apeluri pe minut, dar în practică ANAF permite aproximativ o listare de mesaje pe minut per CIF. Rulează-l din cron, la câteva minute.

Ce fac dacă starea rămâne error?

error este o eroare de transport sau autentificare la noi, deci se poate reîncerca. Dacă persistă, trimite request_id la suport.