A phone call has two views you care about, and this page lines them up. On the wire it’s a SIP dialog — an INVITE, a handful of provisional responses, a 200 OK, an ACK, then media, then a BYE. In your code it’s a single CallStatus that walks dialing → ringing → in_progress → completed, or ends early at no_answer or failed. Both views name the same call by the same sid, and this page is the map between them: what each SIP message means, when the media path comes up, and exactly where an AI agent attaches. You almost never touch raw SIP — the gateway speaks it for you. But when you’re reading a status, debugging a call that never connected, or deciding when it’s safe to attach audio, it helps to know which SIP moment your CallStatus reflects.

The signalling sequence

A back-to-back user agent (B2BUA) in the SIP gateway sits between the caller and the agent. It terminates the caller’s dialog, runs your routing, and drives the signalling on both legs. For a single leg the message flow is:
   caller / carrier                 SIP gateway (B2BUA)
        │                                  │
        │  ── INVITE (SDP offer) ──────────▶│   dialing
        │  ◀──────────── 100 Trying ────────│   dialing   (gateway got it, working)
        │  ◀──────────── 180 Ringing ───────│   ringing   (far end is alerting)
        │  ◀──── 183 Session Progress (SDP) ─│   ringing   (early media — ringback/IVR audio)
        │  ◀──────────── 200 OK (SDP answer)─│   in_progress  (answered; media negotiated)
        │  ── ACK ─────────────────────────▶│   in_progress  (dialog confirmed)
        │  ══════════ RTP media both ways ══│════════════
        │  ── BYE ─────────────────────────▶│   completed (either side can send BYE)
        │  ◀──────────── 200 OK ─────────────│
For inbound calls the direction is mirrored — the carrier sends the INVITE and the gateway answers with 100 / 183 / 200. The state machine is identical; only who sends which message flips.

SIP messages → CallStatus

Your SDK never surfaces individual SIP messages. It collapses them into the six statuses on CallStatus. This is the mapping the gateway applies:
CallStatusSIP moment that triggers itMeaning
dialingINVITE sent, 100 TryingCall placed; far end not yet alerting.
ringing180 Ringing or 183 Session ProgressFar end is alerting; early media (ringback / IVR) may already be audible.
in_progress200 OK + ACKAnswered. Media is flowing both ways.
completedBYE after a 200 OK (Q.850 normal clearing)The call connected and ended normally.
no_answerRing timeout, 480, 486 Busy, or 408 before any 200Nobody picked up (or was busy) — it never reached in_progress.
failed4xx/5xx/6xx rejection, or media setup failedThe call couldn’t be set up at all.
The dividing line that matters most: in_progress is the only status that guarantees a live media path. Anything before it is signalling; completed, no_answer, and failed are all terminal. completed means the call connected then ended; no_answer and failed mean it never connected.

Media setup: where audio actually comes up

SIP negotiates media with SDP (Session Description Protocol) — an offer in the INVITE, an answer in a response. Two details shape when you have audio:
  • Early media (183 + SDP). The gateway answers with 183 Session Progress carrying an SDP answer before the call is picked up. That opens a one-way media path so the caller hears ringback, a “please hold”, or an IVR prompt while still in ringing. This is why an AI receptionist can start talking the instant a caller connects.
  • Same SDP on 200. When the call is answered, the 200 OK repeats the SDP already agreed in the 183, so nothing re-negotiates and there’s no audio gap at pickup.
The gateway answers with 183 Session Progress carrying SDP, not a bare 180 Ringing. Some carriers drop a call (send an unsolicited BYE) if they see a 180 with no media description. If you’re bridging your own carrier and see calls torn down right at the ring stage, this is the first thing to check.
On the wire, phone legs carry G.711 (µ-law or A-law). The media plane decodes that to the runtime’s 8 kHz PCM16 contract, and re-encodes on the way back out — G.711 for a phone leg, Opus for a browser or app leg. You never handle the codec transcoding; see the codec guide for which codec rides which transport.

Where the agent attaches

An AI agent doesn’t wait for the call to be fully answered — it’s wired up during setup so there’s no dead air at pickup:
1

INVITE arrives, routing runs

On the inbound INVITE, the gateway resolves the trunk and asks the routing engine what to do. When the decision is “hand this call to an AI agent,” the runtime is told to start a session for this sid and the media leg is opened on the core that owns the call.
2

The provider connection pre-warms

While the call is still ringing, a realtime (speech-to-speech) agent opens its model connection ahead of answer — during the INVITE/SDP exchange — so the model is ready the moment audio flows. A cascade (ASR → LLM → TTS) agent opens its provider streams the same way.
3

Answer, and audio bridges in

On 200 OK + ACK the call is in_progress. Caller audio, decoded to 8 kHz PCM16, is published as the call’s uplink track (voice/<sid>/uplink); the agent’s replies are published back on the downlink track (voice/<sid>/downlink) and paced out to the caller. The agent is now on the far end of the media bridge.
4

The turn loop runs until teardown

From here the runtime drives greet → listen → think → speak until someone hangs up or a guardrail fires. That inner loop is its own topic — see session lifecycle.
You don’t write any of this attach logic for a server-side agent — passing an agent id to originate (or configuring it on the inbound trunk) is enough, and the gateway attaches the bridge automatically on answer. If you want to handle the audio yourself instead, attach an AudioBridge to the same sid.

Following the lifecycle from the SDK

originate returns as soon as the call is placed — you get a Call in dialing, not a call that’s already connected. Read status (or fetch a fresh snapshot with calls.get) to follow it forward:
import { Voice } from "@telequick/sdk/voice";

const v = new Voice({
  baseUrl: "https://engine.telequick.dev",
  apiKey:  process.env.TELEQUICK_CREDENTIALS!,
  orgId:   "org_abc",
});

// Place the call and hand it to a server-side agent on answer.
const call = await v.calls.originate({
  to:      "+15557654321",
  from:    "+15551234567",
  trunkId: "trunk_default",
  agent:   "sales-qualifier",     // engine attaches the bridge on 200 OK
  ringTimeoutSec: 30,             // → no_answer if unanswered in 30s
});

console.log(call.status);         // "dialing"

// Poll forward (or drive this from lifecycle webhooks — see below).
const now = await v.calls.get({ sid: call.sid });
if (now.status === "in_progress") {
  // media is live; safe to attach audio, start recording, etc.
} else if (now.status === "no_answer" || now.status === "failed") {
  // never connected — retry, fall back, or log
}
ringTimeoutSec (server-clamped 5–120, default 30) is the ceiling on the ringing stage: if no 200 OK arrives in time, the gateway gives up and the call lands on no_answer rather than ringing forever.

Lifecycle events and CDRs

Every transition on the wire is also emitted to the events pipeline, so you don’t have to poll if you’d rather react. Each SIP milestone becomes a call event — initiated (INVITE), ring, established (answer), holds and resumes, transferred (a REFER-based handoff), and cleared (the final BYE, carrying the Q.850 cause and the call duration). On clearing, the gateway also writes a CDR. Subscribe to these via webhooks, and read the assembled per-call timeline in call traces.
Multi-segment calls. If a call is handed from an AI agent to a human (or back), it stays one sid — the events pipeline folds it into multiple segments under that one id, tagged by which handler owned each stretch, so a transfer shows up as one continuous call rather than two. See handoffs.

Hanging up

Either side ends the call with a BYE. When the caller hangs up, the gateway tears the dialog down, the runtime session ends, and the call moves to completed. To end it from your side, call hangup():
await call.hangup();               // gateway sends BYE → completed
Teardown cancels any in-flight model work, flushes the outbound audio, releases the media leg, and emits the cleared event and CDR — covered from the runtime’s side in session lifecycle.

Inbound calls

Receive an INVITE from the carrier and route it to an agent.

Outbound calls

Originate calls and drive them with the paced dialer.

Handoffs

Transfer, REFER, and warm handoff without changing the sid.

Session lifecycle

The greet → listen → think → speak loop inside in_progress.

Codec guide

G.711 on the wire, PCM16 inside, Opus to the browser.

Call traces

The assembled per-call event timeline you read after the fact.