LogiLL ESIR — primeri integracije (REST API i fajlovi)
Ovaj dokument dopunjuje poglavlje 13. Integracije korisničkog uputstva. Ovde su gotovi primeri koji se mogu kopirati: svaki poziv REST API-ja, svaka vrsta računa i svaki oblik fajla za razmenu (JSON, TXT, XML), sa očekivanim odgovorom.
LogiLL ESIR i LogiLL LPFR su u postupku odobrenja Poreske uprave. Primeri važe za sandbox okruženje i probne račune dok proizvod nije odobren.
Pregled svih mogućnosti
Preuzmite gotove primere: primeri-integracije.zip. U njemu su folderi json, txt i xml sa istim artiklima i komitentima, i 27 gotovih računa (json/racuni/) koji pokrivaju svaki način plaćanja i svaku vrstu računa iz ovog pregleda. Fajl README.txt u arhivi objašnjava šta je koji.
| Šta se šalje | JSON | TXT | XML |
|---|---|---|---|
| Artikli | da | da | da |
| Komitenti (kupci) | da | — | — |
| Računi (svih vrsta) | da | — | — |
Vrste računa (vrsta) i tip transakcije (tip)
vrsta |
Šta je | tip |
Posebna polja |
|---|---|---|---|
Promet |
običan fiskalni račun | Prodaja, Refundacija |
referenca kod refundacije; storno: true za poništavanje |
Avans |
uplata unapred | Prodaja |
stavke su uplate po poreskoj oznaci; datum_uplate; referenca na prethodni avans |
Promet + zatvara_avans |
konačni račun koji zatvara avans | Prodaja |
zatvara_avans (PFR broj avansa); ESIR sam izdaje i Avans-Refundaciju |
Predračun |
predračun (nije promet) | Prodaja |
|
Promet + referenca |
promet na osnovu predračuna | Prodaja |
referenca na predračun |
Obuka |
račun za obuku kasira (nije promet) | Prodaja |
|
Kopija |
ponovni primerak izdatog računa | isti tip kao original | referenca je obavezna, stavke se prepisuju |
Promet + bez_naknade |
promet bez naknade (poklon) | Prodaja |
bez_naknade: true, bez plaćanja |
Promet + jednonamenski_vaucer |
prodaja jednonamenskog vaučera | Prodaja |
jednonamenski_vaucer: true, jedna stavka (oznaka i iznos) |
Promet + korporacijska kartica |
plaćanje korporacijskom karticom | Prodaja |
kupac.opciono: "50:…", plaćanje Voucher |
Načini plaćanja (placanja[].nacin)
nacin |
Naziv na računu | Napomene |
|---|---|---|
Cash |
Готовина | jedini koji dozvoljava primljeno (kusur); jednom po računu |
Card |
Платна картица | može više puta na istom računu; povraćaj na karticu samo istog dana |
Check |
Чек | može više puta |
WireTransfer |
Пренос на рачун | |
Voucher |
Ваучер | uz korporacijsku karticu je propisan |
MobileMoney |
Инстант плаћање | može više puta |
Other |
Други безготовински начин плаћања | uz promet bez naknade je propisan |
Pravila za sva plaćanja:
- Zbir
placanja[].iznosmora biti tačno jednak iznosu računa. Kusur nije plaćanje: kod gotovine se upisuje iznos koji zatvara račun, aprimljenosluži samo za izračunavanje kusura. - Podešavanja kase mogu isključiti neke načine (Podešavanja → Načini plaćanja). Ako je režim „ograničen", nema
Card,CheckiMobileMoney(unose se kao gotovina); „Prikaži na kasi" bira koje načine radnja koristi. Račun sa isključenim načinom se odbija. - Kod refundacije novac ide kupcu, pa nema kusura (
primljenose ignoriše).
Polja računa
| Polje | Obavezno | Šta je |
|---|---|---|
radnja |
samo za fajlove | uvek "racun" (kod REST API-ja se ne šalje) |
spoljni_id |
da | vaš jedinstven broj dokumenta (zaštita od duple fiskalizacije) |
vrsta, tip |
da | v. tabelu iznad |
kasir |
da | ime i prezime kasira (štampa se na računu) |
stavke |
da | v. ispod; kod avansa i vaučera samo pfr_oznaka i cena |
placanja |
da | v. iznad; izostavlja se samo kod prometa bez naknade |
kupac |
ne (obavezan kod refundacije prometa) | v. ispod |
referenca |
kod refundacije, kopije, storna, novog avansa, prometa iz predračuna | broj i vreme originalnog računa (PFR broj i PFR vreme) |
izlaz |
ne | ["TERMALNI"], ["A4"], ["PDF"] ili kombinacija; [] = bez štampe; izostavljeno = kao na kasi. Izlaz mora biti uključen u podešavanjima ESIR-a |
reklama |
ne | tekst ispod kraja fiskalnog računa (ne ide Poreskoj upravi) |
datum_uplate |
ne (samo avans) | kad je uplata starija, npr. "2026-10-06 14:00"; ne sme biti u budućnosti |
zatvara_avans |
ne | PFR broj avansa koji se zatvara konačnim računom |
bez_naknade |
ne | true za poklon |
jednonamenski_vaucer |
ne | true za prodaju jednonamenskog vaučera |
storno |
ne | true uz tip: "Refundacija" za poništavanje celog računa |
Stavka (stavke[]): sifra i naziv (obavezni), jm (neobavezno, podrazumevano kom), pfr_oznaka (obavezno, poreska oznaka od PFR-a), kolicina (do 3 decimale, veća od 0), cena (do 2 decimale, veća od 0), gtin (neobavezno; ispravan 8/12/13/14-cifreni).
Kupac (kupac):
| Polje | Obavezno | Šta je |
|---|---|---|
dokument |
da | ID kupca u obliku šifra:broj, npr. 10:101234569 |
opciono |
ne | opciono polje, npr. 20:SNPDV-2026-15 ili 50:broj korporacijske kartice |
naziv, adresa, mesto |
ne | štampaju se ispod fiskalnog dela |
sifra, tip |
ne | ako je sifra upisana, kupac se čuva u komitente (tip PRAVNO ili FIZICKO) |
Šifre ID kupca (dokument): 10 PIB · 11 JMBG (preduzetnik) · 12 PIB:JBKJS · 13 penzionerska kartica · 14 PIB poljoprivrednog gazdinstva · 15 JMBG poljoprivrednog gazdinstva · 16 BPG · 20 lična karta · 21 izbeglička legitimacija · 22 EBS · 23 pasoš · 30 strani pasoš · 31 diplomatska legitimacija · 32–35 lična karta MKD/MNE/ALB/BIH · 36 lična karta EU/CH/NO/IS · 40 strani poreski broj. Opciono polje: 20 broj SNPDV · 21 LNPDV · 30–33 PPO/ZPPO/MPPO/IPPO-PDV · 50 broj korporacijske kartice · 60 period storna korporacijskih kartica.
Artikli i komitenti
Artikal (artikli[]) |
Obavezno | Šta je |
|---|---|---|
sifra |
da | ključ artikla |
naziv |
da | |
jm |
ne | podrazumevano kom |
mp_cena |
da | maloprodajna cena |
pfr_oznaka |
da | poreska oznaka od PFR-a |
gtin (u TXT/XML barkod) |
ne | ispravan GTIN |
aktivan |
ne | false isključuje artikal (brisanja nema) |
Komitent (kupci[]) |
Obavezno | Šta je |
|---|---|---|
sifra |
da | ključ komitenta u vašem programu |
tip |
da | PRAVNO ili FIZICKO |
naziv, adresa, mesto |
naziv da | |
dokumenti |
da | {"10": "101234569"} (šifra vrste ID-a → broj) |
aktivan |
ne | false isključuje komitenta |
Spisak primera u arhivi
| Fajl | Šta pokazuje |
|---|---|
racuni/01–09 |
svih 7 načina plaćanja, mešovito (kartica + gotovina) i dve kartice na istom računu |
racuni/10–12 |
kupac bez šifre (uz opciono polje), kupac sa šifrom, fizičko lice |
racuni/13, 14 |
reklama i izbor štampe, račun bez štampe |
racuni/20–22 |
predračun, promet iz predračuna, obuka |
racuni/30–32 |
avans: prva uplata, naredna uplata, konačni račun |
racuni/40–42 |
bez naknade, jednonamenski vaučer, korporacijska kartica |
racuni/50–53 |
refundacija (gotovina, kartica), kopija, storno |
Računi koji se pozivaju na prethodni račun (21, 31, 32, 50–53) imaju primer broja i vremena u referenca: zamenite ih stvarnim PFR brojem i vremenom. Kopija, storno i zatvaranje avansa rade samo za račune koji su izdati na ovom ESIR-u, a refundacija na karticu samo istog dana kad je original izdat.
Pre prvog primera
- U LogiLL ESIR otvorite Podešavanja → Integracije → Nova integracija i sačuvajte prikazani API ključ (prikazuje se samo jednom).
- Saznajte port: LogiLL ESIR sluša na
127.0.0.1, na portu 8625 (ili sledećem slobodnom do 8635). U primerima je8625. - Poreske oznake (
Ђ,Е, …) nisu iste u sandboxu i produkciji i ne zadajete ih sami. Prvo pozoviteGET /poreske-stope(primer 2) i koristite oznake koje vrati. - Primeri koriste ćirilična slova poreskih oznaka (
Ђ,Е). Šaljite ih u UTF-8.
Sadržaj
- A. REST API — A1 status · A2 poreske stope · A3 sinhronizacija · A4 artikli · A5 kupci · A6 računi (promet, više plaćanja, kupac, bez štampe, avans, predračun, bez naknade, vaučer, korporacijska kartica) · A7 refundacija, kopija, storno · A8 pitanje po
spoljni_id, usklađivanje, PDF · A9 greške · A10 redosled koraka koji ne gubi račune - B. Fajlovi — B1 kako se upisuje zahtev · B2 račun · B3 artikli (JSON, TXT, XML) · B4 kupci · B5 odgovori · B6 kad PFR nije dostupan · B7 čitanje odgovora
A. REST API
U primerima su prikazani samo metod i adresa (i telo, gde ga ima). Isto važi za svaki poziv:
- zaglavlje
Authorization: Bearer VAS_API_KLJUC(osim zaGET /status); - zaglavlje
Content-Type: application/json; charset=utf-8kad se šalje telo; - telo je JSON u UTF-8.
Kao orijentir, ceo HTTP zahtev za izdavanje računa izgleda ovako (alat ili programski jezik kojim ga šaljete nije bitan):
POST /api/v1/racuni HTTP/1.1
Host: 127.0.0.1:8625
Authorization: Bearer VAS_API_KLJUC
Content-Type: application/json; charset=utf-8
{ ...telo računa iz primera... }
U ostalim primerima se ovaj omot ne ponavlja. Telo (racun.json, artikli.json, kupci.json) je JSON iz primera.
U svim primerima: spoljni_id je vaš broj dokumenta, obavezan je i jedinstven (zaštita od duple fiskalizacije, v. A8 i A10). Primeri se šalju na adresu:
POST http://127.0.0.1:8625/api/v1/racuni
telo: racun.json
Poziv je sinhron: čekajte odgovor najmanje 45 sekundi (L-PFR obično odgovara za 1–3 s).
Odgovor (200, i kad je PFR odbio račun — tada je status: "GRESKA" i greska kaže razlog):
{
"id": 128, "spoljni_id": "DOK-58231", "status": "FISKALIZOVAN",
"vrsta": "Promet", "tip": "Prodaja", "iznos": 379.98, "kusur": 20.02,
"pfr": {"broj": "DENJ4FJH-DENJ4FJH-33", "vreme": "2026-10-08T08:07:43+02:00",
"brojac": "19/33ПП", "url": "https://suf.purs.gov.rs/v/?vl=…",
"tekst": "============ ФИСКАЛНИ РАЧУН ============\n…", "qr_gif": "R0lGOD…"},
"stampa": [{"izlaz": "TERMALNI", "ok": true, "poruka": ""}],
"greska": ""
}
Zapamtite pfr.broj i pfr.vreme: potrebni su za refundaciju, kopiju, storno i avans.
A6.1 Prodaja gotovinom (najčešći slučaj)
{
"spoljni_id": "DOK-58231",
"vrsta": "Promet",
"tip": "Prodaja",
"kasir": "Jovan Jović",
"stavke": [
{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 2, "cena": 189.99}
],
"placanja": [{"nacin": "Cash", "iznos": 379.98, "primljeno": 400}]
}
primljeno (neobavezno, samo gotovina) služi za izračunavanje kusura (kusur u odgovoru). Zbir placanja[].iznos mora biti jednak iznosu računa.
Načini plaćanja: Cash, Card, Check, WireTransfer, Voucher, MobileMoney, Other.
A6.2 Više stavki i dva načina plaćanja, uz GTIN
{
"spoljni_id": "DOK-58232",
"vrsta": "Promet",
"tip": "Prodaja",
"kasir": "Jovan Jović",
"stavke": [
{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "gtin": "8601234567899", "pfr_oznaka": "Ђ", "kolicina": 2, "cena": 189.99},
{"sifra": "1002", "naziv": "Hleb beli 500g", "jm": "kom", "pfr_oznaka": "Е", "kolicina": 1, "cena": 79.90},
{"sifra": "2001", "naziv": "Mleko 1l", "jm": "l", "pfr_oznaka": "Е", "kolicina": 1.5, "cena": 120.00}
],
"placanja": [
{"nacin": "Card", "iznos": 300},
{"nacin": "Cash", "iznos": 339.88, "primljeno": 400}
]
}
Količine mogu imati do 3 decimale, iznosi do 2. Artikli iz stavki se čuvaju u šifarniku ESIR-a; cena u stavci važi samo za taj račun, a cena u šifarniku se menja samo preko PUT /artikli (ili kad artikal ne postoji).
A6.3 Račun sa kupcem — dve varijante
Varijanta A: bez sifra. Kupac se ne čuva u komitente; njegov ID ide samo na račun. Koristi se za jednokratne kupce, fizička lica i firme koje ne vodite u šifarniku.
{
"spoljni_id": "DOK-58233", "vrsta": "Promet", "tip": "Prodaja", "kasir": "Jovan Jović",
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 10, "cena": 189.99}],
"placanja": [{"nacin": "WireTransfer", "iznos": 1899.90}],
"kupac": {"dokument": "10:101234569", "opciono": "20:SNPDV-2026-15",
"naziv": "Kupac DOO", "adresa": "Bulevar 1", "mesto": "Beograd"}
}
dokument je u obliku šifra:broj (10: PIB, 11: JMBG, 20: lična karta…). opciono je neobavezno (npr. 20: broj SNPDV obrasca). Naziv, adresa i mesto se štampaju ispod fiskalnog dela.
Varijanta B: sa sifra. Kupac se čuva ili osvežava u komitentima (kao A5) i ide na račun.
{
"spoljni_id": "DOK-58234", "vrsta": "Promet", "tip": "Prodaja", "kasir": "Jovan Jović",
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 1, "cena": 189.99}],
"placanja": [{"nacin": "Card", "iznos": 189.99}],
"kupac": {"sifra": "K-245", "tip": "PRAVNO", "naziv": "Kupac DOO", "dokument": "10:101234569",
"adresa": "Bulevar 1", "mesto": "Beograd"}
}
U obe varijante ESIR proverava oblik ID-a i kontrolnu cifru PIB-a/JMBG-a (loš ID vraća 400).
A6.4 Bez štampe (samo elektronski račun)
Ako sami štampate ili prikazujete račun, isključite štampu u LogiLL ESIR-u:
{
"spoljni_id": "DOK-58235", "vrsta": "Promet", "tip": "Prodaja", "kasir": "Jovan Jović",
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 1, "cena": 189.99}],
"placanja": [{"nacin": "Cash", "iznos": 189.99}],
"izlaz": []
}
izlaz može biti ["TERMALNI"], ["A4"], ["PDF"] ili kombinacija; izostavljeno = kao na kasi (prvi uključeni izlaz). Izabrani izlaz mora biti uključen u podešavanjima ESIR-a. Tekst računa i QR su uvek u odgovoru (pfr.tekst, pfr.qr_gif).
A6.5 Avans — uplata, nastavak i zatvaranje
Prva uplata avansa. Stavke nisu artikli nego uplate po poreskoj oznaci (bez šifre i naziva):
{
"spoljni_id": "AV-1001-1", "vrsta": "Avans", "tip": "Prodaja", "kasir": "Jovan Jović",
"stavke": [{"pfr_oznaka": "Ђ", "cena": 12000}],
"placanja": [{"nacin": "Card", "iznos": 12000}],
"datum_uplate": "2026-10-06 14:00"
}
datum_uplate je neobavezan: koristi se samo kad je uplata starija (ne sme biti u budućnosti).
Naredna uplata poziva se na prethodni avans (mora biti poslednji u lancu i otvoren):
{
"spoljni_id": "AV-1001-2", "vrsta": "Avans", "tip": "Prodaja", "kasir": "Jovan Jović",
"stavke": [{"pfr_oznaka": "Ђ", "cena": 8000}],
"placanja": [{"nacin": "Cash", "iznos": 8000}],
"referenca": {"broj": "DENJ4FJH-DENJ4FJH-41", "vreme": "2026-10-06T14:02:11+02:00"}
}
Konačni račun koji zatvara avans (prodaja stvarne robe; avans se obračunava, placanja pokrivaju samo ostatak, a ako je avans pokrio sve, mogu biti prazna):
{
"spoljni_id": "AV-1001-KONACNI", "vrsta": "Promet", "tip": "Prodaja", "kasir": "Jovan Jović",
"zatvara_avans": "DENJ4FJH-DENJ4FJH-42",
"stavke": [{"sifra": "S-77", "naziv": "Radovi na montaži", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 1, "cena": 20500}],
"placanja": [{"nacin": "Cash", "iznos": 500}],
"kupac": {"dokument": "10:101234569"}
}
zatvara_avans je PFR broj avansa iz lanca (obično poslednje uplate). Iznos stavki konačnog računa mora biti najmanje jednak ukupno uplaćenom avansu, a placanja je ostatak koji kupac još plaća. ESIR sam izdaje i prateću Avans-Refundaciju, pa odgovor nosi i polje prateci.
A6.6 Predračun i promet iz predračuna
{
"spoljni_id": "PRED-77", "vrsta": "Predračun", "tip": "Prodaja", "kasir": "Jovan Jović",
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 5, "cena": 189.99}],
"placanja": [{"nacin": "Cash", "iznos": 949.95}]
}
Kad kupac prihvati, izdajete običan Promet sa istim stavkama i referenca koja pokazuje na predračun:
{
"spoljni_id": "DOK-58240", "vrsta": "Promet", "tip": "Prodaja", "kasir": "Jovan Jović",
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 5, "cena": 189.99}],
"placanja": [{"nacin": "Card", "iznos": 949.95}],
"referenca": {"broj": "DENJ4FJH-DENJ4FJH-50", "vreme": "2026-10-12T09:15:00+02:00"}
}
A6.7 Promet bez naknade (poklon)
Bez placanja:
{
"spoljni_id": "DOK-58250", "vrsta": "Promet", "tip": "Prodaja", "kasir": "Jovan Jović",
"bez_naknade": true,
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 1, "cena": 189.99}]
}
A6.8 Jednonamenski vaučer
Jedna stavka, samo oznaka i iznos:
{
"spoljni_id": "VAU-300", "vrsta": "Promet", "tip": "Prodaja", "kasir": "Jovan Jović",
"jednonamenski_vaucer": true,
"stavke": [{"pfr_oznaka": "Ђ", "cena": 3000}],
"placanja": [{"nacin": "Cash", "iznos": 3000}]
}
A6.9 Korporacijska kartica
Plaćanje je uvek Voucher, a broj kartice ide u opciono polje kupca uz 50::
{
"spoljni_id": "DOK-58260", "vrsta": "Promet", "tip": "Prodaja", "kasir": "Jovan Jović",
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 1, "cena": 189.99}],
"placanja": [{"nacin": "Voucher", "iznos": 189.99}],
"kupac": {"dokument": "10:101234569", "opciono": "50:1234-5678-9012"}
}
A7. Refundacija, kopija i storno
Sve je isti POST /racuni, sa referencom na original (referenca.broj i referenca.vreme — PFR broj i vreme originalnog računa) i svojim novim spoljni_id. ESIR proverava da original postoji, da je fiskalizovan i nije storniran, da svaka stavka postoji na originalu (ista šifra, cena i oznaka) i da količina ne prelazi „kupljeno minus već vraćeno".
Refundacija (cela ili deo). kupac je obavezan kod refundacije prometa:
{
"spoljni_id": "REF-58231-1", "vrsta": "Promet", "tip": "Refundacija", "kasir": "Jovan Jović",
"referenca": {"broj": "DENJ4FJH-DENJ4FJH-33", "vreme": "2026-10-08T08:07:43+02:00"},
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 1, "cena": 189.99}],
"placanja": [{"nacin": "Cash", "iznos": 189.99}],
"kupac": {"dokument": "20:009876543"}
}
Kod povraćaja gotovinom ESIR sam izdaje i Kopiju refundacije; odgovor tada nosi oba računa ("prateci": [ … ]).
Kopija (ponovni primerak originalnog računa). Stavke možete izostaviti, ESIR ih prepisuje sa originala:
{
"spoljni_id": "KOP-58231-1", "vrsta": "Kopija", "tip": "Prodaja", "kasir": "Jovan Jović",
"referenca": {"broj": "DENJ4FJH-DENJ4FJH-33", "vreme": "2026-10-08T08:07:43+02:00"}
}
Ne pravi se kopija kopije: kopija se uvek radi od originalnog računa.
Storno (poništavanje pogrešnog računa u celini). Stavke izostavite ili pošaljite identične originalu; ID kupca (10:PIB prodavca) stavlja ESIR:
{
"spoljni_id": "STO-58231", "vrsta": "Promet", "tip": "Refundacija", "storno": true, "kasir": "Jovan Jović",
"referenca": {"broj": "DENJ4FJH-DENJ4FJH-33"}
}
Kopija i storno rade samo za račune koji su izdati na ovoj kasi (original mora biti u žurnalu LogiLL ESIR-a).
A8. Pitanje po spoljni_id, usklađivanje i PDF
Šta je sa računom ako odgovor nije stigao? Prvo pitajte, pa tek onda ponovo šaljite:
GET http://127.0.0.1:8625/api/v1/racuni?spoljni_id=DOK-58231
Odgovor je isti kao pri izdavanju. Ako račun sa tim spoljni_id nije stigao do ESIR-a, vraća se 404:
{"kod": "NEPOZNAT", "poruka": "račun sa ovim spoljni_id nije stigao do ESIR-a — bezbedno je poslati ga ponovo", "polje": "spoljni_id"}
Tada smete ponovo da šaljete isti račun.
Usklađivanje — svi računi posle zadatog ESIR id (redom, sa izvorom KASA / API / FAJL). Služi za račune izdate ručno na kasi, koje vaš program samo prikazuje:
GET http://127.0.0.1:8625/api/v1/racuni?posle_id=120&limit=200
Pamtite poslednji viđeni id.
PDF računa za arhivu:
GET http://127.0.0.1:8625/api/v1/racuni/128/pdf
A9. Greške
Svaka greška ima oblik {"kod": "...", "poruka": "...", "polje": "..."}. kod je stabilan za mašinsku obradu, poruka je za čoveka (iste poruke kao na kasi).
| HTTP | Značenje | Primer odgovora |
|---|---|---|
400 |
Loš zahtev. PFR-u ništa nije poslato, ispravite i pošaljite ponovo. | {"kod": "PLACANJE", "poruka": "nedostaje 10,00 — zbir plaćanja mora biti 250,00", "polje": "placanja"} |
401 |
Nema ključa, ključ je pogrešan ili je integracija isključena. | {"kod": "KLJUC", "poruka": "API ključ nije važeći ili je integracija isključena"} |
402 |
Licenca nije aktivna (izdavanje je blokirano, ostalo radi). | {"kod": "LICENCA", "poruka": "…"} |
404 |
Samo za pitanje po spoljni_id: račun nije stigao do ESIR-a, bezbedno je poslati ga ponovo. |
{"kod": "NEPOZNAT", …} |
409 |
Isti spoljni_id se upravo obrađuje (sačekajte i pitajte po spoljni_id), ili je avans već zatvoren/storniran (SUKOB). |
{"kod": "U_OBRADI", "poruka": "račun sa ovim spoljni_id se upravo obrađuje — sačekajte"} |
503 |
PFR nije dostupan ili traži PIN. | {"kod": "NIJE_SPREMNA", "poruka": "PFR traži PIN"} |
200 + "status": "GRESKA" |
PFR je odbio račun; razlog je u greska. Ponovni pokušaj radite sa novim spoljni_id (npr. DOK-58231-2). |
Vrednosti kod za loš zahtev (400) su: PLACANJE, STAVKE, KUPAC, REFERENCA, AVANS, JSON (neispravan JSON) i ZAHTEV (ostalo); polje polje pokazuje na deo zahteva. Ostali kodovi: KLJUC, LICENCA, U_OBRADI, SUKOB, NIJE_SPREMNA, NEPOZNAT, INTERNO. Za mašinsku obradu najpre gledajte HTTP status i status računa, a kod koristite za prikaz i evidenciju.
A10. Redosled koraka da se nijedan račun ne izgubi i ne udvostruči
Redosled je isti u svakom programu i jeziku:
- Pre slanja u svojoj bazi zabeležite da je dokument „poslat" (sa njegovim
spoljni_id). GET /api/v1/status: ako jespremna: false, ne šaljite; prikažiterazlog(npr. „PFR traži PIN").POST /api/v1/racunii čekajte odgovor najmanje 45 sekundi.- Po odgovoru:
-
200istatus: FISKALIZOVAN: upišitepfr.broj,pfr.vreme,pfr.urlipfr.tekstuz dokument; dokument je „izdat". -200istatus: GRESKA: PFR je odbio račun (razlog ugreska). Dokument je „odbijen"; novi pokušaj ide sa novimspoljni_id. -400,401,402,503: ništa nije poslato PFR-u. Ispravite uzrok (zahtev, ključ, licenca, PFR/PIN) i pošaljite ponovo istispoljni_id. -409 U_OBRADI: isti račun se upravo obrađuje. Sačekajte nekoliko sekundi i pitajte (korak 5). - Nema odgovora (istek vremena, pad veze, restart programa): ne šaljite ponovo naslepo. Pitajte
GET /api/v1/racuni?spoljni_id=…: -200: račun je izdat (ili odbijen); postupite kao u koraku 4. -404 NEPOZNAT: račun nije stigao do ESIR-a; bezbedno je poslati isti zahtev ponovo. - bez odgovora: pokušajte kasnije; ne smišljajte novispoljni_id.
Čak i kad isti spoljni_id pošaljete ponovo, ESIR PFR-u ništa ne šalje, već vraća već izdat račun, pa udvostručenja nema; pitanje samo jasnije kaže šta se desilo.
B. Razmena preko fajlova
Za program koji ne može da pošalje HTTP zahtev, već samo upisuje fajlove u folder. Razmena se uključuje u LogiLL ESIR-u (Podešavanja → Integracije → Razmena preko fajlova) i ne traži API ključ: kontrola pristupa je pristup folderu.
Folder (podrazumevano C:\ProgramData\LogiLL ESIR\razmena\) ima:
ulaz\ ← vaš program upisuje zahteve
izlaz\ → LogiLL ESIR upisuje <ime>.odgovor.json i <ime>.status.json
obradjeno\ → zahtevi koji su uspeli (briše se posle 30 dana)
greska\ → odbijeni zahtevi
B1. Kako se upisuje zahtev
- Upišite fajl pod imenom
<ime>.json.tmp(ili.txt.tmp,.xml.tmp). - Kad je upis gotov, preimenujte ga u
<ime>.json. Program čita samo fajlove sa pravom ekstenzijom, pa nikad ne pročita nedovršen fajl. - Ime neka počinje datumom i vremenom, npr.
20261008-081500_DOK58231.json. Obrada ide po imenu, redom. Kodiranje je UTF-8 (BOM je dozvoljen), najviše 5 MB. Folder se proverava svake sekunde.
Isti postupak važi bez obzira na jezik ili alat kojim je napisan vaš program; potrebno je samo da program može da upiše fajl i da ga preimenuje. Ako vaš alat ne zna da preimenuje fajl, dovoljno je da upiše ceo fajl u drugi folder na istom disku pa ga premesti u ulaz\ pod pravim imenom (premeštanje na istom disku je trenutno).
Primer redosleda za jedan račun:
1. upiši ulaz\20261008-081500_DOK58231.json.tmp (ceo sadržaj, UTF-8)
2. zatvori fajl
3. preimenuj u ulaz\20261008-081500_DOK58231.json
B2. Račun u fajlu
Sadržaj je isti JSON kao za POST /racuni, uz dodatno polje "radnja": "racun". Primeri A6 i A7 važe i ovde: dodajte samo "radnja": "racun". Isti oblik koristi i kopija, refundacija i storno.
20261008-081500_DOK58231.json:
{
"radnja": "racun",
"spoljni_id": "DOK-58231",
"vrsta": "Promet",
"tip": "Prodaja",
"kasir": "Jovan Jović",
"stavke": [
{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 2, "cena": 189.99}
],
"placanja": [{"nacin": "Cash", "iznos": 379.98, "primljeno": 400}]
}
Refundacija kroz fajl (isto kao A7):
{
"radnja": "racun",
"spoljni_id": "REF-58231-1", "vrsta": "Promet", "tip": "Refundacija", "kasir": "Jovan Jović",
"referenca": {"broj": "DENJ4FJH-DENJ4FJH-33", "vreme": "2026-10-08T08:07:43+02:00"},
"stavke": [{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "pfr_oznaka": "Ђ", "kolicina": 1, "cena": 189.99}],
"placanja": [{"nacin": "Cash", "iznos": 189.99}],
"kupac": {"dokument": "20:009876543"}
}
B3. Artikli u fajlu — JSON, TXT ili XML
Vrsta fajla se prepoznaje po ekstenziji: .json, .txt ili .xml. Pravila su ista kao za A4 (sve ili ništa, brisanje preko aktivan).
JSON — telo sa radnja i nizom artikli:
20261012-093000_artikli.json:
{
"radnja": "artikli",
"artikli": [
{"sifra": "1001", "naziv": "Sok narandža 1l", "jm": "kom", "mp_cena": 189.99, "pfr_oznaka": "Ђ", "gtin": "8601234567899", "aktivan": true},
{"sifra": "1002", "naziv": "Hleb beli 500g", "jm": "kom", "mp_cena": 79.90, "pfr_oznaka": "Е"}
]
}
TXT — kolone razdvojene tabulatorom (ili tačka-zarezom, kao CSV iz Excel-a). Prvi red je zaglavlje; kolone mogu biti u bilo kom redosledu. Bez zaglavlja važi redosled sifra, naziv, jm, mp_cena, pfr_oznaka, barkod, aktivan. Cena sme imati zarez ili tačku. aktivan je 1/0 (ili da/true). Napomena: u TXT i XML-u kolona GTIN-a se zove barkod, a u JSON-u gtin.
20261012-093000_artikli.txt (znak → je tabulator):
sifra→naziv→jm→mp_cena→pfr_oznaka→barkod→aktivan
1001→Sok narandža 1l→kom→189,99→Ђ→8601234567899→1
1002→Hleb beli 500g→kom→79,90→Е→→1
1003→Staro pakovanje→kom→10,00→Ђ→→0
Isti oblik koristi Uvoz na ekranu Artikli. Najlakši uzorak dobijate kad u programu izvezete postojeće artikle (Šifarnici → Artikli → Izvoz → TXT).
XML:
20261012-093000_artikli.xml:
<?xml version="1.0" encoding="UTF-8"?>
<artikli>
<artikal>
<sifra>1001</sifra>
<naziv>Sok narandža 1l</naziv>
<jm>kom</jm>
<mp_cena>189.99</mp_cena>
<pfr_oznaka>Ђ</pfr_oznaka>
<barkod>8601234567899</barkod>
<aktivan>true</aktivan>
</artikal>
<artikal>
<sifra>1002</sifra>
<naziv>Hleb beli 500g</naziv>
<jm>kom</jm>
<mp_cena>79.90</mp_cena>
<pfr_oznaka>Е</pfr_oznaka>
</artikal>
</artikli>
B4. Kupci u fajlu
Samo JSON, sa radnja i nizom kupci (oblik kupca isti kao u A5):
20261012-093500_kupci.json:
{
"radnja": "kupci",
"kupci": [
{"sifra": "K-245", "tip": "PRAVNO", "naziv": "Kupac DOO", "adresa": "Bulevar 1", "mesto": "Beograd",
"dokumenti": {"10": "101234569"}, "aktivan": true}
]
}
B5. Odgovori
Za svaki zahtev LogiLL ESIR upiše izlaz\<ime>.odgovor.json (isti JSON kao odgovor API-ja), pa tek onda premesti zahtev u obradjeno\ (uspeh) ili greska\ (odbijen). Odgovore vi brišete kad ih pročitate; program ih sam ne briše.
Uspešan račun (izlaz\20261008-081500_DOK58231.odgovor.json; zahtev je u obradjeno\):
{"id": 128, "spoljni_id": "DOK-58231", "status": "FISKALIZOVAN", "iznos": 379.98,
"pfr": {"broj": "DENJ4FJH-DENJ4FJH-33", "vreme": "2026-10-08T08:07:43+02:00"}, "greska": ""}
Odbijen račun (zahtev je u greska\):
{"kod": "PLACANJE", "poruka": "nedostaje 10,00 — zbir plaćanja mora biti 250,00", "polje": "placanja"}
Šifarnik (artikli ili kupci):
{"dodato": 2, "izmenjeno": 0, "nepromenjeno": 0, "greske": []}
Nepoznata radnja (greška u radnja):
{"kod": "RADNJA", "poruka": "nepoznata radnja „racn“ (racun, artikli, kupci)", "polje": "radnja"}
B6. Kad PFR nije dostupan
Ako PFR traži PIN, nema veze ili licenca nije aktivna, zahtev za račun ostaje u ulaz\, a LogiLL ESIR upisuje izlaz\<ime>.status.json:
{"status": "CEKA", "razlog": "PFR traži PIN"}
- Ako PFR proradi u roku od 2 minuta od pojave fajla, račun se izdaje sam, redom, a
status.jsonse briše. - Ako je fajl stariji, ESIR ga ne izdaje sam (kupac verovatno više nije na kasi). Status postaje:
json
{"status": "CEKA_ODLUKU", "razlog": "stariji od 2 min — kasir odlučuje"}
Kasir na ekranu bira Izdaj izabrane (izdaje se sa današnjim vremenom) ili Odbaci izabrane. Odbačen zahtev dobija odgovor {"spoljni_id": "…", "status": "ODBACENO", "poruka": "odbačeno na kasi — račun nije izdat"}.
- Zahtev možete otkazati brisanjem fajla iz ulaz\, dok nije obrađen.
- Ako se LogiLL ESIR ugasi usred obrade, fajl ostaje u ulaz\; pri ponovnoj obradi isti spoljni_id vraća već izdat račun, pa ne nastaje dupli fiskalni račun.
Zahtevi iza onog koji čeka takođe čekaju (obrada ide redom).
B7. Čitanje odgovora
Posle upisa zahteva postupak je ovakav:
- Svake sekunde (do npr. 60 s) proverite da li postoji
izlaz\<ime>.odgovor.jsonsa istim imenom kao zahtev. - Kad se pojavi, pročitajte ga (UTF-8) i uzmite polje
status(FISKALIZOVANili greška),pfr.broj,pfr.url,pfr.tekst; kod greškeporukailigreska. - Obrišite odgovor iz
izlaz\kad ga preuzmete (program ga sam ne briše). - Ako odgovora nema, proverite postoji li
izlaz\<ime>.status.json(CEKAiliCEKA_ODLUKU, v. B6), a zatim da li je zahtev prešao uobradjeno\iligreska\.
Ako odgovor ne stigne, ne šaljite isti račun pod novim spoljni_id: proverite izlaz\<ime>.status.json i foldere obradjeno\ i greska\. Ponovljen isti spoljni_id je bezbedan: ESIR vraća već izdat račun.
Najčešće greške u integraciji
400zbog poreske oznake: oznaka mora biti izGET /poreske-stope. Sandbox i produkcija imaju različite oznake.- Zbir plaćanja nije jednak iznosu računa: iznos računa je zbir
kolicina × cenapo stavkama, zaokružen na 2 decimale. - Refundacija bez kupca: za
Promet+Refundacijaobavezan jekupac.dokument. - Isti
spoljni_idza dva različita računa: drugi neće biti izdat, već će vratiti prvi. Svaki dokument mora imati svoj broj. - Ponavljanje posle greške PFR-a (
GRESKA): koristite novispoljni_id. - Fajl se ne obrađuje: proverite da je preimenovan u pravu ekstenziju (ne
.tmp), da je razmena uključena i da je ESIR pokrenut; dnevnik integracija (Podešavanja → Integracije) prikazuje svaki poziv.