API documentation
Journal, reports and state
Everything BokaPOS did for your organization is searchable: the electronic journal with every attempt, CSV export, the turnover report by PFR time, the state of a single operation, certificates and the licence.
Searching the journal
GET /v1/fiscal-documents returns operations of every kind (Normal, Advance, Copy, Proforma, Training; sale and refund), including rejected ones and unknown outcomes. All filters combine.
| Filter | Meaning |
|---|---|
taxpayerId, businessPremiseId | narrow to a taxpayer or premise |
status | one document status (FISCALIZED, REJECTED, OUTCOME_UNKNOWN...) |
invoiceType, transactionType | invoice and transaction type |
createdFrom, createdTo | time of receipt by BokaPOS (inclusive, exclusive) |
pfrFrom, pfrTo | V-PFR signing time; excludes entries without a receipt |
clientReference, idempotencyKey, pfrNumber, cashierId, buyerId | exact value |
search | case-insensitive contains, across safe identifiers |
cursor, pageSize | pagination; pageSize up to 200 |
curl -X GET "https://api.bokapos.rs/v1/fiscal-documents?businessPremiseId=b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22&status=FISCALIZED&createdFrom=2026-09-01T00%3A00%3A00Z&pageSize=50" \
-H "Authorization: Bearer $BOKAPOS_TOKEN"{
"items": [
{
"id": "9f8e7d6c-5b4a-4321-8765-0fedcba98761",
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"idempotencyKey": "order-4127-sale-1",
"clientReference": "ORDER-4127",
"invoiceType": "NORMAL",
"transactionType": "SALE",
"cashierId": "web-shop",
"buyerId": null,
"buyerDetails": null,
"status": "FISCALIZED",
"fiscalized": true,
"failureCode": null,
"retryable": false,
"pfr": {
"invoiceNumber": "JWX4K9PL-JWX4K9PL-1042",
"sdcTime": "2026-09-01T10:15:32.483+02:00",
"requestedBy": "JWX4K9PL",
"signedBy": "JWX4K9PL",
"transactionTypeCounter": 897,
"totalCounter": 1042,
"invoiceCounterExtension": "ПП",
"totalAmount": 8990,
"totalTax": 890.9009,
"verificationUrl": "https://sandbox.suf.purs.gov.rs/v/?vl=A0pXWDRLOVBMSldYNEs5UEwSBAAAEAQAAKCLPAAAAAAAAAABnAqJa1EAAAA...",
"journal": "============ ФИСКАЛНИ РАЧУН ============\n115711881\nBOKA GROUP DOO\nBokaPOS sandbox\nРоза Луксембург 16\nБеоград-Раковица\nКасир: web-shop\nЕСИР број: 1656/1.0.0\n-------------ПРОМЕТ ПРОДАЈА-------------\nАртикли\n========================================\nНазив Цена Кол. Укупно\nBluetooth slušalice/kom (F)\n 8.990,00 1 8.990,00\n----------------------------------------\nУкупан износ: 8.990,00\nПлатна картица: 8.990,00\n========================================\nОзнака Име Стопа Порез\nF ECAL 11,00% 890,90\n----------------------------------------\nУкупан износ пореза: 890,90\n========================================\nПФР време: 01.09.2026. 10:15:32\nПФР број рачуна: JWX4K9PL-JWX4K9PL-1042\nБројач рачуна: 897/1042ПП\n========================================\n======== КРАЈ ФИСКАЛНОГ РАЧУНА ========="
},
"receipt": {
"textUrl": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/official-text",
"jsonUrl": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/canonical-json",
"pdfA4Url": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/pdf-a4",
"pdf80mmUrl": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/pdf-80mm",
"pdf58mmUrl": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/pdf-58mm",
"previewImageUrl": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/preview-png",
"qrImageUrl": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/qr-svg",
"verificationUrl": "https://sandbox.suf.purs.gov.rs/v/?vl=A0pXWDRLOVBMSldYNEs5UEwSBAAAEAQAAKCLPAAAAAAAAAABnAqJa1EAAAA...",
"preferredPaperFormat": "a4"
},
"createdAt": "2026-09-01T08:15:31.902Z",
"updatedAt": "2026-09-01T08:15:32.611Z"
}
],
"nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTA5LTAxVDA4OjE1OjMyLjQ4M1oiLCJpZCI6IjlmOGU3ZDZjIn0"
}Send `nextCursor` as `cursor` for the next page; `null` means the end.
The list never returns pfrRejection; to diagnose a rejected document, read it individually.
curl -X GET "https://api.bokapos.rs/v1/fiscal-documents/1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f" \
-H "Authorization: Bearer $BOKAPOS_TOKEN"{
"id": "1c2d3e4f-5a6b-4c7d-8e9f-0a1b2c3d4e5f",
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"idempotencyKey": "order-4129-sale-1",
"clientReference": "ORDER-4129",
"invoiceType": "NORMAL",
"transactionType": "SALE",
"cashierId": "web-shop",
"buyerId": null,
"buyerDetails": null,
"status": "REJECTED",
"fiscalized": false,
"failureCode": "PFR_VALIDATION_REJECTED",
"retryable": false,
"pfr": null,
"receipt": null,
"createdAt": "2026-09-01T08:15:31.902Z",
"updatedAt": "2026-09-01T08:15:32.611Z",
"pfrRejection": {
"items": [
{
"property": "items[0].unitPrice",
"codes": [
"2804"
]
}
]
}
}Code 2804 (format) is what the sandbox returns for a price with more than two decimals. A rejected document is not a receipt; correct the request and send it with a new key.
Journal export (CSV)
The same filters, a deterministic CSV of at most 10,000 rows, without raw PFR data and without secrets. The Boka-Export-Schema-Version header carries the format version (boka-fiscal-journal-csv-v2). If the filters match more than 10,000 rows, the request fails as a whole (422), so narrow the period.
curl -X GET "https://api.bokapos.rs/v1/fiscal-documents/export?businessPremiseId=b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22&createdFrom=2026-09-01T00%3A00%3A00Z&createdTo=2026-10-01T00%3A00%3A00Z" \
-H "Authorization: Bearer $BOKAPOS_TOKEN" \
--output dnevnik-2026-09.csvschemaVersion,fiscalDocumentId,taxpayerId,businessPremiseId,idempotencyKey,clientReference,invoiceType,transactionType,cashierId,buyerId,status,fiscalized,failureCode,pfrInvoiceNumber,pfrTime,createdAt,updatedAt,retryable,esirNumber,issuingSoftwareVersion,issuingReceiptRepresentationVersion,issuingBuildCommit
boka-fiscal-journal-csv-v2,9f8e7d6c-5b4a-4321-8765-0fedcba98761,3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11,b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22,order-4127-sale-1,ORDER-4127,NORMAL,SALE,web-shop,,FISCALIZED,true,,JWX4K9PL-JWX4K9PL-1042,2026-09-01T08:15:32.483Z,2026-09-01T08:15:31.902Z,2026-09-01T08:15:32.611Z,false,,1.0.0,boka-receipt-representation-v21,1f0d454e8b2c9a7d6f5e4c3b2a1908f7e6d5c4b3The `Boka-Export-Schema-Version: boka-fiscal-journal-csv-v2` header names the format version.
Turnover report
A local immutable sum of fiscalized Normal and Advance receipts by V-PFR signing time, for one premise and period. Sale and refund are separate positive amounts; per-payment-type amounts come from the verified canonical request, the tax per label from the verified original V-PFR response, and the base and total per label from the receipt lines carrying that label (the total is the gross of those lines, the base is that total minus the tax). Amounts carry four decimals, like the tax the V-PFR signs; round them to two for display. It is your report, not a substitute for the daily report on the Tax Administration's SUF portal. The time bounds accept any RFC 3339 offset (Z, +00:00, +02:00) and are compared as instants.
curl -X GET "https://api.bokapos.rs/v1/fiscal-documents/turnover-report?taxpayerId=3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11&businessPremiseId=b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22&pfrFrom=2026-09-01T00%3A00%3A00%2B02%3A00&pfrTo=2026-09-02T00%3A00%3A00%2B02%3A00" \
-H "Authorization: Bearer $BOKAPOS_TOKEN"{
"source": "BOKA_LOCAL_IMMUTABLE_PFR",
"periodBasis": "PFR_SDC_TIME",
"amountConvention": "SALE_REFUND_SEPARATE",
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"pfrFrom": "2026-08-31T22:00:00Z",
"pfrTo": "2026-09-01T22:00:00Z",
"documentCount": 2,
"firstDocument": {
"fiscalDocumentId": "9f8e7d6c-5b4a-4321-8765-0fedcba98761",
"pfrInvoiceNumber": "JWX4K9PL-JWX4K9PL-1042",
"pfrTime": "2026-09-01T10:15:32.483+02:00"
},
"lastDocument": {
"fiscalDocumentId": "a1b2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d",
"pfrInvoiceNumber": "JWX4K9PL-JWX4K9PL-1045",
"pfrTime": "2026-09-01T16:40:05.120+02:00"
},
"paymentTotals": [
{
"securityElementJid": "JWX4K9PL",
"paymentType": "CARD",
"saleAmount": 8990,
"refundAmount": 8990
}
],
"taxTotals": [
{
"invoiceType": "NORMAL",
"categoryType": 0,
"label": "F",
"rate": 11,
"categoryName": "ECAL",
"saleTaxableAmount": 8099.0991,
"saleTaxAmount": 890.9009,
"saleTotalAmount": 8990,
"refundTaxableAmount": 8099.0991,
"refundTaxAmount": 890.9009,
"refundTotalAmount": 8990
}
]
}curl -X GET "https://api.bokapos.rs/v1/fiscal-documents/turnover-report/export?taxpayerId=3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11&businessPremiseId=b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22&pfrFrom=2026-09-01T00%3A00%3A00%2B02%3A00&pfrTo=2026-09-02T00%3A00%3A00%2B02%3A00" \
-H "Authorization: Bearer $BOKAPOS_TOKEN" \
--output promet-2026-09-01.csvOperation state
GET /v1/operations/{operationId} is the lighter shape of a document, from the database, without contacting the V-PFR. The operation identifier equals the document id. Use it when a 409 returns an operationId, and as the call you poll after OUTCOME_UNKNOWN.
curl -X GET "https://api.bokapos.rs/v1/operations/9f8e7d6c-5b4a-4321-8765-0fedcba98761" \
-H "Authorization: Bearer $BOKAPOS_TOKEN"{
"id": "4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f70",
"kind": "FISCAL_DOCUMENT",
"status": "OUTCOME_UNKNOWN",
"fiscalized": false,
"failureCode": "PFR_RESPONSE_NOT_OBSERVED",
"retryable": false,
"resourceUrl": "/v1/fiscal-documents/4d5e6f7a-8b9c-4d0e-9f1a-2b3c4d5e6f70",
"createdAt": "2026-09-01T09:00:00.000Z",
"updatedAt": "2026-09-01T09:00:31.000Z"
}resourceUrl leads to the full document. When an unknown outcome is resolved, status becomes FISCALIZED (the receipt existed at the V-PFR) and the order is fiscalized without a single new request.
Security elements
Safe certificate metadata per premise: JID, environment, validity, certificateExpiryStatus (current, warning 30 days before expiry, critical 7 days, expired) and replacementRecommended. Secrets are never returned. Useful for monitoring: warn the Owner before expiry, because the replacement is done by them in the Tax Administration portal and in the BokaPOS portal.
curl -X GET "https://api.bokapos.rs/v1/security-elements?businessPremiseId=b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22" \
-H "Authorization: Bearer $BOKAPOS_TOKEN"{
"items": [
{
"id": "e5f6a7b8-c9d0-4e1f-8a2b-3c4d5e6f7a80",
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"environment": "sandbox",
"jid": "JWX4K9PL",
"certificateThumbprint": "A1B2C3D4E5F60718293A4B5C6D7E8F9012345678",
"certificateSubject": "CN=JWX4K9PL, O=BOKA GROUP DOO, C=RS",
"certificateIssuer": "CN=Sandbox ICA, O=Poreska uprava Republike Srbije, C=RS",
"certificateSerialNumber": "3F9C2A8E6B1D",
"certificateNotBefore": "2026-08-20T00:00:00Z",
"certificateNotAfter": "2028-08-20T00:00:00Z",
"certificateExpiryStatus": "current",
"replacementRecommended": false,
"status": "active",
"createdAt": "2026-08-21T09:10:00.000Z",
"updatedAt": "2026-08-21T09:12:00.000Z"
}
]
}Licence
GET /v1/license says whether production fiscalization is currently allowed, which modules are enabled and which prices apply. Call it at start-up and after any 403 LICENSE_*. The sandbox is never billed and never blocked.
curl -X GET "https://api.bokapos.rs/v1/license" \
-H "Authorization: Bearer $BOKAPOS_TOKEN"{
"state": "active",
"productionFiscalizationAllowed": true,
"modules": {
"advance": true,
"email": false
},
"startsOn": "2026-09-01",
"endsOn": null,
"prices": {
"basePricePerElement": 1600,
"includedDocuments": 600,
"overageDocumentPrice": 1,
"advanceModulePrice": 600,
"emailModulePrice": 600,
"vatRate": 0.2
}
}