API për zhvilluesit e 4invoices

REST mbi HTTPS, JSON, një specifikim OpenAPI publik. Faturim, klientë, seri dhe cikli i plotë i faturimit elektronik kombëtar (ANAF e-Factura në Rumani) — nga ERP-ja, dyqani ose CRM-ja jote.

API publike e 4invoices dërgon të dhënat e faturimit nga sistemi yt te 4invoices dhe e çon faturën deri në sistemin kombëtar të e-faturimit (në Rumani: SPV i ANAF). Një host i vetëm në prodhim, një rrjedhë client_credentials, shkrime fiskale idempotente dhe një zarf i vetëm gabimi në çdo rrugë.

https://api.4invoices.net/v1 · Specifikimi OpenAPI (pa çelës)

Çfarë është API e 4invoices

  • API publike e 4invoices është REST mbi HTTPS, me JSON hyrës dhe dalës.
  • Një host i vetëm në prodhim: https://api.4invoices.net/v1. Nuk ka host të veçantë sandbox.
  • Specifikimi OpenAPI 3.1 është publik dhe pa çelës — importoje direkt në Postman ose në një gjenerues klientësh.
  • Çdo përgjigje mban header-in X-Request-Id; citoje kur kërkon mbështetje.
  • Çdo shkrim fiskal është idempotent: një rinisje pas timeout-it s'lëshon kurrë dokument të dytë.
Vetëm server-me-server. Mos e thirr kurrë API nga JavaScript i shfletuesit: client_secret do të arrinte te vizitori, dhe CORS e bllokon çdo origjinë në çdo rast.
  • E gjithë rrjedha e e-faturimit kombëtar përmes API (në Rumani: e-Factura ANAF): verifikimi paraprak, paraqitja, ndjekja, përgjigja e nënshkruar dhe kutia hyrëse e marrjes. Asnjë konkurrent rumun s'e ekspozon këtë.
  • SmartBill nuk ka asnjë pikë fundore për dërgimin në sistemin kombëtar të e-faturimit (ANAF, në Rumani) — dërgimi është vetëm një cilësim llogarie në ndërfaqe — dhe as nuk ka fare pikë fundore për listimin e faturave.
  • Oblio mund të krijojë klientë dhe produkte vetëm si efekt anësor i lëshimit të një dokumenti, jo si burime të veçanta.
  • Gjenerimi i XML UBL pa paraqitje (CIUS-RO për Rumaninë): merr dokumentin ligjor si skedar pa prekur sistemin kombëtar të e-faturimit.
  • Idempotencë te shkrimet fiskale: një riprovim pas timeout-it s'prodhon faturë të dytë dhe s'harxhon numër të dytë.
  • Një kuti hyrëse e lexueshme programatikisht e faturave të furnitorëve — baza e pajtimit automatik.

Fatura jote e parë në 6 hapa

Para thirrjes së parë
  1. Krijo një kredencial në panel te Faturim → Cilësime → Aksesi API dhe kopjo client_secret — shfaqet vetëm një herë.
  2. Plotëso profilin e kompanisë dhe aktivizo të paktën një seri të tipit fiscale; përndryshe lëshimi kthen issuer_profile_incomplete ose no_series_configured.
  1. Krijo një kredencial në panel te Faturim → Cilësime → Aksesi API dhe kopjo client_secret — shfaqet vetëm një herë.
  2. Plotëso profilin e kompanisë dhe aktivizo të paktën një seri të tipit fiscale; përndryshe lëshimi kthen issuer_profile_incomplete ose no_series_configured.
  3. Shkëmbe kredencialin me një token: POST /v1/auth/token me grant_type client_credentials. Tokeni vlen një orë — ruaje në memorie të përkohshme, mos kërko një për çdo kërkesë.
  4. Lësho faturën: POST /v1/invoices me header-in Idempotency-Key dhe vat_rate si përqindje (21, jo 0,21).
  5. Bëj verifikimin paraprak (CIUS-RO për Rumaninë) me POST /v1/invoices/{id}/efactura/validate, pastaj dërgoje në sistemin kombëtar të e-faturimit me POST /v1/invoices/{id}/efactura/submit.
  6. Ndiq gjendjen me GET /v1/efactura/submissions/{id} derisa të arrijë accepted ose rejected.
