Documentation
TypeScript SDK
@ruut/voice-sdk is a typed, tested client for the Ruut Voice REST API, TwiML builder, and webhook verification. It runs in Node.js and browsers.
Install
npmbash
npm install @ruut/voice-sdk
Quickstart
Make a call with inline TwiMLts
import { RuutVoice, VoiceResponse } from "@ruut/voice-sdk";
const client = new RuutVoice({
accountSid: process.env.RUUT_ACCOUNT_SID,
authToken: process.env.RUUT_AUTH_TOKEN,
baseUrl: "https://voice.ruut.chat",
timeoutMs: 10_000,
maxRetries: 2,
});
// Make a call with inline TwiML
const call = await client.calls.create({
to: "+2348000000001",
from: "+2348000000002",
twiml: new VoiceResponse().say("Hello from Ruut Voice!").toXml(),
statusCallback: "https://app.example.com/calls/status",
});
Client resources
| Parameter | Type | Description |
|---|---|---|
client.calls | Create, list, fetch, update, redirect, hold, resume, transfer, move to conference, waitFor. | |
client.messages | Send and list SMS messages. | |
client.recordings | List, fetch, and build media URLs (WAV/MP3) — including transcription fields. | |
client.incomingPhoneNumbers | Provision, list, update, remove numbers. | |
client.availablePhoneNumbers | Search the number inventory. | |
client.agentExtensions | Provision extensions, get credentials, update presence. | |
client.twiml | Build TwiML with VoiceResponse. |
Calls
Createts
// Create
await client.calls.create({ to, from, twiml | url, statusCallback });
await client.calls.createSipCall({ sipUri, from, url });
await client.calls.createAgentCall({ agentUsername, sipDomain, from, twiml });
// Read
await client.calls.list({ status, pageSize });
await client.calls.get("CA…");
// Control
await client.calls.redirect("CA…", { twiml });
await client.calls.hold("CA…", "https://hold-music.mp3");
await client.calls.resume("CA…", { url });
await client.calls.transfer("CA…", "+2348000000003", { callerId });
await client.calls.moveToConference("CA…", "support-room");
// Poll until a terminal state
const done = await client.calls.waitFor("CA…", {
statuses: ["completed", "busy", "failed"],
timeoutMs: 60_000,
});
Recordings & transcripts
Examplets
const recs = await client.recordings.list({ callSid: "CA…" });
const rec = await client.recordings.get("RE…");
console.log(rec.transcription_status); // "completed"
console.log(rec.transcription_provider); // "whisperx"
for (const seg of rec.transcription_segments ?? []) {
console.log(`${seg.speaker}: ${seg.text}`);
}
const wav = client.recordings.mediaUrl("RE…", { format: "wav" });
const mp3 = client.recordings.mediaUrl("RE…", { format: "mp3" });
Webhooks
Examplets
import {
parseWebhook,
isTerminalWebhook,
isTranscriptionWebhook,
parseTranscriptionSegments,
validateWebhookSignature,
} from "@ruut/voice-sdk";
const valid = await validateWebhookSignature({
url, params: req.body, signature: req.headers["x-twilio-signature"],
authToken: process.env.RUUT_AUTH_TOKEN,
});
if (!valid) return res.status(403).end();
const payload = parseWebhook(req.body);
if (isTerminalWebhook(payload)) { /* call done */ }
if (isTranscriptionWebhook(payload)) {
const segments = parseTranscriptionSegments(payload);
}
Error handling
Examplets
import { RuutApiError, RuutTimeoutError, RuutValidationError } from "@ruut/voice-sdk";
try {
await client.calls.get("CA…");
} catch (err) {
if (err instanceof RuutApiError) {
console.error(`API ${err.status}: ${err.message} (${err.code}, request ${err.requestId})`);
}
}