Timbro Invoices for Python
timbro-invoices is the Python client for the canonical /v1/invoices API.
Invoice request and response wire shapes are defined by the Timbro API; the installed package carries a generated projection of that contract.
Requires Python 3.10 or later.
pip install timbro-invoices
Compatibility
timbro-invoices 0.9 belongs to the same compatible set as @timbro/payments, @timbro/invoices, and @timbro/protocol 0.9. Packages that share a minor version work together.
The client validates requests strictly and accepts additional properties in responses. Timbro may add a property to a response, at any depth and in any union variant, without a breaking release; the client ignores what it does not know and returns it unchanged. Required fields, types, formats, and enum values stay enforced, so removing or renaming a field, or adding a value to an existing enum, is a breaking change. An unknown webhook event type is returned to you, after the envelope and scope checks, instead of raising.
from timbro_invoices import TimbroInvoices
client = TimbroInvoices(api_key="your-invoice-api-key")
preview = client.preview_invoice(invoice_request)
invoice = client.create_invoice(invoice_request)
current = client.retrieve_invoice(invoice["id"])
page = client.list_invoices(invoice_reference="odoo:2026:1042")
xml = client.download_xml(invoice["id"])
pdf = client.download_pdf(invoice["id"])
# Replace a retained, replaceable Invoice with a new canonical request.
replacement = client.replace_invoice(
rejected_invoice["id"],
{**invoice_request, "invoiceReference": "odoo:2026:1042-r1"},
)
# Share an accepted receipt with a payment service.
receipt_access = client.share_receipt(invoice["id"])
receipt = client.retrieve_receipt(receipt_access)
receipt_pdf = client.download_receipt_pdf(receipt_access)
Keep the receipt access grant on your server and pass it to the receiving service over an authenticated channel. Restricted reads use its accessToken; the token is never sent in the URL and grants access only to receipt data and its PDF. Receipt PDF downloads verify the Invoice identity, media type, and SHA-256 headers. Other file downloads also verify Timbro's security metadata. HTTP problems preserve Timbro's status and machine-readable code. The distribution uses jsonschema and regex to validate data against the generated OpenAPI contract.
A 422 admission refusal has no retained Invoice ID. Correct the request and call create_invoice; replace_invoice applies to a retained replaceable Invoice. Authority-rejected numbering gaps still require the existing administrator authorization. A replacement retains the predecessor's Source ID, uses a new Source version and invoiceReference, and exposes its predecessor in replacesInvoiceId.
Deliveries
Email an Invoice to its buyer and read the delivery back. Retrying with the same idempotency key (16 to 255 characters from A-Z, a-z, 0-9, ., _, :, and -) returns the same delivery. retrieve_delivery returns None when Timbro has no such delivery for the Invoice.
delivery = client.create_delivery(
invoice["id"],
recipient_email="buyer@example.do",
idempotency_key="delivery-order-1042-0001",
account_claim_url="https://example.do/account/claim", # optional, https only
)
current = client.retrieve_delivery(invoice["id"], delivery["id"])
Webhooks
verify_webhook_signature checks the Standard Webhooks signature over the original request bytes. parse_invoice_webhook_event does not check the signature, so call the verifier first. The parser then checks the event envelope against the generated contract and confirms that the event belongs to your organization, environment, and Source connection. An event type that this package version does not know is returned as an UnknownInvoiceWebhookEvent instead of raising; is_known_invoice_webhook_event narrows the result for type checkers.
verify_webhook_signature(body, headers, signing_secret)
event = parse_invoice_webhook_event(
body, message_id=headers["webhook-id"], organization_id=organization_id,
environment="production", source_connection_id=source_connection_id,
)
if is_known_invoice_webhook_event(event) and event["type"] == "invoice.accepted":
...
Errors and validation
InvalidInvoiceRequest, aValueError, is raised before any request is sent when a request does not match the contract. Itspathattribute names the failing field as a JSON path, for example$.items[0].quantity; a failure on a method argument, such asidempotency_key, names the argument instead. The message never contains the rejected value.TimbroHttpErrorcarries Timbro'sstatus, machine-readablecode,request_id, andproblems. A response that breaks the contract raises it with the codeinvalid_invoice_response.validate_contract_schema(name, value)validates a value strictly against a named schema of the generated contract and raisesSchemaValidationError, aValueErrorwith apath. Use it to check a payload before you store or queue it.InvalidWebhookis raised for a bad signature or signing secret, a malformed envelope, or an event outside your organization, environment, or Source connection.
Development
Regenerate the contract projection with python python-sdk/scripts/generate_contract.py. Run the contract check and the package tests in a temporary virtual environment with python python-sdk/scripts/verify.py, or run only the tests with PYTHONPATH=python-sdk python -m unittest discover -s python-sdk/tests. Add --wheel path/to/timbro_invoices-0.9.0-py3-none-any.whl to verify.py to test a built wheel instead of the source tree.
Metadata
Release files for timbro-invoices 0.9.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| timbro_invoices-0.9.0.tar.gz | 40.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| timbro_invoices-0.9.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 74.3 kB
Release files / timbro_invoices-0.9.0.tar.gz
| Download URL | timbro_invoices-0.9.0.tar.gz |
|---|---|
| Size | 40.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
424b08571ce2802c0a1aac39f35eb967356cfb965921be63a8b245b9fdd7616b
|
|
BLAKE2b-256 checksum How to use checksums |
8107a603d948da7afd4f030ed3666349e60a261d553066b839c47f4fc54ff009
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|
Release files / timbro_invoices-0.9.0-py3-none-any.whl
| Download URL | timbro_invoices-0.9.0-py3-none-any.whl |
|---|---|
| Size | 34.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
ad8db61da34d06edca981663c85156addc72a5588db238168bfbb2a1fd35417c
|
|
BLAKE2b-256 checksum How to use checksums |
dd00fd276c499bbfb52506beeba8d4db6b213f0dfe0ff6384ed02b82d3890260
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.4
|