bash
# 1 — token (1 orë, ruaje në memorie të përkohshme)
ACCESS_TOKEN=$(curl -sS -X POST https://api.4invoices.net/v1/auth/token \
  -H 'Content-Type: application/json' \
  -d '{"grant_type":"client_credentials","client_id":"cli_XXX","client_secret":"sec_XXX"}' \
  | python3 -c 'import sys,json; print(json.load(sys.stdin)["access_token"])')

# 2 — lësho faturën (Idempotency-Key është I DETYRUESHËM)
curl -sS -X POST https://api.4invoices.net/v1/invoices \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-10457-invoice' \
  -d '{"buyer":{"name":"Exemplu Comert SRL","tax_id":"RO12345678","county":"Cluj","city":"Cluj-Napoca","country":"RO"},
       "lines":[{"description":"Abonament SaaS","quantity":1,"unit_price":400,"vat_rate":21}]}'

# 3 — preflight CIUS-RO, then send to ANAF
curl -sS -X POST https://api.4invoices.net/v1/invoices/inv_01J7ABC/efactura/validate \
  -H "Authorization: Bearer $ACCESS_TOKEN"

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'
javascript
const BASE = "https://api.4invoices.net/v1";

const token = await fetch(`${BASE}/auth/token`, {
  method: "POST",
  headers: { "Content-Type": "application/json" },
  body: JSON.stringify({
    grant_type: "client_credentials",
    client_id: process.env.FOURINVOICES_CLIENT_ID,
    client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
  }),
}).then((r) => r.json()).then((d) => d.access_token);

const invoice = await fetch(`${BASE}/invoices`, {
  method: "POST",
  headers: {
    Authorization: `Bearer ${token}`,
    "Content-Type": "application/json",
    "Idempotency-Key": `order-${orderId}-invoice`,
  },
  body: JSON.stringify({
    buyer: { name: "Exemplu Comert SRL", tax_id: "RO12345678", county: "Cluj", city: "Cluj-Napoca", country: "RO" },
    lines: [{ description: "Abonament SaaS", quantity: 1, unit_price: 400, vat_rate: 21 }],
    currency: "RON",
    metadata: { order_id: String(orderId) },
  }),
}).then((r) => r.json());

console.log(invoice.number, invoice.totals); // "FCT-000123" { net, vat, gross }
python
import os, uuid, requests

BASE = "https://api.4invoices.net/v1"

token = requests.post(f"{BASE}/auth/token", json={
    "grant_type": "client_credentials",
    "client_id": os.environ["FOURINVOICES_CLIENT_ID"],
    "client_secret": os.environ["FOURINVOICES_CLIENT_SECRET"],
}, timeout=30).json()["access_token"]

headers = {
    "Authorization": f"Bearer {token}",
    # Një çelës për çdo operacion LOGJIK — ripërdore në riprovim, mos e rigjenero kurrë.
    "Idempotency-Key": f"order-{order_id}-invoice",
}

invoice = requests.post(f"{BASE}/invoices", headers=headers, json={
    "buyer": {"name": "Exemplu Comert SRL", "tax_id": "RO12345678",
              "county": "Cluj", "city": "Cluj-Napoca", "country": "RO"},
    "lines": [{"description": "Abonament SaaS", "quantity": 1,
               "unit_price": 400, "vat_rate": 21}],   # përqindje, jo 0,21
    "currency": "RON",
}, timeout=60).json()

print(invoice["number"], invoice["totals"])

Autentikimi

  • Rrjedha është client_credentials: shkëmben client_id + client_secret me një access_token Bearer.
  • Tokeni skadon pas 3600 sekondash. Rinovoje para skadimit, jo në çdo thirrje — POST /auth/token ka kufirin e vet për IP.
  • client_secret ruhet vetëm si hash dhe s'mund të rikuperohet. Nëse e humbet, krijon një kredencial të re dhe revokon të vjetrën.
  • Vetëm server-me-server. Asnjë origjinë shfletuesi s'kalon CORS: nga JavaScript i faqes sekreti do t'i rrjedhte vizitorit.
  • Fushëveprimet jepen për kredencial. Krijo një kredencial të veçantë për çdo sistem dhe jep çdonjërit minimumin e fushëveprimeve që i duhen.

