REST API za izdavanje fiskalnih računa u Srbiji (e-fiskalizacija Poreske uprave). Ovo je cela površina API-ja — jedan poziv za račun, po jedan za avans, refundaciju, kopiju, predračun i obuku, jedan za zatvaranje avansa, pretraga izdatih računa i lista artikala.
| Bazni URL | https://api.fiskalapi.rs |
|---|---|
| Format | JSON (Content-Type: application/json) |
| Autentikacija | Authorization: Bearer <API_KLJUC> |
Dobijate dva ključa. fapi_test_… radi u sandbox režimu — pravi tok, probni računi, ne naplaćuje se i ne troši limit. fapi_live_… izdaje prave fiskalne račune. Isti pozivi, samo zamenite ključ.
POST /api/racuni — promet prodaja (fiskalni račun)
curl https://api.fiskalapi.rs/api/racuni \
-H "Authorization: Bearer fapi_live_…" \
-H "Content-Type: application/json" \
-d '{
"paymentType": "Card",
"items": [
{ "name": "Pretplata Pro/kom", "quantity": 1, "unitPrice": 2400, "labels": ["А"] }
],
"kupac": { "email": "kupac@primer.rs" }
}'
{
"mode": "live",
"brojRacuna": "NRXJ2JLE-XXXXXXXX-1",
"qrKod": "data:image/png;base64,…",
"verifikacija": "https://suf.purs.gov.rs/v/?vl=…",
"zurnal": "…tekstualni fiskalni isečak…",
"brojaci": { "invoiceCounter": 1, "totalCounter": 1 },
"sdcDateTime": "2026-08-28T12:41:05+02:00"
}
sdcDateTime je vreme koje je računu dodelila Poreska uprava. Sačuvajte ga — ide kao referentDocumentDT kad taj račun budete refundirali. Vraća se i u sandbox režimu.
| Polje | Opis |
|---|---|
items[] | Stavke: name, quantity, unitPrice (RSD), labels (poreske oznake), opciono gtin. Umesto stavki može i amountRsd + description. |
payments[] / paymentType | Način plaćanja: Cash, Card, WireTransfer, Voucher, MobileMoney, Check, Other. |
labels | Poreske oznake iz GET /api/status. Npr. А = Nije u PDV (0%), Ђ = opšta (20%), Е = posebna (10%). |
buyerId | Opciono — identifikacija kupca (npr. "10:PIB") za račun na firmu. |
transactionId | Opciono, ali preporučeno — vaš ID; idempotency ključ. Ponovljen poziv sa istim ID-em vraća isti račun i "ponovljen": true, ne izdaje novi. |
occurredAt | Opciono — vreme uplate (ЕСИР време), samo kad je novac primljen pre izdavanja računa. Šaljite apsolutan trenutak u ISO 8601 sa zonom: 2026-08-04T15:20:00+02:00 ili 2026-08-04T13:20:00Z. Zapis bez zone se čita kao beogradsko vreme. |
adText | Opciono — slobodan tekst koji se ispisuje ispod fiskalnog dela računa (posle linije „КРАЈ ФИСКАЛНОГ РАЧУНА"). Na konačnom računu posle avansa obavezno nosi broj i datum poslednjeg avansnog računa, vidi Avansni račun. |
POST /api/racuni/avans — kad je novac primljen pre isporuke (pretplate, uplate unapred, plaćanje karticom pre slanja robe). Ista struktura tela kao promet prodaja.
POST /api/racuni/obuka/refundacija — ОБУКА РЕФУНДАЦИЈА. Obavezan je referentDocumentNumber — PFR broj računa za obuku na koji se odnosi. Sa live ključem poziv se odbija ako taj broj nije obuka prodaja sa vašeg naloga.
Na avansnom računu stavka se ne zove po artiklu, nego po poreskoj stopi avansa, uvek sa količinom 1 (uputstvo Poreske uprave):
name | Oznaka | Za šta |
|---|---|---|
10: Аванс | Ђ | avans po opštoj stopi PDV-a (20%) |
11: Аванс | Е | avans po posebnoj stopi PDV-a (10%) |
12: Аванс | Г | avans za promet oslobođen PDV-a |
13: Аванс | А | obveznik koji nije u sistemu PDV-a (npr. paušalac) |
Artikle na koje se avans odnosi možete upisati u adText, koje se ispisuje ispod fiskalnog dela računa:
{
"transactionId": "1284",
"paymentType": "Card",
"items": [
{ "name": "10: Аванс", "quantity": 1, "unitPrice": 2400, "labels": ["Ђ"] }
],
"adText": "Аванс за: Naziv artikla"
}
Ako za istu kupovinu stigne još jedan avans, svaki sledeći avansni račun šalje referentDocumentNumber i referentDocumentDT prethodnog avansnog računa.
Konačni račun se ne vezuje direktno za avans. Pri isporuci idu dva poziva, a veza se pravi preko referentDocumentNumber i referentDocumentDT (isti transactionId nije dovoljan).
1. POST /api/racuni/avans/refundacija — zatvara avans. Obavezni su referentDocumentNumber i referentDocumentDT poslednjeg avansnog računa (brojRacuna i sdcDateTime iz odgovora na njega). Stavke i iznos su isti kao na avansu. Ovaj račun se ne daje kupcu.
{
"transactionId": "1284",
"referentDocumentNumber": "<brojRacuna poslednjeg avansa>",
"referentDocumentDT": "<sdcDateTime poslednjeg avansa>",
"paymentType": "Card",
"items": [
{ "name": "10: Аванс", "quantity": 1, "unitPrice": 2400, "labels": ["Ђ"] }
]
}
2. POST /api/racuni — konačni račun sa pravim artiklima. Referenca je avansna refundacija iz prvog koraka, ne avans. U adText je obavezno broj i datum poslednjeg avansnog računa:
{
"transactionId": "1284",
"referentDocumentNumber": "<brojRacuna avansne refundacije>",
"referentDocumentDT": "<sdcDateTime avansne refundacije>",
"paymentType": "Card",
"items": [
{ "name": "Naziv artikla", "quantity": 1, "unitPrice": 2400, "labels": ["Ђ"] }
],
"adText": "Аванс: <brojRacuna poslednjeg avansa> од <datum>"
}
Otkazivanje pre isporuke: samo prvi korak (avansna refundacija), bez konačnog računa.
Isti transactionId sme za avans, avansnu refundaciju i konačni račun — to su različite vrste računa. Poreska oznaka u primerima je samo ilustracija; šaljete onu koja važi za vašu firmu. Ceo tok se može ispratiti test ključem.
Račun svom kupcu šaljete vi, svojim mejlom i sa svog domena: uzmite qrKod i verifikacija iz odgovora i ubacite ih u svoju potvrdu porudžbine. Polje "kupac": { "email": "…" } se podrazumevano zanemaruje (u odgovoru tada stiže napomena, a mejlPoslat je null) — mejl bi išao sa našeg domena, pa bi tuđi odbijeni mejlovi trošili reputaciju sa koje isporučujemo API ključeve i alarme.
POST /api/racuni/obuka — račun tipa Обука na vašem pravom bezbednosnom elementu. Prolazi ceo lanac do Poreske uprave, ali nije promet: nema poreske obaveze, ne ulazi u vašu evidenciju prodaje i ne naplaćujemo ga. Koristite ga da proverite da kasa radi pre prve prave kupovine. Ista struktura tela kao promet prodaja.
POST /api/racuni/refundacija — zahteva referentDocumentNumber (PFR broj originalnog računa) i referentDocumentDT.
Obe vrednosti stižu u odgovoru na račun koji stornirate: brojRacuna → referentDocumentNumber, sdcDateTime → referentDocumentDT. Isto važi i u sandboxu, pa se refundacija može ispratiti od početka do kraja test ključem.
Delimične refundacije: refundacija sme da nosi isti transactionId kao prodaja koju stornirate — to su za nas dva različita računa. Ali druga delimična refundacija iste porudžbine mora imati drugačiji transactionId (npr. 1284-ref-1, 1284-ref-2). Ako pošaljete isti, dobićete nazad prvu refundaciju uz "ponovljen": true — to nije greška, nego zaštita: sa iste strane ne razlikujemo „ponovi drugu ratu" od „webhook se ponovio".
POST /api/racuni/kopija — izdaje kopiju već izdatog računa. Kopija ide preko Poreske uprave kao poseban dokument sa pozivom na original i na njoj piše „ОВО НИЈЕ ФИСКАЛНИ РАЧУН". Ponovna štampa originalnog žurnala nije kopija.
Telo je isto kao kod originala (stavke, plaćanja, iznos) uz referentDocumentNumber — PFR broj originala (brojRacuna). Sa live ključem vreme originala, vrstu prometa (kopija refundacije je „КОПИЈА РЕФУНДАЦИЈА") i kupca uzimamo iz evidencije, pa referentDocumentDT nije obavezan. Kopija se može izdati i za račun star više dana, ali samo za račun za promet ili za avans izdat sa vašim ključem (ne za obuku, predračun ili drugu kopiju), i iznos mora biti isti kao na originalu. Sa test ključem probni računi se ne pamte, pa je dobro da pošaljete i referentDocumentDT (sdcDateTime originala) — bez njega kopija nosi današnje poreske stope.
Pri štampi: natpis „ОВО НИЈЕ ФИСКАЛНИ РАЧУН" iz žurnala mora biti odštampan slovima najmanje dvostruko većim od ostalog teksta (Pravilnik o vrstama fiskalnih računa, čl. 2).
Kopija se ne naplaćuje i ne ulazi u mesečni limit. Za svaku novu kopiju istog računa pošaljite drugi transactionId (ili ga izostavite) — isti transactionId vraća već izdatu kopiju.
POST /api/racuni/predracun — ПРЕДРАЧУН ПРОДАЈА: ponuda kupcu pre prodaje ili pre avansa. Telo je isto kao kod prodaje. Predračun nije fiskalni račun i nije promet: na njemu piše „ПРЕДРАЧУН" i „ОВО НИЈЕ ФИСКАЛНИ РАЧУН", ne naplaćuje se i ne ulazi u mesečni limit.
POST /api/racuni/predracun/refundacija — ПРЕДРАЧУН РЕФУНДАЦИЈА, uz obavezan referentDocumentNumber predračuna. Sa live ključem poziv se odbija ako taj broj nije predračun prodaja sa vašeg naloga.
Prodaja po predračunu: konačni račun je običan POST /api/racuni sa referentDocumentNumber predračuna (Pravilnik o vrstama fiskalnih računa, čl. 11 t. 4).
Pošaljite svoj transactionId uz svaki poziv. Ponovljen poziv sa istim ID-em vraća isti račun i "ponovljen": true (HTTP 200, isti oblik odgovora) — ne izdaje se drugi. To pokriva ponovljene webhookove, duple klikove i istovremene pozive.
Bez transactionId te zaštite NEMA. Svaki poziv je tada nov račun: ako procesor ponovi webhook, izdaće se drugi pravi fiskalni račun za istu kupovinu — a to se ispravlja jedino refundacijom, na teret vaše firme. Zato u odgovoru na takav poziv stiže i napomena koja na to podseća. Polje je formalno opciono samo zbog starijih integracija; tretirajte ga kao obavezno.
Ključ je klijent + tip računa + smer + transactionId, pa isti ID sme da se koristi za promet, avans i obuku — to su različiti računi i ne poništavaju se međusobno.
GET /api/racuni/{id} — vraća već izdat račun, po vašem transactionId ili po PFR broju računa. Za slučaj da izgubite odgovor sa izdavanja: dokument je već prijavljen Poreskoj upravi i mora da postoji način da se pročita nazad.
Vraćaju se brojRacuna, iznos, sdcDateTime i verifikacija, a qrKod, zurnal i brojaci dok god je zapis o izdavanju kod nas (35 dana). Ako isti transactionId nosi više dokumenata (prodaja pa refundacija), racun je najnoviji, a ceo lanac stoji u racuni.
Vide se samo vaši i samo pravi (live) računi — test računi se ne pamte. Nepoznat ID vraća 404. U sandboxu je zato odgovor na POST jedini izvor — sadrži sva polja, sdcDateTime uključujući.
GET /api/racuni?od=2026-10-01&do=2026-10-31&kupac=10:115672200 — spisak vaših izdatih računa, najnoviji prvi. Svi parametri su opcioni: od i do (datum YYYY-MM-DD po beogradskom vremenu, ili ISO trenutak), kupac (buyerId), broj (PFR broj), transactionId, vrsta (Normal, Advance, Copy, Training, Proforma) i limit (podrazumevano 100, najviše 1000).
Odgovor: ukupno (koliko računa odgovara), vraceno i niz racuni sa istim poljima kao kod čitanja jednog računa, bez QR koda i žurnala. Kao i kod čitanja, vide se samo pravi (live) računi.
GET /api/artikli — izvoz liste artikala vašeg naloga (JSON).
PUT /api/artikli — uvoz: telo je JSON niz [{ "id", "name", "unitPrice", "labels", "gtin", "unit" }] i zamenjuje celu listu. Obavezni su name i unitPrice. Ako je bilo koji artikal neispravan, ništa se ne upisuje i stara lista ostaje. Telo zahteva sme da ima najviše 100 KB.
GET /api/status — podaci obveznika, ESIR i aktuelne poreske stope (oznake i procenti). Uvek povlači stope od Poreske uprave — nikad ih ne kucajte ručno.
GET /api/usage — broj računa, mesečni trošak i iskorišćenost limita za tekući mesec (opciono ?month=YYYY-MM).
| Kod | Značenje |
|---|---|
401 | Nevalidan API ključ. |
403 | Nalog nije aktivan ili je suspendovan (neizmirena obaveza). |
402 | Dostignut mesečni limit računa. |
400 | Neispravno telo zahteva (npr. zbir plaćanja ≠ iznos, nepoznata oznaka). |
409 | Prethodni pokušaj sa istim transactionId nije razrešen — račun je možda već izdat, pa drugi ne izdajemo. Javite nam transactionId; proveravamo kod Poreske uprave. |
502 | Greška prema V-PFR-u Poreske uprave. Ako odgovor nosi "statusRacuna": "nepoznato", veza je pukla posle slanja i račun je možda izdat — ne ponavljajte automatski. |
Ako zahtev ode Poreskoj upravi, a odgovor ne stigne (timeout, prekid veze), niko na našoj strani ne zna da li je račun izdat. Tada dobijate 502 sa "statusRacuna": "nepoznato".
Automatsko ponavljanje bi u tom slučaju moglo da napravi drugi pravi fiskalni račun za istu kupovinu — greška koja se ispravlja jedino refundacijom. Zato ponovljen poziv sa istim transactionId vraća 409 dok se ne proveri šta se stvarno desilo. Ako se račun u međuvremenu nađe u evidenciji, sve se razrešava samo i dobijate ga nazad sa "ponovljen": true.
| Datum | Šta se promenilo |
|---|---|
2026-10-22 |
Novo: POST /api/racuni/kopija — kopija izdatog računa, i za račune stare više dana (vidi Kopija računa).
Probni žurnal ima poreski deo — oznaka, naziv, stopa i iznos poreza po oznaci i ukupan porez, kao na pravom računu. Stope su sa vašeg elementa kad je povezan, inače probne. Na probnoj kopiji, obuci i predračunu piše „ОВО НИЈЕ ФИСКАЛНИ РАЧУН". Novo: POST /api/racuni/predracun i /api/racuni/predracun/refundacija (Predračun), POST /api/racuni/obuka/refundacija, GET /api/racuni — pretraga izdatih računa po datumu, kupcu i vrsti (Pretraga), i GET|PUT /api/artikli (Lista artikala).
|
2026-08-28 |
Sandbox vraća sdcDateTime i brojaci — odgovor sa test ključem sada ima ista polja kao live. Refundacija traži referentDocumentDT, a test računi se ne pamte, pa se to vreme uzima iz odgovora na sam POST.
|
2026-08-22 |
Novo: GET /api/racuni/{id} — izdat račun se sada može pročitati nazad, po transactionId ili po PFR broju. Ranije je odgovor na POST bio jedini primerak.
Ispravljeno u ovoj dokumentaciji: kupac.email se podrazumevano zanemaruje — mejl kupcu šalje prodavac. Ranije je ovde pisalo da račun „odmah stiže kupcu na mejl".
|
2026-08-09 |
occurredAt se čita kao apsolutan trenutak. Ranije se vrednost prosleđivala Poreskoj upravi doslovno, a V-PFR cifre štampa neizmenjene — pa je vreme na računu izlazilo pomereno za pomak zone, i integracije koje su to primetile slale su beogradski sat sa oznakom Z da bi ispis bio tačan.
Od ovog datuma vreme prevodimo mi: pošaljite stvaran trenutak ( 2026-08-04T13:27:37Z ili 2026-08-04T15:27:37+02:00) i na računu piše 15:27:37. Zapis bez zone se čita kao beogradsko vreme.
Ako je vaša integracija ranije dodavala sat/dva da bi ispis bio tačan — uklonite to, inače će račun sada nositi vreme pomereno unapred. Prepoznajemo taj obrazac i upozorenje vam stoji u „Moj nalog". |
2026-08-09 |
Zaštita od duplog računa i kod 409. Ponovljen transactionId vraća isti račun umesto novog; prekid veze posle slanja daje 502 sa "statusRacuna": "nepoznato", a naredni pokušaj 409 dok se ne razreši. |
2026-08-09 |
Vremena u prikazima i obračunu su beogradska. Dan i mesec se seku na beogradskoj ponoći — račun izdat 1. u 00:30 pripada novom mesecu (fakture, KPO knjiga). |
Pitanja? Kontakt · Početna · English version