eliDocs
Integrations

Python SDK

The official Beliq SDK for Python. Generate, validate, parse, and convert EN 16931 e-invoices, with sync and async clients.

Available

The official Python SDK for Beliq. Same API surface as the Node SDK, with sync (Beliq) and async (AsyncBeliq) clients. JSON responses are Pydantic models that preserve fields not explicitly typed (such as per-country authority versions on a validation result).

Install

Install

pip install beliq

Requires Python 3.10 or newer.

Authentication

Authentication

Create an API key in the Beliq dashboard under Integration → API Keys:

client.py
from beliq import Beliq

Beliq(api_key="blq_...")                          # sends X-API-Key (default)
Beliq(api_key="blq_...", auth="bearer")            # sends Authorization: Bearer
Beliq(api_key="blq_...", base_url="https://api.beliq.eu")  # default; set only for a self-hosted endpoint
Quick start

Quick start

generate_and_validate.py
from beliq import Beliq

beliq = Beliq(api_key="blq_...")

# Account, plan, and quota context (no quota cost).
account = beliq.me()

# Generate an XRechnung document from an EN 16931 invoice.
generated = beliq.generate(
    standard="xrechnung",
    verify=True,
    invoice={
        "number": "INV-2026-001",
        "issueDate": "2026-01-15",
        "currencyCode": "EUR",
        "seller": {"name": "Seller GmbH", "address": {"city": "Berlin", "postalCode": "10115", "countryCode": "DE"}},
        "buyer": {"name": "Buyer GmbH", "address": {"city": "Munich", "postalCode": "80331", "countryCode": "DE"}},
        "lines": [
            {"description": "Consulting", "quantity": 10, "unitCode": "HUR", "unitPrice": 100, "lineTotal": 1000, "vatRate": 19, "vatCategoryCode": "S"}
        ],
        "totalNetAmount": 1000,
        "totalTaxAmount": 190,
        "totalGrossAmount": 1190,
    },
)
print(generated.xml, generated.meta.schematron_version)

# Validate a document against the rule packs and schemas of its format.
result = beliq.validate(generated.xml, format="auto")
if not result.valid:
    for issue in result.errors:
        print(issue.rule_id, issue.message)
Async

Async

AsyncBeliq mirrors the sync client with await:

async_validate.py
import asyncio
from beliq import AsyncBeliq

async def main():
    async with AsyncBeliq(api_key="blq_...") as beliq:
        result = await beliq.validate(open("invoice.xml", "rb").read(), format="auto")
        print(result.valid)

asyncio.run(main())
Methods

Methods

Method Endpoint Returns
me() GET /v1/me AccountInfo (no quota cost)
generate(...) POST /v1/generate GenerateResult
validate(document, ...) POST /v1/validate ValidationResult
parse(document, ...) POST /v1/parse ParseResult
convert(document, ...) POST /v1/convert ConvertResult

document accepts a str, bytes, or bytearray. Errors raise BeliqApiError with a typed .code, HTTP .status, and any .details.

Method options

Method options

Each method also takes keyword arguments that map onto one API field. AsyncBeliq takes the same ones, and an argument left out (or None) is not sent.

Method Argument API field Effect
generate template="standard" template The built-in invoice layout for output="pdf". xrechnung and peppol-bis need it (or pdf_template_id) to return a PDF at all: a visualization PDF with no embedded XML. ZUGFeRD and Factur-X render the same layout onto their hybrid PDF with or without it.
generate pdf_template_id="k3d-9mp" pdfTemplateId Renders the PDF from one of your PDF templates. Takes precedence over template. See Styling the PDF.
validate france_ctc=True franceCtc Also runs the BR-FR-CTC Flux 2 rules on a CII or UBL document. They run without it when BT-24 declares EXTENDED-CTC-FR or BT-23 carries a cadre de facturation code, so False does not switch them off. See the France guide.
convert target_profile targetProfile The profile of a zugferd or facturx target, en16931 when left out (allowed values). The SDK does not send it for other targets.
convert drop_france_ctc_overlay=True dropFranceCtcOverlay Accepts losing a French cadre de facturation code (BT-23) when a CII source converts to a UBL target, instead of 422 CONVERSION_LOSSY_FAILCLOSED. See lossy conversions.
all four advanced body or query A dict deep-merged over what the SDK sends (the JSON body on generate, the query string on the others); its values win. For a field the API accepts before the SDK has an argument for it.
See also

See also