Lizzard Solutions

IPS QR Code on Invoices: Setup Guide for Serbian Businesses

· Lizzard Solutions
IPS QR codeinvoicinginstant paymentsSerbiaautomation

By Nemanja Vukmirović, Lizzard Solutions. Last updated 12 November 2026.

Your customer opens the invoice, types an 18-digit account number into their banking app, gets one digit wrong, and the payment lands nowhere useful. Then you spend a morning matching bank statements to invoices by hand.

An IPS QR code on invoices removes that step. The customer scans, checks the pre-filled amount and pays. This guide shows you exactly what goes into the code under the National Bank of Serbia (NBS) rules, the mistakes that make it fail, and how to generate it automatically from your invoicing system.

TL;DR

  • The NBS IPS QR code is a line of text with fixed tags (account, payee, amount, payment code, reference) encoded as a QR code that customers scan in their mobile banking app.
  • Most failures come from formatting: dashes in the account number, a decimal point instead of a comma, or empty optional tags.
  • NBS runs a free generator and validator, on a web page and as an API, so you can test every code before it reaches a customer.

What is an IPS QR code on an invoice?

An NBS IPS QR code is a QR code that contains all the data needed for an instant credit transfer in Serbia: the payee’s account, name, amount in dinars, payment code, and optionally the purpose and reference number. The payer scans it in a mobile banking app, the payment form fills itself in, and they only confirm.

The rules come from the NBS. Its recommendations for NBS IPS QR data describe every tag in detail, and NBS also requires the label “NBS IPS QR” next to, above or below the code when you print it on an invoice.

This code is different from the IPS codes merchants show at a till or in a web shop checkout. Those use other identification codes (PT and EK) and need a contract with an acquiring bank. If you sell online, our guide to payments and fiscalization for Serbian web shops covers that side.

Do this today

Look at your last invoice. Does it show an account number the customer has to retype? That is the step a QR code removes.


Which fields go into the IPS QR code?

The content is one line of text. Each field is a tag, a colon and a value, and fields are separated by a vertical bar (|). Here is a valid example we checked with the NBS validator on 12 November 2026:

K:PR|V:01|C:1|R:840000000095584510|N:Primer DOO|I:RSD12000,00|SF:221|S:Uplata po racunu 2026-117|RO:9714123412
TagMeaningRule (per NBS recommendations)
K, V, CIdentification code, version, character setAlways K:PR, V:01 and C:1 (UTF-8). Mandatory.
RPayee accountExactly 18 digits, no dashes. Only one account per code. Mandatory.
NPayee nameUp to 70 characters including spaces, up to three lines. Mandatory.
ICurrency and amount“RSD” plus the amount with a decimal comma, no space, e.g. RSD1025,12. Mandatory.
SFPayment code (šifra plaćanja)Three digits. Mandatory.
PPayerOptional, up to 70 characters. The bank may replace it with the actual account owner.
SPurpose of paymentOptional, up to 35 characters, one line.
ROModel and reference numberOptional, up to 25 characters. Starts with the model (e.g. 97) or with 00 if no model is used.

How to turn your account number into 18 digits

Bank account numbers in Serbia are written as bank code, account number and two control digits. For the QR code, you pad the middle part with zeros so the total is 18 digits. The NBS gives this example: 840-955845-10 becomes 840000000095584510.

Choosing the payment code

The first digit is 1 for cash and 2 for cashless payments. NBS notes that 189 and 289 are only for payments ordered by households, so a company or entrepreneur paying you needs another code. Among the most frequently used, NBS lists 121/221 for trade in goods and services and 122/222 for public enterprise services. Confirm the right code with your accountant.

Do this today

Write down your account number in the 18-digit form and the payment code you will use. These two values never change between invoices.


The 6 mistakes that make an IPS QR code fail

We sent a deliberately broken code to the NBS validator to see what it catches:

K:PR|V:01|C:1|R:845-0000000404849-87|N:JP EPS BEOGRAD|I:RSD3702.65|SF:289

The response listed three errors: the account “must contain 18 numeric characters exclusively”, its control digits did not match model 97, and the amount had an “invalid format” because of the decimal point. Watch for these six:

  1. Dashes or spaces in the account number. Use the 18-digit form only.
  2. A decimal point in the amount. Serbia uses a comma: RSD3702,65, not RSD3702.65.
  3. Empty optional tags. NBS does not allow something like |S:|. If you have no purpose or payer, leave the tag out entirely.
  4. A wrong model 97 reference. If RO starts with 97, the control digits must be correct. We confirmed the validator rejects a reference where they are not. Use 00 at the start if you do not calculate a model.
  5. Too-long text. More than 70 characters in the name or 35 in the purpose breaks the code.
  6. Extra characters at the end. No trailing space or new line after the last tag.

