Skip to content

API documentation

BokaPOS API

One HTTP call, one fiscal receipt. Your web shop, ERP or platform sends the items and payments, BokaPOS fiscalizes them through the Tax Administration's V-PFR and returns the receipt number, the verification link, a PDF and a QR code. Everything an integrator needs is here: a quick start, the rules, the workflows and a reference for every operation.

Updated: 29 August 2026 · Contract version 1.0.0

What the API does

  • Issues fiscal receipts for distance commerce: Normal (sale), refund, advance, proforma, training and copy, with every reference the regulations require.
  • Returns the complete receipt package: PFR number, time and counter, the Tax Administration verification link, the official journal text, PDF in A4, 80 mm and 58 mm, a PNG preview and the QR code.
  • Keeps an electronic journal of every operation, including rejected ones and unknown outcomes, with search, export and a turnover report.
  • Runs the complex workflows for you: a refund with the automatic copy for cash, an advance chain with closure, a proforma with references. You send a business request; BokaPOS composes the fiscal documents.
  • E-mails the receipt to the customer from the platform when the E-mail module is enabled.
  • Never invents: a receipt exists only once the V-PFR returns a signed response and BokaPOS stores it durably. No fake success, no silent retries.

Quick start: the first receipt in the sandbox

  1. 01

    Request sandbox access

    Write to office@bokagroup.rs or use the contact page. BokaPOS opens the organization, assigns a sandbox security element and issues a client id (boka-sbx-...) and a secret. The secret is shown once; keep it in your server's secrets, never in code or a browser. The sandbox is free.

  2. 02

    Get a token

    OAuth 2.0 client credentials at https://auth.bokapos.rs/realms/boka/protocol/openid-connect/token. The token lives 300 seconds; cache it and refresh before expiry.

  3. 03

    Verify access

    GET /v1/runtime returns your organization, the client id and whether the fiscal adapter is ready.

  4. 04

    Find the taxpayer and premise

    GET /v1/taxpayers, then GET /v1/taxpayers/{taxpayerId}/business-premises. Those two identifiers go into every fiscal request; keep them in configuration.

  5. 05

    Read the tax labels

    GET /v1/tax-rates with both identifiers. The labels in the response are the only ones a receipt may carry. Sandbox and production have different sets, so never hard-code them.

  6. 06

    Issue the receipt

    POST /v1/fiscal-documents with an Idempotency-Key header. A 201 with fiscalized: true is a fiscal receipt; nothing else is.

  7. 07

    Fetch the PDF and the link

    Take pfr.verificationUrl and receipt.pdfA4Url from the response and store the document id with the order.

1. Token

POST token
curl -X POST "https://auth.bokapos.rs/realms/boka/protocol/openid-connect/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "client_id=$BOKAPOS_CLIENT_ID" \
  -d "client_secret=$BOKAPOS_CLIENT_SECRET"
Token response
{
  "access_token": "eyJhbGciOiJSUzI1NiIsInR5cCIgOiAiSldUIiwia2lkIiA6...",
  "expires_in": 300,
  "token_type": "Bearer",
  "scope": "tenant:read operations:read catalogue:read catalogue:write fiscal:read fiscal:write refund:write proforma-training:write advance:write advance:close configuration:read security-elements:read"
}

Every following call carries Authorization: Bearer <access_token>. In the examples below the token sits in the BOKAPOS_TOKEN environment variable.

2. Verify access

GET /v1/runtime
curl -X GET "https://api.bokapos.rs/v1/runtime" \
  -H "Authorization: Bearer $BOKAPOS_TOKEN"
200 OK
{
  "manufacturer": "BOKA GROUP DOO",
  "productName": "BokaPOS",
  "esirNumber": "",
  "softwareVersion": "1.0.0",
  "buildCommit": "1f0d454e8b2c9a7d6f5e4c3b2a1908f7e6d5c4b3",
  "instanceId": "api-bokapos-rs",
  "organizationId": "7c1e9a4b-2d3f-4e5a-b6c7-8d9e0f1a2b3c",
  "clientId": "boka-sbx-k7m2p9x4q1wz",
  "fiscalEndpointsEnabled": true,
  "pfrAdapter": "configured"
}

3. Taxpayer and premise

GET /v1/taxpayers
curl -X GET "https://api.bokapos.rs/v1/taxpayers" \
  -H "Authorization: Bearer $BOKAPOS_TOKEN"
GET /v1/taxpayers/{taxpayerId}/business-premises
curl -X GET "https://api.bokapos.rs/v1/taxpayers/3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11/business-premises" \
  -H "Authorization: Bearer $BOKAPOS_TOKEN"
200 OK
{
  "items": [
    {
      "id": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
      "taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
      "puIdentifier": "1234567",
      "name": "Web shop",
      "commerceMode": "distance",
      "environment": "sandbox",
      "paymentMode": "all",
      "status": "active",
      "createdAt": "2026-08-21T09:05:00.000Z",
      "updatedAt": "2026-08-21T09:05:00.000Z"
    }
  ]
}

4. Tax labels

GET /v1/tax-rates
curl -X GET "https://api.bokapos.rs/v1/tax-rates?taxpayerId=3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11&businessPremiseId=b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22" \
  -H "Authorization: Bearer $BOKAPOS_TOKEN"
200 OK
{
  "source": "PFR",
  "environment": "sandbox",
  "taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
  "businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
  "currentTaxGroupId": 8,
  "validFrom": "2022-05-01T00:00:00",
  "fetchedAt": "2026-09-01T08:14:02.118Z",
  "labels": [
    {
      "label": "F",
      "category": "ECAL",
      "categoryType": 0,
      "rate": 11,
      "activeFrom": "2022-05-01T00:00:00"
    },
    {
      "label": "N",
      "category": "N-TAX",
      "categoryType": 0,
      "rate": 0,
      "activeFrom": "2022-05-01T00:00:00"
    },
    {
      "label": "P",
      "category": "PBL",
      "categoryType": 2,
      "rate": 0.5,
      "activeFrom": "2022-05-01T00:00:00"
    },
    {
      "label": "E",
      "category": "STT",
      "categoryType": 0,
      "rate": 6,
      "activeFrom": "2022-05-01T00:00:00"
    },
    {
      "label": "T",
      "category": "TOTL",
      "categoryType": 1,
      "rate": 2,
      "activeFrom": "2022-05-01T00:00:00"
    },
    {
      "label": "A",
      "category": "VAT",
      "categoryType": 0,
      "rate": 10,
      "activeFrom": "2022-05-01T00:00:00"
    },
    {
      "label": "B",
      "category": "VAT",
      "categoryType": 0,
      "rate": 0,
      "activeFrom": "2022-05-01T00:00:00"
    },
    {
      "label": "Ж",
      "category": "VAT",
      "categoryType": 0,
      "rate": 19,
      "activeFrom": "2022-05-01T00:00:00"
    },
    {
      "label": "C",
      "category": "VAT-EXCL",
      "categoryType": 0,
      "rate": 0,
      "activeFrom": "2022-05-01T00:00:00"
    }
  ]
}

The Tax Administration sandbox carries a generic test label set. In production you get the official Serbian labels (for example Ђ 20%, Е 10%, Г 0%, А non-VAT). Never hard-code labels.

5. The first receipt

POST /v1/fiscal-documents
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",
    "displayName": "Web shop"
  },
  "items": [
    {
      "name": "Bluetooth slušalice",
      "unitOfMeasure": "kom",
      "quantity": 1,
      "unitPrice": 8990,
      "gtin": "8606012345678",
      "taxLabels": [
        "F"
      ]
    }
  ],
  "payments": [
    {
      "type": "CARD",
      "amount": 8990
    }
  ],
  "metadata": {
    "orderId": "4127",
    "channel": "web"
  }
}'
201 Created
{
  "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"
}

6. The receipt PDF

GET /v1/fiscal-documents/{fiscalDocumentId}/representations/{representationFormat}
curl -X GET "https://api.bokapos.rs/v1/fiscal-documents/9f8e7d6c-5b4a-4321-8765-0fedcba98761/representations/pdf-a4" \
  -H "Authorization: Bearer $BOKAPOS_TOKEN" \
  --output racun-ORDER-4127.pdf

The same document has seven representations (text, JSON, QR, PDF for three paper formats, PNG). See Receipt representations and delivery.

Where to go next

What is done in the portal, not through the API

An API credential has a fixed set of permissions: fiscalization, catalogue, reading taxpayers, premises, certificates and the licence. The following are deliberately outside the API and are done in the portal at cloud.bokapos.rs (the organization's Owner or Administrator) or by BokaPOS Administration:

  • creating taxpayers and premises (the PIB and the premise identifier are immutable),
  • uploading and activating the production security element (certificate),
  • issuing and revoking API credentials,
  • receipt branding (logo, contact, thank-you note) and e-mail delivery settings,
  • users and roles, the activity log, subscription and invoices.