# Swiss QR-bill Generator (QR-facture / QR-Rechnung) (`najx/swiss-qr-bill-generator`) Actor

Generate compliant Swiss QR-bills as PDF, SVG or PNG from JSON or a CSV file: payment part and receipt with QR code, IBAN or QR-IBAN, QRR or SCOR reference, in French, German, Italian or English. One bill or thousands per run.

- **URL**: https://apify.com/najx/swiss-qr-bill-generator.md
- **Developed by:** [Najim Abdelmoula](https://apify.com/najx) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 qr bills

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.
Actors are written with capital "A".

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

### What does Swiss QR-bill Generator do?

**Swiss QR-bill Generator** turns a JSON object or a CSV file into ready-to-print **Swiss QR-bills** (QR-facture, QR-Rechnung, QR-fattura): the payment part and receipt with the Swiss QR code, as **PDF, SVG or PNG**, in French, German, Italian or English. One bill or thousands per run, with the creditor set once and the debtors, amounts and references varying per bill. It is a **Swiss QR-bill API** for invoicing tools, automations and AI agents, following the Swiss Payment Standards implementation guidelines used by every Swiss bank since 2022.

It does not send invoices, does not talk to any bank, and keeps nothing after the run.

### Why use Swiss QR-bill Generator?

- 🧾 **Compliant output**: QR-IBAN with 27-digit QR reference (QRR), regular IBAN with RF creditor reference (SCOR) or no reference, structured or combined addresses, CHF and EUR, amount left blank when the payer fills it in, Swico billing information.
- 📄 **Print-ready**: full A4 page with the bill at the bottom, or the 210 × 105 mm payment part alone to append to your own invoice PDF.
- 📦 **Bulk**: pass an array or a CSV export from your accounting tool and get one file per bill plus a table linking each bill to its file.
- 🤖 **Automation-friendly**: call it from n8n, Make, Zapier or the Apify API, or let an AI agent generate a bill through the Apify MCP server. Structured input, structured output, no PDF service to host.
- ✅ **Validation you can act on**: a bill with a wrong IBAN, a reference that does not match the account type, or a text over 140 characters is reported as an error with the reason, and is not billed.

Typical users: small businesses and freelancers who invoice in Switzerland, fiduciaries, SaaS products adding Swiss payments, agencies automating invoicing for clients, and developers who need a QR-bill without integrating a library.

### What does it produce?

One row per bill in the dataset, and one file per bill in the run's key-value store.

| Field | Type | Description |
| --- | --- | --- |
| `id` | string | Your bill id, or `bill-0001` when omitted |
| `status` | string | `ok` or `error` |
| `fileUrl` | string | Link to the generated PDF / SVG / PNG |
| `filename` | string | `<id>.pdf`, `<id>.svg` or `<id>.png` |
| `amount` / `currency` | string | Amount as printed (empty when left to the payer) and currency |
| `referenceType` | string | `QRR`, `SCOR` or empty |
| `language` | string | Language of the printed labels |
| `qrPayload` | string | The exact Swiss Payments Code encoded in the QR code, for checks and archiving |
| `errors` | array | Validation messages for rejected bills |

### How to generate a Swiss QR-bill

1. Open the Actor and paste your bills as JSON in **Bills**, or put the URL of a CSV file in **CSV file URL**.
2. Set the **default account** and **default creditor** once if they are the same for every bill.
3. Choose the **output format** (PDF, SVG, PNG), the **language**, and whether you want a **full A4 page** or the payment part only.
4. Click **Start**. Each bill appears in the Output tab with a link to its file.
5. Download the files from the **Storage** tab, or read `fileUrl` from the dataset in your automation.

#### Which reference should I use?

- **QR-IBAN** (the IBAN your bank gave you for QR-bills, IID 30000 to 31999): you must provide a 27-digit **QR reference** (`reference`), for example `210000000003139471430009017`. The Actor checks the check digit.
- **Regular IBAN**: either no reference, or an ISO 11649 **creditor reference** starting with `RF`, for example `RF18539007547034`.
- Mixing them is rejected with an explicit message, as banks would reject the payment.

#### What goes in additionalInformation and billingInformation?

`additionalInformation` is the free message printed on the bill (up to 140 characters). `billingInformation` is the optional structured Swico string for accounting software, starting with `//S1/`. Together they may not exceed 140 characters.

### How much does it cost?

The Actor is **paid per generated bill** (see the pricing box on this page); rejected bills are free. Generating 100 invoices costs a few cents. The Apify free plan is enough for a small business's monthly invoicing.

### Input

See the Input tab for all options. Minimal example, one bill with a regular IBAN and no reference:

```json
{
  "account": "CH5800791123000889012",
  "creditor": {"name": "ACME Sàrl", "street": "Rue du Lac", "houseNumber": "12", "postalCode": "1000", "city": "Lausanne", "country": "CH"},
  "bills": [
    {"id": "INV-2026-001", "debtor": {"name": "Client SA", "street": "Bahnhofstrasse", "houseNumber": "1", "postalCode": "8001", "city": "Zürich"}, "amount": 1250.00, "additionalInformation": "Invoice INV-2026-001"}
  ],
  "format": "pdf",
  "language": "fr"
}
```

CSV alternative: a file with the columns `id, account, amount, currency, reference, additional_information, language, creditor_name, creditor_street, creditor_house_number, creditor_postal_code, creditor_city, creditor_country, debtor_name, debtor_street, debtor_house_number, debtor_postal_code, debtor_city, debtor_country`, comma or semicolon separated. Columns left empty fall back to the defaults.

### Output

You can download the dataset in JSON, CSV, Excel or HTML formats. Two items:

```json
[
  {
    "id": "2026-0042",
    "status": "ok",
    "filename": "2026-0042.pdf",
    "fileUrl": "https://api.apify.com/v2/key-value-stores/.../records/2026-0042.pdf",
    "format": "pdf",
    "amount": "1949.75",
    "currency": "CHF",
    "referenceType": "QRR",
    "language": "fr",
    "qrPayload": "SPC\n0200\n1\nCH4431999123000889012\nS\nRobert Schneider AG\n...",
    "errors": []
  },
  {
    "id": "2026-0044",
    "status": "error",
    "errors": ["The reference number is invalid"]
  }
]
```

### Using the Actor from code and AI agents

Call it through the [Apify API](https://docs.apify.com/api/v2) in any language, or expose it to Claude, ChatGPT, Cursor or any MCP client through the [Apify MCP server](https://mcp.apify.com/). Example with the Python client:

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_API_TOKEN>")
run = client.actor("<ACTOR_ID>").call(run_input={  # Actor ID or "username/name" from the API tab
    "account": "CH5800791123000889012",
    "creditor": {"name": "ACME Sàrl", "postalCode": "1000", "city": "Lausanne"},
    "bills": [{"id": "INV-1", "amount": 99.9, "debtor": {"name": "Client SA", "postalCode": "8001", "city": "Zürich"}}],
})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item["id"], item["status"], item.get("fileUrl"), item["errors"])
```

### Privacy and data handling

Bill data is processed in memory inside your own Actor run. The generated files and the result table are written only to the run's storage, which belongs to your Apify account and follows your data retention settings. The Actor author never receives, logs or stores your bills.

### Frequently asked questions

#### Is the output accepted by Swiss banks and scanning apps?

The Actor implements the Swiss Payment Standards QR-bill specification (Swiss QR Code version 0200) through a widely used open-source library, and validates IBANs, QR references and creditor references. As with any generator, print a test bill and scan it with your e-banking app before sending a batch.

#### Can I put the QR-bill on my existing invoice PDF?

Generate the payment part only (`fullPage: false`) as PDF or PNG and place it at the bottom of your last page with your PDF tool. A companion Actor that reads QR-bills back into data is available from the same author.

#### Which characters are allowed?

The Swiss Payments Code uses a restricted Latin character set. Names and messages with accents from French, German and Italian are fine; emoji and non-Latin scripts are not.

#### Something looks wrong

Open an issue in the **Issues** tab with a minimal bill (without real customer data).

### Development

Python 3.12, Apify SDK, [`qrbill`](https://github.com/claudep/swiss-qr-bill) for the SVG and CairoSVG for PDF and PNG. `pytest tests` covers references, addresses, formats and CSV parsing; `apify run` runs the Actor locally.

# Actor input Schema

## `bills` (type: `array`):

One object per bill. Fields: id, account (IBAN or QR-IBAN), creditor {name, street, houseNumber, postalCode, city, country}, debtor (same shape, optional), amount (number, optional), currency (CHF/EUR), reference (27-digit QR reference for a QR-IBAN, or RF... creditor reference), additionalInformation (max 140 chars), billingInformation (Swico, starts with //), language (fr/de/it/en).

## `csvUrl` (type: `string`):

Public URL (or Apify key-value store record URL) of a CSV with one bill per row. Columns: id, account, amount, currency, reference, additional\_information, billing\_information, language, creditor\_name, creditor\_street, creditor\_house\_number, creditor\_postal\_code, creditor\_city, creditor\_country, debtor\_name, debtor\_street, debtor\_house\_number, debtor\_postal\_code, debtor\_city, debtor\_country. Comma or semicolon separated, UTF-8.

## `account` (type: `string`):

Used for every bill that has no account of its own. QR-IBANs (IID 30000-31999) require a 27-digit QR reference; regular IBANs accept an RF creditor reference or no reference.

## `creditor` (type: `object`):

Used for every bill that has no creditor of its own. {name, street, houseNumber, postalCode, city, country}.

## `language` (type: `string`):

Language of the printed labels.

## `currency` (type: `string`):

Used for every bill that has no currency of its own. Swiss QR-bills accept CHF or EUR only.

## `format` (type: `string`):

File format of every generated bill. PDF is the usual choice for printing and e-mailing; SVG for embedding in web pages or further processing; PNG for images.

## `fullPage` (type: `boolean`):

true = A4 page with the QR-bill at the bottom (ready to print or to append to an invoice); false = payment part and receipt only (210 x 105 mm).

## `pngDpi` (type: `integer`):

Only for PNG output. 150 dpi is enough for screens, 300 dpi for print.

## Actor input object example

```json
{
  "bills": [
    {
      "id": "2026-0042",
      "account": "CH4431999123000889012",
      "creditor": {
        "name": "Robert Schneider AG",
        "street": "Rue du Lac",
        "houseNumber": "1268",
        "postalCode": "2501",
        "city": "Biel",
        "country": "CH"
      },
      "debtor": {
        "name": "Pia-Maria Rutschmann-Schnyder",
        "street": "Grosse Marktgasse",
        "houseNumber": "28",
        "postalCode": "9400",
        "city": "Rorschach",
        "country": "CH"
      },
      "amount": 1949.75,
      "currency": "CHF",
      "reference": "210000000003139471430009017",
      "additionalInformation": "Order of 15 June 2026",
      "language": "fr"
    }
  ],
  "language": "fr",
  "currency": "CHF",
  "format": "pdf",
  "fullPage": true,
  "pngDpi": 150
}
```

# Actor output Schema

## `bills` (type: `string`):

No description

## `files` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "bills": [
        {
            "id": "2026-0042",
            "account": "CH4431999123000889012",
            "creditor": {
                "name": "Robert Schneider AG",
                "street": "Rue du Lac",
                "houseNumber": "1268",
                "postalCode": "2501",
                "city": "Biel",
                "country": "CH"
            },
            "debtor": {
                "name": "Pia-Maria Rutschmann-Schnyder",
                "street": "Grosse Marktgasse",
                "houseNumber": "28",
                "postalCode": "9400",
                "city": "Rorschach",
                "country": "CH"
            },
            "amount": 1949.75,
            "currency": "CHF",
            "reference": "210000000003139471430009017",
            "additionalInformation": "Order of 15 June 2026",
            "language": "fr"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("najx/swiss-qr-bill-generator").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = { "bills": [{
            "id": "2026-0042",
            "account": "CH4431999123000889012",
            "creditor": {
                "name": "Robert Schneider AG",
                "street": "Rue du Lac",
                "houseNumber": "1268",
                "postalCode": "2501",
                "city": "Biel",
                "country": "CH",
            },
            "debtor": {
                "name": "Pia-Maria Rutschmann-Schnyder",
                "street": "Grosse Marktgasse",
                "houseNumber": "28",
                "postalCode": "9400",
                "city": "Rorschach",
                "country": "CH",
            },
            "amount": 1949.75,
            "currency": "CHF",
            "reference": "210000000003139471430009017",
            "additionalInformation": "Order of 15 June 2026",
            "language": "fr",
        }] }

# Run the Actor and wait for it to finish
run = client.actor("najx/swiss-qr-bill-generator").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "bills": [
    {
      "id": "2026-0042",
      "account": "CH4431999123000889012",
      "creditor": {
        "name": "Robert Schneider AG",
        "street": "Rue du Lac",
        "houseNumber": "1268",
        "postalCode": "2501",
        "city": "Biel",
        "country": "CH"
      },
      "debtor": {
        "name": "Pia-Maria Rutschmann-Schnyder",
        "street": "Grosse Marktgasse",
        "houseNumber": "28",
        "postalCode": "9400",
        "city": "Rorschach",
        "country": "CH"
      },
      "amount": 1949.75,
      "currency": "CHF",
      "reference": "210000000003139471430009017",
      "additionalInformation": "Order of 15 June 2026",
      "language": "fr"
    }
  ]
}' |
apify call najx/swiss-qr-bill-generator --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,najx/swiss-qr-bill-generator"
        }
    }
}

```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/VQYRb4qqmFT3yBEno/builds/u6guYlfut6w5396u3/openapi.json
