Skip to main content

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 stoa import Stoa, InsufficientBalanceError

# Reads STOA_API_KEY and STOA_APP_ID from environment
stoa = Stoa()

# 1. Register or reuse the member from your backend
stoa.register_member(
    registration_secret=STOA_REGISTRATION_SECRET,
    user_id="user_123",
    email="ada@example.com",
)

# 2. Use your app's own 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 InsufficientBalanceError as e:
    print(f"Please top up: {e.topup_url}")

Typical flow:

  1. call stoa.register_member(...) at one reliable server-side onboarding point for the user
  2. keep using your own app user_id in SDK billing calls
  3. send the user to e.topup_url if they need funds

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.

User onboards via your app

From your backend, call the SDK once with your registration secret and the user's verified app identity:

from stoa import Stoa

stoa = Stoa(api_key=STOA_API_KEY, base_url=STOA_BASE_URL, app_id=STOA_APP_ID)

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 its own user_id.

Optional: open a hosted top-up page

If you want an explicit "Add funds" action in your product:

topup_url = stoa.get_topup_url(user_id=user.id)

This returns a hosted Stoa payment page for that app user.

User installs via Stoa marketplace

Marketplace installs use the install flow below.

Install callback

Add a callback endpoint that verifies the Stoa install token and activates the membership for your app user. Both flows should converge on the same stored membership binding in your app.

from stoa import Stoa

stoa = Stoa()


def stoa_callback(token: str):
    claims = stoa.verify_install_callback(token=token)

    user = find_or_create_user(
        email=claims["email"],
        name=claims["name"],
    )

    install = stoa.exchange_install_token(
        token=token,
        user_id=user.id,
    )

    persist_membership_binding(
        user_id=user.id,
        membership_id=install.membership_id,
    )
    return create_session_and_redirect(user)

The SDK fetches Stoa's public key for you and keeps the server-side activation step in place, so the secure flow does not become app boilerplate.

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_APP_ID No - Your Stoa application ID (required for member registration unless passed explicitly)
STOA_BASE_URL No https://api.onstoa.com Stoa API base URL (for self-hosted or testing)
STOA_REGISTRATION_SECRET No - Registration signing secret for onboarding users from your app

Example .env file

# Required
STOA_API_KEY=stoa_app_xxx
STOA_APP_ID=app_xxx
STOA_REGISTRATION_SECRET=stoa_reg_xxx

# Optional - override API endpoint
STOA_BASE_URL=https://api.onstoa.com

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

onstoa-0.2.1.tar.gz (120.1 kB view details)

Uploaded Source

Built Distribution

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

onstoa-0.2.1-py3-none-any.whl (27.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: onstoa-0.2.1.tar.gz
  • Upload date:
  • Size: 120.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for onstoa-0.2.1.tar.gz
Algorithm Hash digest
SHA256 8f347cdec33f04b7d81d65ef823cbe5a6d7e2076cd24fb5426d8ca0dcd4c71aa
MD5 ee1bb86b6899fdf5cdfc392cf91c06b4
BLAKE2b-256 12552a7d0b0ec8fe8347aa3b613baa98ce699617a14217414ff89f40bd4799f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for onstoa-0.2.1.tar.gz:

Publisher: publish-sdk-python.yml on stoa-org/stoa

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

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

File metadata

  • Download URL: onstoa-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 27.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for onstoa-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 551a5144e72ebff9ccf4535664504e5189d2ec8501a2515b283126930966bb29
MD5 464bf2d5789a37a1bc9675af7e83f8c2
BLAKE2b-256 428f7e9787ed75339b5d8a338b4f1aa34473a4f7ad749b9f495c8a8704c09bb8

See more details on using hashes here.

Provenance

The following attestation bundles were made for onstoa-0.2.1-py3-none-any.whl:

Publisher: publish-sdk-python.yml on stoa-org/stoa

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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