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 theruffconfiguration passesnpm run typecheck:python-client– validates mypy typing coveragenpm run test:python-client– executes the pytest suite withrespxmocksnpm run build:python-client– builds wheel/sdist and performs atwine checknpm run docs:validate-all– keeps the docs manifest in sync across SDKsnpm run publish:python-client– builds and uploads viatwine(requiresPYPI_TOKEN)
Available clients
AuthClient– wallet, email/password, and magic link flowsSessionsClient– current session, validation, listing, revocationPaymentsClient– checkout sessions, wallet deposits, crypto invoicesUsageClient– feature usage snapshots, recording, aggregated historySecureMessagesClient– encrypted message creation and retrievalMetricsClient– 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_consentforces Stripe’s Terms/Privacy checkbox.legal_consent_textis 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file spaps-0.4.1.tar.gz.
File metadata
- Download URL: spaps-0.4.1.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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
abb96970024fe0fab742dd0cd3288d64b9c1f450a5837d660b19fc23f0518a4b
|
|
| MD5 |
e73592e2e6f4a3989f3a644d23cb7c89
|
|
| BLAKE2b-256 |
44ff9ce966278c9416a6cb26136868ac2f8002f5e302d38d1b0b6af52baf381d
|
File details
Details for the file spaps-0.4.1-py3-none-any.whl.
File metadata
- Download URL: spaps-0.4.1-py3-none-any.whl
- Upload date:
- Size: 74.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b527e18063fb88b8fe618de6c58fc275f2ba7cc6eebaa86f4ef15e4e74490ac
|
|
| MD5 |
c1ab959e6bad6472d1ec4bb8e293742c
|
|
| BLAKE2b-256 |
c5b5f58ea1096ec8f36ea6922e9f956a91c929d9067e51c5ef35ddfd625a6c3a
|