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.3.0.tar.gz (71.3 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.3.0-py3-none-any.whl (67.9 kB view details)

Uploaded Python 3

File details

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

File metadata

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

File hashes

Hashes for spaps-0.3.0.tar.gz
Algorithm Hash digest
SHA256 20550bdc71d564bcd0657749460cd5326103ee0ebebd9d603cc524010ff51609
MD5 dbed8917ba2a7c4feda1d99f7bb8dac3
BLAKE2b-256 84ad391b59a66235b13e539d6edbcb81847872507e3c4ac48ac3bf59d7fefd7b

See more details on using hashes here.

File details

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

File metadata

  • Download URL: spaps-0.3.0-py3-none-any.whl
  • Upload date:
  • Size: 67.9 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.3.0-py3-none-any.whl
Algorithm Hash digest
SHA256 458fcb0a630e2f579e5cd0d3898521da8411fc388e7d6f92e55590cf5f621cc4
MD5 126bd51624e83fbf4b151259d0ccb734
BLAKE2b-256 2fe76a9920aee0b53d5d60ecf9d738b25b662f3b95bfcc7dd66ad79dd718f968

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