Skip to main content

py-powens

PyPI version Python versions CI License: MIT Checked with mypy Ruff

Unofficial, third-party SDK. Not affiliated with or endorsed by Powens. "Powens" is used here only to describe compatibility with the Powens API. Users of this SDK are bound by Powens' own Terms of Service.

Status

Alpha (0.x) — the public surface may still change in minor versions until 1.0. Pin strictly (py-powens==0.1.*) for reproducibility. Semantic versioning applies from 1.0.0 onwards.

A modern, typed, async-only Python SDK for the Powens banking API, built 1:1 from the public API reference.

  • Python 3.13+, fully typed, py.typed.
  • Async-only on top of httpx.
  • Immutable Pydantic v2 models, permissive on unknown fields.
  • Both paginations supported: offset (most endpoints) and relational cursor (_links.next.href, used by transactions).
  • Typed exception hierarchy that parses the Powens error envelope { code, description, message, request_id }.
  • Light retry on transient errors + injectable circuit breaker.
  • Composition over inheritance — inject an httpx.AsyncClient or a test transport for full control.

The SDK speaks to the Powens API and nothing else: no DB, no cache, no scheduler, no cross-provider abstractions. Anything beyond "talk to the Powens API" is the caller's job.


Installation

uv add py-powens      # recommended
pip install py-powens
poetry add py-powens

Requires Python 3.13+. Runtime dependencies: httpx and pydantic (v2).

30-second example

import asyncio
from powens import PowensClient

async def main() -> None:
    async with PowensClient(
        base_url="https://demo.biapi.pro/2.0",
        access_token="<USER_TOKEN>",
    ) as client:
        # Iterate accounts lazily (offset pagination under the hood)
        async for account in client.accounts.list():
            print(account.id, account.name, account.balance)

asyncio.run(main())

Prefer the envelope (with aggregated balances per currency) in a single call? Use list_all():

envelope = await client.accounts.list_all()
for account in envelope.accounts:
    print(account.id, account.name, account.balance)
print("EUR total:", envelope.balances and envelope.balances.get("EUR"))

Quickstart

import asyncio
from powens import PowensClient

async def main() -> None:
    async with PowensClient(
        base_url="https://your-domain.biapi.pro/2.0",
        access_token="<USER_TOKEN>",
    ) as client:
        # Offset-paginated listing
        async for conn in client.connections.list():
            print(conn.id, conn.state)

        # Cursor-paginated listing (transactions)
        async for tx in client.transactions.list(limit=500):
            print(tx.id, tx.value, tx.wording)

asyncio.run(main())

Authentication

The SDK exposes every documented auth endpoint:

# Create a new end-user
token = await c.auth.init_user(client_id="...", client_secret="...")
c.set_access_token(token.auth_token)

# Generate a temporary webview code
code = await c.auth.generate_code(type_="singleAccess")

# Exchange a code for a permanent token
permanent = await c.auth.exchange_code(
    code=code.code, client_id="...", client_secret="...",
)

# Renew a token (for a known user)
new = await c.auth.renew_token(
    client_id="...", client_secret="...", id_user=42,
)

# Revoke the current permanent token
await c.auth.revoke_token()

# Issue a service token (Pay product)
svc = await c.auth.generate_service_token(
    client_id="...", client_secret="...",
    scope="payments:admin",
)

Webview

