API documentation
Proforma and Training
Предрачун is an offer that looks like a receipt but has no tax effect; Обука is practice for operators and tests. Both go through one bounded workflow with clear reference rules.
Updated: 29 August 2026 · Contract version 1.0.0
When they are used
- Proforma (
PROFORMA): an offer or pro-forma invoice to the customer before payment, for example a B2B order paid by wire transfer. It printsОВО НИЈЕ ФИСКАЛНИ РАЧУН. When the customer pays and the goods ship, a real Normal Sale receipt is issued (which does not reference the proforma). - Training (
TRAINING): a trial document for operator training or testing a flow. It has no tax effect and also printsОВО НИЈЕ ФИСКАЛНИ РАЧУН. In production it is the document with which BokaPOS proves the activation of your certificate.
Rules
| Document | Reference (`original`) |
|---|---|
| Предрачун Продаја | none, or a BokaPOS proforma (sale or refund) |
| Предрачун Рефундација | mandatory, a BokaPOS Предрачун Продаја; repeats every item and payment and identifies the buyer |
| Обука Продаја | none |
| Обука Рефундација | mandatory, a BokaPOS Обука Продаја; repeats the whole source document |
A source can be refunded only once and in full; a second attempt returns 409. External documents are not supported. Tax labels, amounts and payments follow the same rules as a Normal Sale.
Proforma
curl -X POST "https://api.bokapos.rs/v1/proforma-training-workflows" \
-H "Authorization: Bearer $BOKAPOS_TOKEN" \
-H "Idempotency-Key: quote-2210-proforma-1" \
-H "Content-Type: application/json" \
-d '{
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"clientReference": "QUOTE-2210",
"invoiceType": "PROFORMA",
"transactionType": "SALE",
"cashier": {
"id": "web-shop"
},
"buyer": {
"id": "10:106952811"
},
"items": [
{
"name": "Bluetooth slušalice",
"unitOfMeasure": "kom",
"quantity": 1,
"unitPrice": 8990,
"gtin": "8606012345678",
"taxLabels": [
"F"
]
}
],
"payments": [
{
"type": "WIRE_TRANSFER",
"amount": 8990
}
],
"commercialFooter": "Ponuda važi 7 dana."
}'{
"id": "0a1b2c3d-4e5f-4a6b-8c7d-8e9f0a1b2c3d",
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"clientReference": "QUOTE-2210",
"invoiceType": "PROFORMA",
"transactionType": "SALE",
"state": "COMPLETED",
"original": null,
"document": {
"id": "1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e",
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"idempotencyKey": "quote-2210-proforma-1",
"clientReference": "QUOTE-2210",
"invoiceType": "PROFORMA",
"transactionType": "SALE",
"cashierId": "web-shop",
"buyerId": "10:106952811",
"buyerDetails": null,
"status": "FISCALIZED",
"fiscalized": true,
"failureCode": null,
"retryable": false,
"pfr": {
"invoiceNumber": "JWX4K9PL-JWX4K9PL-1047",
"sdcTime": "2026-09-01T10:15:32.483+02:00",
"requestedBy": "JWX4K9PL",
"signedBy": "JWX4K9PL",
"transactionTypeCounter": 902,
"totalCounter": 1047,
"invoiceCounterExtension": "ПрП",
"totalAmount": 8990,
"totalTax": 890.9009,
"verificationUrl": "https://sandbox.suf.purs.gov.rs/v/?vl=A0pXWDRLOVBMSldYNEs5UEwSBAAAEAQAAKCLPAAAAAAAAAABnAqJa1EAAAA...",
"journal": "============ ФИСКАЛНИ РАЧУН ============\n...\nПФР број рачуна: JWX4K9PL-JWX4K9PL-1047\nБројач рачуна: 902/1047ПрП\n========================================\n======== КРАЈ ФИСКАЛНОГ РАЧУНА ========="
},
"receipt": {
"textUrl": "/v1/fiscal-documents/1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e/representations/official-text",
"jsonUrl": "/v1/fiscal-documents/1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e/representations/canonical-json",
"pdfA4Url": "/v1/fiscal-documents/1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e/representations/pdf-a4",
"pdf80mmUrl": "/v1/fiscal-documents/1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e/representations/pdf-80mm",
"pdf58mmUrl": "/v1/fiscal-documents/1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e/representations/pdf-58mm",
"previewImageUrl": "/v1/fiscal-documents/1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e/representations/preview-png",
"qrImageUrl": "/v1/fiscal-documents/1b2c3d4e-5f6a-4b7c-8d9e-0f1a2b3c4d5e/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"
},
"failureCode": null,
"createdAt": "2026-09-02T07:02:10.000Z",
"updatedAt": "2026-09-02T07:02:11.204Z"
}Training
curl -X POST "https://api.bokapos.rs/v1/proforma-training-workflows" \
-H "Authorization: Bearer $BOKAPOS_TOKEN" \
-H "Idempotency-Key: training-2026-09-02-1" \
-H "Content-Type: application/json" \
-d '{
"taxpayerId": "3f9c2a8e-6b1d-4e5a-9c47-1d2b8e6f0a11",
"businessPremiseId": "b7d4e2c1-9a3f-4c8e-8f21-6e5a0c9d3b22",
"clientReference": "TRAINING-1",
"invoiceType": "TRAINING",
"transactionType": "SALE",
"cashier": {
"id": "operater-1"
},
"items": [
{
"name": "Test artikal",
"unitOfMeasure": "kom",
"quantity": 1,
"unitPrice": 100,
"taxLabels": [
"F"
]
}
],
"payments": [
{
"type": "CASH",
"amount": 100
}
]
}'Workflow states
| `state` | HTTP | Meaning |
|---|---|---|
COMPLETED | 201 (200 on replay) | the document is signed; document carries the PFR facts and representations |
PENDING | 202 or 503 | reserved, not sent; replay with the same key |
OUTCOME_UNKNOWN | 503 | sent, response missing; do not retry, read GET /v1/proforma-training-workflows/{id} |
REJECTED | 422 | the V-PFR rejected; fix and send with a new key |
FAILED | 503 | an error before sending; failureCode |
curl -X GET "https://api.bokapos.rs/v1/proforma-training-workflows/0a1b2c3d-4e5f-4a6b-8c7d-8e9f0a1b2c3d" \
-H "Authorization: Bearer $BOKAPOS_TOKEN"Proforma and Training errors
| HTTP | Code | Meaning | What to do | Retry |
|---|---|---|---|---|
| 403 | MODULE_NOT_LICENSED | The base licence is valid but the module in module (advance or email) is not enabled. | Enable the module through BokaPOS Administration or do not use that feature in production. | later |
| 422 | TAX_LABEL_NOT_CURRENT | At least one tax label is not in the fresh V-PFR configuration (field invalidLabels). | Read GET /v1/tax-rates and use only the labels it returns; sandbox and production have different sets. | fix the request |
| 422 | REFERENCE_DOCUMENT_NOT_FOUND | The referenced document (reference.fiscalDocumentId) does not exist. | Check the identifier from the original receipt's response. | fix the request |
| 422 | REFERENCE_DOCUMENT_TYPE_NOT_ALLOWED | This invoice and transaction type may not reference that kind of source document (the official reference matrix). | See the reference table on the Conventions page. | fix the request |
| 409 | PROFORMA_TRAINING_WORKFLOW_RESERVATION_CONFLICT | The source document already has an unresolved or completed refund. | Read the workflow from the workflowId in the response. | never |
| 409 | PROFORMA_TRAINING_SOURCE_ALREADY_REFUNDED | The Proforma or Training document was already refunded in full. | No further action. | never |