Dial a phone number from your backend: calls.originate({ to, from, trunkId }) returns immediately with a sid, and the control plane is request/response, so you re-fetch with calls.get({ sid }) to watch the call progress. Optionally pass agent and the engine attaches a server-side voice agent on answer — no audio bridge in your process.

Client

Every snippet below assumes a configured Voice client.
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

Originate over a SIP trunk and read the returned sid — the universal key you use to address the call for status, transfer, hangup, and audio.
const call = await v.calls.originate({
  to:      "+15551234567",   // E.164 destination
  from:    "+15558675309",   // caller-id, must be routable on the trunk
  trunkId: "trunk_main",
});
console.log("dialing", call.sid, call.status);   // dialing
trunkId names a SIP trunk you have already provisioned. Create one in the console or via the admin API before calling originate — see SIP trunking.

Attach an AI agent on answer

Pass agent and the engine wires the audio bridge automatically when the callee answers — the server-side agent drives both legs of the conversation, so you do not open an AudioBridge yourself.
const call = await v.calls.originate({
  to:      "+15551234567",
  from:    "+15558675309",
  trunkId: "trunk_main",
  agent:   "appointment-reminder",
});

Cap the ring time

Give up after 15 seconds instead of the default 30. The server clamps this to 5..120.
const call = await v.calls.originate({
  to:             "+15551234567",
  from:           "+15558675309",
  trunkId:        "trunk_main",
  ringTimeoutSec: 15,
});

Poll the call’s status

The control plane is request/response — re-fetch to read the latest status. Status is one of dialing, ringing, in_progress, completed, failed, or no_answer.
const c = await v.calls.get({ sid: call.sid });
if (c.status === "in_progress") console.log("connected");

Wait for the call to connect

Poll until the call leaves the ringing states, then act on the outcome.
async function waitConnected(sid: string): Promise<CallStatus> {
  for (;;) {
    const c = await v.calls.get({ sid });
    if (c.status !== "dialing" && c.status !== "ringing") return c.status;
    await new Promise((r) => setTimeout(r, 500));
  }
}

const outcome = await waitConnected(call.sid); // in_progress | failed | no_answer | completed
if (outcome === "in_progress") console.log("callee picked up");
else console.log("call ended early:", outcome);
For high-volume outbound — thousands of numbers at a paced dials-per-second — do not loop originate yourself. Use the built-in paced campaign dialer, which owns the pacing and concurrency caps engine-side. See Outbound & dialer.

Hang up

End the call when you are done. If you attached an AudioBridge yourself (rather than passing agent), close it first so both tracks tear down cleanly.
await call.hangup();

Bring your own ASR

Skip the agent and bridge caller audio into your own recognizer.

Transfer to a human

Hand a live call off to a person or a different agent.

Outbound & dialer

Paced campaigns, concurrency caps, and the originate app modes.

Calls API

Full request/response shape for originate, get, transfer, and hangup.