Skip to Content
API ReferenceTypeScript SDK Reference

TypeScript SDK Reference

The @curate-me/sdk package provides two main classes:

  1. CurateGateway — configures OpenAI and Anthropic SDK clients to route through the gateway
  2. GatewayAdmin — manages policies, secrets, API keys, and queries usage

The SDK has zero runtime dependencies — it uses the global fetch() API (Node 18+) for admin requests and only builds configuration objects for provider SDKs.

Installation

npm install @curate-me/sdk

Optional peer dependencies for provider SDKs:

npm install @curate-me/sdk openai # For OpenAI integration npm install @curate-me/sdk @anthropic-ai/sdk # For Anthropic integration

CurateGateway

Constructor

import { CurateGateway } from '@curate-me/sdk'; const gw = new CurateGateway( 'cm_sk_your_key', 'https://api.curate-me.ai', // default { timeout: 60, // seconds, default retry: { maxRetries: 2 }, // optional }, );
ParameterTypeDefaultDescription
apiKeystringrequiredYour Curate-Me API key (cm_sk_...)
gatewayUrlstringhttps://api.curate-me.aiBase URL of the gateway
options.timeoutnumber60Request timeout in seconds
options.retryGatewayRetryPolicy2 retries, exponential backoffRetry policy

openaiConfig()

Returns a configuration object for the OpenAI SDK constructor:

import OpenAI from 'openai'; const config = gw.openaiConfig('sk-your-openai-key'); const client = new OpenAI(config); const response = await client.chat.completions.create({ model: 'gpt-4o', messages: [{ role: 'user', content: 'Hello!' }], }); console.log(response.choices[0].message.content);

Use without a provider key to rely on a stored secret:

const client = new OpenAI(gw.openaiConfig());

openai()

Convenience method that dynamically imports and returns an OpenAI client:

const client = await gw.openai('sk-your-openai-key'); // Or use a stored secret const client = await gw.openai(); const response = await client.chat.completions.create({ model: 'gpt-4o', messages: [{ role: 'user', content: 'Hello!' }], });

Throws an error if the openai package is not installed.

anthropicConfig()

Returns a configuration object for the Anthropic SDK constructor:

import Anthropic from '@anthropic-ai/sdk'; const config = gw.anthropicConfig('sk-ant-your-key'); const client = new Anthropic(config); const message = await client.messages.create({ model: 'claude-sonnet-4-20250514', max_tokens: 1024, messages: [{ role: 'user', content: 'Hello, Claude!' }], }); console.log(message.content[0].text);

anthropic()

Convenience method that dynamically imports and returns an Anthropic client:

const client = await gw.anthropic('sk-ant-your-key'); const message = await client.messages.create({ model: 'claude-sonnet-4-20250514', max_tokens: 1024, messages: [{ role: 'user', content: 'Hello!' }], });

Throws an error if the @anthropic-ai/sdk package is not installed.

admin()

Returns a GatewayAdmin client for managing the gateway:

const admin = gw.admin();

GatewayAdmin

The admin client uses the global fetch() API with built-in retry and typed error handling.

Constructor

import { GatewayAdmin } from '@curate-me/sdk'; const admin = new GatewayAdmin( 'cm_sk_your_key', 'https://api.curate-me.ai', { timeout: 30, retry: { maxRetries: 2 } }, );

Or create it from a CurateGateway instance:

const admin = gw.admin();

Policies

getPolicies(orgId?)

const policies = await admin.getPolicies();

getPolicy(orgId)

const policy = await admin.getPolicy('org_abc123');

setPolicy(orgId, policy)

Replace the governance policy for an org (PUT semantics):

await admin.setPolicy('org_abc123', { rpm_limit: 100, daily_budget: 50.0, monthly_budget: 1000.0, max_cost_per_request: 2.0, pii_scan_enabled: true, pii_action: 'block', allowed_models: ['gpt-4o-mini', 'claude-haiku-3-5-20241022'], hitl_cost_threshold: 10.0, });

updatePolicy(policy)

Create or update a policy (POST semantics):

await admin.updatePolicy({ org_id: 'org_abc123', daily_budget: 100.0, });

deletePolicy(orgId)

Delete a policy, reverting to tier defaults:

await admin.deletePolicy('org_abc123');

simulatePolicy(draftPolicy, replayHours)

Simulate a draft policy against recent traffic:

const result = await admin.simulatePolicy( { rpm_limit: 30, daily_budget: 10.0 }, 24, // replay last 24 hours );

Usage and Costs

getUsage(options?)

const usage = await admin.getUsage({ days: 7, limit: 100 });
OptionTypeDefaultDescription
daysnumber7Look-back period
limitnumber100Max records
orgIdstring-Org filter

getDailyCosts(options?)

const costs = await admin.getDailyCosts({ days: 30 });

getUsageRecord(requestId)

const record = await admin.getUsageRecord('gw_a1b2c3d4');

Latency

getLatencyStats()

const stats = await admin.getLatencyStats(); // stats.providers.openai.p50_ms, p95_ms, p99_ms

API Keys

listApiKeys()

const keys = await admin.listApiKeys(); // keys.keys = [{key_id, name, created_at, ...}]

createApiKey(name, scopes?)

const newKey = await admin.createApiKey('staging-api', ['proxy']); // newKey.key = "cm_sk_abc..." (plaintext, shown only once)

Secrets (stored provider keys)

storeSecret(provider, key, label?)

await admin.storeSecret('openai', 'sk-your-openai-key', 'Production OpenAI');

listSecrets(orgId?)

const secrets = await admin.listSecrets();

rotateSecret(provider, newKey)

await admin.rotateSecret('openai', 'sk-new-openai-key');

revokeSecret(provider)

await admin.revokeSecret('openai');

Models

listModels()

const models = await admin.listModels(); // models.data = [{id: "gpt-4o", object: "model", ...}, ...]

Provider Targets

getProviderTargets(orgId?)

const targets = await admin.getProviderTargets();

triggerDiscovery(providerId, apiKey?)

const result = await admin.triggerDiscovery('openai'); // result.models = ["gpt-4o", "gpt-4o-mini", ...]

Discovery

getDiscoveryCatalog(options?)

const catalog = await admin.getDiscoveryCatalog({ limit: 50 });

getDiscoveryHistory(options?)

const history = await admin.getDiscoveryHistory({ limit: 10 });

HITL (Human-in-the-Loop)

waitForApproval(approvalId, timeout?)

Poll an approval until it is resolved or times out:

const result = await admin.waitForApproval('apr_abc123', 300); // result.status = "approved" | "rejected" | "expired"

Throws Error if not resolved within the timeout.

Policy GitOps

validatePolicyBundle(bundle, strict?)

const result = await admin.validatePolicyBundle(myBundle, true);

exportPolicyBundle(orgId, version?)

const bundle = await admin.exportPolicyBundle('org_abc123');

importPolicyBundle(orgId, bundle, options?)

const result = await admin.importPolicyBundle('org_abc123', myBundle, { dryRun: true, mergeStrategy: 'replace', });

diffPolicy(orgId, draftPolicy)

const diff = await admin.diffPolicy('org_abc123', { rpm_limit: 30 });

listPolicyVersions(orgId, limit?)

const versions = await admin.listPolicyVersions('org_abc123', 10);

rollbackPolicy(orgId, targetVersion, reason?)

await admin.rollbackPolicy('org_abc123', 'v3', 'Reverted budget change');

GatewayRetryPolicy

Configure retry behavior:

const gw = new CurateGateway('cm_sk_your_key', 'https://api.curate-me.ai', { retry: { maxRetries: 3, // default: 2 initialDelay: 1.0, // seconds, default: 0.5 maxDelay: 16.0, // seconds, default: 8.0 backoffFactor: 2.0, // default: 2.0 retryableStatusCodes: [429, 500, 502, 503, 504], // defaults }, });

Error handling

The SDK throws typed errors for gateway failures:

import { GatewayError, GatewayAuthenticationError, GatewayGovernanceError, GatewayRateLimitError, } from '@curate-me/sdk'; try { const usage = await admin.getUsage(); } catch (err) { if (err instanceof GatewayAuthenticationError) { console.error(`Bad API key: ${err.message}`); console.error(`Request ID: ${err.requestId}`); } else if (err instanceof GatewayGovernanceError) { console.error(`Blocked by policy: ${err.message}`); } else if (err instanceof GatewayRateLimitError) { console.error(`Rate limited. Retry after: ${err.retryAfter}s`); } else if (err instanceof GatewayError) { console.error(`Gateway error [${err.statusCode}]: ${err.message}`); } }
Error ClassStatusWhen
GatewayAuthenticationError401Invalid or missing API key
GatewayGovernanceError403Blocked by governance policy
GatewayRateLimitError429Rate limit exceeded (includes retryAfter)
GatewayErroranyBase class for all gateway errors

All error classes include:

  • statusCode — HTTP status code
  • requestId — The X-Request-ID from the gateway
  • body — Raw response body text

Complete example

import { CurateGateway } from '@curate-me/sdk'; async function main() { const gw = new CurateGateway('cm_sk_your_key'); const admin = gw.admin(); // 1. Store your OpenAI key (one-time setup) await admin.storeSecret('openai', 'sk-your-openai-key', 'Production'); // 2. Set governance policy await admin.setPolicy('org_abc123', { rpm_limit: 100, daily_budget: 50.0, max_cost_per_request: 2.0, pii_scan_enabled: true, allowed_models: ['gpt-4o', 'gpt-4o-mini'], hitl_cost_threshold: 10.0, }); // 3. Make governed requests (no provider key needed) const client = await gw.openai(); const response = await client.chat.completions.create({ model: 'gpt-4o', messages: [{ role: 'user', content: 'Summarize this document...' }], }); console.log(response.choices[0].message.content); // 4. Check costs const costs = await admin.getDailyCosts({ days: 7 }); for (const day of (costs as any).days || []) { console.log(`${day.date}: $${day.total_cost.toFixed(2)}`); } } main().catch(console.error);

Next steps