Usage-based billing SDK for AI applications
Project description
Stoa SDK
Usage-based billing SDK for AI applications. Wrap your AI provider calls to automatically meter usage and bill your users.
Installation
pip install onstoa
Quick Start
from fastapi.responses import RedirectResponse
from stoa import Stoa, StoaChargeRequiredError
# Reads STOA_API_KEY from environment
stoa = Stoa()
# Use your app's user ID for billing calls
client = stoa.openai(user_id="user_123")
try:
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello!"}]
)
except StoaChargeRequiredError:
payment = stoa.create_payment(
user_id="user_123",
email="ada@example.com",
return_url="https://app.example.com/billing/stoa-return",
)
raise RedirectResponse(payment.hosted_url, status_code=303)
Typical flow:
- call
stoa.create_payment(...)when you want to start a payment flow - keep using your app
user_idin SDK billing calls - if a metered call raises
StoaChargeRequiredError, callstoa.create_payment(...)
If you already have users who predate your Stoa integration, you can also add a one-time lazy fallback before their first billable AI request. The operation is idempotent.
Onboard Users
Stoa can stay invisible to the customer while still owning the canonical user and membership records.
Explicitly bootstrap a member
register_member(...) is still available if you want to bootstrap a user eagerly
during signup.
from stoa import Stoa
stoa = Stoa(api_key=STOA_API_KEY, base_url=STOA_BASE_URL)
result = stoa.register_member(
registration_secret=STOA_REGISTRATION_SECRET,
user_id=user.id,
email=user.email,
name=user.name,
avatar_url=user.avatar_url,
)
# Optional: store the membership ID for debugging or richer account UX.
persist_membership_binding(
user_id=user.id,
membership_id=result.membership_id,
)
Stoa registers the user for billing in your app.
Your app can continue billing that user with their user_id.
Start a payment flow
If you want an explicit pay or add-funds action in your product:
payment = stoa.create_payment(
user_id=user.id,
email=user.email,
return_url="https://app.example.com/billing/stoa-return",
)
Send the user to payment.hosted_url. The response also carries the payment ID.
Recover from StoaChargeRequiredError
If a metered call fails because the user is not yet chargeable in Stoa, start a
hosted payment flow explicitly with create_payment(...):
from fastapi.responses import RedirectResponse
from stoa import StoaChargeRequiredError
client = stoa.openai(user_id=user.id)
try:
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Hello!"}]
)
except StoaChargeRequiredError:
payment = stoa.create_payment(
user_id=user.id,
email=user.email,
return_url="https://app.example.com/billing/stoa-return",
)
raise RedirectResponse(payment.hosted_url, status_code=303)
Supported Providers
OpenAI
client = stoa.openai(user_id="user_123")
# Chat completions
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": "Explain quantum computing"}]
)
# Embeddings
embeddings = client.embeddings.create(
model="text-embedding-3-small",
input="Hello world"
)
Anthropic
client = stoa.anthropic(user_id="user_123")
response = client.messages.create(
model="claude-3-5-sonnet-20241022",
max_tokens=1024,
messages=[{"role": "user", "content": "Write a haiku about Python"}]
)
OpenRouter
Access 100+ models through a single API:
client = stoa.openrouter(user_id="user_123")
# Use any model available on OpenRouter
response = client.chat.completions.create(
model="meta-llama/llama-3.1-70b-instruct",
messages=[{"role": "user", "content": "Hello!"}]
)
ElevenLabs
client = stoa.elevenlabs(user_id="user_123")
audio = client.text_to_speech.convert(
voice_id="JBFqnCBsd6RMkjVDRZzb",
text="Hello, welcome to our application!"
)
Environment Variables
| Variable | Required | Default | Description |
|---|---|---|---|
STOA_API_KEY |
Yes | - | Your Stoa application API key |
STOA_REGISTRATION_SECRET |
No | - | Registration signing secret for onboarding users from your app |
Example .env file
# Required
STOA_API_KEY=stoa_app_xxx
STOA_REGISTRATION_SECRET=stoa_reg_xxx
# Optional - override API endpoint
STOA_BASE_URL=https://www.onstoa.com/api
Documentation
See docs.onstoa.com for full documentation.
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
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 onstoa-0.2.6.tar.gz.
File metadata
- Download URL: onstoa-0.2.6.tar.gz
- Upload date:
- Size: 128.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0b8cf55dbb4d207b5f86cb318415d8a917246f6197ed3cd304e8cf3585360e0b
|
|
| MD5 |
264df8c48853f97cf050d8c0d71ee29a
|
|
| BLAKE2b-256 |
ae862e9ee0df9dc76ea425ce8fd389c6739b5cc634b94a8039097b708ed7e36d
|
Provenance
The following attestation bundles were made for onstoa-0.2.6.tar.gz:
Publisher:
publish-sdk-python.yml on stoa-org/stoa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
onstoa-0.2.6.tar.gz -
Subject digest:
0b8cf55dbb4d207b5f86cb318415d8a917246f6197ed3cd304e8cf3585360e0b - Sigstore transparency entry: 1437674331
- Sigstore integration time:
-
Permalink:
stoa-org/stoa@b1bd9eb9e65d548c93c18c594ea0adb7f58f398c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/stoa-org
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk-python.yml@b1bd9eb9e65d548c93c18c594ea0adb7f58f398c -
Trigger Event:
workflow_run
-
Statement type:
File details
Details for the file onstoa-0.2.6-py3-none-any.whl.
File metadata
- Download URL: onstoa-0.2.6-py3-none-any.whl
- Upload date:
- Size: 26.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4d46dc76c7491caf52d7a71ef579b7c2a1f7809d30e08d956f843628dc1d0122
|
|
| MD5 |
aaefd80aea9a5838d1ee0d7a978c57df
|
|
| BLAKE2b-256 |
11275572b94c711c7685eb4f58e021f4cfe9d3008da1ec2c20418ccdc0c1f535
|
Provenance
The following attestation bundles were made for onstoa-0.2.6-py3-none-any.whl:
Publisher:
publish-sdk-python.yml on stoa-org/stoa
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
onstoa-0.2.6-py3-none-any.whl -
Subject digest:
4d46dc76c7491caf52d7a71ef579b7c2a1f7809d30e08d956f843628dc1d0122 - Sigstore transparency entry: 1437674357
- Sigstore integration time:
-
Permalink:
stoa-org/stoa@b1bd9eb9e65d548c93c18c594ea0adb7f58f398c -
Branch / Tag:
refs/heads/main - Owner: https://github.com/stoa-org
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish-sdk-python.yml@b1bd9eb9e65d548c93c18c594ea0adb7f58f398c -
Trigger Event:
workflow_run
-
Statement type: