Skip to main content

PPUSSH Ecosystem SDK — Accounts (OIDC) + Payments client for Python

Project description

ppussh

Official Python SDK for the PPUSSH platform — Accounts (OIDC / OAuth 2.0) and Payments in a single, async-first client.

Requirements

  • Python 3.12+
  • An Accounts client_id and client_secret (obtain from the Accounts admin console)
  • A running instance of the Accounts and Payments services

Installation

pip install ppussh

Configuration

The SDK requires the base URLs for both services. Set them via environment variables (recommended for production) or pass them directly to the constructor.

Environment variable Purpose
PPUSSH_ACCOUNTS_URL Base URL of the Accounts API
PPUSSH_PAYMENTS_URL Base URL of the Payments API
export PPUSSH_ACCOUNTS_URL="https://accounts.example.com"
export PPUSSH_PAYMENTS_URL="https://payments.example.com"

Quick start

from ppussh import PpusshClient

# URLs are read from PPUSSH_ACCOUNTS_URL / PPUSSH_PAYMENTS_URL env vars,
# or pass them explicitly:
client = PpusshClient(
    client_id="your-product-client-id",
    client_secret="your-product-client-secret",
    payments_admin_key="your-payments-admin-key",  # optional; needed for admin calls
    # accounts_url="https://accounts.example.com",  # or set PPUSSH_ACCOUNTS_URL
    # payments_url="https://payments.example.com",  # or set PPUSSH_PAYMENTS_URL
)

OIDC callback (FastAPI example)

from fastapi import FastAPI, Query
from ppussh import PpusshClient

app = FastAPI()
client = PpusshClient(client_id="...", client_secret="...")

REDIRECT_URI = "https://yourapp.example.com/auth/callback"

@app.get("/auth/callback")
async def callback(code: str = Query(...)):
    token = await client.accounts.exchange_code(code, redirect_uri=REDIRECT_URI)
    # token.user contains the authenticated user's profile
    return {"user_id": token.user.id, "email": token.user.email}

Token verification middleware

from fastapi import Request, HTTPException
from ppussh import PpusshClient, PpusshAuthError

client = PpusshClient(client_id="...", client_secret="...")

async def require_auth(request: Request) -> str:
    auth_header = request.headers.get("Authorization", "")
    if not auth_header.startswith("Bearer "):
        raise HTTPException(status_code=401)
    bearer = auth_header.removeprefix("Bearer ")
    try:
        result = await client.accounts.verify_token(bearer)
    except PpusshAuthError:
        raise HTTPException(status_code=401)
    return result.user_id

Token refresh

# Uses the refresh token stored internally after exchange_code()
new_token = await client.accounts.refresh()

# Or pass an explicit refresh token:
new_token = await client.accounts.refresh(refresh_token="...")

Logout

await client.accounts.logout()  # uses stored refresh token

Billing — create a customer and subscription

from uuid import uuid4

# Create or retrieve a customer record
customer = await client.payments.create_customer(
    owner_user_id=token.user.id,
    workspace_id="ws-123",  # optional
)

# List available plans for a product
plans = await client.payments.list_plans(payment_product_id="prod-abc")

# Subscribe the customer
subscription = await client.payments.create_subscription(
    customer_id=customer.id,
    payment_product_id="prod-abc",
    plan_key="pro",
    idempotency_key=str(uuid4()),
)

Async context manager (scripts / one-off usage)

async with PpusshClient(client_id="...", client_secret="...") as client:
    token = await client.accounts.exchange_code(code, redirect_uri=REDIRECT_URI)

For long-lived services, call await client.aclose() during application shutdown to drain the connection pool.

Error handling

All exceptions are subclasses of PpusshError:

from ppussh import (
    PpusshError,          # base class
    PpusshAuthError,      # 401 — invalid or expired token / credentials
    PpusshConsentRequired,# 403 — user hasn't consented to this product's scopes
    PpusshPaymentError,   # non-2xx from the Payments service
    PpusshNetworkError,   # all retries exhausted / connection failure
)

try:
    token = await client.accounts.exchange_code(code, redirect_uri=REDIRECT_URI)
except PpusshConsentRequired as exc:
    # Redirect the user to the consent flow
    redirect_to_consent(exc.client_id, exc.product_name)
except PpusshAuthError:
    # Invalid code or expired credentials
    ...
except PpusshNetworkError:
    # Retry later
    ...

Retry policy

Condition Behaviour
5xx / network error Up to 3 attempts, exponential backoff (0.5 s, 1 s, 2 s)
429 Too Many Requests Respects Retry-After header, max 2 retries
4xx (not 429) Never retried — raises immediately

API reference

client.accounts

Method Description
exchange_code(code, *, redirect_uri) Exchange an auth code for tokens (OIDC callback)
refresh(refresh_token?) Refresh the access token
verify_token(access_token) Validate an incoming bearer token (use in middleware)
logout(refresh_token?) Revoke the session
get_user(access_token?) Fetch the authenticated user's profile
get_entitlements(access_token?) List the user's product entitlements
get_sessions(access_token?) List the user's active sessions

client.payments

Method Description
create_customer(owner_user_id, ...) Create or retrieve a customer record
get_customer(customer_id) Fetch a customer by ID
create_subscription(...) Create a subscription
list_subscriptions(customer_id, ...) List subscriptions for a customer
get_subscription(subscription_id) Fetch a subscription by ID
cancel_subscription(subscription_id, ...) Cancel a subscription
list_plans(payment_product_id) List billing plans (requires payments_admin_key)
get_product_by_accounts_id(accounts_product_id) Resolve a payments product by its Accounts ID (requires payments_admin_key)
get_mrr(...) Fetch MRR analytics (requires payments_admin_key)

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ppussh-0.2.4.tar.gz (17.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ppussh-0.2.4-py3-none-any.whl (23.2 kB view details)

Uploaded Python 3

File details

Details for the file ppussh-0.2.4.tar.gz.

File metadata

  • Download URL: ppussh-0.2.4.tar.gz
  • Upload date:
  • Size: 17.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for ppussh-0.2.4.tar.gz
Algorithm Hash digest
SHA256 429d576fbf69a2e1499501254a161f739d005a9161974f76a497e793c11f9e42
MD5 a2a06a569c99d433fcb0136f6863896d
BLAKE2b-256 3626f669caae014cd7f8e1972d02b75691be466f4ff95be9b20f3b5763d4531c

See more details on using hashes here.

File details

Details for the file ppussh-0.2.4-py3-none-any.whl.

File metadata

  • Download URL: ppussh-0.2.4-py3-none-any.whl
  • Upload date:
  • Size: 23.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.5

File hashes

Hashes for ppussh-0.2.4-py3-none-any.whl
Algorithm Hash digest
SHA256 6834205eef274ad9644f4fd4826ec125ede8851fae016e27bf0768235da53ff5
MD5 99744ecc3273e0ec35899e31f58d42f6
BLAKE2b-256 058304d215a9b3c334103058edac7c2d764d85b596e4c44154b34f71eaf235bd

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page