Fintray Extract — ghid de integrare
Trimiteți o factură primită de clientul dumneavoastră, ca fotografie sau PDF, și primiți înapoi
datele ei structurate, ca JSON. Fiecare endpoint, câmp și eveniment e descris în
referința API, construită din openapi.json (OpenAPI 3.1).
Limitele, politica de versiuni și istoricul modificărilor sunt în Limite și versiuni
și în changelog.
1. Cheia
Primiți două chei:
ftk_test_…(sandbox): fiecare document întoarce aceeași factură fictivă, fără model și fără cost. Cu ea vă construiți integrarea.ftk_live_…(producție): documentele sunt citite pe bune și facturate.
Cheile le emitem noi, la cerere; o cheie sandbox o primiți înainte de orice contract.
GET /v1/whoami verifică o cheie:
curl https://api.fintray.ro/v1/whoami -H "Authorization: Bearer ftk_test_…"
# {"tenant_id": "ten_…", "key_id": "key_…", "mode": "test"}
Cheia merge și în antetul X-API-Key. Orice cheie greșită, revocată sau expirată primește același 401.
2. Trimiterea unui document
POST /v1/documents:
curl https://api.fintray.ro/v1/documents \
-H "Authorization: Bearer ftk_live_…" \
-H "Idempotency-Key: factura-8841" \
-F [email protected] \
-F external_id=factura-8841 \
-F 'metadata={"client_id": "c-102"}' \
-F buyer_vat=RO12345678 \
-F 'buyer_name=Client SRL'
| Câmp | Ce face |
|---|---|
file |
PDF, JPEG, PNG, GIF sau WebP, cel mult 14 MiB și 50 de pagini |
external_id |
identificatorul dumneavoastră, de cel mult 128 de caractere. Nu e unic și se poate filtra după el. |
metadata |
până la 20 de valori scalare, întoarse neschimbate |
buyer_vat |
obligatoriu. CUI-ul firmei care a primit factura, adică al clientului în al cărui cont o încărcați. Un CUI românesc, cu sau fără RO, trebuie să treacă cifra de control. Pentru o firmă din UE, trimiteți codul de TVA cu prefixul țării. Cu el, modelul nu confundă furnizorul cu cumpărătorul, iar răspunsul vă spune dacă factura e într-adevăr a acestui client. |
buyer_name |
opțional, cel mult 200 de caractere. Numele aceleiași firme. |
mode |
async (implicit, răspunde 202) sau sync (așteaptă până la 30 s, apoi 202) |
retention |
standard sau zero (vezi secțiunea 6) |
webhook_url |
https://… pentru acest document. Altfel se folosește URL-ul contului. |
Alternativ, un corp JSON: {"file_base64": "...", "filename": "factura.pdf", "buyer_vat": "RO12345678", "external_id": "..."}.
Un exemplu complet, în Python: examples/submit.py.
Idempotency-Key. Aceeași cheie cu aceeași cerere întoarce același document, cu antetul
Idempotent-Replayed: true. Aceeași cheie cu altă cerere primește 409. Cheia e reținută 24 de ore.
3. Rezultatul
GET /v1/documents/{id}:
curl https://api.fintray.ro/v1/documents/doc_… -H "Authorization: Bearer ftk_live_…"
status trece prin queued → processing → succeeded sau failed. La succeeded, răspunsul conține:
document: furnizor, client, număr, date, monedă, linii, totaluri, IBAN;fields: încrederea per câmp:high(verificat independent),medium(nimic nu-l contrazice) saulow(de verificat înainte de înregistrare);warnings:totals_mismatch,vendor_vat_missing,vendor_vat_unverified,invoice_date_in_future, plus două care compară factura cubuyer_vat:buyer_vat_mismatch: pe factură apare alt client. Ori a fost încărcată în contul greșit, ori nu e adresată acestui client.buyer_is_vendor: CUI-ul trimis apare ca furnizor, deci e o factură emisă de client, nu una primită.
Un câmp high poate fi preluat automat: pe corpusul nostru de evaluare a fost corect în 99,6% din
cazuri. Un câmp low trebuie arătat utilizatorului.
GET /v1/documents?external_id=factura-8841 listează documentele dumneavoastră, cele mai noi primele.
4. Webhook
Când un document se termină, trimitem un POST la webhook_url-ul documentului sau, dacă nu are,
la URL-ul contului (îl setăm noi, la cererea dumneavoastră). Evenimentul e document.succeeded sau
document.failed:
{"type": "document.succeeded", "created_at": "…",
"data": {"id": "doc_…", "object": "document", "external_id": "factura-8841",
"status": "succeeded", "url": "/v1/documents/doc_…"}}
Evenimentul nu conține extracția; o citiți cu GET, cu cheia dumneavoastră. La document.failed,
data.error.code spune de ce. Verificați semnătura din antetul Fintray-Signature cu secretul
whsec_… primit de la noi; exemplul e în examples/verify_webhook.py.
Fintray-Event-Id rămâne același la fiecare reîncercare a unui eveniment, deci deduplicați după el.
Orice răspuns în afară de 2xx e reîncercat timp de 24 de ore. Un eveniment pierdut se cere din nou cu
POST /v1/documents/{id}/webhook.
5. Erori
Toate erorile au forma {"error": {"code": "...", "message": "..."}}. Lista codurilor e în
Coduri de eroare.
6. Retenție și ștergere
retention |
Fișierul | Extracția |
|---|---|---|
standard |
se șterge la 24 h după procesare | se șterge la 30 de zile |
zero |
se șterge imediat după procesare | se șterge la primul GET reușit, cel mult 24 h |
DELETE /v1/documents/{id} șterge documentul: fișierul, extracția și tot ce îl descrie. Rămân doar
statusul, numărul de pagini și datele, pentru facturare.
7. Versiuni, limite, consum
Fintray-Version: antetul fiecărui răspuns. Cheia rămâne pe versiunea de la crearea ei, iar o cerere poate cere explicit alta. Ce garantăm într-o versiune și ce se întâmplă la una nouă: Limite și versiuni.- Limita de rată: 120 de trimiteri pe minut pe cheie, cu rafale de 20. Peste ea primiți
429cuRetry-After. Toate limitele: Limite și versiuni. GET /v1/usage?month=2026-10: documentele și paginile facturabile ale lunii.