Skip to main content

factora-python

PyPI version License: MIT

Official Python SDK for the Factora E-Invoicing API — create legally compliant German and European electronic invoices (XRechnung and ZUGFeRD, both based on EN 16931) from a single HTTP call.

Installation

pip install factora

Requires Python 3.9+.

Quickstart

An invoice is created with one POST to /api/v1/invoices/atomic/. The SDK wraps that endpoint in FactoraClient.create_atomic_invoice().

import uuid

from factora import FactoraAPIError, FactoraClient

client = FactoraClient(api_key="fa_live_your_api_key")

payload = {
    "api_mode": "atomic_single_post",
    "invoice_header": {
        "invoice_number": "RE-2026-0001",
        "invoice_date": "2026-08-06",
        "currency": "EUR",
        "invoice_type": "380",
        "buyer_reference": "04011000-12345-34",  # Leitweg-ID, required by BR-DE
        "profile": "xrechnung",  # or "en16931"; omit to get "xrechnung"
    },
    "seller_snapshot": {
        "name": "Muster GmbH",
        "street": "Musterstrasse 1",
        "zip": "10115",
        "city": "Berlin",
        "country": "DE",
        "vat_id": "DE123456789",
        "contact": {
            "name": "Alex Muster",
            "phone": "+49 30 1234567",
            "email": "billing@muster-gmbh.example",
        },
    },
    "buyer": {
        "name": "Beispiel AG",
        "street": "Beispielweg 7",
        "zip": "80331",
        "city": "Muenchen",
        "country": "DE",
        "vat_id": "DE987654321",  # or buyer["contact"]["email"]
    },
    "items": [
        {
            "description": "Consulting services, August 2026",
            "quantity": "2",
            "unit": "H87",  # UN/ECE Rec. 20 code, H87 = piece
            "unit_price_net": "750.00",
            "vat_rate": "19.00",
        }
    ],
    "validation_totals": {
        "net_amount": "1500.00",
        "vat_amount": "285.00",
        "gross_amount": "1785.00",
    },
}

try:
    result = client.create_atomic_invoice(
        payload,
        idempotency_key=str(uuid.uuid4()),
    )
except FactoraAPIError as exc:
    print(f"HTTP {exc.status_code}: {exc}")
    print(exc.response_data)  # full response envelope, incl. errors[]
else:
    print(result["valid"], result["data"])

FactoraClient is also a context manager, which closes the underlying HTTP session for you:

with FactoraClient(api_key="fa_live_your_api_key") as client:
    result = client.create_atomic_invoice(payload)

Idempotency

Pass idempotency_key with a value you generate (a UUID works well). Replaying the same key returns the original result instead of creating a second invoice — safe to use for retries after a timeout.

Request essentials

The API validates strictly; a rejected request comes back as HTTP 400 with a list of errors rather than a partially created invoice.

Top level

Field Required Notes
api_mode yes Must be "atomic_single_post"
invoice_header yes See below
validation_totals yes net_amount, vat_amount, gross_amount
seller_snapshot or mandant_id yes Exactly one — sending both or neither returns 400
buyer yes See below
items yes At least one line item

invoice_headerinvoice_number and invoice_date are required; currency defaults to "EUR" and invoice_type to "380" (commercial invoice). profile also lives here: "xrechnung" (default) or "en16931". It is not a top-level field — sent at the top level it is ignored without an error and the invoice silently falls back to "xrechnung". The resolved profile is always returned in the response.

seller_snapshotname is required.

buyername is required.

items[] — each line needs description, quantity, unit (UN/ECE Rec. 20 code, e.g. "H87"), unit_price_net and vat_rate.

Additional rules under invoice_header.profile: "xrechnung"

The German CIUS (BR-DE rules) requires these on top of the base fields:

  • invoice_header.buyer_reference — the Leitweg-ID
  • seller_snapshot.city and seller_snapshot.zip
  • seller_snapshot.contact.phone and seller_snapshot.contact.email
  • buyer.city and buyer.zip
  • an electronic address for the buyer — either buyer.vat_id with a DE prefix, or buyer.contact.email

Response envelope

Every call returns the same envelope:

{
  "valid": true,
  "data": { "...": "created invoice" },
  "errors": [],
  "meta": { "...": "request metadata" }
}

Error entries always carry code, severity and message, and may additionally include field, rule, bt (the EN 16931 business term) and location.

Error handling

Any non-2xx response, and any transport failure, raises FactoraAPIError:

Attribute Description
status_code HTTP status code, or None if the request never reached the server
response_data Decoded response envelope, or None when the body was absent or not JSON
try:
    client.create_atomic_invoice(payload)
except FactoraAPIError as exc:
    if exc.status_code == 400 and exc.response_data:
        for error in exc.response_data.get("errors", []):
            print(error["code"], error["severity"], error["message"])
    else:
        raise

Configuration

FactoraClient(
    api_key="fa_live_your_api_key",
    base_url="https://console.factora.software",  # default
    timeout=30,                                    # seconds, default
)

API keys are issued in the Factora Console. Keys prefixed fa_test_ target the sandbox, fa_live_ target production. Keep them out of source control — read them from an environment variable or a secrets manager.

Documentation

Full API reference: https://console.factora.software/docs

License

MIT — see LICENSE.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

factora-0.1.2.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

factora-0.1.2-py3-none-any.whl (7.8 kB view details)

Uploaded Python 3

File details

Details for the file factora-0.1.2.tar.gz.

File metadata

  • Download URL: factora-0.1.2.tar.gz
  • Upload date:
  • Size: 8.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for factora-0.1.2.tar.gz
Algorithm Hash digest
SHA256 d326cdd58f58c73ab44b762ef17b4cef4bc9979ba8bb3cd61b0b7ab4f613e36f
MD5 d233ddcabe858835e7004d2a33bbc10a
BLAKE2b-256 8cf65abb87c6d44201a7144b06096c9a797e8271eae0f6c5a4f715eac57b0d34

See more details on using hashes here.

Provenance

The following attestation bundles were made for factora-0.1.2.tar.gz:

Publisher: publish.yml on factora-software/factora-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file factora-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: factora-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 7.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for factora-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 2ae05d122b3cc48315a3a531f6883d66df625d2c6dcd3798a50255532e8ce291
MD5 4250f118fd971485844b8352dbc1e945
BLAKE2b-256 5e598d16e559a316beefb15c39848ad9dabe99fb28950a8c140d55ca18ff4e53

See more details on using hashes here.

Provenance

The following attestation bundles were made for factora-0.1.2-py3-none-any.whl:

Publisher: publish.yml on factora-software/factora-python

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page