Common mistake

Copying the account number from a PDF letterhead into the generator. It almost always contains dashes, and the code will be rejected.


How to generate IPS QR codes: manual, API or automatic

OptionBest forHow it works
NBS web generatorA few invoices a monthFill in the fields on the NBS IPS QR generator and validator page and download the image.
NBS APIDevelopers testing or generating codesPOST the text to the NBS endpoints described in the NBS Generator/Validator API guidelines.
Built into your invoicingRecurring invoices, many customersYour system builds the text from invoice data, renders the QR locally and prints it with the “NBS IPS QR” label.

The NBS API has four methods: gen returns an image, generate returns a validation result with a base64 image, validate only checks the text, and upload checks an existing PNG or JPEG. Adding ?lang=en returns errors in English.

A worked example in Python

This short script builds the payload from invoice data and checks it with the NBS validator. It is the same logic we would put into an invoicing system:

import requests

def ips_account(acc: str) -> str:
    """'840-955845-10' -> '840000000095584510' (18 digits)"""
    bank, middle, check = acc.split("-")
    return bank + middle.zfill(13) + check

def ips_payload(acc, name, amount, sf, purpose=None, ref=None):
    tags = ["K:PR", "V:01", "C:1", "R:" + ips_account(acc),
            "N:" + name, "I:RSD" + f"{amount:.2f}".replace(".", ","),
            "SF:" + sf]
    if purpose: tags.append("S:" + purpose)   # max 35 characters
    if ref:     tags.append("RO:" + ref)      # model + reference, max 25
    return "|".join(tags)                     # empty tags are left out

payload = ips_payload("840-955845-10", "Primer DOO", 12000, "221",
                      "Uplata po racunu 2026-117", "9714123412")
r = requests.post("https://nbs.rs/QRcode/api/qr/v1/validate?lang=en",
                  data=payload.encode("utf-8"),
                  headers={"Content-Type": "text/plain"})
print(r.json()["s"])   # {'code': 0, 'desc': 'Ok.'}

Our suggestion for production: render the QR image in your own system with a standard QR library, and use the NBS validator in automated tests or as a check before sending. That way invoices do not depend on an outside service being reachable at the moment you issue them.

If you already send invoices to the state system, the same invoice data can feed the QR code. Our eFaktura (SEF) integration guide explains how that flow works, and our API integration guide covers connecting tools like this in general.

Do this today

Open the NBS generator, enter your own account in 18-digit form and a test amount, and scan the result with your banking app without confirming. You will see exactly what your customers will see.


What changes after you add the code

The customer no longer retypes your account, amount or reference. If every invoice carries a correct model 97 reference, each incoming payment shows which invoice it belongs to, which makes matching payments to invoices much easier for you or your accountant. That matching step is a typical candidate for business process automation.

Without the codeWith the code
Customer types account, amount and referenceCustomer scans and confirms
Typos in account or reference are possibleData comes from your system
Payments matched by name and amountPayments matched by reference number

FAQ

Is the IPS QR code mandatory on invoices in Serbia?

The NBS rules we cite describe how the code must look if you use it, not an obligation to add it to every invoice. If you do print it, follow the specification and place the label “NBS IPS QR” next to the code. Check with your accountant if your sector has specific rules.

Can I generate an IPS QR code for free?

Yes. The National Bank of Serbia offers a free generator and validator on its IPS website and as an API. You can create single codes manually or have your software send the text to the API and receive a validated code or image.

Why does my IPS QR code show an error when scanned?

Usually the text breaks a formatting rule: dashes in the account, a decimal point instead of a comma, an empty optional tag, a wrong model 97 reference or text that is too long. Paste the exact text into the NBS validator and it will list the problem.

Which payment code should I use for B2B invoices?

Codes 189 and 289 are only for payments ordered by households. For goods and services, NBS lists 121 or 221 among the most frequently used codes, where 2 means cashless. Your accountant can confirm the right code for your type of income.

Want IPS QR codes on every invoice automatically?

We connect your invoicing or CRM to generate validated IPS QR codes and match incoming payments, without changing how your team works.

Talk to Lizzard Solutions