Faturim → Cilësime → Aksesi API

bash
curl -sS -X POST https://api.4invoices.net/v1/auth/token \
  -H 'Content-Type: application/json' \
  -d '{
    "grant_type": "client_credentials",
    "client_id": "cli_XXXXXXXXXXXX",
    "client_secret": "sec_XXXXXXXXXXXXXXXXXXXX"
  }'

# → {"access_token":"eyJ...","token_type":"Bearer","expires_in":3600,
#    "scope":"invoices:read invoices:write efactura:submit"}
javascript
// Ruaje tokenin në memorie të përkohshme; mos krijo një për çdo kërkesë.
let cached = { token: "", expiresAt: 0 };

async function getToken() {
  if (cached.token && Date.now() < cached.expiresAt - 60_000) return cached.token;

  const res = await fetch("https://api.4invoices.net/v1/auth/token", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      grant_type: "client_credentials",
      client_id: process.env.FOURINVOICES_CLIENT_ID,
      client_secret: process.env.FOURINVOICES_CLIENT_SECRET,
    }),
  });
  if (!res.ok) throw new Error(`token ${res.status}`);

  const data = await res.json();
  cached = { token: data.access_token, expiresAt: Date.now() + data.expires_in * 1000 };
  return cached.token;
}

Normat e TVSH-së janë përqindje

vat_rate: 21 ✓  ·  vat_rate: 0.19 ✗  ·  vat_rate: 1 ✗
  • vat_rate është PËRQINDJE: 21 do të thotë 21%.
  • Vlerat në (0, 1] refuzohen — 0,19 është thyesë, dhe 1 është e paqartë midis 1% dhe 100%.
  • 0 është e vlefshme dhe do të thotë e përjashtuar ose reverse charge (tatimi i kundërt); vendos shënimin ligjor te notes.
  • unit_price është ÇMIMI NJËSI NETO kur lëshuesi është tatimpagues i TVSH-së.
  • Të duhen totalet përpara se të angazhohesh? POST /v1/invoices/preview-totals kryen të njëjtën aritmetikë pa konsumuar asnjë numër fiskal.

Idempotenca te shkrimet fiskale

  • Header-i Idempotency-Key është I DETYRUESHËM te POST /invoices, POST /invoices/{id}/storno dhe POST /invoices/{id}/efactura/submit.
  • Çelësat mbahen mend për 24 orë. Përsëritja e të njëjtit çelës me të njëjtin body kthen rezultatin origjinal dhe vendos Idempotency-Replayed: true.
  • I njëjti çelës me body tjetër kthen 409 idempotency_key_reuse — një dokument fiskal i lëshuar tashmë nuk mbishkruhet kurrë.
  • Një çelës për çdo operacion LOGJIK, jo për çdo tentativë HTTP: order-10457-invoice, jo një UUID të ri në çdo riprovim.
  • Arsyeja është ligjore, jo teknike: një numër fiskal i konsumuar dhe një faturë e paraqitur në sistemin kombëtar të e-faturimit nuk mund të tërhiqen.
bash
curl -sS -X POST https://api.4invoices.net/v1/invoices \
  -H "Authorization: Bearer $ACCESS_TOKEN" \
  -H 'Content-Type: application/json' \
  -H 'Idempotency-Key: order-10457-invoice' \
  -d '{
    "buyer": {
      "name": "Exemplu Comert SRL",
      "tax_id": "RO12345678",
      "address": "Str. Fabricii 12",
      "city": "Cluj-Napoca",
      "county": "Cluj",
      "country": "RO",
      "email": "[email protected]"
    },
    "lines": [
      { "description": "Abonament SaaS, iulie", "quantity": 1, "unit_price": 400, "vat_rate": 21, "unit": "buc" },
      { "description": "Implementare", "quantity": 6, "unit_price": 250, "vat_rate": 21, "unit": "ora" }
    ],
    "currency": "RON",
    "document_kind": "factura",
    "due_date": "2026-08-15",
    "metadata": { "order_id": "10457" }
  }'

Çdo pikë fundore

MetodaPika fundoreFushëveprimiIdempotency-KeyKërkesa / minutë
POST/auth/token
Shkëmbe kredencialet me një token aksesi
——120
GET/me
Klienti, fushëveprimet dhe kufijtë aktualë
invoices:read—120
POST/invoices
Lëshon një faturë ose proformë
invoices:writee detyrueshme30
GET/invoices
Liston faturat (faqosje me kursor)
invoices:read—120
POST/invoices/preview-totals
Llogarit totalet pa krijuar asgjë
invoices:read—120
GET/invoices/{invoice_id}
Merr një faturë
invoices:read—120
GET/invoices/{invoice_id}/pdf
Shkarkon PDF-në e faturës
invoices:read—120
GET/invoices/{invoice_id}/xml
Shkarkon XML-in UBL (CIUS-RO për Rumaninë)
invoices:read—120
POST/invoices/{invoice_id}/storno
Lëshon një notë kredie që anulon këtë faturë
invoices:writee detyrueshme30
POST/invoices/{invoice_id}/payments
Shënon faturën si të paguar
invoices:write—30
DELETE/invoices/{invoice_id}/payments
Shënon faturën si të papaguar
invoices:write—30
GET/clients
Liston klientët
clients:read—120
POST/clients
Krijon ose përditëson një klient
clients:write—30
GET/lookup/company/{tax_id}
Validon një numër tatimor në regjistrin zyrtar (në Rumani: ANAF)
clients:read—120
GET/series
Liston seritë e numërimit
invoices:read—120
POST/invoices/{invoice_id}/efactura/validate
Verifikim paraprak — validon pa dërguar
efactura:read—120
POST/invoices/{invoice_id}/efactura/submit
Paraqet faturën në sistemin kombëtar të e-faturimit
efactura:submite detyrueshme10
GET/efactura/submissions
Liston paraqitjet në sistemin kombëtar
efactura:read—120
GET/efactura/submissions/{submission_id}
Merr një paraqitje
efactura:read—120
POST/efactura/submissions/{submission_id}/refresh
Kërkon gjendjen aktuale nga sistemi kombëtar
efactura:read—10
GET/efactura/submissions/{submission_id}/download
Shkarkon arkivin e përgjigjes së nënshkruar
efactura:read—120
GET/efactura/inbox
Faturat e furnitorëve të marra përmes sistemit kombëtar
efactura:read—120
GET/efactura/inbox/{inbound_id}
Merr një faturë hyrëse
efactura:read—120
GET/efactura/inbox/{inbound_id}/download
Shkarkon arkivin e faturës hyrëse
efactura:read—120
POST/efactura/inbox/sync
Tërheq mesazhet e reja të sistemit kombëtar në kutinë hyrëse
efactura:read—10

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

Fushëveprimet

  • invoices:read
  • invoices:write
  • clients:read
  • clients:write
  • efactura:read
  • efactura:submit

Cikli i e-faturimit kombëtar

not_sentvalidatingqueuedsentprocessingacceptedrejectederror
  • Dallimi kryesor: e gjithë rrjedha drejt sistemit kombëtar të e-faturimit kryhet përmes API, jo vetëm gjenerimi i dokumentit.
  • POST /invoices/{id}/efactura/validate kryen verifikimin paraprak (CIUS-RO për Rumaninë) dhe kthen fushat e sakta që sistemi kombëtar i e-faturimit do t'i refuzonte, pa dërguar asgjë.
  • GET /invoices/{id}/xml gjeneron XML-in UBL (CIUS-RO për Rumaninë) pa asnjë paraqitje — i dobishëm për arkivin tënd ose për një auditim të brendshëm.
  • POST /invoices/{id}/efactura/submit e paraqet në sistemin kombëtar të e-faturimit. Është e pakthyeshme: një kopje e dytë e së njëjtës faturë nuk mund të tërhiqet nga sistemi.
  • Cikli i jetës është i normalizuar: not_sent → validating → queued → sent → processing → accepted | rejected | error. accepted do të thotë e transmetuar ligjërisht; error është dështim transporti nga ana jonë dhe mund të riprovohet pa rrezik.
  • GET /efactura/submissions/{id}/download merr arkivin me përgjigjen e nënshkruar të sistemit kombëtar të e-faturimit.
  • Ekziston edhe krahu i marrjes: POST /efactura/inbox/sync tërheq mesazhet e reja nga sistemi kombëtar i e-faturimit, dhe GET /efactura/inbox liston faturat që t'ua kanë dërguar furnitorët e tu.
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)

