# Voice Calls with the TypeScript SDK

> Place outbound voice-agent calls, read transcripts, and hang up active calls via the Zavu TypeScript SDK.

Voice calls are conversations handled by the AI agent configured on a sender. Placing a call dials the recipient and connects them to the agent — speech recognition, the agent's LLM, and speech synthesis run in Zavu's managed voice pipeline.

The `calls` resource is available since `@zavudev/sdk` 0.56.0.

## Place a Call

`to` is the only required field. The sender's agent must have `voice.enabled: true`.

```typescript
const { call } = await client.calls.create({
  to: "+56912345678",
});

console.log(call.id, call.status); // call_xxx "queued"
```

### With Overrides

`greeting`, `language`, and `maxDurationMinutes` override the agent's configuration for this call only. `metadata` is returned on the call object and included in voice webhooks.

```typescript
const { call } = await client.calls.create({
  to: "+56912345678",
  senderId: "snd_abc123",
  greeting: "Hi, this is Acme calling about your appointment.",
  language: "es-ES", // or "auto" to follow the caller
  maxDurationMinutes: 10,
  metadata: { campaign: "appointment_reminders" },
});
```

The call is returned immediately with status `queued` while it starts dialing. Track progress via the `call.initiated`, `call.answered`, `call.completed`, and `call.failed` webhook events, or by polling `calls.retrieve`.

## Get a Call and Its Transcript

Fetching a single call includes the full transcript once the conversation has produced turns. Each turn is `{ seq, role, text }` where `role` is `user`, `assistant`, or `tool`.

```typescript
const { call } = await client.calls.retrieve("call_abc123");

console.log(call.status, call.durationSeconds, call.endReason, call.cost);

for (const turn of call.transcript ?? []) {
  console.log(`${turn.role}: ${turn.text}`);
}
```

`durationSeconds`, `endReason`, `turnCount`, and `cost` populate once the call ends. `cost` is the total in USD, combining the managed voice pipeline and telephony.

## List Calls

Transcripts are omitted from list responses — fetch a single call to get one. The list auto-paginates:

```typescript
for await (const call of client.calls.list({
  status: "completed",
  direction: "outbound",
})) {
  console.log(call.id, call.to, call.durationSeconds);
}
```

## Hang Up a Call

Ends an active call. The call must still be `queued`, `ringing` or `in_progress`; a call that already ended returns `409 conflict`.

```typescript
const { call } = await client.calls.hangup("call_abc123");

console.log(call.status);
```

## Requirements and Errors

- The sender's agent needs `voice.enabled: true`, or `create` fails with `400 "The sender's agent does not have voice enabled"`.
- Placing and hanging up calls is not available with test-mode API keys; reads are.
- Calls are billed per connected minute plus telephony from your prepaid balance. `402 insufficient_balance` means the balance cannot cover the call.

## Related

- [Voice Agents overview](https://www.zavu.dev/docs/guides/voice-agents/overview) — configuring the agent that answers
- [Voice webhooks](https://www.zavu.dev/docs/guides/voice-agents/webhooks) — `call.*` event payloads
