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.

Telnyx

This recipe connects a Telnyx number with TeXML. Your server returns the stream instruction, owns the bidirectional media WebSocket, creates one Inkibra session per call, and translates between Telnyx PCMU and Inkibra PCM16.
Read Server media first, then initialize the server application:
bash
npx @inkibra/voice-cli init

Prerequisites

  • A Telnyx number and TeXML Application
  • The account's Ed25519 public key for webhook validation
  • A Telnyx API key if your server creates outbound calls
  • INKIBRA_API_KEY stored on your server
  • Public https:// and wss:// routes

1. Configure Telnyx

Set the TeXML Application's Voice URL to POST https://voice.example.com/telnyx/answer, then assign the number to that Application. Send stream status callbacks to POST https://voice.example.com/telnyx/status.
Verify every HTTP webhook before processing it. Use the Telnyx SDK's Ed25519 helper with the raw request body, telnyx-signature-ed25519, telnyx-timestamp, and the account public key. Reject stale timestamps and make callbacks idempotent by event ID.

2. Return TeXML

Create a random, single-use nonce bound to the expected call, then return:
xml
<?xml version="1.0" encoding="UTF-8"?> <Response> <Start> <Stream url="wss://voice.example.com/telnyx/media" codec="PCMU" bidirectionalMode="rtp" bidirectionalCodec="PCMU" bidirectionalSamplingRate="8000" enableReconnect="false" statusCallback="https://voice.example.com/telnyx/status"> <Parameter name="nonce" value="NONCE" /> </Stream> </Start> </Response>
Read nonce from the WebSocket start event, claim it once, and bind the received call_control_id and stream_id. Telnyx media upgrades are not Ed25519 webhook requests, so the nonce is the media socket credential. Leave enableReconnect="false" until your application supports resuming the same Inkibra session safely.

3. Open Inkibra server media

When Telnyx sends start, pass the connected media socket to your Telnyx audio transport and connect Inkibra:
ts
import LiveVoice from "@inkibra/voice-sdk/server"; const session = await LiveVoice.connect({ apiKey: process.env.INKIBRA_API_KEY!, audio: new TelnyxAudioTransport(telnyxSocket, streamId), prompt: "Answer questions about the customer's order.", conversation: { starts: "assistant" }, tools: {}, });
LiveVoice.connect creates, prepares, and starts the Inkibra session. The transport class implements the provider-specific audio mapping in the next step.

4. Bridge audio and playback state

Telnyx media.payload is a base64 RTP payload without an RTP header. Reorder media using its sequence/chunk metadata, decode PCMU at 8 kHz to signed PCM16, resample to 24 kHz with persistent state, and send raw little-endian PCM16 to Inkibra in 480-sample, 20 ms binary frames.
For each SDK enqueue command, command.pcm is PCM16LE mono at 24 kHz. Keep mode: "buffer" chunks private until the matching release. Downsample released audio to 8 kHz, encode PCMU, then send media followed by a mark:
ts
telnyx.send(JSON.stringify({ event: "media", media: { payload: pcmuAudio.toString("base64") }, })); telnyx.send(JSON.stringify({ event: "mark", mark: { name: generationId }, }));
When the SDK sends done, send one mark after the generation's final media chunk. Call handlers.receipt with started when playout begins and completed when Telnyx echoes that mark. On cancel, discard unsent chunks and send:
ts
telnyx.send(JSON.stringify({ event: "clear" }));
Telnyx returns queued marks after clear; classify those generations as cancelled, not completed. Report the number of 24 kHz samples actually played. Honor block-foreground, release, and reaction-versus-foreground lanes exactly as described in Server media.

5. End the session

On Telnyx stop, streaming.stopped, call hangup, or either WebSocket closing:
ts
session.stop(); await session.closed;
Make lifecycle handlers idempotent by event ID and call_control_id. If Inkibra sends session.limit, a provider error, or closes the WebSocket, send clear, then hang up the Telnyx call.
For outbound calls, configure an outbound voice profile and create the call with this TeXML Application or with Voice API streaming fields equivalent to the XML above. Store the Telnyx API key server-side; ordinary API keys are account-wide.

Smoke test

  1. Call the Telnyx number and confirm exactly one POST /v1/sessions request.
  2. Speak for five seconds; verify reordered PCMU input becomes continuous 480-sample Inkibra frames.
  3. Confirm the assistant opening is audible and that buffered audio is not played before release.
  4. Interrupt the assistant; verify clear, a cancelled receipt, and no stale audio after the returned marks.
  5. Hang up; verify session.stop, both sockets closed, and the nonce/call record removed.
  6. Send a modified or stale webhook and reuse the nonce; both must be rejected.