Skip to content
Patch AMD

Telnyx

Telnyx streams call audio to a WebSocket URL you give it. Mint a signed stream URL on your server and hand it to Telnyx; Patch AMD posts the decision to your webhook.

Option A: start streaming on answer

// Your Telnyx webhook, on call.answered for the outbound leg
const stream = await fetch('https://api.patchamd.com/v1/streams', {
  method: 'POST',
  headers: { authorization: `Bearer ${process.env.PATCH_AMD_KEY}`, 'content-type': 'application/json' },
  body: JSON.stringify({ webhook_url: 'https://you.example/amd', metadata: { lead: '42' } }),
}).then(r => r.json());

await fetch(`https://api.telnyx.com/v2/calls/${callControlId}/actions/streaming_start`, {
  method: 'POST',
  headers: { authorization: `Bearer ${process.env.TELNYX_API_KEY}`, 'content-type': 'application/json' },
  body: JSON.stringify({ stream_url: stream.url, stream_track: 'inbound_track' }),
});

Option B: stream from dial

Pass the same URL on the Dial command so no audio is missed between answer and streaming_start:

{
  "to": "+15551234567",
  "from": "+15557654321",
  "connection_id": "…",
  "stream_url": "<stream.url>",
  "stream_track": "inbound_track"
}

The socket opens at dial; Patch AMD starts the clock at Telnyx's start message, which arrives on answer. Turn off answering_machine_detection on the Dial.

Route the call on the decision

data.call_id is the Telnyx call_control_id.

const { result, call_id } = event.data;
if (result === 'human' || result === 'not_sure') await bridgeToRep(call_id);
else await telnyxAction(call_id, 'hangup');

Audio

We read the codec from Telnyx's media_format: PCMU and PCMA at 8 kHz, or L16 at 16 kHz. Other codecs fail open (not_sure, detector_failed, not billed).