Async Python client for Qonto Business API
Project description
qodev-qonto-api
Async Python client for Qonto Business API with full type safety.
Features
- Async-first design built on httpx
- Full Pydantic v2 models with
extra="allow"for forward compatibility - Context manager support for clean resource management
- Sandbox support via
QONTO_BASE_URLenvironment variable orbase_url=kwarg - ~40 API methods across 15+ resource types (organizations, memberships, labels, bank accounts, transactions, attachments, clients, invoices, quotes, credit notes, supplier invoices, products, SEPA transfers, bulk transfers, internal transfers, beneficiaries)
- Multipart attachment upload helper for receipts and documents
- Typed exceptions —
AuthenticationError,NotFoundError,ValidationError,RateLimitError,APIError - Generic
PaginatedResponse[T]with Qonto meta-envelope flattening - Rate-limit header tracking via
client.rate_limit_status - py.typed marker for downstream type checking
Installation
pip install qodev-qonto-api
Or with uv:
uv add qodev-qonto-api
Quick Start
import asyncio
from qodev_qonto_api import QontoClient
async def main():
async with QontoClient() as client: # reads QONTO_LOGIN + QONTO_SECRET_KEY
org = await client.get_organization()
print(org.legal_name)
accounts = await client.list_bank_accounts()
for account in accounts:
txns = await client.list_transactions(
bank_account_id=account.id, per_page=10,
)
print(f"{account.iban}: {len(txns.items)} recent")
asyncio.run(main())
Configuration
Credentials
Set the two required environment variables:
export QONTO_LOGIN="your-org-login"
export QONTO_SECRET_KEY="your-secret-key"
Or pass directly:
async with QontoClient(login="your-org-login", secret_key="your-secret-key") as client:
...
Important: The Qonto
Authorizationheader is the literal string{login}:{secret}with a real colon. This is not HTTP Basic Authentication — there is no Base64 encoding.
Sandbox
Switch to the staging sandbox via env var:
export QONTO_BASE_URL="https://thirdparty-sandbox.staging.qonto.co/v2"
Or via kwarg:
async with QontoClient(base_url="https://thirdparty-sandbox.staging.qonto.co/v2") as client:
...
Timeout
Customize request timeout (default 30 seconds):
async with QontoClient(timeout=60.0) as client:
...
Rate Limiting
Qonto enforces these limits (per IP):
- 1,000 requests / 10 seconds
- 10,000 requests / 10 minutes
Rate-limit headers are captured defensively (Qonto does not officially document header names — the client captures any ratelimit-* or x-ratelimit-* header) and exposed as a raw dict:
async with QontoClient() as client:
await client.list_bank_accounts()
print(client.rate_limit_status) # {"x-ratelimit-remaining": "998", ...}
API Methods
Organization
org = await client.get_organization()
Memberships & Labels
members = await client.list_memberships()
labels = await client.list_labels()
Bank Accounts
accounts = await client.list_bank_accounts()
Transactions
GET /transactions requires either bank_account_id or iban:
txns = await client.list_transactions(bank_account_id="acc_123", per_page=50)
txn = await client.get_transaction("txn_456")
Attachments
attachment = await client.upload_attachment(
file_path="invoice.pdf",
idempotency_key="unique-key-123",
)
await client.attach_to_transaction(transaction_id="txn_456", attachment_ids=[attachment.id])
Clients
clients = await client.list_clients()
client_obj = await client.create_client(type="company", name="Acme Corp", email="billing@acme.com")
Client Invoices
invoices = await client.list_client_invoices()
invoice = await client.create_client_invoice(client_id="cl_1", items=[...])
Quotes & Credit Notes
quotes = await client.list_quotes()
credit_notes = await client.list_credit_notes()
Supplier Invoices
supplier_invoices = await client.list_supplier_invoices()
si = await client.get_supplier_invoice("si_123")
Products
products = await client.list_products()
SEPA Transfers
# VoP (Verification of Payee) must be called manually — pass the resulting
# vop_proof_token via extra_fields. See roadmap.
transfer = await client.create_sepa_transfer(
debit_account_id="acc_1",
beneficiary_id="ben_1",
amount="100.00",
currency="EUR",
reference="Invoice INV-001",
vop_proof_token="token-from-verify-payee",
)
Bulk Transfers & Internal Transfers
bulk = await client.create_bulk_transfer(debit_account_id="acc_1", transfers=[...])
internal = await client.create_internal_transfer(
debit_account_id="acc_1",
credit_account_id="acc_2",
amount="50.00",
)
Beneficiaries
beneficiaries = await client.list_beneficiaries()
Error Handling
from qodev_qonto_api import (
QontoClient,
QontoError,
AuthenticationError,
NotFoundError,
ValidationError,
RateLimitError,
APIError,
)
try:
async with QontoClient() as client:
await client.get_transaction("does-not-exist")
except AuthenticationError:
print("Invalid login / secret key")
except NotFoundError:
print("Resource not found")
except ValidationError as e:
for err in e.errors:
print(f"{err.get('source', {}).get('pointer')}: {err.get('detail')}")
except RateLimitError as e:
print(f"Rate limited. Retry after {e.retry_after} seconds")
except APIError as e:
print(f"API error: {e} (status: {e.status_code})")
except QontoError as e:
print(f"Qonto client error: {e}")
Development
make install # Install dependencies
make check # Lint, format, typecheck, typos
make test # Run tests with coverage
Roadmap (Out of Scope for v0.1.0)
- OAuth2 / Qonto Connect — partner app integrations
- PSD2 QSeal certificates — regulatory signing
- Cards API — virtual/physical card management
- Webhooks — event subscriptions
- Onboarding API — account creation flows
- VoP integration — Verification of Payee for SEPA transfers (currently manual via
extra_fields) - Payment links
- Embed iframe features
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file qodev_qonto_api-0.1.0.tar.gz.
File metadata
- Download URL: qodev_qonto_api-0.1.0.tar.gz
- Upload date:
- Size: 65.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e1fbffffbdd16e4315c91b3436581b8a6fe52bc3d9f83b08b6615ad04ecbc3f1
|
|
| MD5 |
b411489a7f0ef046d44a520e641c3324
|
|
| BLAKE2b-256 |
b44276fd4bfa9a32ada2a8dc6e92987a557b7d3c1b2246084339dc605ea5d2e7
|
Provenance
The following attestation bundles were made for qodev_qonto_api-0.1.0.tar.gz:
Publisher:
publish.yml on qodevai/qonto-api
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qodev_qonto_api-0.1.0.tar.gz -
Subject digest:
e1fbffffbdd16e4315c91b3436581b8a6fe52bc3d9f83b08b6615ad04ecbc3f1 - Sigstore transparency entry: 1247162521
- Sigstore integration time:
-
Permalink:
qodevai/qonto-api@9a1ac57bf928ee0d442106203dbfa4b024ed319f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/qodevai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9a1ac57bf928ee0d442106203dbfa4b024ed319f -
Trigger Event:
push
-
Statement type:
File details
Details for the file qodev_qonto_api-0.1.0-py3-none-any.whl.
File metadata
- Download URL: qodev_qonto_api-0.1.0-py3-none-any.whl
- Upload date:
- Size: 16.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9e6782de12f986abf69124f492df5ea14434dfbaa756147793895028a7adff92
|
|
| MD5 |
9e8f1d2a7d2e87478ce687065f0ae9f5
|
|
| BLAKE2b-256 |
3e96c2a9c009944dd64cb04bf89e4df7aa269bfa8f9dc4c8edce949f2c949167
|
Provenance
The following attestation bundles were made for qodev_qonto_api-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on qodevai/qonto-api
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
qodev_qonto_api-0.1.0-py3-none-any.whl -
Subject digest:
9e6782de12f986abf69124f492df5ea14434dfbaa756147793895028a7adff92 - Sigstore transparency entry: 1247162549
- Sigstore integration time:
-
Permalink:
qodevai/qonto-api@9a1ac57bf928ee0d442106203dbfa4b024ed319f -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/qodevai
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@9a1ac57bf928ee0d442106203dbfa4b024ed319f -
Trigger Event:
push
-
Statement type: