Agent-readable docs index: /docs/llms.txt. Full docs in one file: /docs/llms-full.txt. Download /docs/docs.zip to grep all markdown files locally.

Authentication

The Twilio-compatible API uses account credentials and scoped tokens; the carrier API uses a bearer token. Callback signing varies by event type.

REST API authentication

Send your Account SID as the username and Auth Token as the password with HTTP Basic auth:
Authorization: Basic base64("{AccountSid}:{AuthToken}")
Equivalently, in curl:
curl -u "$RUUT_ACCOUNT_SID:$RUUT_AUTH_TOKEN" \ "https://voice.ruut.chat/2010-04-01/Accounts/$RUUT_ACCOUNT_SID/Calls"
Failed authentication returns 401 Unauthorized.

Scoped API keys

For production, create scoped API keys in the dashboard instead of using your master Auth Token. Keys can be restricted to specific resources (e.g. calls only) and revoked independently — limit blast radius if a key leaks. Use the account SID as the Basic auth username and the scoped key as the password. For example, a key with phone_calls_read can list calls:
curl -u "$RUUT_ACCOUNT_SID:$RUUT_API_KEY" \ "https://voice.ruut.chat/2010-04-01/Accounts/$RUUT_ACCOUNT_SID/Calls"
Never expose your Auth Token or a scoped key in client-side code. Always proxy through your server (e.g. use the browser SDK's server-side credentials flow).

Webhook signature verification

Recording and transcription callbacks use HMAC-SHA1 over the URL and sorted body parameters, keyed by your Auth Token, and send X-Twilio-Signature. The current call-status callback job does not add that header; see call status webhooks.
Verify the signature before trusting a signed recording or transcription callback. The following examples use a recording callback:
import { validateWebhookSignature } from "@ruut/voice-sdk"; const valid = await validateWebhookSignature({ url: "https://app.example.com/webhooks/recording", params: req.body, signature: req.headers["x-twilio-signature"], authToken: process.env.RUUT_AUTH_TOKEN, }); if (!valid) return res.status(403).end();
Or use the Express middleware, which verifies and parses in one step:
import { ruutWebhook } from "@ruut/voice-sdk/express"; app.post("/webhooks/recording", ruutWebhook({ authToken: process.env.RUUT_AUTH_TOKEN }), (req, res) => { console.log(req.ruutWebhook.RecordingStatus); res.sendStatus(200); } );

SIP authentication

  • Inbound — only source IPs in your trunk's allowlist are accepted.
  • Agent softphones — digest authentication against the extension's ephemeral credentials.