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).
- Package:
beliqon PyPI - Source: github.com/beliq-eu/beliq-sdk-python
Install
pip install beliq
Requires Python 3.10 or newer.
Authentication
Create an API key in the Beliq dashboard under Integration → API Keys:
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 endpointQuick start
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
AsyncBeliq mirrors the sync client with await:
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
| 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
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
- Quickstart: the underlying API in five minutes.
- Authentication: keys, quotas, and rate limits.
- API reference: full request and response schemas.