TypeScript SDK
Install, authenticate, and use the @outcallerai/sdk package to call the OutCallerAI public API from Node.js and browser-based backends.
The @outcallerai/sdk package provides a typed, promise-based client for the
OutCallerAI public API. It supports ESM and CommonJS, runs on Node.js 20 and
22, and works in serverless environments.
Installation
npm install @outcallerai/sdkpnpm add @outcallerai/sdkyarn add @outcallerai/sdkbun add @outcallerai/sdkRequires Node.js 20+.
Package: @outcallerai/sdk on npm
Quick start
import {OutCallerAI} from "@outcallerai/sdk";
const client = new OutCallerAI({
apiKey: process.env.OUTCALLERAI_API_KEY!,
});
const workspace = await client.workspace.getWorkspace();
console.log(workspace.name);Configuration
| Option | Type | Default | Description |
|---|---|---|---|
apiKey | string | (required) | Workspace API key |
baseUrl | string | https://api.outcallerai.com | API origin |
timeoutMs | number | 30000 | Request timeout in milliseconds |
maxRetries | number | 2 | Maximum retry attempts for safe operations |
maxRetryElapsedMs | number | 15000 | Maximum total time spent retrying |
maxBackoffMs | number | 5000 | Maximum delay between retries |
fetch | function | globalThis.fetch | Custom fetch implementation |
onResponse | function | undefined | Callback for response metadata |
const client = new OutCallerAI({
apiKey: process.env.OUTCALLERAI_API_KEY!,
baseUrl: "https://api.outcallerai.com",
timeoutMs: 60_000,
maxRetries: 3,
onResponse: ({method, path, status, requestId, durationMs}) => {
console.log(`${method} ${path} -> ${status} (${durationMs}ms)`);
},
});Resources
The client maps one-to-one with the REST API.
| Resource | Methods |
|---|---|
workspace | getWorkspace, updateWorkspace |
usecases | listUsecases, getUsecase, createUsecase, updateUsecase, deleteUsecase |
agents | listAgents, getAgent, createAgent, updateAgent, deleteAgent |
leads | listLeads, getLead, createLead, updateLead, deleteLead |
calls | listCalls, getCall, createCall |
jobs | createCallExportJob, getJob, cancelJob |
Complete usage guide
Workspace
// Get workspace
const workspace = await client.workspace.getWorkspace();
console.log(workspace.id, workspace.name);
// Update workspace name
const updated = await client.workspace.updateWorkspace({
workspaceUpdateRequest: {name: "Acme Corp"},
});Usecases
// List usecases
const usecases = await client.usecases.listUsecases();
// Get usecase by ID
const usecase = await client.usecases.getUsecase({useCaseId: "uc_abc123"});
// Create usecase
const created = await client.usecases.createUsecase({
useCaseWriteRequest: {name: "Q4 Outreach", description: "Quarterly sales push"},
});
// Update usecase
const updated = await client.usecases.updateUsecase({
useCaseId: "uc_abc123",
useCaseWriteRequest: {name: "Updated Usecase"},
});
// Delete usecase
await client.usecases.deleteUsecase({useCaseId: "uc_abc123"});Agents
// List agents
const agents = await client.agents.listAgents({limit: 50});
// Get agent by ID
const agent = await client.agents.getAgent({agentId: "ag_abc123"});
// Create agent
const created = await client.agents.createAgent({
agentCreateRequest: {name: "Sales Agent", gender: "female"},
});
// Update agent
const updated = await client.agents.updateAgent({
agentId: "ag_abc123",
agentUpdateRequest: {name: "Updated Name", gender: "male"},
});
// Delete agent
await client.agents.deleteAgent({agentId: "ag_abc123"});Leads
// List leads for an agent
const leads = await client.leads.listLeads({
agentId: "ag_abc123",
limit: 50,
});
// Get lead by ID
const lead = await client.leads.getLead({agentId: "ag_abc123", leadId: "ld_xyz789"});
// Create lead
const newLeads = await client.leads.createLead({
agentId: "ag_abc123",
body: {
name: "Jane Doe",
email: "jane@example.com",
phone: "+911234567890",
description: "Interested in pricing",
},
});
// Update lead
const updatedLead = await client.leads.updateLead({
agentId: "ag_abc123",
leadId: "ld_xyz789",
leadUpdateRequest: {name: "Jane Smith"},
});
// Delete lead
await client.leads.deleteLead({agentId: "ag_abc123", leadId: "ld_xyz789"});Calls
// List calls for an agent
const calls = await client.calls.listCalls({agentId: "ag_abc123", limit: 50});
// Get call by ID
const call = await client.calls.getCall({agentId: "ag_abc123", callId: "cl_xyz789"});
// Create call (initiate outbound call to a lead)
const newCalls = await client.calls.createCall({
agentId: "ag_abc123",
callCreateRequest: {leadId: "ld_xyz789"},
});
console.log(newCalls[0].id, newCalls[0].status);
// Bulk call creation (initiate calls to multiple leads at once)
const bulkCalls = await client.calls.createCall({
agentId: "ag_abc123",
callCreateRequest: {leadIds: ["ld_xyz789", "ld_abc456", "ld_def012"]},
});
console.log(`Created ${bulkCalls.length} calls`);
bulkCalls.forEach((call) => console.log(call.id, call.status));Note: createCall accepts either leadId (single) or leadIds (bulk array). Provide one of the two — not both. Bulk creation deduplicates the leadIds array and returns an array of call objects.
Jobs
// Create call export job
const job = await client.jobs.createCallExportJob({
callExportJobRequest: {agentId: "ag_abc123", limit: 100},
idempotencyKey: crypto.randomUUID(),
});
// Get job status
const jobStatus = await client.jobs.getJob({jobHandle: job.handle});
// Cancel job
await client.jobs.cancelJob({jobHandle: job.handle});Pagination
Use the paginate helper to iterate over all records.
import {paginate} from "@outcallerai/sdk";
for await (const lead of paginate(
async (cursor) =>
client.leads.listLeads({
agentId: "ag_abc123",
cursor,
limit: 50,
}),
{maxPages: 1_000},
)) {
console.log(lead.id, lead.name);
}Idempotency
Supply an idempotencyKey to make create operations safe to retry.
const lead = await client.leads.createLead({
agentId: "ag_abc123",
body: {
name: "Jane",
email: "jane@example.com",
phone: "+911234567890",
description: "Interested in pricing",
},
idempotencyKey: crypto.randomUUID(),
});If the same key is reused with a different payload the request returns 409.
Cancellation
Pass an AbortSignal to cancel in-flight requests.
const controller = new AbortController();
setTimeout(() => controller.abort(), 5_000);
const agents = await client.agents.listAgents({}, {signal: controller.signal});Error handling
The SDK throws typed errors with category, status, requestId, code, and
retryable fields.
import {
AuthenticationError,
OutCallerAIError,
RateLimitError,
} from "@outcallerai/sdk";
try {
const agent = await client.agents.createAgent({ ... });
} catch (error) {
if (error instanceof AuthenticationError) {
// The API key is invalid or has been revoked
} else if (error instanceof RateLimitError) {
// Back off - the SDK already retried when safe
} else if (error instanceof OutCallerAIError) {
console.error(error.code, error.requestId, error.category);
}
throw error;
}| Error type | HTTP status | Retryable |
|---|---|---|
AuthenticationError | 401 | No |
PermissionError | 403 | No |
NotFoundError | 404 | No |
RequestValidationError | 400/422 | No |
ConflictError | 409 | No |
RateLimitError | 429 | Yes |
TimeoutError | 408/0 | Yes |
ServerError | 5xx | Yes |
NetworkError | 0 | Yes |
Response metadata
Track request details with the onResponse callback.
const client = new OutCallerAI({
apiKey: process.env.OUTCALLERAI_API_KEY!,
onResponse: ({method, path, status, requestId, durationMs, rateLimit}) => {
console.log(`${method} ${path} -> ${status} (${durationMs}ms)`);
console.log("Rate limit:", rateLimit.remaining, "/", rateLimit.limit);
},
});How is this guide?
