TypeScript SDK Reference
The @keystore/sdk package provides the Keystore class for routing API requests through the Keystore proxy. It works in Node.js, Deno, Bun, and any runtime with globalThis.fetch.
npm install @keystore/sdkKeystore class
Constructor
import { Keystore } from "@keystore/sdk";
const ks = new Keystore({
agentToken: "ks_a1b2c3d4e5f6...",
proxyHost: "proxy.keystore.sh", // optional, custom proxy hostname
proxyUrl: "https://proxy.keystore.sh", // optional, full proxy URL
});Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
agentToken | string | Yes | A Keystore agent token. Must start with ks_. |
proxyHost | string | No | Custom proxy hostname. Takes precedence over proxyUrl. |
proxyUrl | string | No | Full proxy base URL. Used if proxyHost is not set. |
Throws: Error if the token does not start with ks_.
Properties
| Property | Type | Description |
|---|---|---|
agentToken | string (readonly) | The agent token passed to the constructor. |
isIntercepting | boolean (getter) | Whether fetch interception is currently active. |
interceptAll()
Patches globalThis.fetch to intercept all outgoing requests to supported provider APIs and route them through the Keystore proxy. This is the simplest integration method — it works with any SDK that uses fetch internally.
ks.interceptAll(providers?, options?): KeystoreParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
providers | ProviderSlug[] | No | Only intercept these providers. If omitted, all supported providers are intercepted. |
options.includeS3 | boolean | No | Include S3 interception. Disabled by default because SigV4 signing breaks on URL rewrite. |
Returns: this (for method chaining).
Supported provider slugs: "openai", "anthropic", "neon", "vercel", "resend", "s3"
Example — Intercept all providers:
import { Keystore } from "@keystore/sdk";
import OpenAI from "openai";
import Anthropic from "@anthropic-ai/sdk";
const ks = new Keystore({ agentToken: "ks_..." });
ks.interceptAll();
// Both clients are automatically proxied
const openai = new OpenAI({ apiKey: "unused" });
const anthropic = new Anthropic({ apiKey: "unused" });
const chat = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Hello" }],
});
const message = await anthropic.messages.create({
model: "claude-sonnet-4-20250514",
max_tokens: 1024,
messages: [{ role: "user", content: "Hello" }],
});
ks.restore();Example — Intercept specific providers:
ks.interceptAll(["openai", "anthropic"]);
// Only OpenAI and Anthropic requests are proxied
// Requests to other APIs pass through unmodifiedrestore()
Restores the original globalThis.fetch, undoing the patch applied by interceptAll(). Safe to call even if interception is not active.
ks.restore(): voidExample:
ks.interceptAll();
// ... do work ...
ks.restore();
// fetch is back to normalsetupEnv()
Sets environment variables to point provider SDKs at the Keystore proxy. Useful for frameworks or tools that read standard environment variables like OPENAI_BASE_URL.
ks.setupEnv(providers: SupportedProvider[]): voidParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
providers | SupportedProvider[] | Yes | Which providers to configure. |
Environment variables set per provider:
| Provider | Variables set |
|---|---|
"openai" | OPENAI_BASE_URL, OPENAI_API_KEY |
"anthropic" | ANTHROPIC_BASE_URL, ANTHROPIC_API_KEY |
"neon" | DATABASE_URL |
"vercel" | VERCEL_API_URL, VERCEL_TOKEN |
"resend" | RESEND_BASE_URL, RESEND_API_KEY |
"s3" | AWS_ENDPOINT_URL_S3 |
Example:
const ks = new Keystore({ agentToken: "ks_..." });
ks.setupEnv(["openai", "anthropic"]);
// process.env.OPENAI_BASE_URL is now set to the proxy URL
// process.env.OPENAI_API_KEY is now set to the agent token
// Any SDK that reads these env vars will go through the proxygetProxyUrl()
Returns the proxy URL for a specific provider. Useful when you need to configure a client manually.
ks.getProxyUrl(provider: SupportedProvider): stringParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
provider | SupportedProvider | Yes | The provider slug. |
Returns: The full proxy URL, e.g. https://proxy.keystore.sh/v1/openai.
Example:
const url = ks.getProxyUrl("openai");
// "https://proxy.keystore.sh/v1/openai"
const openai = new OpenAI({
baseURL: url,
apiKey: ks.agentToken,
});wrap()
Auto-detects the SDK client type and rewrites its base URL to the Keystore proxy. Supports OpenAI, Anthropic, Resend, and S3 clients.
ks.wrap<T>(client: T): TParameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
client | T | Yes | An SDK client instance. |
Returns: The same client instance, mutated to point at the proxy.
Throws: Error if the client type cannot be detected. Use a provider-specific wrapper instead.
Example:
import { Keystore } from "@keystore/sdk";
import OpenAI from "openai";
import Anthropic from "@anthropic-ai/sdk";
const ks = new Keystore({ agentToken: "ks_..." });
const openai = ks.wrap(new OpenAI({ apiKey: "unused" }));
const anthropic = ks.wrap(new Anthropic({ apiKey: "unused" }));Provider-specific wrappers
For cases where wrap() cannot auto-detect the client, or when you want explicit imports, use the provider-specific wrappers. Each is available as a deep import.
wrapOpenAI
import { wrapOpenAI } from "@keystore/sdk/wrap/openai";
const openai = wrapOpenAI(new OpenAI({ apiKey: "unused" }), ks);Rewrites client.baseURL to the proxy and sets client.apiKey to the agent token.
wrapAnthropic
import { wrapAnthropic } from "@keystore/sdk/wrap/anthropic";
const anthropic = wrapAnthropic(new Anthropic({ apiKey: "unused" }), ks);Rewrites client.baseURL to the proxy and sets client.apiKey to the agent token.
wrapNeon
import { wrapNeon } from "@keystore/sdk/wrap/neon";
import { neon } from "@neondatabase/serverless";
const sql = wrapNeon(neon, ks);
const result = await sql`SELECT * FROM users`;Wraps the Neon serverless driver function. The returned function routes queries through the proxy, which injects the real connection string.
wrapResend
import { wrapResend } from "@keystore/sdk/wrap/resend";
import { Resend } from "resend";
const resend = wrapResend(new Resend("unused"), ks);
await resend.emails.send({
from: "hello@example.com",
to: "user@example.com",
subject: "Hello",
text: "Sent through Keystore",
});wrapVercel
import { wrapVercel } from "@keystore/sdk/wrap/vercel";Wraps a Vercel API client to route through the proxy.
wrapS3
import { wrapS3 } from "@keystore/sdk/wrap/s3";
import { S3Client } from "@aws-sdk/client-s3";
const s3 = wrapS3(new S3Client({ region: "us-east-1" }), ks);Wraps an AWS S3 client to route through the proxy.
Types
KeystoreConfig
interface KeystoreConfig {
agentToken: string;
proxyUrl?: string;
proxyHost?: string;
}SupportedProvider
type SupportedProvider =
| "openai"
| "anthropic"
| "neon"
| "vercel"
| "resend"
| "s3"
| (string & {}); // extensible for custom providersInterceptHandle
Returned internally by interceptAll(). You do not need to use this directly — call ks.restore() instead.
interface InterceptHandle {
restore(): void;
isActive(): boolean;
}Full example
import { Keystore } from "@keystore/sdk";
import OpenAI from "openai";
async function main() {
const ks = new Keystore({
agentToken: process.env.KEYSTORE_AGENT_TOKEN!,
});
// Option 1: Global interception
ks.interceptAll(["openai"]);
const openai = new OpenAI({ apiKey: "unused" });
// Option 2: Explicit wrapping (pick one, not both)
// const openai = ks.wrap(new OpenAI({ apiKey: "unused" }));
try {
const response = await openai.chat.completions.create({
model: "gpt-4o",
messages: [{ role: "user", content: "Summarize Keystore in one sentence." }],
});
console.log(response.choices[0].message.content);
} finally {
ks.restore();
}
}
main();Next steps
- Quickstart — Get running in 5 minutes
- How the Vault Works — Understand what happens behind the proxy
- Agent Tokens — Token format, scoping, and best practices