Package Exports
- @onstoa/sdk
Readme
Stoa TypeScript SDK
Business telemetry and payments for AI products.
Stoa instruments native AI provider clients, attaches your application's
userId, and helps you understand which users, features, and product areas are
driving AI usage, cost, and outcomes.
Installation
npm install @onstoa/sdkQuick Start
import OpenAI from "openai";
import { Stoa } from "@onstoa/sdk";
const stoa = new Stoa();
// Idempotently create or update the user profile in Stoa.
await stoa.identify({
userId: user.id,
metadata: { plan: "pro" },
});
// Build the native provider client in your app, then wrap it with Stoa.
const openai = stoa.openai(new OpenAI({ timeout: 30_000 }), {
userId: user.id,
});
const generateSummary = stoa.context(
{ feature: "summary_export", product: "docs" },
async (document: string) => {
const response = await openai.responses.create({
model: "gpt-4.1-mini",
input: `Summarize this document:\n\n${document}`,
});
await stoa.track("summary_export.completed", {
userId: user.id,
metadata: { format: "pdf" },
});
return response;
}
);Identify Users
Call identify when a user signs up, logs in, or when you want to sync stable
user metadata.
await stoa.identify({
userId: "user_123",
metadata: {
plan: "enterprise",
workspaceId: "ws_456",
},
});identify is idempotent. It creates the user profile if it does not exist and
updates metadata if it does. It does not set active identity; provider
instrumentation and custom events still require an explicit userId.
Instrument AI Providers
Construct provider clients exactly as you would without Stoa, then pass them to Stoa.
const openai = stoa.openai(new OpenAI({ apiKey: "sk-...", timeout: 30_000 }), {
userId: user.id,
});Every provider call made through the returned client is attributed to that
userId.
OpenAI
const openai = stoa.openai(new OpenAI(), { userId: user.id });
const response = await openai.responses.create({
model: "gpt-4.1-mini",
input: "Write a release note",
});Anthropic
import Anthropic from "@anthropic-ai/sdk";
const anthropic = stoa.anthropic(new Anthropic(), { userId: user.id });
const message = await anthropic.messages.create({
model: "claude-sonnet-4-5",
max_tokens: 1024,
messages: [{ role: "user", content: "Write a release note" }],
});ElevenLabs
import { ElevenLabsClient } from "@elevenlabs/elevenlabs-js";
const elevenlabs = stoa.elevenlabs(new ElevenLabsClient(), {
userId: user.id,
});
const audio = await elevenlabs.textToSpeech.convert(
"JBFqnCBsd6RMkjVDRZzb",
{
modelId: "eleven_multilingual_v2",
text: "Welcome back",
}
);OpenRouter
OpenRouter uses the OpenAI SDK with an OpenRouter base URL.
const openrouter = stoa.openrouter(
new OpenAI({
apiKey: process.env.OPENROUTER_API_KEY,
baseURL: "https://openrouter.ai/api/v1",
}),
{ userId: user.id }
);Add Context
Use withContext to attach feature, product, workflow, experiment, or route
metadata to work done inside a scope.
await stoa.withContext({ feature: "chat", product: "assistant" }, async () => {
await openai.responses.create(...);
});context is available when you want a reusable function wrapper.
const generateSummary = stoa.context(
{ feature: "summary_export", product: "docs" },
async (document: string) => {
return await openai.responses.create({
model: "gpt-4.1-mini",
input: document,
});
}
);Nested context merges automatically. Inner values override outer values.
Track Custom Events
App-defined business events.
await stoa.track("report.exported", {
userId: user.id,
metadata: {
format: "csv",
rows: 1200,
},
});Tracked events inherit active context metadata.
Create Payments
Use createPayment when you want to start a Stripe payment flow for a user.
const payment = await stoa.createPayment({
userId: user.id,
email: user.email,
returnUrl: "https://app.example.com/billing/return",
});
redirectUserTo(payment.checkoutUrl);Billing Webhooks
Stoa's SDK does not block AI provider calls by default.
Use webhooks to react to billing events such as:
balance.low
balance.depleted
payment.succeeded
payment.failed
subscription.updatedYour app decides what to do when those events arrive, such as notifying the user, prompting for payment, or changing access.
Environment Variables
STOA_API_KEY=...
STOA_BASE_URL=https://www.onstoa.com/api