SDK
npm install @assistant-billing/sdkThree clients: GatewayClient for AI requests, BillingClient for workspace billing, AdminBillingClient for operator-level customer management.
GatewayClient
Proxy AI requests through the gateway. One request shape reaches every provider you have configured.
import { GatewayClient } from "@assistant-billing/sdk"
const gateway = new GatewayClient({
apiKey: "sk_ab_live_xyz789",
baseURL: "https://gateway.assistant-billing.dev",
})Constructor Options
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | ASSISTANT_BILLING_GATEWAY_API_KEY env | Gateway API key |
baseURL | string? | https://gateway.assistant-billing.dev | Gateway URL |
appTitle | string? | — | App name (X-Title header) |
appUrl | string? | — | App URL (HTTP-Referer header) |
defaultHeaders | Record<string, string>? | — | Extra headers |
timeout | number? | 60000 | Timeout in ms |
Chat Completions
// Non-streaming
const response = await gateway.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello!" }],
})
console.log(response.choices[0].message.content)
// Streaming
const stream = await gateway.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello!" }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "")
}Embeddings
const result = await gateway.embeddings.create({
model: "text-embedding-3-small",
input: "The quick brown fox",
dimensions: 256,
})List Models
const models = await gateway.models.list()
// → [{ id: "gpt-4o", object: "model", created: 1715367049, owned_by: "openai" }, ...]Feedback and Scores
// Single numeric feedback
await gateway.feedback("rl_a1b2c3d4e5f6", 5, { session: "abc" })
// Multiple named scores
await gateway.scores("rl_a1b2c3d4e5f6", {
quality: 5,
relevance: 3,
thumbs_up: true,
})Context Methods
Return a new GatewayClient instance with the context applied. Chainable.
const customGateway = gateway
.withMetadata({ session: "abc" }) // attach metadata to request log
.withUser("user_456") // set X-AB-User-Id header
.withProvider("anthropic") // prefer a specific provider
.withNoCache() // bypass cacheProvider Preferences
Pass provider in the request body for per-request routing control.
await gateway.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello!" }],
provider: {
order: ["openai", "azure"],
allow_fallbacks: true,
},
})| Field | Type | Description |
|---|---|---|
order | string[] | Ordered list of provider slugs to try |
only | string[] | Only allow these providers |
ignore | string[] | Skip these providers |
allow_fallbacks | boolean | Allow fallback to other providers (default: true) |
BillingClient
Manage workspace billing from your backend. Supports both platform key auth (server-side) and session token auth (client-side).
import { BillingClient } from "@assistant-billing/sdk"
// Server-side: platform key auth
const billing = new BillingClient({
platformKey: "sk_pj_live_abc123",
workspaceId: "ws_team_123",
userId: "user_456",
})
// Client-side: session token auth
const billing = new BillingClient({
getToken: () => fetchSessionToken(),
})Constructor Options
| Option | Type | Default | Description |
|---|---|---|---|
platformKey | string? | ASSISTANT_BILLING_PLATFORM_API_KEY env | Platform key (sk_pj_*) |
workspaceId | string? | — | Customer workspace ID |
userId | string? | — | User performing the action |
getToken | () => Promise<string>? | — | Session token callback (client-side) |
baseURL | string? | https://api.assistant-billing.dev/v1/platform | API URL |
timeout | number? | 30000 | Timeout in ms |
Sessions
const { token, expires_at } = await billing.sessions.create({
expiresIn: 3600, // optional, seconds (default: 1 hour)
})
// → { token: "sess_eyJhbG...", expires_at: "2026-03-15T00:00:00Z" }Wallet
const balance = await billing.wallet.getBalance()
// → { currency: "USD", amount: "100.00" }
const transactions = await billing.wallet.getTransactions({ limit: 20, offset: 0 })
// → { data: [{ type: "credit", amount_usd: "50.00", ... }] }Checkout
const checkout = await billing.checkout.create({
amount: 50,
successUrl: "https://yourapp.com/billing?status=success",
cancelUrl: "https://yourapp.com/billing?status=cancelled",
})
// → { url: "https://checkout.stripe.com/...", base_amount: "50.00",
// platform_fee: "2.50", markup: "5.00", total_amount: "57.50" }API Keys
const keys = await billing.apiKeys.list()
// → [{ id: "key_0...", name: "default", suffix: "x1y2z3", lastAccessedAt: "..." }]
const { id, key } = await billing.apiKeys.create({ name: "production" })
// → { id: "key_0...", key: "sk_ab_gw01_0a1b2c3d..." } ← shown once only
await billing.apiKeys.revoke("key_0...")
// → { success: true }Temporary Keys
Short-lived keys with permissions, rate limits, and budgets.
const { key, id, expires_at } = await billing.tempKeys.create({
name: "contributor-key",
ttl: 3600, // 1 hour (or use expires_at)
permissions: { models: ["gpt-4o"] },
rate_limit_rpm: 30,
rate_limit_tpm: 100000,
monthly_budget_usd: 5.0,
})
// → { key: "temp_ab_gw01_...", id: "ak_0...", expires_at: "2026-03-14T01:00:00Z" }
const keys = await billing.tempKeys.list()
await billing.tempKeys.revoke("ak_0...")Provider Keys (BYOK)
const providers = await billing.providerKeys.list()
// → [{ providerId: "openai", name: "OpenAI", hasKey: true, env: ["OPENAI_API_KEY"] }]
await billing.providerKeys.set("openai", { OPENAI_API_KEY: "sk-proj-..." })
// → { success: true }
const result = await billing.providerKeys.test("openai")
// → { valid: true } or { valid: false, error: "Invalid API key" }
await billing.providerKeys.remove("openai")
// → { success: true }Analytics
const overview = await billing.analytics.getOverview({
from: "2026-03-01",
to: "2026-03-14",
})
// → { total_requests: 1500, total_cost: "42.50", avg_latency: 850, ... }
const timeseries = await billing.analytics.getTimeseries({
from: "2026-03-01",
to: "2026-03-14",
})
// → [{ date: "2026-03-01", request_count: 120, total_cost: "3.50", ... }]Cache
const stats = await billing.cache.getStats({
from: "2026-03-01",
to: "2026-03-14",
})
// → { total_requests: 1500, cache_hits: 300, cache_misses: 1200, hit_rate: 0.2 }Project Info
const info = await billing.project.getInfo()
// → { name: "My Project", slug: "my-app", gateway_url: "https://gateway.assistant-billing.dev", gateway_custom_domain: null }Models
const models = await billing.models.list()
// → [{ id: "gpt-4o", object: "model", created: 1715367049, owned_by: "openai" }]AdminBillingClient
Operator-level customer management. Platform key only, no workspace scope.
import { AdminBillingClient } from "@assistant-billing/sdk"
const admin = new AdminBillingClient({
platformKey: "sk_pj_live_abc123",
})Constructor Options
| Option | Type | Default | Description |
|---|---|---|---|
platformKey | string? | ASSISTANT_BILLING_PLATFORM_API_KEY env | Platform key |
baseURL | string? | https://api.assistant-billing.dev/v1/platform | API URL |
timeout | number? | 30000 | Timeout in ms |
Customers
const { data } = await admin.customers.list({ limit: 50, offset: 0 })
// → { data: [{ workspace_id: "ws_team_123", balance_usd: "100.00", ... }] }
const balance = await admin.customers.getBalance("ws_team_123")
// → { workspace_id: "ws_team_123", balance: "100.00", sufficient: true }
const transactions = await admin.customers.getTransactions("ws_team_123", { limit: 20 })
// → { data: [{ type: "debit", amount_usd: "0.003", ... }] }
const usage = await admin.customers.getUsage("ws_team_123", {
from: "2026-03-01",
to: "2026-03-14",
})
// → { total_requests: 500, total_cost: "12.50", total_input_tokens: "150000", total_output_tokens: "80000" }Error Handling
The SDK throws typed errors for gateway requests.
import {
GatewayError,
GatewayAuthError,
GatewayRateLimitError,
} from "@assistant-billing/sdk"
try {
await gateway.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello!" }],
})
} catch (err) {
if (err instanceof GatewayRateLimitError) {
// 429 — retry after the specified delay
console.log(`Rate limited, retry in ${err.retryAfterMs}ms`)
} else if (err instanceof GatewayAuthError) {
// 401 — invalid or expired API key
console.log("Invalid API key")
} else if (err instanceof GatewayError) {
// All other gateway errors
console.log(`Error ${err.status}: ${err.message}`)
console.log(`Request ID: ${err.requestId}`)
}
}| Error Class | Status | Properties |
|---|---|---|
GatewayError | any | message, status, code?, requestId? |
GatewayAuthError | 401 | message, requestId? |
GatewayRateLimitError | 429 | message, requestId?, retryAfterMs? |