Skip to main content
The CallingBox TypeScript SDK wraps the same public /v1 API you see in the API Reference, but gives you a typed, async-native interface for managing numbers, creating calls, polling for results, and handling errors.

Install

npm install callingbox

Authenticate

The SDK reads your API key from CALLINGBOX_API_KEY by default:
export CALLINGBOX_API_KEY=sk_live_...
Then create a client instance:
import { Callingbox } from "callingbox";

const client = new Callingbox();
const numbers = await client.numbers.list();
If you prefer to pass your key explicitly:
import { Callingbox } from "callingbox";

const client = new Callingbox({ apiKey: "sk_live_..." });
const numbers = await client.numbers.list();

Custom API base URL

The SDK uses https://api.callingbox.io by default. If your organization uses a private CallingBox deployment, set the base URL via the environment and optional client options:
export CALLINGBOX_BASE_URL=https://your-deployment.example
export CALLINGBOX_API_KEY=sk_live_...
import { Callingbox } from "callingbox";

const client = new Callingbox({
  apiKey: "sk_live_...",
  baseUrl: "https://your-deployment.example",
});

Manage phone numbers

Numbers are the connection between agents and the outside world. The TypeScript SDK exposes the same public number APIs as the dashboard.

List your numbers

import { Callingbox } from "callingbox";

const client = new Callingbox();
const numbers = await client.numbers.list();
for (const number of numbers.data) {
  console.log(number.e164, number.status, number.inboundAgentId);
}

Search for available numbers

const available = await client.numbers.searchAvailable({
  countryCode: "US",
  areaCode: "415",
  numberType: "local",
  limit: 10,
});

for (const number of available) {
  console.log(number.phoneNumber, number.monthlyCostCents);
}

Purchase a number

const number = await client.numbers.purchase({
  phoneNumber: "+14155551234",
});
console.log(number.e164);

Create an outbound agent

Agents are where persona, instructions, voice, language, returns schema, tools, and caller IDs live. Create one once, then dispatch calls against it.
import { Callingbox } from "callingbox";

const client = new Callingbox();

const agent = await client.agents.create({
  name: "Appointment reminders",
  type: "outbound",
  instructions: "Confirm dental appointments. Offer to reschedule if needed.",
  returns: { confirmed: "boolean", reschedule_to: "string" },
  numberIds: [number.id],
  primaryNumberId: number.id,
});

console.log(agent.id);

Dispatch a call

Once you have an outbound agent with an attached number, calls.create(...) needs only agentId and to. Everything else is optional per-call overrides.
const call = await client.calls.create({
  agentId: agent.id,
  to: "+15551234567",
  context: { patient: "Maria Lopez", doctor: "Dr. Chen" },
});

console.log(call.id, call.status);

Choose a specific caller ID

const call = await client.calls.create({
  agentId: agent.id,
  to: "+15551234567",
  fromNumber: "+15557654321",
});
The SDK sends fromNumber to the API as from_number. The value must already be attached to the agent; otherwise the API returns 400.

Replace instructions for a single call

Per-call instructions wholly replace the agent’s default for this one execution. Persona, voice, and tools stay the same.
const call = await client.calls.create({
  agentId: agent.id,
  to: "+15551234567",
  instructions:
    "Follow up on the invoice sent last week. Negotiate a payment plan if needed.",
});

Poll for completion

Call creation is immediate, but the conversation and result extraction happen asynchronously. Poll the call until it reaches a terminal status:
import { Callingbox, TERMINAL_STATUSES } from "callingbox";

const client = new Callingbox();

let call = await client.calls.create({
  agentId: agent.id,
  to: "+15551234567",
});

while (!TERMINAL_STATUSES.has(call.status)) {
  await new Promise((r) => setTimeout(r, 2000));
  call = await client.calls.get(call.id);
}

console.log(call.status);
console.log(call.result);
Terminal statuses are:
  • completed
  • no_answer
  • busy
  • canceled
  • failed

List and retrieve calls

// List recent calls (inbound and outbound)
const calls = await client.calls.list();

// Get a single call by ID
const call = await client.calls.get("CALL_ID");
console.log(call.direction, call.agentId, call.status);
console.log(call.result);

Fetch the transcript

The transcript is stored separately from the call object. Fetch it on demand:
const segments = await client.calls.getTranscript("CALL_ID");
for (const s of segments) {
  console.log(`${s.role}: ${s.text}`);
}

Error handling

The SDK throws typed exceptions based on the API response:
import {
  Callingbox,
  APIError,
  AuthenticationError,
  BadRequestError,
  NotFoundError,
} from "callingbox";

const client = new Callingbox();

try {
  await client.calls.create({ agentId: "YOUR_AGENT_ID", to: "+15551234567" });
} catch (error) {
  if (error instanceof BadRequestError) {
    console.log(`Invalid request: ${error.message}`);
  } else if (error instanceof AuthenticationError) {
    console.log("Check your API key");
  } else if (error instanceof NotFoundError) {
    console.log("Resource not found");
  } else if (error instanceof APIError) {
    console.log(`API error: ${error.message}`);
  }
}

Webhooks

Manage endpoints and verify signatures with client.webhooks and the static Webhooks.constructEvent:
import { Callingbox, Webhooks } from "callingbox";

const cb = new Callingbox({ apiKey: process.env.CALLINGBOX_API_KEY });

// Create an endpoint (signingSecret is returned once)
const endpoint = await cb.webhooks.createEndpoint({
  url: "https://your-server.com/callingbox-webhook",
  description: "Production CRM sync",
  enabledEvents: ["call.completed", "call.failed"],
});
console.log(endpoint.signingSecret); // whsec_...; store securely

// Verify an incoming webhook (raw body required, not parsed JSON!)
app.post(
  "/callingbox-webhook",
  express.raw({ type: "application/json" }),
  (req, res) => {
    const event = Webhooks.constructEvent(
      req.body,                                 // Buffer
      req.headers["callingbox-signature"] as string,
      process.env.CALLINGBOX_WEBHOOK_SECRET!,
    );
    // event.type, event.data.call are now trustworthy
    res.sendStatus(200);
  },
);

// Replay a failed delivery
await cb.webhooks.redeliver("9c1d9f9e-21a1-4f6d-8fce-bf4a4b8a9e3f");
See Webhooks for the full integration guide.

Next steps

SDK overview

Compare the Python SDK, TypeScript SDK, CLI, and raw HTTP.

API basics

See the underlying /v1 endpoints the SDK wraps.

Call object

Understand every field returned by create, list, and get.

Delivery

Polling vs webhooks for receiving results.