Skip to main content

qrid — Python

Decode and encode MergeID electronic invoice QR codes.

Python port of qrid/codec (PHP). All three implementations (PHP, Node.js, Python) share the same payload format and function signatures, so QR codes generated by any one of them scan correctly in the others.

Typical usage flow

sequenceDiagram
    actor Staff as Billing Staff
    participant ERP as Billing / ERP System
    participant Lib as qrid
    participant QR as Invoice QR Code
    participant App as MergeID App

    Staff->>ERP: create invoice
    ERP->>Lib: encode_qr_id(id, company, email, address, activity_code)
    Lib-->>ERP: SVG QR code
    ERP->>QR: print / embed on invoice

    Note over App,QR: later, at point of scan
    App->>QR: scan with camera
    QR-->>App: base64 payload string
    App->>Lib: decode_qr_id(encoded)
    Lib-->>App: { v, id, company, email, address, activity_code }
    App-->>Staff: display verified invoice identity

Installation

# Decode only (no extra dependencies)
pip install qrid

# Decode + encode SVG
pip install 'qrid[encode]'

Usage

Decode

from qrid import decode_qr_id

# `encoded` is the raw string value scanned from a MergeID QR code
payload = decode_qr_id(encoded)

print(payload["v"])             # Payload schema version (int, currently 1)
print(payload["id"])            # Tax or company ID              (e.g. "3101679980")
print(payload["company"])       # Company legal name
print(payload["email"])         # Billing e-mail address
print(payload["address"])       # Physical address
print(payload["activity_code"]) # Installation / activity code (e.g. "ACT-001"), or "" if blank

decode_qr_id strips surrounding whitespace before decoding, so strings copied with accidental padding are handled transparently.

Exceptions raised:

Exception Cause
ValueError Input is not valid base64
json.JSONDecodeError Decoded bytes are not valid JSON
import json
from qrid import decode_qr_id

try:
    payload = decode_qr_id(raw)
except ValueError:
    # QR data was not base64
    ...
except json.JSONDecodeError:
    # QR data decoded but was not the expected JSON structure
    ...

Encode (requires qrid[encode])

from qrid import encode_qr_id

svg = encode_qr_id(
    id="3101679980",
    company="Acme Corp S.A.",
    email="billing@acme.example",
    address="123 Main St, San José, Costa Rica",
    activity_code="ACT-001",
)

# Write to a file
with open("invoice_qr.svg", "w") as f:
    f.write(svg)

# Or serve directly
# Content-Type: image/svg+xml

activity_code is optional and defaults to "" (blank). A blank activity code signals a consuming system to generate an electronic ticket instead of using an activity code.

Exceptions raised:

Exception Cause
ImportError segno is not installed (pip install 'qrid[encode]')

Payload format

The QR code data is a UTF-8 JSON object encoded as standard base64 (no line-breaks):

{
  "v": 1,
  "id": "3101679980",
  "company": "Acme Corp S.A.",
  "email": "billing@acme.example",
  "address": "123 Main St, San José, Costa Rica",
  "activity_code": "ACT-001"
}
Field Type Description
v int Payload schema version. Currently always 1.
id str Tax / company registration ID.
company str Legal company name (UTF-8, including accented characters).
email str Primary billing or contact e-mail address.
address str Physical address of the company.
activity_code str Installation or activity code that links the QR to an internal record. May be blank (""), which signals a consuming system to generate an electronic ticket instead.

Requirements

Dependency Version Required for
Python >= 3.9 Always
segno >= 1.6 encode_qr_id() only

Running tests

pip install 'qrid[dev]'
pytest

Publishing

Releases to PyPI are fully automated — there is no manual twine upload step:

  1. Bump version in pyproject.toml and merge to main.
  2. release.yml runs on every push to main. It reads the version from pyproject.toml; if no vX.Y.Z tag already exists for it, it runs the test suite and creates that tag plus a GitHub Release.
  3. In that same run, release.yml dispatches publish.yml via the GitHub API (gh workflow run publish.yml), which re-runs the tests, builds the sdist/wheel, and uploads to PyPI using Trusted Publishing (OIDC) — no stored API token.

publish.yml is dispatched as an independent, top-level run via the Actions API rather than invoked as a reusable workflow (workflow_call) or relying on the release: published event. Both alternatives were tried and both are broken for this use case:

  • release: published never fires for releases created with the Actions-internal GITHUB_TOKEN (GitHub's anti-recursion guard).
  • workflow_call chaining runs publish.yml as a job within release.yml's own run, so the OIDC certificate's build-config claim identifies the caller (release.yml) instead of publish.yml — PyPI's Trusted Publisher verification then rejects the upload outright (does not match expected Trusted Publisher). PyPI's own docs confirm reusable workflows are not supported for Trusted Publishing.

A workflow_dispatch API call made with GITHUB_TOKEN is explicitly exempt from the anti-recursion guard and starts a genuine new top-level run of publish.yml, so its OIDC certificate correctly identifies publish.yml as the source. publish.yml also still accepts release: published (for a release cut by hand) and workflow_dispatch (manual re-run) as a fallback.

Pushes to main that don't change the version are a no-op for release.yml (the tag already exists), so unrelated commits (docs, CI tweaks) don't trigger a release.

One-time PyPI setup (already done for this project, documented here for reference): add a pending trusted publisher at pypi.org/manage/account/publishing with owner Quality-XP-Development-SESSA, repository qrid-python, workflow filename publish.yml, and environment name pypi; the same pypi environment must exist under the repo's GitHub Settings → Environments.

License

MIT

Metadata

Release files for qrid 1.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for qrid 1.1.0
File Size Uploaded Provenance Actions
qrid-1.1.0.tar.gz 6.3 kB With provenance Details for qrid-1.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for qrid 1.1.0
File Interpreter ABI Platform Actions
qrid-1.1.0-py3-none-any.whl Python 3 none any Details for qrid-1.1.0-py3-none-any.whl

Total release size: 11.5 kB

Release files / qrid-1.1.0.tar.gz

Download URL qrid-1.1.0.tar.gz
Size 6.3 kB
Tags Source
SHA-256 checksum
How to use checksums
1472b2580db0098c81a2377b3f01e03c466df621f7b1786f865462b9b52823e6
BLAKE2b-256 checksum
How to use checksums
f1d4e5003da527d4866e4847605cc4f440a97612c3dcf1106e8cae64ee363d5c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.

Transparency log

Release files / qrid-1.1.0-py3-none-any.whl

Download URL qrid-1.1.0-py3-none-any.whl
Size 5.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0ed79c01130037025226cd23e5aa569320a682404b805e2e1741c8f50526c4ba
BLAKE2b-256 checksum
How to use checksums
de94ab7e2d24c24bd7f5eff59dddbd26c5f479ae1060efb1bd61790337519ea8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.

Transparency log

Security for qrid 1.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for qrid-1.1.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 10, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page