Python SDK

The Plugipay Python SDK is the recommended way to call Plugipay from Python — Flask, FastAPI, Django, a scheduled job, a Jupyter notebook, or anything else that runs on Python 3.9+.

pip install plugipay
from plugipay import PlugipayClient

plug = PlugipayClient(key_id="pk_live_...", secret="sk_live_...")
customer = plug.customers.create(email="ada@example.com", name="Ada Lovelace")

That's it. HMAC signing, request envelopes, idempotency keys, timestamp generation, retry-able timeouts, and webhook verification all live inside the SDK so you don't have to think about them.

What it does for you

Concern What the SDK handles
Authentication Signs every request with HMAC-SHA256. You only see key_id + secret.
Envelope unwrapping Returns the inner data directly; raises PlugipayError for any error.
Idempotency Auto-generates Idempotency-Key headers for write methods that need them.
Pagination Cursor-based lists return a PageResult with data, cursor, has_more.
Errors One exception hierarchy — PlugipayError and three subclasses.
Webhooks verify_webhook(raw_body, header, secret) returns a parsed WebhookEvent.
Platform keys client.for_merchant(account_id) returns a new client scoped via X-Plugipay-On-Behalf-Of.
Connection pooling Uses one httpx.Client per PlugipayClient; with block closes it.

You provide a key_id and secret; everything else is automatic.

What it doesn't do

  • It doesn't validate request shapes — if you pass an invalid argument, the server returns 400 invalid_request and the SDK raises PlugipayError. The same is true of every Plugipay SDK.
  • It doesn't speak async. The client is synchronous (built on httpx.Client). If you need to call Plugipay from asyncio code, run it in a thread pool with asyncio.to_thread(). A first-class async client is on the roadmap; the wire protocol is identical.
  • It doesn't retry on its own. Network blips raise PlugipayNetworkError — wrap the call yourself if you want retries. See Errors for a recipe.

Sub-pages

Same shape as the Node SDK:

  • Installation — pip, poetry, uv, pipenv. Python version requirements.
  • Quickstart — first customer + first checkout session, end-to-end.
  • Authentication — constructor options, env vars, platform keys, custom httpx clients, timeouts.
  • Errors — the PlugipayError hierarchy, retrying network failures.
  • PaginationPageResult, manual cursor loops, generator helpers.
  • Webhooksverify_webhook, Flask/FastAPI/Django patterns, raw body gotchas.
  • Reference — every resource namespace and method signature in one place.

Resource namespaces

The client exposes one attribute per resource group, in Python snake_case:

plug.customers          # cus_…
plug.plans              # pln_…
plug.checkout_sessions  # cs_…
plug.invoices           # inv_…
plug.subscriptions      # sub_…
plug.refunds            # ref_…
plug.payouts            # po_…
plug.ledger             # double-entry rows + balances
plug.reports            # pnl, cash_flow
plug.events             # event store (search delivery history)
plug.webhook_endpoints  # register/delete endpoints
plug.adapters           # provider configs (xendit, midtrans, paypal, manual)
plug.api_keys           # mint/revoke keys
plug.templates          # checkout/invoice/receipt templates
plug.workspaces         # multi-workspace support
plug.account            # the authenticated merchant profile
plug.portal_sessions    # customer self-serve portal links
plug.receipts           # receipt summaries
plug.checkout_settings  # workspace-level checkout defaults
plug.uploads            # upload images (logos, etc.)
plug.onboarding         # provision managed adapter accounts
plug.billing            # Plugipay's own billing tiers/plans
plug.admin              # platform-admin only: provision merchants
plug.admin_portal       # internal operator endpoints

Method names also use snake_case: plug.checkout_sessions.create(...), plug.subscriptions.cancel(sub_id), plug.payouts.mark_paid(po_id, reference="…"). The full method list is on the Reference page.

Every list method returns a PageResult[T]. Every other method returns a Resource subclass — a dict-backed object you can index (customer["email"]), .get(), or read .raw from.

Python idioms

The SDK leans into normal Python conventions:

  • snake_case everywherecheckout_sessions, success_url, customer_id, mark_in_transit. The Node SDK is camelCase; the wire payload is camelCase; the Python SDK translates at the call site so your code stays Pythonic.
  • Keyword-only arguments — all SDK methods take their parameters as keyword arguments (plug.customers.create(email=..., name=...)). Positional ids are positional (plug.customers.get("cus_…")).
  • Context managerwith PlugipayClient(...) as plug: closes the underlying httpx.Client for you. Skip it if your process is short-lived; use it in tests and short scripts.
  • Exceptions, not result objects — failures raise PlugipayError (or a subclass). No error tuples, no Result[T, E].
  • Dict access on resources — the typed classes (Customer, Invoice, …) wrap a dict. Use obj["field"] or obj.get("field"); or read obj.raw for the whole payload.

Source & issues

Next

  • Installation — install and verify the SDK works.
  • Quickstart — round-trip a customer + checkout session in under 30 lines.
  • API reference — the underlying HTTP API, if you ever need to drop below the SDK.
Plugipay — Payments that don't tax your success