Gabimet

  • Çdo 4xx dhe 5xx përdor të njëjtin zarf: { "error": { type, code, message, param?, doc_url, request_id, errors? } }.
  • type është klasa e përgjithshme sipas së cilës vendos («mund ta riprovoj?»), dhe code është arsyeja e qëndrueshme që e lidh me sistemin tënd.
  • param është rruga me pika e fushës problematike, për shembull lines.0.vat_rate.
  • errors[] shfaqet kur një kërkesë e vetme ka probleme në më shumë se një fushë.
  • request_id regjistrohet nga ana jonë. Citoje në çdo kërkesë për mbështetje — e lidh me kërkesën e saktë.
  • Kthehet gjithashtu 404 për një id që i përket një tjetri klient: ne nuk konfirmojmë kurrë që ekzistojnë të dhënat e dikujt tjetër.
json
{
  "error": {
    "type": "invalid_request_error",
    "code": "validation_failed",
    "message": "Datele trimise nu sunt valide.",
    "param": "lines.0.vat_rate",
    "doc_url": "https://4invoices.net/ro/api-dezvoltatori#errors",
    "request_id": "req_8a893f2f33d4472da8d6e144",
    "errors": [
      { "param": "lines.0.vat_rate", "message": "VAT rate must be a percent (21), not a fraction", "type": "value_error" }
    ]
  }
}
StatusiLlojiKodi
401authentication_errormissing_bearer_token
401authentication_errorinvalid_client
401authentication_errortoken_expired
401authentication_errorinvalid_token
401authentication_errorunauthorized
403permission_errorinsufficient_scope
403permission_errorforbidden
404not_found_errornot_found
409conflict_erroridempotency_key_reuse
409conflict_erroridempotency_in_progress
409conflict_errorno_series_configured
422invalid_request_errorvalidation_failed
422invalid_request_errorissuer_profile_incomplete
422invalid_request_errorcius_ro_incomplete
422invalid_request_errorcannot_storno_draft
422invalid_request_errornothing_to_storno
422invalid_request_errorinvalid_json_number
429rate_limit_errorrate_limit_exceeded
502upstream_errorupstream_error
503service_unavailable_errorservice_unavailable

Kufijtë e kërkesave

GrupiKërkesa / minutëÇfarë do të thotë
read120GET *, POST /invoices/preview-totals, POST /invoices/{id}/efactura/validate
write30POST /invoices, POST /invoices/{id}/storno, POST|DELETE /invoices/{id}/payments, POST /clients
submit10POST /invoices/{id}/efactura/submit, POST /efactura/submissions/{id}/refresh, POST /efactura/inbox/sync
  • Kufijtë janë për kredencial, për minutë: 120 për leximet, 30 për shkrimet, 10 për operacionet e e-faturimit (submit, refresh, inbox/sync).
  • X-RateLimit-Limit, X-RateLimit-Remaining dhe X-RateLimit-Reset shfaqen në ÇDO përgjigje, përfshirë 429.
  • Një 429 mban edhe Retry-After në sekonda. Respektoje; mos riprovo në një cikël të ngushtë.
  • Grupi 10/minutë ekziston sepse në Rumani vetë ANAF lejon afërsisht një thirrje listimi mesazhesh për minutë për CIF.
  • Vendose /efactura/inbox/sync në një cron, jo në një polling agresiv.
  • Të duhen tavane më të larta? Kërkoje përmes Kontaktit, duke treguar vëllimin tënd ditor të pritshëm.

X-RateLimit-Limit · X-RateLimit-Remaining · X-RateLimit-Reset · Retry-After

http
HTTP/2 429
X-RateLimit-Limit: 30
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1785312000
Retry-After: 17
Content-Type: application/json

