Skip to main content

Python client for the docs101 invoicing API

Project description

docs101

PyPI License: MIT Python

Python client for the docs101 invoicing API — create customers, generate EU-compliant invoices, and export to DATEV.

Installation

pip install docs101

Quick Start

from docs101 import Docs101Client

client = Docs101Client(api_key="ak_live_YOUR_KEY_HERE")

# Create a customer
customer = client.customers.create(
    organization_name="Acme Corp",
    email="billing@acme.com",
    contact_type="B2B",
    vat_id="DE123456789",
    language="English",
)
customer_id = customer["id"]

# Add an address
client.customers.create_address(
    customer_id,
    address_line_1="Musterstraße 1",
    postal_code="10115",
    city="Berlin",
    country_code="DE",
    is_default=True,
)

# Create an invoice
invoice = client.invoices.create(
    customer_id=customer_id,
    benefit_period_start="2026-04-01",
    benefit_period_end="2026-04-30",
    invoice_format="ZUGFERD",
)
invoice_id = invoice["invoice_id"]

# Add a position
client.invoices.add_position(
    invoice_id,
    title="Pro Plan — Monthly Subscription",
    quantity=1.0,
    unit_id="HUR",
    unit_net_amount=25.00,
    single_net_amount=25.00,
    tax_rate=0.19,
    tax_treatment_id="standard",
)

# Validate and finalize
validation = client.invoices.validate(invoice_id)
assert validation["valid"], f"Validation failed: {validation['errors']}"

client.invoices.finalize(invoice_id)

# Get PDF
pdf = client.invoices.get_pdf_url(invoice_id)
print(f"PDF ready: {pdf['filename']}{pdf['url']}")

Features

  • Typed exceptionsAuthenticationError, ValidationError, NotFoundError, LimitExceededError, and more
  • Async job pollingfinalize() and create_datev() automatically poll until the job completes
  • DATEV export — Configure DATEV settings and trigger exports with automatic download handling
  • ZUGFeRD, Peppol, FatturaPA, Facturae — Full support for EU e-invoicing formats
  • Type hints — Full type annotations with py.typed marker (PEP 561)

Usage

Customers

# List all customers
customers = client.customers.list()

# Get a single customer
customer = client.customers.get(42)

# Update a customer
client.customers.update(42, email="new@acme.com")

# Manage addresses
addresses = client.customers.list_addresses(42)
client.customers.create_address(42, address_line_1="New St 1", city="Munich", country_code="DE")
client.customers.update_address(42, 1, city="Hamburg")
client.customers.delete_address(42, 1)

Invoices

# List invoices (paginated)
invoices = client.invoices.list(page=1, limit=25)

# Create, add positions, validate, finalize
invoice = client.invoices.create(customer_id=42, invoice_format="ZUGFERD")
invoice_id = invoice["invoice_id"]

client.invoices.add_position(invoice_id,
    title="Consulting", quantity=10, unit_id="HUR",
    unit_net_amount=150.00, single_net_amount=150.00,
    tax_rate=0.19, tax_treatment_id="standard",
)

client.invoices.validate(invoice_id)
client.invoices.finalize(invoice_id)

# Download links
pdf = client.invoices.get_pdf_url(invoice_id)
xml = client.invoices.get_xml_url(invoice_id)

# Status management
client.invoices.mark_as_sent(invoice_id)
client.invoices.mark_as_paid(invoice_id,
    paid_date="2026-04-15",
    payment_method="BANK_TRANSFER",
)

# Duplicate or cancel
new = client.invoices.duplicate(invoice_id)
client.invoices.cancel(invoice_id)

DATEV Export

# Configure DATEV
client.exports.configure_datev(
    consultant_number=1234567,
    client_number=12345,
    chart_of_accounts="SKR03",
)

# Run export (polls automatically)
result = client.exports.create_datev(
    start_date="2026-01-01",
    end_date="2026-03-31",
)

# Download all parts
for download_id in result["download_ids"]:
    url_info = client.downloads.get_url(download_id)
    print(f"Download: {url_info['url']}")

Templates

templates = client.templates.list()
template = client.templates.get(1)

Error Handling

from docs101 import (
    Docs101Error,
    AuthenticationError,
    ValidationError,
    NotFoundError,
    LimitExceededError,
    VatOverrideRequiredError,
    JobFailedError,
    Docs101TimeoutError,
)

try:
    client.invoices.finalize(invoice_id)
except LimitExceededError as e:
    print(f"Limit reached: {e.used}/{e.limit}, resets {e.reset_date}")
except VatOverrideRequiredError:
    client.invoices.finalize(invoice_id, vat_override_confirmed=True)
except JobFailedError as e:
    print(f"Job failed: {e.error_message}")
except Docs101TimeoutError:
    print("Job timed out — check status manually")

Examples

See the examples/ directory for complete, runnable scripts:

API Documentation

Contributing

  1. Clone the repo
  2. Create a virtual environment: python -m venv .venv && source .venv/bin/activate
  3. Install dev dependencies: pip install -e ".[dev]"
  4. Run tests: pytest tests/ -v

License

MIT

Project details


Download files

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

Source Distribution

docs101-0.1.0.tar.gz (13.8 kB view details)

Uploaded Source

Built Distribution

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

docs101-0.1.0-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

File details

Details for the file docs101-0.1.0.tar.gz.

File metadata

  • Download URL: docs101-0.1.0.tar.gz
  • Upload date:
  • Size: 13.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for docs101-0.1.0.tar.gz
Algorithm Hash digest
SHA256 7da2e50b18f2e3a03e52083a90fed08d8b3f83b7fd5b0f9964218d05139428b3
MD5 03462a283c5898df9b8dd0506eb20afa
BLAKE2b-256 a91630350eceb5be16c69ea204c2e20528e944febf632c4b20b3f8ae2ae908d2

See more details on using hashes here.

File details

Details for the file docs101-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: docs101-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for docs101-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 05f81fd4604e8d78014b6dab98d9ab9d9e2087313d8105a68287ec823693a319
MD5 bd697adf1fc81c4113a5999ee7ee5daa
BLAKE2b-256 aec507047fe8ce23dcaae38facca611a2d9367b417c043fe1dbe0819771fbd02

See more details on using hashes here.

Supported by

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