API dokumentacija
Konvencije
Pravila koja važe za sve pozive: identifikatori, idempotencija, statusi dokumenta i kako ih tumačiti, iznosi, vreme, vrste računa, reference, načini plaćanja, kupac, paginacija i oblik grešaka.
Identifikatori u svakom zahtevu
| Polje | Šta je | Odakle |
|---|---|---|
taxpayerId | obveznik (pravno lice sa PIB-om) | GET /v1/taxpayers |
businessPremiseId | prodajno mesto (poslovni prostor Poreske uprave) sa svojim bezbednosnim elementom | GET /v1/taxpayers/{taxpayerId}/business-premises |
clientReference | vaša referenca: broj porudžbine, fakture ili transakcije; pretraživa u dnevniku | vaš sistem |
cashier.id | identifikator kasira ili sistema koji izdaje račun; štampa se na računu | vaš sistem (na primer web-shop) |
Idempotency-Key | zaglavlje koje sprečava dupli račun | vaš sistem, iz clientReference i vrste radnje |
Idempotency-Key
Svaka fiskalna izmena (POST na /v1/fiscal-documents, /copies, /v1/refund-workflows, /v1/advance-cases*, /v1/proforma-training-workflows, /v1/receipt-deliveries) zahteva zaglavlje Idempotency-Key dužine 16 do 200 znakova. Ključ je jedinstven unutar vaše organizacije i vezuje se za kanonski sadržaj zahteva:
- isti ključ, isti sadržaj: API vraća originalnu operaciju (200 umesto 201) i ne izdaje drugi račun, ma koliko puta ponovili;
- isti ključ, drugačiji sadržaj:
409 IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_REQUESTsaoperationIdoriginala; - nov ključ: nova operacija, i potencijalno nov račun.
{
"code": "IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_REQUEST",
"operationId": "9f8e7d6c-5b4a-4321-8765-0fedcba98761"
}Statusi dokumenta
Svaki fiskalni zahtev postaje trajna operacija sa statusom. Status je istina; HTTP kod je samo njegov sažetak.
| Status | Značenje | HTTP | `fiscalized` | `retryable` |
|---|---|---|---|---|
FISCALIZED | V-PFR je potpisao račun i odgovor je trajno sačuvan. Jedini status koji znači račun. | 201 (200 pri ponavljanju) | true | false |
REJECTED | V-PFR je odbio zahtev (validacija). Nije račun. pfrRejection na pojedinačnom čitanju kaže koje polje. | 422 | false | false |
NOT_FISCALIZED | V-PFR nije bio dostupan pre slanja; ništa nije poslato. | 503 | false | true |
OUTCOME_UNKNOWN | Zahtev je možda poslat, odgovor nije stigao. Nije račun, ali može da postane. Ne ponavljati. | 503 | false | false |
RECONCILING | BokaPOS proverava kod V-PFR-a da li nepoznat ishod postoji (samo čitanjem). Prelazno. | 503 | false | false |
RECEIVED, VALIDATED, SUBMITTING | Prelazni statusi tokom sinhronog poziva; vidite ih samo u dnevniku ako čitate u toku obrade. | n/a | false | false |
Kako tumačiti odgovor
01
201 i fiscalized: true
Račun postoji. Sačuvajte
id,pfr.invoiceNumber,pfr.sdcTime,pfr.verificationUrli, po potrebi, PDF. Porudžbina je fiskalizovana.02
503 i retryable: true
Ništa nije poslato (
NOT_FISCALIZED, na primerPFR_SUBMISSION_FAULTiliCURRENT_TAX_CONFIGURATION_UNAVAILABLE). Sačekajte nekoliko sekundi i pošaljite isti zahtev sa istim ključem. Ograničite broj pokušaja i posle toga prepustite operateru.03
503 i status OUTCOME_UNKNOWN
Ne šaljite nov zahtev za istu prodaju. Zapamtite
idi proveravajteGET /v1/operations/{id}(na primer na 30 sekundi, pa ređe). BokaPOS u pozadini razrešava ishod isključivo čitanjem kod V-PFR-a; kada ga nađe, status postajeFISCALIZED. Ako ishod ostane nepoznat, operater odlučuje u portalu.04
422
Zahtev krši pravilo (naše ili V-PFR-ovo). Ništa nije izdato. Ispravite zahtev i pošaljite ga sa novim ključem, jer je stari ključ vezan za pogrešan sadržaj.
05
403
Okruženje ili licenca. Ništa nije izdato. Sandbox nikad ne dobija 403 zbog licence.
06
409
Sukob: ključ ponovo upotrebljen sa drugim sadržajem, ili radnja koja nije dozvoljena u trenutnom stanju toka (avans, predračun). Pročitajte stanje i nastavite od njega.
Iznosi, količine i zaokruživanje
- Sve cene i iznosi su bruto, u dinarima, sa najviše dve decimale (
8990.00). Više decimala V-PFR odbija (šifra 2804). unitPriceje konačna jedinična cena posle popusta. Porez ne šaljete: BokaPOS ga računa iz poreske oznake po zvaničnim pravilima i V-PFR ga potpisuje.unitPriceBeforeDiscountje opciona cena pre popusta, samo za prikaz izvan fiskalnog dela računa; mora biti veća odunitPrice.quantityima do tri decimale (1.5), minimum0.001.- Zbir
quantity × unitPricepo stavkama, zaokružen na dve decimale, mora biti jednak zbirupayments. Inače422sa greškom u poljutotals. - Više načina plaćanja na istom računu je dozvoljeno (
paymentsje lista).
Vreme
- Sva vremena su ISO 8601.
createdAtiupdatedAtsu u UTC (Z).pfr.sdcTimeje vreme potpisa V-PFR-a sa pomakom koji je V-PFR poslao (+02:00ili+01:00); to je zvanično vreme računa. - Filteri
pfrFrom/pfrTou dnevniku i izveštajima se odnose nasdcTime;createdFrom/createdTona trenutak kada je BokaPOS primio zahtev. Donja granica je uključena, gornja isključena. - Ne šaljete vreme računa. Jedini izuzetak je avansna uplata virmanom primljena ranije (
paymentOccurredAt), po zvaničnom pravilu; vidite Avans.
Vrste računa i transakcija
| `invoiceType` | `transactionType` | Zvanično | Operacija |
|---|---|---|---|
NORMAL | SALE | Промет Продаја | POST /v1/fiscal-documents |
NORMAL | REFUND | Промет Рефундација | POST /v1/refund-workflows |
COPY | SALE / REFUND | Копија | POST /v1/fiscal-documents/{id}/copies (i automatski kod refundacije gotovinom) |
ADVANCE | SALE / REFUND | Аванс | /v1/advance-cases/... |
PROFORMA | SALE / REFUND | Предрачун | POST /v1/proforma-training-workflows |
TRAINING | SALE / REFUND | Обука | POST /v1/proforma-training-workflows |
POST /v1/fiscal-documents prihvata samo NORMAL SALE; sve ostalo ima svoj tok koji BokaPOS vodi na serveru, sa ispravnim referencama i redosledom.
Reference između dokumenata
Refundacija, kopija i konačni račun posle avansa moraju da se pozovu na izvorni dokument (PFR broj i vreme). Kada je izvor dokument koji je BokaPOS izdao, šaljete samo njegov fiscalDocumentId ({ "source": "BOKA", "fiscalDocumentId": "..." }) i BokaPOS upisuje tačne PFR podatke; na istom obvezniku i prodajnom mestu. Referenca na dokument drugog ESIR-a (source: EXTERNAL) traži tačan PFR broj, vreme i vrstu i podržana je samo za kopiju kroz POST /v1/fiscal-documents; refundacija i avans spoljne dokumente ne prihvataju.
| Novi dokument | Sme da se pozove na |
|---|---|
| Промет Рефундација | Промет Продаја (BokaPOS izvor) |
| Копија | Промет ili Аванс, prodaja ili refundacija, koji je fiskalizovan |
| Аванс Продаја (sledeća uplata) | prethodnu Аванс Продају istog slučaja (automatski) |
| Аванс Рефундација | poslednju Аванс Продају (automatski) |
| Промет Продаја (konačni račun) | Аванс Рефундацију zatvaranja (automatski) |
| Предрачун Рефундација | Предрачун Продају (BokaPOS izvor) |
| Обука Рефундација | Обука Продају (BokaPOS izvor) |
Načini plaćanja
| `type` | Zvanično | Tipična upotreba |
|---|---|---|
CARD | Платна картица | kartično plaćanje online |
WIRE_TRANSFER | Пренос на рачун | virman, uplatnica, e-banking |
INSTANT_PAYMENT | Инстант плаћање | IPS QR, instant transfer |
CASH | Готовина | pouzeće naplaćeno u gotovini; refundacija gotovinom traži kopiju sa potpisom |
VOUCHER | Ваучер | vaučer, poklon kartica, korporativna kartica (uz opciono polje kupca 50:) |
CHECK | Чек | retko |
OTHER | Друго безготовинско плаћање | sve ostalo bezgotovinsko |
Prodajno mesto može da radi u ograničenom režimu plaćanja (samo OTHER, CASH, WIRE_TRANSFER, VOUCHER); tada ostali načini vraćaju 422 PAYMENT_TYPE_NOT_ALLOWED_ON_PREMISE. Režim se vidi u polju paymentMode prodajnog mesta.
Identifikacija kupca
buyer.id je zvanični prefiks:vrednost. Obavezan je na svakoj refundaciji, kod prodaje firmi koje traže PIB na računu, i u drugim slučajevima koje propisi nabrajaju. Za domaću firmu (10:, 12: ili 14: sa važećim PIB-om) BokaPOS automatski dodaje naziv i adresu kupca iz registra NBS ispod identifikacije, na svim prikazima; vraća ih i u buyerDetails.
| Prefiks | Vrednost |
|---|---|
10: | PIB domaćeg pravnog lica ili preduzetnika |
11: | JMBG domaćeg fizičkog lica koje obavlja samostalnu delatnost |
12: | PIB i JBKJS budžetskog korisnika, PIB:JBKJS |
13: | broj penzionerske kartice |
14: / 15: / 16: | PIB, JMBG odnosno BPG poljoprivrednog gazdinstva |
20: | broj lične karte |
21: | broj izbegličke legitimacije |
22: | EBS stranca sa boravkom u Srbiji |
23: | broj domaćeg pasoša |
30: | broj stranog pasoša |
31: do 36: | diplomatske i strane lične karte prema zvaničnoj listi |
40: | strani poreski broj (TIN) |
buyer.optionalField je opciono polje kupca, takođe prefiks:vrednost: 20: SNPDV, 21: LNPDV, 30: do 33: PPO-PDV obrasci, 50: broj korporativne kartice (plaćanje je VOUCHER), 60: period refundacije korporativne kartice ddMMyyyy_ddMMyyyy. Isti prefiks znači različite stvari u dva polja.
Paginacija
Liste dnevnika koriste stabilan keyset: odgovor nosi nextCursor, koji šaljete kao cursor za sledeću stranicu; null je kraj. pageSize je do 200 (podrazumevano 50). Lista proizvoda koristi isti obrazac sa UUID cursor-om. Redosled je po createdAt pa id, opadajuće, pa nova stranica nikad ne preskače i ne ponavlja zapis.
Oblik grešaka
| Oblik | Kada | Primer |
|---|---|---|
{ "code": "...", "message"?: "..." } | pravilo BokaPOS-a ili V-PFR-a, 4xx i 5xx | { "code": "TAX_LABEL_NOT_CURRENT", "invalidLabels": ["Ђ"] } |
RFC 9457 problem (application/problem+json) | validacija polja, 422 | { "status": 422, "errors": { "items[0].unitOfMeasure": ["..."] } } |
{ "code": "IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_REQUEST", "operationId": "..." } | 409 | vidite iznad |
fiskalni dokument sa fiscalized: false | 503 na fiskalnom pozivu | status i failureCode kažu šta se desilo |
Potpun katalog kodova sa preporukom šta uraditi je na stranici Greške.