The SIX Group's Swiss QR standard is 60 pages of payment specifications. Your code doesn't need to understand any of it.
If you're building invoicing or payment automation for Switzerland, whether you're an accountant's app, a logistics platform, or an automation builder, you'll eventually face the Swiss QR bill. It looks like a dense two-dimensional grid at the bottom of an invoice. The standard itself is authoritative, technical, and aimed at payment system designers, not at the applications that use them. What you actually need is the endpoint that generates it, and a clear mapping from your invoice fields to the fields the API expects.
This is that guide. No SIX standard reading required.
Why Swiss QR matters
The Swiss QR code is a structured barcode. It encodes specific, validated payment instructions in a machine-readable format that Swiss banks, accounting software, and postal services can process automatically. Before Swiss QR existed, paper invoices came with either a six-digit ESR reference or QR codes that did nothing more than repeat the invoice amount and number in a generic format. Swiss QR changed that: it's a standard that combines banking details (creditor IBAN), payment reference (structured or unstructured), amount, and metadata into a single, validated data structure.
Practically: when an invoice arrives with a Swiss QR bill, accounting software can scan it, extract the creditor, amount, and reference in one read, and match it against an accounts-payable entry with far less manual keying than a plain-text invoice requires. For you, the invoice generator, that means your customers can process your invoices faster, and Swiss QR adoption for B2B invoicing keeps expanding, which is reason enough to build it in now rather than retrofit it later.
What Create Swiss QR Bill actually does
Create Swiss QR Bill takes your invoice's payment data, creditor and ultimate debtor details, IBAN, amount, currency, reference type, language, and separator style, and returns a Swiss QR-bill-standard-compliant slip as PDF, PNG, JPEG, or TIFF. Optionally pass an existing document (as Base64, a blob id, or a URL) and the slip overlays directly onto it. You pass structured fields; the API validates and encodes them. You don't parse the spec; the API does.
Every request carries the same shape: creditor identity (name, address, IBAN), debtor identity (name, address), the amount and currency, a reference type and, when required, the reference value itself, plus formatting choices (language, separator line style, output format).
The API validates them against the Swiss QR-bill standard before returning anything, so you get immediate, specific feedback if your IBAN is malformed or a required field is missing, rather than a bill that fails at the bank.
The one endpoint you need
POST https://api.pdf4me.com/api/v2/CreateSwissQrBill
The endpoint takes a flat JSON payload, not nested creditor/debtor objects. Here's a working example, live-verified against the docs reference and the official Python sample in the pdf4me-api-samples repository:
{
"docContent": "",
"docName": "",
"iban": "CH0200700110003765824",
"crName": "Test AG",
"crAddressType": "S",
"crStreetOrAddressLine1": "Test Strasse",
"crStreetOrAddressLine2": "1",
"crPostalCode": "8000",
"crCity": "Zurich",
"amount": "1000",
"currency": "CHF",
"udName": "Test Debt AG",
"udAddressType": "S",
"udStreetOrAddressLine1": "Test Deb Strasse",
"udStreetOrAddressLine2": "2",
"udPostalCode": "8000",
"udCity": "Zurich",
"referenceType": "NON",
"languageType": "English",
"seperatorLine": "LineWithScissor",
"formatType": "pdf",
"pagingOptions": "first",
"IsAsync": true
}
Every field with a cr prefix describes the creditor, you, getting paid. Every field with ud describes the ultimate debtor, your customer. Leave docContent and docName empty to generate a standalone QR slip, or pass a Base64-encoded PDF in docContent to overlay the slip directly onto an existing invoice.
Required on every request: iban, crName, crAddressType, crStreetOrAddressLine1, crStreetOrAddressLine2, crPostalCode, crCity, amount, currency, udName, udAddressType, udStreetOrAddressLine1, udStreetOrAddressLine2, udPostalCode, udCity, referenceType, languageType, seperatorLine, formatType, and IsAsync. Note the field is genuinely spelled seperatorLine, one "a", in the live API. That is not a typo you are introducing.
Set crAddressType and udAddressType to S (Structured) for production. That stores street, house number, postal code, and city as separate fields, which is what most automated Swiss bank reconciliation expects. K (Combined) packs the address into two free-form lines instead, simpler to populate but less compatible with automated matching.
The referenceType field decides how the bill gets matched to a payment on the receiving end:
-
NON: No structured reference. UseunstructuredMessagefor a free-text note instead. -
QRR: A 27-digit numeric reference for domestic Swiss bills with PostFinance or Swiss bank IBANs. Requiresreference. -
SCOR: An ISO 11649 creditor reference, starting with "RF", for cross-border, SEPA-style matching. Also requiresreference.
formatType controls what comes back: pdf, png, jpeg, or tiff. When it's pdf, pagingOptions decides where the slip lands: first page, last page, AddPageAtEnd, or custom with a specific pageNumber. For image formats, leave pagingOptions as null.
One discrepancy worth knowing before you copy-paste: the live docs page documents the async flag as IsAsync, PascalCase, true for HTTP 202 plus polling, false for a synchronous 200. The official Python sample in the pdf4me-api-samples repository actually sends it lowercase, as "async": True. Both were observed on live, current sources. If your first call gets ignored, that field-name casing is worth checking first.
The response is always JSON, never a raw binary stream. A successful call returns docName and docContent, with docContent holding the generated file as a Base64 string you decode before saving.
The API validates you so you don't have to
If you pass an invalid IBAN, the API rejects it. Swiss IBANs are strictly validated: CH followed by 19 digits, 21 characters total, tied to a PostFinance or Swiss bank account. Miss a required field, send a malformed reference for QRR or SCOR, or send invalid Base64 in docContent, and you'll get an HTTP 400 with an error message in the JSON body, not a silently malformed bill. That's good: you catch configuration errors in development, not at invoice time. The spec's 60 pages define exactly what's valid; the API enforces it for you.
Use the API Tester to experiment with field combinations before you code. Paste your API key, fill in the creditor and debtor fields, set referenceType, languageType, and seperatorLine, and see the bill render in real time. This is how you learn what the API expects without reading the spec.
Every platform can do this
If you're building in Make, Zapier, Power Automate, or n8n, you don't call the REST endpoint directly. Your platform has a native module that wraps it.
Make: Create Swiss QR Bill in Make. The module surfaces the same fields, creditor details, amount, reference, optional debtor, as text inputs and dropdowns. No code needed.
Zapier: Create Swiss QR Bill in Zapier. Same interface, same field structure. Build a Zap that pulls invoice data from your accounting system and appends the bill to the PDF.
Power Automate: Create Swiss QR Bill in Power Automate. The action takes your invoice fields as inputs, generates the bill, and outputs it for saving to SharePoint or email.
n8n: Create Swiss QR Bill in n8n. The node surfaces the same structured inputs. Chain it after a read from your database, a transform, and a write to cloud storage.
All four wrap the same validation and the same output formats. Pick the platform you're already using, and your learning curve is the same: understand creditor IBAN, amount, reference, and debtor.
One more thing: reading Swiss QR bills
If you're on the receiving end, a lender, a vendor, or an accounting system processing incoming invoices with embedded bills, you can also read Swiss QR codes. Pass the PDF or image, and the API extracts the creditor, amount, reference, and payment instructions as structured JSON. This is the inverse of generation and covers the full cycle.
You can also split a PDF by Swiss QR if you receive a batch of invoices. Each invoice in the batch is separated at the QR bill boundary, so you can process them individually. This is how big accounting systems handle invoice ingestion at scale.
Getting started: three steps
- Get your credentials. Connect to the PDF4me API. You'll need an API key.
- Gather your invoice data. Creditor IBAN, name, address. Amount and currency. Reference type and reference value if you're using QRR or SCOR.
- Call Create Swiss QR Bill. Pass the JSON, receive the bill. Overlay it on your PDF or embed it directly.
One API call. Done. Your invoices now carry machine-readable payment instructions that Swiss banks and accounting software know how to read.
The SIX Group's 60-page standard is still there if you want to audit the spec end-to-end. Most of it describes validation rules, edge cases, and payment-system behavior, the things the API already checks for you. You don't need to read it to generate a valid bill.
Website: pdf4me.com
Documentation: docs.pdf4me.com
Developer portal: dev.pdf4me.com
Top comments (0)