JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 30
  • Score
    100M100P100Q89275F
  • License MIT

TypeScript SDK for Stoa usage-based billing

Package Exports

  • @onstoa/sdk

Readme

Stoa SDK

Usage-based billing SDK for AI applications. Wrap your AI provider calls to automatically meter usage and bill your users.

Installation

npm install @onstoa/sdk

Quick Start

import { InsufficientBalanceError, Stoa } from "@onstoa/sdk";

// Reads STOA_API_KEY and STOA_APP_ID from environment
const stoa = new Stoa();

// 1. Register or reuse the member from your backend
await stoa.registerMember({
  registrationSecret: process.env.STOA_REGISTRATION_SECRET!,
  userId: "user_123",
  email: "ada@example.com",
});

// 2. Use your app's own user ID for billing calls
const client = stoa.openai("user_123");

try {
  const response = await client.chat.completions.create({
    model: "gpt-4",
    messages: [{ role: "user", content: "Hello!" }],
  });
} catch (error) {
  if (error instanceof InsufficientBalanceError) {
    console.log(`Please top up: ${error.topupUrl}`);
  }
}

Typical flow:

  1. call stoa.registerMember(...) at one reliable server-side onboarding point for the user
  2. keep using your own app userId in SDK billing calls
  3. send the user to error.topupUrl 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:

import { Stoa } from "@onstoa/sdk";

const stoa = new Stoa({
  apiKey: process.env.STOA_API_KEY,
  baseUrl: process.env.STOA_BASE_URL,
  appId: process.env.STOA_APP_ID,
});

const result = await stoa.registerMember({
  registrationSecret: process.env.STOA_REGISTRATION_SECRET!,
  userId: user.id,
  email: user.email,
  name: user.name,
  avatarUrl: user.avatarUrl,
});

// Optional: store the membership ID for debugging or richer account UX.
await persistMembershipBinding({
  userId: user.id,
  membershipId: result.membershipId,
});

Stoa registers the user for billing in your app. Your app can continue billing that user with its own userId.

Optional: open a hosted top-up page

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

const topupUrl = await stoa.getTopupUrl(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.

import { Stoa } from "@onstoa/sdk";

const stoa = new Stoa();

async function stoaCallback(token: string) {
  const claims = await stoa.verifyInstallCallback(token);

  const user = await findOrCreateUser({
    email: claims.email,
    name: claims.name,
  });

  const install = await stoa.exchangeInstallToken(token, user.id);

  await persistMembershipBinding({
    userId: user.id,
    membershipId: install.membershipId,
  });

  return createSessionAndRedirect(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

const client = stoa.openai("user_123");

const response = await client.chat.completions.create({
  model: "gpt-4",
  messages: [{ role: "user", content: "Explain quantum computing" }],
});

const embeddings = await client.embeddings.create({
  model: "text-embedding-3-small",
  input: "Hello world",
});

Anthropic

const client = stoa.anthropic("user_123");

const response = await client.messages.create({
  model: "claude-3-5-sonnet-20241022",
  max_tokens: 1024,
  messages: [{ role: "user", content: "Write a haiku about TypeScript" }],
});

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

# 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.