Team working on a SaaS product
SaaS teams shipping AI to their own users

Embed paid AI features in your SaaS

  • No subscription, pay only for inference
  • Use with any model
  • Backend is optional
  • Per-customer limits and analytics
  • Hide system prompts
  • Tool use and structured output included
Flow demo
sdk + webhook
Mint browser session
publishable key
import { createApiKeySdk } from "keystash-sdk";

const sdk = createApiKeySdk({
  baseUrl: "https://api.keystash.dev"
});

await sdk.account.connect(import.meta.env.VITE_KEYSTASH_PUBLISHABLE_KEYUse a publishable app key here, not an admin key. Scope it to one space, one origin, and specific feature ids.);

const session = await sdk.runtime.sessions.create({
  spaceId: "acme-prod",
  endUserId: auth.user.idUse the same stable SaaS user id in frontend runtime calls and in Stripe metadata or client_reference_id. No separate create-user step is required.,
  operationIds: ["op_live_abc123"Feature id returned by the control plane. Scope the publishable key to the same id.],
  ttlMinutes: 15Keystash returns a short-lived runtime token instead of provider credentials.
});

await sdk.runtime.connect(session.tokenResult: kst_rt_... scoped to acme-prod, one user id, one feature id, and a 15 minute TTL.);
  • Use your own SaaS auth user id
  • Publishable keys mint sessions only for allowed origins and feature ids
  • No separate create-user call is required
Define
  • One feature per product action
  • Provider key stays server-side
  • Prompt stays hidden
Run
  • Mint runtime sessions per end user
  • Invoke features from browser or app shell
  • Keep models and prompts scoped
Meter
  • Track calls and token usage by space
  • Track usage by feature
  • Debit the space balance as users run features

SDK first

  • `sdk.spaces.operations.create(...)`
  • `sdk.runtime.sessions.create(...)`
  • `sdk.runtime.invoke(...)`
  • `sdk.runtime.usage(...)`
Backend is optional
Ship a client-side app with one app key. KeyStash mints short-lived runtime sessions for each customer.
Hidden system prompts
Feature prompts live in KeyStash. The browser only sends input and receives output.
Stripe webhook flow
If you already run your own checkout flow, Stripe can still call Keystash directly to increase one end user's remaining spend.
Create feature
Admin
const feature = await sdk.spaces.operations.create("acme-prod", {
  title: "Summarize ticket",
  slug: "summarize_ticket",
  model: "openai/gpt-5.4-mini",
  systemPrompt: "You summarize support tickets for internal agents.",
  userTemplate: "Ticket:\n{{ticket}}\n\nReturn a concise summary.",
  monthlyInvocationLimit: 10000,
  allowedOrigins: ["https://app.acme.com"]
});
Dashboard preview
summarize_ticket
openai/gpt-5.4-mini
active
Calls
12,842
Tokens
3.2M
Runtime sessions
TTL 15 min
Origin lock app.acme.com
What ships now
  • Any-model routing
  • Client-side app flow
  • Per-customer limits
  • Per-customer analytics
  • Hidden system prompts
  • Tool use and structured output