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",
    "profile": "xrechnung",  # or "en16931"
    "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
    },
    "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"
profile no "xrechnung" (default) or "en16931"
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).

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 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.1.tar.gz (8.7 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.1-py3-none-any.whl (7.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: factora-0.1.1.tar.gz
  • Upload date:
  • Size: 8.7 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.1.tar.gz
Algorithm Hash digest
SHA256 06e706ba71cc80897017ef08d2746e1872703178f40f954df9e74e5553b7d778
MD5 2d47ca4af921b5071f9e5a65219243d1
BLAKE2b-256 cd4fdd4ba56573ea51710603b0c05172761936d572b556a134c0d09b66d21f65

See more details on using hashes here.

Provenance

The following attestation bundles were made for factora-0.1.1.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.1-py3-none-any.whl.

File metadata

  • Download URL: factora-0.1.1-py3-none-any.whl
  • Upload date:
  • Size: 7.7 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.1-py3-none-any.whl
Algorithm Hash digest
SHA256 3c430b0a20985a6716cc7562501a0f9141e6546b8453f10109d1e55e6609ef39
MD5 0e55ba3e27eb83af2cc1e9dde0e2e8fc
BLAKE2b-256 b40e440a9d39c3bab0d579f6b1407e0721943d24ff6a21e172e8f377fe66cc60

See more details on using hashes here.

Provenance

The following attestation bundles were made for factora-0.1.1-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