The official Node.js and TypeScript SDK for the NextGenSwitch Programmable Voice API. Create and modify calls, generate escaped Voice XML, stream audio to AI services, and parse Gather and Dial callbacks.
- Node.js 18 or newer
- A NextGenSwitch deployment and API credentials
npm install @nextgenswitch/sdkUntil the first npm release:
npm install github:nextgenswitch/nextgenswitch-nodejsimport { NextGenSwitchClient } from "@nextgenswitch/sdk";
const client = new NextGenSwitchClient({
baseUrl: process.env.NEXTGENSWITCH_BASE_URL!,
authorization: process.env.NEXTGENSWITCH_AUTHORIZATION!,
authorizationSecret: process.env.NEXTGENSWITCH_AUTHORIZATION_SECRET!,
});The SDK uses Node's built-in Fetch API and sends the documented X-Authorization and X-Authorization-Secret headers. Keep credentials outside source control and use HTTPS.
import { VoiceResponse } from "@nextgenswitch/sdk";
const flow = new VoiceResponse()
.say("Welcome to NextGenSwitch.")
.gather(
{
action: "https://example.com/gather",
method: "POST",
numDigits: 1,
timeout: 10,
},
(gather) => gather.say("Press one for sales."),
);
const result = await client.createCall({
to: "2001",
from: "1001",
responseXml: flow,
statusCallback: "https://example.com/call-status",
});Use responseUrl instead of responseXml for a hosted XML document. Exactly one response source is required.
const updated = new VoiceResponse()
.pause(2)
.say("Your call flow has been updated.")
.dial("1000", { answerOnBridge: true });
await client.modifyCall("CALL-123", updated);| XML verb | SDK method |
|---|---|
<Say> |
say(text, attributes) |
<Play> |
play(url, attributes) |
<Gather> |
gather(attributes, children) |
<Dial> |
dial(to, attributes, children) |
<Record> |
record(attributes) |
<Connect><Stream> |
stream(url, parameters, attributes) |
<Hangup> |
hangup() |
<Pause> |
pause(seconds) |
<Redirect> |
redirect(url, method) |
<Bridge> |
bridge(callId, bridgeAfterEstablish) |
<Leave> |
leave() |
The builder escapes all text and attribute values rather than concatenating untrusted XML.
const flow = new VoiceResponse()
.say("Please leave your message after the beep.")
.record({
action: "https://example.com/recording",
method: "POST",
timeout: 5,
finishOnKey: "#",
transcribe: true,
trim: true,
beep: true,
})
.hangup();
await client.createCall({ to: "2001", from: "1001", responseXml: flow });const flow = new VoiceResponse().stream(
"wss://voice.example.com/session",
{ session_id: "session-123", tenant: "example" },
{ name: "assistant-stream" },
);Resolve AI-provider keys on the WebSocket service. Never put secrets in Voice XML.
import { parseGatherResult, VoiceResponse } from "@nextgenswitch/sdk";
const gather = parseGatherResult(requestBody);
const response =
gather.digits === "1"
? new VoiceResponse().say("Connecting sales.").dial("1001")
: new VoiceResponse().say("No valid selection received.").hangup();Use parseDialResult(payload) for documented Dial completion fields. A callback signature scheme is not currently documented; require TLS, restrict endpoints, validate fields, and apply deployment-appropriate authentication.
ValidationError: invalid SDK inputApiError: non-2xx API response withstatusCodeandresponseBodyTransportError: timeout or network failureNextGenSwitchError: base SDK exception
Configure NEXTGENSWITCH_BASE_URL, NEXTGENSWITCH_AUTHORIZATION, and NEXTGENSWITCH_AUTHORIZATION_SECRET, then adapt:
All example.com endpoints are placeholders for TLS services you control.
Inject a compatible Fetch implementation for proxies, tracing, or deterministic tests:
const client = new NextGenSwitchClient({
baseUrl,
authorization,
authorizationSecret,
fetch: customFetch,
timeoutMs: 15_000,
});npm ci
npm run check
npm pack --dry-runThe package builds ESM, CommonJS, source maps, and TypeScript declarations. GitHub Actions validates Node.js 18, 20, 22, and 24.