Skip to main content
Pre-release

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 to max_retries (default 2). Backoff is exponential with jitter, and the SDK waits out Retry-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, pass idempotency_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 code has its own exception: ValidationError (with .fields), InvalidStateError, NotFoundError, RateLimitError, IdempotencyError and the rest. They all extend APIError, which carries status, code, detail and request_id.
  • Webhooks. client.webhooks.construct_event(raw_body, headers, secret) (or Webhook(secret).verify(raw_body, headers)) verifies the Standard Webhooks signature and returns a typed WebhookEvent.
  • Money. Amounts are integers in minor units. to_minor("25.00", "USD"), from_minor(2500, "USD") (a Decimal) and format_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)

Source distribution for horizonpay-invoice-ai 0.1.0rc1
File Size Uploaded
horizonpay_invoice_ai-0.1.0rc1.tar.gz 44.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for horizonpay-invoice-ai 0.1.0rc1
File Interpreter ABI Platform
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 log

Release 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

Release history Release notifications | RSS feed

0.1.0

2 release files

This release

0.1.0rc1 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page