Serbian fiscalization API: a fiscal receipt from your code
BokaPOS is a REST API for fiscalization in Serbia. Your system sends the items and payments in one call, and BokaPOS issues the fiscal receipt through the Tax Administration's V-PFR and returns the PFR number, verification link, QR code and PDF. BokaPOS is an approved ESIR (IB 1774) for distance selling; the sandbox is free.
Examples in curl, Node.js, PHP, C# and Python. The OpenAPI contract is public.
Approved by the Tax Administration
- Decision
000-092-00-00256/2026-0000- Date
- 29 October 2026
- Model
- BokaPOS 1.0.1, ESIR class Advanced
- Scope
- Distance selling only, portable
What the API does
You send a business request; BokaPOS assembles the fiscal document by the Tax Administration's rules.
Issues fiscal receipts
Normal (sale and refund), advance, proforma, training and copy, with every reference the rules require.
Returns a finished receipt
PFR number, time and counter, verification link, official text, PDF in A4, 80 mm and 58 mm, PNG preview and QR code.
Runs the complex flows
Refunds with a copy for cash, the advance chain with closure, proforma with a reference: BokaPOS runs them on the server.
Keeps the journal
Every operation, including rejected ones and unknown outcomes, with search, export and a turnover report.
Your first receipt in three calls
Token, tax labels, receipt. A fourth call fetches the PDF or another representation when you need it; the URLs are already in the response.
Get a token
POST
auth.bokapos.rs/realms/boka/ protocol/ openid-connect/ token OAuth 2.0 client credentials with your client id and secret. The token is valid for 300 seconds; cache it and refresh it before expiry.
Read the tax labels
GET
/v1/tax-rates The labels in the response are the only ones a receipt may carry. Sandbox and production have different sets, so never hard-code them.
Issue the receipt
POST
/v1/fiscal-documents With an
Idempotency-Keyheader derived from the order. A 201 withfiscalized: trueis a fiscal receipt; nothing else is.Fetch a representation (when needed)
GET
/v1/fiscal-documents/ {id}/ representations/ pdf-a4 When you need the PDF itself, an image or the QR code. The same document has seven representations.
Before the first receipt, read your taxpayerId and businessPremiseId once (GET /v1/taxpayers) and keep them in configuration.
curl -X POST "https://api.bokapos.rs/v1/fiscal-documents" \
-H "Authorization: Bearer $BOKAPOS_TOKEN" \
-H "Idempotency-Key: order-4127-sale-1" \
-H "Content-Type: application/json" \
-d '{
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"clientReference": "ORDER-4127",
"invoiceType": "NORMAL",
"transactionType": "SALE",
"cashier": {
"id": "web-shop"
},
"items": [
{
"name": "Bluetooth slušalice",
"unitOfMeasure": "kom",
"quantity": 1,
"unitPrice": 8990,
"taxLabels": [
"F"
]
}
],
"payments": [
{
"type": "CARD",
"amount": 8990
}
]
}'{
"id": "9f8e7d6c-5b4a-4321-8765-0fedcba98761",
"clientReference": "ORDER-4127",
"status": "FISCALIZED",
"fiscalized": true,
"pfr": {
"invoiceNumber": "JWX4K9PL-JWX4K9PL-1042",
"sdcTime": "2026-09-01T10:15:32.483+02:00",
"totalAmount": 8990,
"verificationUrl": "https://sandbox.suf.purs.gov.rs/v/?vl=A0pXWDRLOVBMSldYNEs5UEwSBAAAEAQAAKCLPAAAAAAAAAABnAqJa1EAAAA..."
},
"receipt": {
"pdfA4Url": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/pdf-a4",
"qrImageUrl": "/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/qr-svg"
}
}What is in the response
The 201 response carries everything the customer and the accountant need, from the V-PFR's signed response.
Fields you keep with the order
pfr.invoiceNumber- the PFR receipt number, the official number assigned by the V-PFR
pfr.sdcTime- the PFR time, the official time of the receipt
pfr.verificationUrl- the link for checking at the Tax Administration; the same one is in the QR code
pfr.journal- the official text of the receipt
id- the key for copies, refunds and journal search
Receipt representations
Every fiscalized receipt has seven representations. Send the customer a PDF or a link, and your system the JSON.
- Official text
official-text - PDF A4
pdf-a4 - PDF 80 mm
pdf-80mm - PDF 58 mm
pdf-58mm - Image for e-mail
preview-png - QR code for verification
qr-svg - JSON package
canonical-json
No duplicate receipts
Every fiscal mutation carries an Idempotency-Key header, 16 to 200 characters long, derived from your order. The key is bound to the request content, so repeating never issues a second receipt.
- Example key
Idempotency-Key: order-4127-sale-1
- Same key, same content
200The API returns the original operation (200 instead of 201) and never issues a second receipt, however many times you repeat.
- Same key, different content
409IDEMPOTENCY_KEY_REUSED_WITH_DIFFERENT_REQUEST with the original's operationId. Nothing is issued.
- Nothing was sent
503, retryable: trueWait a few seconds and send the same request with the same key; the attempt that issues the receipt answers 201 with the same id.
- Outcome unknown
OUTCOME_UNKNOWNDo not send a new request for the same sale. Poll GET /v1/operations/{id}; BokaPOS resolves the outcome purely by reading from the V-PFR.
Who it is for
Any system that sells at a distance and knows when an order is paid.
- Web shopOne call per paid order; the customer gets the receipt link and PDF.
- ERPReceipts for online orders and business invoicing, with buyer identification and journal export.
- SaaS and subscriptionsA receipt for every charge, from the service that already knows the payment went through.
- MarketplaceA receipt for every order, from the same flow in which the platform confirms payment.
What is free and what is paid
Development and testing cost nothing. Production is paid, per security element and by volume.
Free
- Sandbox
- no expiry, never blocked by licensing
- WooCommerce plugin
- no charge for installation, updates or support
- Integration help
- sandbox access and examples for your system, with support from BokaPOS Administration
Paid monthly
VAT included- Base per production element
- RSD 1,600
- Documents included per organization
- 600
- Each additional document
- RSD 1
- Advance module
- RSD 600
- E-mail module
- RSD 600
The first month is prorated by day. Rejected and failed attempts are not charged.
Three routes to a fiscal receipt
The receipt is the same whichever route you take: the Tax Administration's V-PFR signs it. What differs is the work left to you.
What the integrator does on each route
A taxpayer may use only an ESIR that the Tax Administration has approved and entered in its public register. Guide in Serbian: the free Tax Administration ESIR or a cloud ESIR
Integrating with AI?
Give the assistant two sources: the documentation bundle for AI and the OpenAPI contract. The prompt points it at both, gives it our rules (idempotency, unknown outcomes, tax labels) and tells it which questions to ask you before it writes code.
The prompt points at the English documentation because field names, codes and examples are English. The assistant answers in whichever language you use.
Questions about the API
Answers from the documentation, in short.
Is there a free sandbox?
Yes. The sandbox is free, has no expiry and is never blocked by licensing. BokaPOS opens the organization, assigns a test security element and issues a sandbox credential; test receipts are issued under BOKA GROUP DOO's PIB and verify at sandbox.suf.purs.gov.rs.
Which programming languages have examples?
Five: curl, Node.js, PHP, C# and Python, for every operation. The API follows a public OpenAPI contract (api.bokapos.rs/openapi.yaml) from which you can generate a client in any language, and the documentation exists in Serbian and English, and as a PDF.
How does a system sign in to the API?
With OAuth 2.0 client credentials over TLS. The client id and secret get you a token valid for 300 seconds, which you cache and send as Authorization: Bearer. An Owner or Administrator of the organization collects the secret once in the portal, and it stays only on your server.
Do sandbox and production have different URLs?
No. Both environments use https://api.bokapos.rs; the credential decides the environment (boka-sbx-... or boka-prod-...). Every key sees only its own environment's data, so test and real receipts never mix.
What if I send the same request twice?
Nothing is issued twice. The same Idempotency-Key with the same content returns the original operation (200 instead of 201), and the same key with different content returns 409. Derive the key from the order, for example order-4127-sale-1.
How long does an integration take?
A day or two for a typical API integration, including sale and refund testing in the sandbox. With the WooCommerce plugin, setup takes an hour or two, without code.
Can one system issue receipts for several taxpayers or premises?
Yes. Every request carries taxpayerId and businessPremiseId, so the same code issues receipts for all taxpayers and premises of its organization, and each premise has its own security element. An agency gets a separate organization for every client.
What does going to production involve?
The code does not change. The Owner obtains the security element from the Tax Administration and uploads it to the portal, BokaPOS verifies and activates it and issues the licence and the production credential, and you swap the client id and secret in your configuration.
Where is the data stored?
In the European Union, separated per organization, with every receipt stored for good. The taxpayer's security element is encrypted in a vault and opened only for the exact business premise and purpose.
What if the Tax Administration does not answer?
Nothing is blindly sent again. If nothing was sent, the answer is 503 with retryable: true and you repeat the same request with the same key. If the request may have arrived, the status is OUTCOME_UNKNOWN: you send no new request, you poll GET /v1/operations/{id}, and BokaPOS resolves the outcome purely by reading from the V-PFR.
Is there a plugin for Shopify or other platforms?
No, a ready plugin exists only for WooCommerce, and it is free. Shopify, Magento, PrestaShop, OpenCart and custom systems call the same API, with one call per order, following the guide for each platform on the Integrations page.
How much does it cost?
RSD 1,600 per month per production security element, with 600 documents a month included per organization and RSD 1 per additional document, VAT included. The Advance and E-mail modules are RSD 600 a month each; the sandbox and the WooCommerce plugin are free.
Can I call the API from a browser or a mobile app?
No. The credential secret must never go into a browser, a mobile app, a public repository or a log; your backend always makes the calls to BokaPOS.
Do I send tax rates and the tax amount?
No. You send the gross price and a tax label from GET /v1/tax-rates; BokaPOS calculates the tax by the official rules and the V-PFR signs it. Do not hard-code labels, because sandbox and production differ.
Does the API work for sales in a physical shop?
No. BokaPOS is approved for distance selling only and does not support an L-PFR. Face-to-face sales need an L-PFR; for that the same company makes BokaLPFR.
Sandbox access and examples, the same working day
Send us a few sentences about your system. We reply the same working day with sandbox access and examples for your system.