Docs/SDK Reference/TypeScript SDK Reference

TypeScript SDK Reference

Complete API reference for the @keystore/sdk package — the Keystore class, fetch interception, client wrapping, and provider-specific helpers.


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.

bash
1
npm install @keystore/sdk

Keystore class

Constructor

typescript
1
2
3
4
5
6
7
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:

ParameterTypeRequiredDescription
agentTokenstringYesA Keystore agent token. Must start with ks_.
proxyHoststringNoCustom proxy hostname. Takes precedence over proxyUrl.
proxyUrlstringNoFull proxy base URL. Used if proxyHost is not set.

Throws: Error if the token does not start with ks_.

Properties

PropertyTypeDescription
agentTokenstring (readonly)The agent token passed to the constructor.
isInterceptingboolean (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.

typescript
1
ks.interceptAll(providers?, options?): Keystore

Parameters:

ParameterTypeRequiredDescription
providersProviderSlug[]NoOnly intercept these providers. If omitted, all supported providers are intercepted.
options.includeS3booleanNoInclude 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:

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
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:

typescript
1
2
3
ks.interceptAll(["openai", "anthropic"]);
// Only OpenAI and Anthropic requests are proxied
// Requests to other APIs pass through unmodified

restore()

Restores the original globalThis.fetch, undoing the patch applied by interceptAll(). Safe to call even if interception is not active.

typescript
1
ks.restore(): void

Example:

typescript
1
2
3
4
ks.interceptAll();
// ... do work ...
ks.restore();
// fetch is back to normal

setupEnv()

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.

typescript
1
ks.setupEnv(providers: SupportedProvider[]): void

Parameters:

ParameterTypeRequiredDescription
providersSupportedProvider[]YesWhich providers to configure.

Environment variables set per provider:

ProviderVariables 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:

typescript
1
2
3
4
5
6
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 proxy

getProxyUrl()

Returns the proxy URL for a specific provider. Useful when you need to configure a client manually.

typescript
1
ks.getProxyUrl(provider: SupportedProvider): string

Parameters:

ParameterTypeRequiredDescription
providerSupportedProviderYesThe provider slug.

Returns: The full proxy URL, e.g. https://proxy.keystore.sh/v1/openai.

Example:

typescript
1
2
3
4
5
6
7
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.

typescript
1
ks.wrap<T>(client: T): T

Parameters:

ParameterTypeRequiredDescription
clientTYesAn 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:

typescript
1
2
3
4
5
6
7
8
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

typescript
1
2
3
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

typescript
1
2
3
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

typescript
1
2
3
4
5
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

typescript
1
2
3
4
5
6
7
8
9
10
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

typescript
1
import { wrapVercel } from "@keystore/sdk/wrap/vercel";

Wraps a Vercel API client to route through the proxy.

wrapS3

typescript
1
2
3
4
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

typescript
1
2
3
4
5
interface KeystoreConfig {
  agentToken: string;
  proxyUrl?: string;
  proxyHost?: string;
}

SupportedProvider

typescript
1
2
3
4
5
6
7
8
type SupportedProvider =
  | "openai"
  | "anthropic"
  | "neon"
  | "vercel"
  | "resend"
  | "s3"
  | (string & {});  // extensible for custom providers

InterceptHandle

Returned internally by interceptAll(). You do not need to use this directly — call ks.restore() instead.

typescript
1
2
3
4
interface InterceptHandle {
  restore(): void;
  isActive(): boolean;
}

Full example

typescript
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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