eFiskalizacija.cloud

API Referenca

Kompletna referenca svih API endpointa eFiskalizacija.cloud platforme. Za detalje o autentifikaciji pogledajte Autentifikacija (HMAC).

Bazni URL

https://efiskalizacija.cloud
Svi zahtevi moraju sadržati HMAC autentifikacione hedere. Pogledajte vodič za autentifikaciju za detalje.

Endpointi

Endpoint Metod Opis
/api/multitenant.php/fiskalizacija POST Fiskalizacija računa
/api/multitenant.php/status GET Status tenanta
/api/multitenant.php/invoice GET Lista računa
/api/multitenant.php/pdf GET PDF računa
/api/multitenant.php/send-email POST Slanje računa na email
/api/multitenant.php/test POST Test fiskalizacija (samo sandbox)

POST /fiskalizacija

Glavni endpoint za fiskalizaciju računa. Šalje račun na VSDC PFR i vraća verifikacioni (PFR) broj i QR kod.

Request body (JSON)

Polje Tip Obavezno Podrazumevano Opis
stavke array Da - Niz stavki računa
tip_racuna string Ne prodaja Tip fiskalnog računa
tip_transakcije string Ne sale Tip transakcije: sale ili refund
nacin_placanja string Ne gotovina Način plaćanja
kasir string Ne - Ime kasira
broj_racuna string Ne Automatski Interni broj računa
kupac object Ne - Podaci o kupcu
referentni_dokument string Uslovno - PFR broj referentnog dokumenta (obavezno za refundaciju/kopiju)
reklamni_tekst string Ne - Reklamni tekst (za avansne račune)

Stavka - polja

Polje Tip Obavezno Opis
naziv string Da Naziv artikla
kolicina number Da Količina (min 0.001)
jedinicna_cena number Da Jedinična cena sa PDV-om
pdv_stopa number Da PDV stopa: sandbox 19/10/0, produkcija 20/10/0
pdv_kategorija string Ne Za 0% PDV: oslobodjen ili nije_u_pdv. Default: oslobodjen
sifra string Ne Šifra artikla
jedinica_mere string Ne Jedinica mere (podrazumevano: "kom")
popust number Ne Fiksni iznos popusta u RSD (pre PDV-a). Ne moze biti veci od kolicina x jedinicna_cena. Default: 0
rabat_procenat number Ne Procentualni popust (0-100%). Primenjuje se na osnovicu pre PDV-a. Default: 0
Popusti: Polja popust i rabat_procenat su međusobno isključiva, pa ne mogu da se koriste oba na istoj stavci. Popust se uvek primenjuje na osnovicu pre obračuna PDV-a.

Kupac - polja

Polje Tip Opis
ime string Ime kupca ili naziv firme
pib string PIB (9 cifara) ili JMBG (13 cifara)
adresa string Adresa kupca
mesto string Mesto kupca
email string Email adresa kupca
telefon string Telefon kupca

Način plaćanja - vrednosti

Vrednost Kod VSDC Opis
gotovina G 1 Gotovina
kartica K 2 Platna kartica
virman V 4 Prenos na racun (virman)
vaucer U 5 Vaucer
instant I 6 Instant plaćanje (IPS QR)
drugo O 0 Drugo bezgotovinsko plaćanje
Napomena: Ček (VSDC kod 3) nije podržan jer je ESIR namenjen isključivo za web-šopove i daljinsku prodaju.

Tip računa - vrednosti

Vrednost Kod Opis
prodaja P Promet (fiskalni račun)
avans A Avansni račun
proforma F Predračun
kopija K Kopija računa
obuka T Račun za obuku (trening)

Primer zahteva

POST /api/multitenant.php/fiskalizacija
Content-Type: application/json
X-Api-Key: vaš_api_ključ
X-Timestamp: 1706000000
X-Signature: hmac_potpis

{
  "stavke": [
    {
      "naziv": "Laptop ASUS VivoBook",
      "kolicina": 1,
      "jedinicna_cena": 89990.00,
      "pdv_stopa": 20,
      "sifra": "LAP-001"
    },
    {
      "naziv": "Miš bežični",
      "kolicina": 2,
      "jedinicna_cena": 1990.00,
      "pdv_stopa": 20,
      "sifra": "MIS-005",
      "rabat_procenat": 15
    }
  ],
  "nacin_placanja": "kartica",
  "kasir": "Marko Petrović",
  "kupac": {
    "ime": "Tech Solutions d.o.o.",
    "pib": "107026577",
    "adresa": "Knez Mihailova 10",
    "mesto": "Beograd"
  }
}

Uspešan odgovor (200)

