@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.1npm install @ruut/voice-sdk
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", });
| 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. |
// 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, });
1234567891011const 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" });
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); }
123456789import { 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})`); } }