The Powens webview is served from a separate host (https://webview.powens.com/{lang}/{flow}). The SDK exposes URL builders — no HTTP call is issued:

url = client.webview.connect_url(
    client_id="...",
    redirect_uri="https://your-app/cb",
    lang="fr",
    connector_capabilities=["bank"],
).url

Four flows are supported: connect, reconnect, manage, payment.

For the separate /webauth-url API endpoint (not the webview), use client.connections.webauth_url(...).

Resources

Resource Coverage
client.auth init_user, generate_code, exchange_code, revoke_token, renew_token, generate_service_token
client.users me, get(id), list_all, delete
client.connectors list, get, update, batch_update, list_sources, get_source, update_source
client.connections create, list, list_all, get, update (incl. OTP via fields), sync, delete, list_sources, get_source, update_source, webauth_url, list_logs_raw
client.accounts list, list_all (envelope with balances/coming_balances), get, update
client.account_types list, get
client.currencies list
client.transactions list (cursor), list_page, get, update
client.investments list, list_all (portfolio aggregates), get, history
client.market_orders list, get
client.pockets list, get
client.loan_amortizations list
client.balances get
client.account_ownerships list (feature-gated)
client.indicators get
client.webview connect_url, reconnect_url, manage_url, payment_url

Pagination

# Offset (connections, accounts, investments, market orders, …)
async for c in client.connections.list():
    ...

async for page in client.connections.list(limit=50).by_page():
    print(page.total, [c.id for c in page.items])

# Relational cursor (transactions)
async for tx in client.transactions.list(limit=1000):
    ...

# Single-page call that exposes the envelope dates
env = await client.transactions.list_page(
    account_id=1, min_date=date(2024, 1, 1),
)
print(env.first_date, env.last_date)

Error handling

The SDK parses the common Powens error envelope and exposes a typed hierarchy. Powens explicitly recommends branching on error_code over HTTP status — so PowensHTTPError.error_code is a first-class attribute.

PowensError
├── PowensHTTPError            # base (has .error_code, .error_description, ...)
│   ├── PowensBadRequestError        # 400
│   ├── PowensAuthError              # 401 / 403
│   ├── PowensNotFoundError          # 404
│   ├── PowensConflictError          # 409
│   ├── PowensRateLimitError         # 429 (has .retry_after)
│   ├── PowensServerError            # 500
│   └── PowensServiceUnavailableError# 503
├── PowensConnectionError      # network failure
├── PowensSerializationError   # response shape mismatch
└── PowensCircuitOpenError     # injected breaker short-circuited
from powens import PowensErrorCode, PowensHTTPError

try:
    await client.accounts.get(account_id=999)
except PowensHTTPError as err:
    if err.error_code == PowensErrorCode.WRONG_PASS.value:
        ...

Retry + circuit breaker

Transient retries apply to network errors, 429, 502, 503, 504 — never 500 (a 500 on a finance API is ambiguous; silently retrying write requests risks double-effects). Only idempotent verbs (GET/HEAD/OPTIONS/PUT/DELETE) are retried by default.

from powens import PowensClient, RetryPolicy

policy = RetryPolicy(max_attempts=5, base_delay=0.5, max_delay=5.0)
async with PowensClient(base_url=..., retry_policy=policy) as c:
    ...

A NoOpCircuitBreaker ships by default. Inject your own implementation (conforming to the CircuitBreaker protocol) to integrate with an observability / control plane.

Development

mise install
uv sync
uv run ruff check .
uv run ruff format --check .
uv run mypy .
uv run pytest

Tests use respx and do not need network access.

Fidelity

This SDK mirrors the public Powens API reference 1:1 — every documented field appears on the corresponding Pydantic model, including deprecated fields (marked in code). Enums list the documented values but tolerate unknown strings, as the reference requires.

Known limitations

  • Async-only; no sync wrapper. Use asyncio.run(...) in scripts or integrate inside an existing event loop.
  • client.indicators and client.account_ownerships depend on feature-gated Powens endpoints — your domain must have them enabled.
  • Webhooks are not covered (they are a server-side concern, not an API-client one).
  • The SDK does not persist tokens; token refresh and storage are the caller's responsibility.

Support

This is a community-maintained SDK. For bugs and feature requests, use GitHub Issues. For questions about the Powens API itself, refer to the official documentation.

License

MIT — see LICENSE.

Metadata

Release files for py-powens 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-powens 0.1.1
File Size Uploaded
py_powens-0.1.1.tar.gz 49.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for py-powens 0.1.1
File Interpreter ABI Platform
py_powens-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 106.5 kB

Release files / py_powens-0.1.1.tar.gz

Download URL py_powens-0.1.1.tar.gz
Size 49.6 kB
Tags Source
SHA-256 checksum
How to use checksums
6d4e065a9485f19e804656b05acb7beef3e45b8292846c6cc82c18e085a7eef4
BLAKE2b-256 checksum
How to use checksums
a7e20ead1e02c27fa27c9c4511f5a128b195aae3bb639c237d22dd8aab50fc16
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 22, 2026.

Transparency log

Release files / py_powens-0.1.1-py3-none-any.whl

Download URL py_powens-0.1.1-py3-none-any.whl
Size 56.8 kB
Tags Python 3
SHA-256 checksum
How to use checksums
ffa448b2ff60697469cdda566cfab1746a7a368b8cae1fa635943b85e7d47b44
BLAKE2b-256 checksum
How to use checksums
e29e530ee3a6500a8665f356a8f118cbb92d1a3e84bdeb8fd1b5ca607df6f4a1
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

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 Apr 22, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.1 This release

2 release files

0.1.0

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