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.2.1.tar.gz (66.7 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.2.1-py3-none-any.whl (64.7 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for spaps-0.2.1.tar.gz
Algorithm Hash digest
SHA256 e3c5faa8c208a4d3a6c1fb5cbd932b03ef46acb2bad9cfd6f1dc6b37855d7174
MD5 b0699ddcdb4ed51f4c9e79b24e7cc2c0
BLAKE2b-256 9f13acc59888c3ce63422044616ce526510bef685764c4a9733375f0846851ec

See more details on using hashes here.

File details

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

File metadata

  • Download URL: spaps-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 64.7 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.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f906e19438d00b294ee5374e0058c980ce32aee7e327368c6133c09cc026e200
MD5 36a8591b2dc02ae20f0fb31d76b71eb7
BLAKE2b-256 c5adbd11b6bf98d13f8e0c5e09b07a13bdbe30d6e6e5408a7138a096eef93dde

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