This release is a pre-release and may not be stable for production use.
horizonpay-invoice-ai
The official Python SDK for the Invoice-AI API. It supports Python 3.10+, with a sync client (InvoiceAI) and an asyncio client (AsyncInvoiceAI), and depends only on httpx and pydantic.
pip install horizonpay-invoice-ai # or: uv add horizonpay-invoice-ai
from invoice_ai import InvoiceAI
client = InvoiceAI() # reads INVOICE_AI_API_KEY
customer = client.customers.create(name="Acme", email="ap@acme.com")
draft = client.invoices.create(customer=customer.id, items=[{"price": "price_…", "quantity": 1}])
client.invoices.finalize(draft.id)
client.invoices.send(draft.id)
for inv in client.invoices.list(status="open"): # walks every page
print(inv.number)
Async works the same way:
from invoice_ai import AsyncInvoiceAI
async with AsyncInvoiceAI() as client:
invoice = await client.invoices.retrieve("in_…")
async for inv in client.invoices.list(status="open"):
print(inv.number)
What it handles for you
- Retries. Network errors, timeouts, 408, 409
conflict, 429 and 5xx are retried up tomax_retries(default 2). Backoff is exponential with jitter, and the SDK waits outRetry-After/RateLimit-Reset. A PATCH or DELETE that may have reached the server is never resent. - Idempotency. Every POST gets an
Idempotency-Key, and retries reuse it, so a retried create can't run twice. To choose the key yourself, passidempotency_key=.... - Pagination.
list()returns one page (data,next_cursor,has_more). Iterating it (for/async for) walks every page..to_list(limit=500)collects a bounded number of items. - Errors. Each server
codehas its own exception:ValidationError(with.fields),InvalidStateError,NotFoundError,RateLimitError,IdempotencyErrorand the rest. They all extendAPIError, which carriesstatus,code,detailandrequest_id. - Webhooks.
client.webhooks.construct_event(raw_body, headers, secret)(orWebhook(secret).verify(raw_body, headers)) verifies the Standard Webhooks signature and returns a typedWebhookEvent. - Money. Amounts are integers in minor units.
to_minor("25.00", "USD"),from_minor(2500, "USD")(aDecimal) andformat_money(5000, "JPY")use each currency's own number of decimals. - Types. Every response is a Pydantic v2 model generated from the OpenAPI spec (
invoice_ai.types). Parsing is lenient: a field or enum value the SDK doesn't know yet never raises.
Every method takes keyword arguments, with path parameters first (client.invoices.void("in_…", reason="Duplicate")), plus the request options idempotency_key, timeout (in seconds, not milliseconds), max_retries and extra_headers. To read headers, use .with_raw_response:
raw = client.invoices.with_raw_response.retrieve("in_…")
raw.request_id; raw.rate_limit.remaining; raw.idempotent_replayed
invoice = raw.parse()
For endpoints the SDK doesn't wrap yet, use client.request("GET", "/business").
Verifying webhooks
Pass the raw request body to Webhook.verify (or client.webhooks.construct_event). A body that has been parsed and re-serialised as JSON won't match the signature. With FastAPI:
import os
from fastapi import FastAPI, HTTPException, Request
from invoice_ai import Webhook, WebhookVerificationError
app = FastAPI()
webhook = Webhook(os.environ["INVOICE_AI_WEBHOOK_SECRET"]) # whsec_…, from webhook_endpoints.create()
@app.post("/webhooks/invoice-ai")
async def invoice_ai_webhook(request: Request) -> dict[str, bool]:
raw = await request.body() # bytes, exactly as sent
try:
event = webhook.verify(raw, request.headers)
except WebhookVerificationError as e:
raise HTTPException(status_code=400, detail=str(e)) from e
if event.type == "invoice.paid":
print(f"{event.data.object.number} was paid")
return {"received": True}
Deliveries can repeat, so deduplicate on event.id. For a standard-library version, see examples/verify_webhook.py.
Configuration
| Option | Env var | Default |
|---|---|---|
api_key |
INVOICE_AI_API_KEY |
— |
base_url |
INVOICE_AI_BASE_URL |
https://invoice.horizonpay.co/api/v1 |
timeout |
60 (seconds; a float, e.g. 2.5) |
|
max_retries |
2 |
|
log_level |
INVOICE_AI_LOG |
warn (debug logs each request to the invoice_ai logger, with secrets redacted) |
http_client |
a new httpx.Client / httpx.AsyncClient |
|
default_headers |
— |
For runnable scripts, see examples/.
Development
The spec is the source of truth. After changing spec/openapi.json, run pnpm sdk:gen from the repo root. It regenerates invoice_ai/resources/, invoice_ai/types/, _operations.py and _meta.py; don't edit those by hand.
uv sync
uv run pytest # unit tests
uv run pytest -m contract # every method against a Prism mock of the spec (needs npx)
uv run ruff check && uv run mypy invoice_ai
Metadata
Release files for horizonpay-invoice-ai 0.1.0rc1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| horizonpay_invoice_ai-0.1.0rc1.tar.gz | 44.6 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| horizonpay_invoice_ai-0.1.0rc1-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 105.2 kB
Release files / horizonpay_invoice_ai-0.1.0rc1.tar.gz
| Download URL | horizonpay_invoice_ai-0.1.0rc1.tar.gz |
|---|---|
| Size | 44.6 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
c606790fc32e066356b0d394e3e131bdde83511c1781f6ed91208864f894c583
|
|
BLAKE2b-256 checksum How to use checksums |
2e3e390e13cc62f8f32410d413cab124386f0f446f08f519d83e7b0a3deab72d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency logRelease files / horizonpay_invoice_ai-0.1.0rc1-py3-none-any.whl
| Download URL | horizonpay_invoice_ai-0.1.0rc1-py3-none-any.whl |
|---|---|
| Size | 60.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
90af7a5dc7e25544fce1ece59e78e2781ea49eeb590bc9126daccaa986250927
|
|
BLAKE2b-256 checksum How to use checksums |
7a15acefcfc0b7ed60314bfcda3cb168bbc45c59e893d66b7c37a39c8c2cce4c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Oct 4, 2026.
Transparency log