{
  "success": true,
  "data": {
    "invoice_id": 156,
    "broj_racuna": "1/156",
    "pfr_broj": "F7W3XLMA-F7W3XLMA-12345",
    "pfr_datum": "2026-01-23T10:30:00+01:00",
    "ukupan_iznos": 93970.00,
    "qr_code": "https://suf.purs.gov.rs/v/?vl=F7W3XLMAF7W3XLMA12345...",
    "status": "success"
  }
}

Greška - nedostaje polje (400)

{
  "success": false,
  "error": "Validacija neuspešna",
  "details": {
    "stavke": "Polje stavke je obavezno",
    "stavke.0.naziv": "Naziv stavke je obavezan"
  }
}

Greška - neautorizovan (401)

{
  "success": false,
  "error": "Nevažeći API ključ ili potpis"
}

Greška - pristup odbijen (403)

{
  "success": false,
  "error": "Tenant nije aktivan ili nema podešen sertifikat"
}

Greška - previše zahteva (429)

{
  "success": false,
  "error": "Prekoračen limit zahteva. Pokušajte ponovo za 60 sekundi."
}

GET /status

Vraća status tenanta uključujući informacije o nalogu i statistiku računa.

Primer zahteva

GET /api/multitenant.php/status
X-Api-Key: vaš_api_ključ
X-Timestamp: 1706000000
X-Signature: hmac_potpis

Uspešan odgovor (200)

{
  "success": true,
  "data": {
    "tenant": {
      "naziv": "Moj Web Shop",
      "pib": "107026577",
      "status": "active",
      "sertifikat_istice": "2027-03-15"
    },
    "statistika": {
      "ukupno_racuna": 1523,
      "danas": 12,
      "ovog_meseca": 287,
      "ukupan_promet": 4520890.50
    },
    "api_verzija": "1.2.0"
  }
}

GET /invoice

Vraća listu fiskalizovanih računa sa paginacijom.

Query parametri

Parametar Tip Podrazumevano Opis
limit integer 50 Broj rezultata po stranici (max 100)
offset integer 0 Pomak za paginaciju

Primer zahteva

GET /api/multitenant.php/invoice?limit=10&offset=0
X-Api-Key: vaš_api_ključ
X-Timestamp: 1706000000
X-Signature: hmac_potpis

Uspešan odgovor (200)

{
  "success": true,
  "data": {
    "invoices": [
      {
        "id": 156,
        "broj_racuna": "1/156",
        "pfr_broj": "F7W3XLMA-F7W3XLMA-12345",
        "ukupan_iznos": 93970.00,
        "tip_racuna": "prodaja",
        "tip_transakcije": "sale",
        "nacin_placanja": "kartica",
        "status": "success",
        "created_at": "2026-01-23T10:30:00+01:00"
      },
      {
        "id": 155,
        "broj_racuna": "1/155",
        "pfr_broj": "F7W3XLMA-F7W3XLMA-12344",
        "ukupan_iznos": 2500.00,
        "tip_racuna": "prodaja",
        "tip_transakcije": "sale",
        "nacin_placanja": "instant",
        "status": "success",
        "created_at": "2026-01-23T09:15:00+01:00"
      }
    ],
    "total": 1523,
    "limit": 10,
    "offset": 0
  }
}

GET /pdf

Vraća PDF verziju fiskalnog računa kao direktan binarni sadržaj (NE JSON).

Query parametri

Parametar Tip Obavezno Opis
pfr string Da PFR broj računa
download integer Ne Kontroliše Content-Disposition header (vidi tabelu)

Parametar download

Vrednost Content-Disposition Ponašanje pregledača
1 (ili truthy) attachment Pregledač pokreće DOWNLOAD dialog
0 (ili izostavljen) inline Pregledač PRIKAZUJE PDF direktno

Primer zahteva

GET /api/multitenant.php/pdf?pfr=F7W3XLMA-F7W3XLMA-12345&download=1
X-Api-Key: vaš_api_ključ
X-Timestamp: 1706000000
X-Signature: hmac_potpis

Uspešan odgovor (200)

API vraća direktan PDF binarni sadržaj:

Content-Type: application/pdf
Content-Disposition: attachment; filename="racun-F7W3XLMA-F7W3XLMA-12345.pdf"
Cache-Control: no-store, no-cache, must-revalidate, max-age=0

%PDF-1.4
...binarni PDF sadržaj...
Napomena: Za greške (404, 500) API vraća JSON sa success: false. Pogledajte PDF računi za primere u različitim jezicima.

POST /send-email

Slanje fiskalnog računa na email adresu kupca. Email sadrži PDF računa kao prilog.

Request body

PoljeTipObaveznoOpis
pfr string Da PFR verifikacioni broj računa
email string Da Email adresa primaoca

Primer zahteva