{"error":{"type":"rate_limit_error","code":"rate_limit_exceeded",
 "message":"...","doc_url":"https://4invoices.net/ro/api-dezvoltatori#errors",
 "request_id":"req_..."}}
javascript
// Respekto Retry-After; mos riprovo kurrë një 4xx tjetër përveç 429.
async function call(url, init, attempt = 0) {
  const res = await fetch(url, init);
  if (res.status === 429 || res.status >= 500) {
    if (attempt >= 5) return res;
    const retryAfter = Number(res.headers.get("Retry-After")) || 2 ** attempt;
    await new Promise((r) => setTimeout(r, retryAfter * 1000));
    return call(url, init, attempt + 1);
  }
  return res;
}

// Riprovimi i një shkrimi DUHET të ripërdorë të NJËJTIN Idempotency-Key, përndryshe lëshon
// një dokument të dytë fiskal.

Udhëzues sipas temës

Çdo temë ka faqen e vet me pikat fundore, shembujt dhe gabimet përkatëse.

Gabimet e zakonshme

  • Dërgimi i TVSH-së si thyesë (0,19) ose si 1. Të dyja refuzohen; dërgo 19 ose 21.
  • Krijimi i një tokeni për çdo kërkesë. Tokeni vlen një orë; ruaje në memorie të përkohshme, përndryshe do të bjerësh në kufirin për IP të pikës fundore të tokenit.
  • Gjenerimi i një çelësi idempotence të ri në çdo riprovim — pikërisht skenari që prodhon fatura të dyfishta.
  • Thirrja nga JavaScript i shfletuesit. CORS bllokon çdo origjinë dhe sekreti do të ekspozohej gjithsesi.
  • Paraqitja në sistemin kombëtar të e-faturimit pa verifikimin paraprak. Një dorëzim i gabuar nuk mund të tërhiqet.
  • Pyetja e /efactura/submissions/{id}/refresh më shumë se 10 herë në minutë — ky grup ndahet me submit.
  • Lëshimi i faturave para se profili i kompanisë të jetë i plotë dhe të ekzistojë një seri fiskale aktive.

Pyetje dhe përgjigje për zhvilluesit

Si i marr kredencialet e API-t të 4invoices?

Në panel, te Faturim → Cilësime → Aksesi API. Merr një client_id dhe një client_secret; sekreti shfaqet vetëm një herë dhe ruhet vetëm si hash.

Sa vlen access_token?

3600 sekonda, pra një orë. Ruaje në memorie të përkohshme dhe rinovoje para skadimit — pika fundore e tokenit ka kufirin e vet të kërkesave për IP.

Si e dërgoj normën e TVSH-së?

Si përqindje: 21 për 21%. Vlerat në (0, 1] refuzohen, pra si 0,19 ashtu edhe 1 dështojnë në validim.

Cilat thirrje kërkojnë Idempotency-Key?

POST /invoices, POST /invoices/{id}/storno dhe POST /invoices/{id}/efactura/submit. Çelësat mbahen mend për 24 orë, dhe një përsëritje kthen dokumentin origjinal me Idempotency-Replayed: true.

A mund ta dërgoj një faturë në sistemin kombëtar të e-faturimit direkt nga API?

Po. Bëj verifikimin paraprak me /efactura/validate, paraqite me /efactura/submit, pyet statusin e normalizuar te /efactura/submissions/{id} dhe shkarko përgjigjen e nënshkruar të sistemit (në Rumani: ANAF).

Cilët janë kufijtë e kërkesave?

Për kredencial, për minutë: 120 leximë, 30 shkrime dhe 10 operacione e-faturimi. Çdo përgjigje mban titujt X-RateLimit-*, dhe një 429 shton Retry-After.

A mund ta thirr API nga frontend-i im?

Jo. Është vetëm server-me-server: asnjë origjinë shfletuesi nuk kalon CORS, dhe client_secret nuk ka vend në kodin që arrin te vizitori.

Pse marr issuer_profile_incomplete në faturën e parë?

Profili i kompanisë është i paplotë ose s'ka asnjë seri aktive të tipit fiscale. Plotësoji të dyja në panel; API refuzon të prodhojë një dokument fiskal të pavlefshëm.