Skip to main content

Sweet Potato Authentication & Payment Service Python client

Project description


id: spaps-python-sdk title: Sweet Potato Python Client category: sdk tags:

  • sdk
  • python
  • client ai_summary: | Explains installation, configuration, and usage patterns for the spaps Python SDK, including environment setup, async support, and integration guidance for backend services. last_updated: 2025-10-14

Sweet Potato Python Client

Python SDK for the Sweet Potato Authentication & Payment Service (SPAPS).

This package is under active development. The sections below outline the supported surface area, test coverage, and release checks we use to keep the client aligned with the SPAPS API.

Installation

Install from PyPI:

pip install spaps

For local development inside this repository:

pip install -e .[dev]

Development

Source for the Python client lives in src/spaps_client/. Tests are split between tests/unit/ (feature coverage) and tests/integration/ (build/install guards). Use pytest directly during local TDD, or run the npm script npm run test:python-client from the repo root if you need the full harness. The repository npm scripts automatically install the dev extras (pip install -e .[dev]) before linting, typing, or testing so you do not have to manage that bootstrap step manually.

pytest

Quality Checks

Before opening a PR or publishing, run the standard gates:

  • npm run lint:python-client – ensures the ruff configuration passes
  • npm run typecheck:python-client – validates mypy typing coverage
  • npm run test:python-client – executes the pytest suite with respx mocks
  • npm run build:python-client – builds wheel/sdist and performs a twine check
  • npm run docs:validate-all – keeps the docs manifest in sync across SDKs
  • npm run publish:python-client – builds and uploads via twine (requires PYPI_TOKEN)

Available clients

  • AuthClient – wallet, email/password, and magic link flows
  • SessionsClient – current session, validation, listing, revocation
  • PaymentsClient – checkout sessions, wallet deposits, crypto invoices
  • UsageClient – feature usage snapshots, recording, aggregated history
  • SecureMessagesClient – encrypted message creation and retrieval
  • MetricsClient – health and metrics convenience helpers

Quickstart

from spaps_client import SpapsClient

spaps = SpapsClient(base_url="http://localhost:3301", api_key="test_key_local_dev_only")

# Authenticate (tokens are persisted automatically)
spaps.auth.sign_in_with_password(email="user@example.com", password="Secret123!")

# Call downstream services using the stored access token
current = spaps.sessions.get_current_session()
print(current.session_id)

checkout = spaps.payments.create_checkout_session(
    price_id="price_123",
    mode="subscription",
    success_url="https://example.com/success",
    cancel_url="https://example.com/cancel",
    require_legal_consent=True,
    legal_consent_text="I am 18+ and accept the HTMA Terms & Privacy.",
)
print(checkout.checkout_url)

spaps.close()

require_legal_consent forces Stripe’s Terms/Privacy checkbox. legal_consent_text is stripped to plain text, must be ≤120 characters, and defaults to “I agree to the Terms of Service and Privacy Policy.” when omitted.

Configure retry/backoff and structured logging when constructing the client:

from spaps_client import SpapsClient, RetryConfig, default_logging_hooks

spaps = SpapsClient(
    base_url="http://localhost:3301",
    api_key="test_key_local_dev_only",
    retry_config=RetryConfig(max_attempts=4, backoff_factor=0.2),
    logging_hooks=default_logging_hooks(),
)

Magic Link & Wallet Authentication

# Send a sign-in email
spaps.auth.send_magic_link(email="user@example.com")

# Later, exchange the token from the link for session tokens (persisted automatically)
magic_result = spaps.auth.verify_magic_link(token="token-from-email")
print(magic_result.user.email)

# Wallet flow (Solana/Ethereum)
nonce = spaps.auth.request_nonce(wallet_address="0xabc...", chain="ethereum")
signature = sign_message_with_wallet(nonce.message)  # your wallet integration
wallet_tokens = spaps.auth.verify_wallet(
    wallet_address="0xabc...",
    signature=signature,
    message=nonce.message,
    chain="ethereum",
)
print(wallet_tokens.user.wallet_address)

Current User Profile

profile = spaps.auth.get_current_user()
print(profile.id, profile.email, profile.tier)

Password Reset

spaps.auth.request_password_reset(email="user@example.com")

spaps.auth.confirm_password_reset(
    token="reset-token-from-email",
    new_password="Sup3rStrong!",
)

Product Catalog

catalog = spaps.payments.list_products(category="subscription", active=True, limit=10)
for product in catalog.products:
    print(product.name, product.default_price)

detail = spaps.payments.get_product("prod_123")
print(detail.prices[0].nickname)

Subscription & Billing Helpers

# Fetch active subscriptions for the current user
subs = spaps.payments.list_subscriptions(status="active")
print(subs.subscriptions[0].status)

# Inspect a specific subscription and switch to a new price
detail = spaps.payments.get_subscription(subscription_id="sub_123")
print(detail.plan.interval)

spaps.payments.update_subscription(subscription_id="sub_123", price_id="price_plus")

# Cancel immediately (versus at period end)
spaps.payments.cancel_subscription(subscription_id="sub_123", immediately=True)

Checkout Session Management

# Lookup previously created checkout sessions
session = spaps.payments.get_checkout_session(session_id="cs_test_123")
print(session.payment_status)

sessions = spaps.payments.list_checkout_sessions(limit=5)
print(len(sessions.sessions))

# Force-expire a stale session
spaps.payments.expire_checkout_session(session_id="cs_test_123")
# API-key-only guest checkout helpers
guest = spaps.payments.create_guest_checkout_session(
    customer_email="guest@example.com",
    mode="payment",
    line_items=[{"price_id": "price_basic", "quantity": 1}],
    success_url="https://example.com/success",
    cancel_url="https://example.com/cancel",
)

guest_detail = spaps.payments.get_guest_checkout_session(session_id=guest.id)
print(guest_detail.payment_status)

guest_sessions = spaps.payments.list_guest_checkout_sessions(limit=10)
print(guest_sessions.sessions[0].session_id)

Payment History

history = spaps.payments.list_payment_history(limit=20, status="succeeded")
for charge in history.payments:
    print(charge.id, charge.amount, charge.status)

detail = spaps.payments.get_payment_detail(payment_id="pi_123")
print(detail.metadata)

Async Quickstart

import asyncio
from spaps_client import AsyncSpapsClient

async def main():
    client = AsyncSpapsClient(base_url="http://localhost:3301", api_key="test_key_local_dev_only")
    try:
        await client.auth.sign_in_with_password(email="user@example.com", password="Secret123!")
        current = await client.sessions.list_sessions()
        print(len(current.sessions))
    finally:
        await client.aclose()

asyncio.run(main())

Async helpers mirror the synchronous API:

nonce = await client.auth.request_nonce(wallet_address="0xabc...", chain="solana")
signature = await sign_message_async(nonce.message)
await client.auth.verify_wallet(
    wallet_address="0xabc...",
    signature=signature,
    message=nonce.message,
    chain="solana",
)
profile = await client.auth.get_current_user()
print(profile.username)

Permission Utilities

from spaps_client import PermissionChecker

checker = PermissionChecker(customAdmins=["founder@example.com"])
role = checker.getRole("user@example.com")
if checker.requiresAdmin({"email": "user@example.com"}):
    raise PermissionError(checker.getErrorMessage("admin", role, action="change billing settings"))

Documentation Notes

Additional API references under docs/api/ include Python usage snippets for sessions, payments, usage, whitelist, and secure messages. Those guides ship with the repository; clone the project if you need the full documentation set.

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

spaps-0.4.0.tar.gz (78.0 kB view details)

Uploaded Source

Built Distribution

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

spaps-0.4.0-py3-none-any.whl (74.4 kB view details)

Uploaded Python 3

File details

Details for the file spaps-0.4.0.tar.gz.

File metadata

  • Download URL: spaps-0.4.0.tar.gz
  • Upload date:
  • Size: 78.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for spaps-0.4.0.tar.gz
Algorithm Hash digest
SHA256 0221feac8eddf545cb4ed139cb75d0801498f222712a685ef650d2bf20bef65b
MD5 cc46369a409c0379ad986c0763edbeef
BLAKE2b-256 5d464f5884cef5fef4e38ee2d055acbf31cd1a1eb9954b2ae81e2c0329c314fc

See more details on using hashes here.

File details

Details for the file spaps-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: spaps-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 74.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.12

File hashes

Hashes for spaps-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 47c1074012519fc2462673ea54e6817b28f7ac64a1240d911e4f0e3472fe4e82
MD5 7fcf98d07a3fdb68db2ea9cad4af4f1d
BLAKE2b-256 4697e3252a9ae2d9deaef0a13a446768b4caaf4782955e34f9d38eacb8aa14ab

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