POST /api/multitenant.php/send-email
Content-Type: application/json
X-Api-Key: vaš_api_ključ
X-Timestamp: 1706000000
X-Signature: hmac_potpis

{
  "pfr": "F7W3XLMA-F7W3XLMA-12345",
  "email": "kupac@example.com"
}

Uspešan odgovor (200)

{
  "success": true,
  "data": {
    "message": "Email uspešno poslat",
    "email": "kupac@example.com",
    "pfr": "F7W3XLMA-F7W3XLMA-12345"
  },
  "timestamp": "2026-01-25T23:30:00+01:00"
}

Greške

KodOpis
400Nedostaje pfr ili email parametar, ili email nije validan
404Račun sa datim PFR brojem nije pronađen
400Račun nije fiskalizovan (samo fiskalizovani se mogu slati)
Napomena: Pogledajte PDF računi za više detalja o slanju emaila.

POST /test

Test endpoint za proveru integracije. Dostupan samo u sandbox okruženju. Šalje račun tipa "obuka" koji se ne evidentira u fiskalnom sistemu.

Ovaj endpoint je dostupan samo u sandbox okruženju. Na produkciji vraća grešku 403.

Primer zahteva

POST /api/multitenant.php/test
Content-Type: application/json
X-Api-Key: vaš_api_ključ
X-Timestamp: 1706000000
X-Signature: hmac_potpis

{
  "stavke": [
    {
      "naziv": "Test artikal",
      "kolicina": 1,
      "jedinicna_cena": 100.00,
      "pdv_stopa": 20
    }
  ]
}

Uspešan odgovor (200)

{
  "success": true,
  "data": {
    "message": "Test fiskalizacija uspešna",
    "pfr_broj": "TEST-F7W3XLMA-99999",
    "tip_racuna": "obuka"
  }
}

Zaštita od duplih računa

eFiskalizacija automatski štiti od kreiranja duplih fiskalnih računa na VSDC-u. Ovo je posebno važno u situacijama kada dođe do mrežnog timeout-a ili greške u komunikaciji.

Kako funkcioniše

Svaki zahtev za fiskalizaciju dobija jedinstveni RequestId (UUID) koji se šalje VSDC-u zajedno sa podacima računa. Sistem automatski:

  1. Čuva RequestId za svaki pokušaj fiskalizacije
  2. Pri ponovnom pokušaju (retry) proverava da li je prethodni zahtev već uspeo
  3. Ako je VSDC već kreirao račun — koristi postojeći odgovor umesto ponovnog slanja
  4. Ako status prethodnog zahteva nije poznat — ponovo koristi isti RequestId

Scenariji zaštite

Situacija Šta se dešava
Timeout pri fiskalizaciji Sistem čuva RequestId. Pri retry-u proverava VSDC i ponovo koristi isti RequestId.
Korisnik klikne "Ponovi" u admin panelu Sistem detektuje prethodni pokušaj i sprečava duplikat.
VSDC već kreirao račun ali naš sistem ne zna VSDC inquiry proverava status pre ponovnog slanja.
Napomena: Zaštita od duplikata radi automatski — ne zahteva nikakve izmene na strani API klijenta. RequestId se generiše i upravlja interno na serveru.

Ograničenje broja zahteva (Rate Limiting)

API je ograničen na 60 zahteva po minutu po API ključu. Status ograničenja se vraća u hederima odgovora:

Heder Opis
X-RateLimit-Limit Maksimalan broj zahteva u periodu (60)
X-RateLimit-Remaining Preostali broj zahteva u trenutnom periodu
X-RateLimit-Reset Unix timestamp kada se period resetuje

Kada se limit prekorači, API vraća status 429 Too Many Requests sa hederom Retry-After koji označava koliko sekundi treba sačekati pre ponovnog zahteva.

Kodovi grešaka

HTTP kod Značenje Opis
400 Bad Request Neispravan format zahteva ili neuspela validacija
401 Unauthorized Nevažeći API ključ ili HMAC potpis
403 Forbidden Tenant neaktivan ili nema pristup resursu
404 Not Found Traženi resurs ne postoji
422 Unprocessable Entity Podaci su ispravnog formata ali semantički neispravni
429 Too Many Requests Prekoračen limit zahteva (60/min)
500 Internal Server Error Interna greška servera
502 Bad Gateway VSDC PFR servis nije dostupan
503 Service Unavailable Servis privremeno nedostupan (održavanje)

Format greške

Sve greške vraćaju isti format odgovora:

{
  "success": false,
  "error": "Opis greške na srpskom",
  "details": { ... }  // opciono - detalji validacionih grešaka
}
Za interaktivno testiranje API-ja koristite Swagger UI gde možete direktno slati zahteve i videti odgovore.