> ## Documentation Index
> Fetch the complete documentation index at: https://docs.agentline.cloud/llms.txt
> Use this file to discover all available pages before exploring further.

# Calls

> Make outbound calls, hang up, and read transcripts.

# Calls

Calls use a hybrid relay pipeline: the provider answers, plays the greeting,
records caller speech, transcribes it (Deepgram), and your agent replies with
text that is spoken back (TTS). The full transcript is saved automatically.
Voice calls cost **\$0.10 per minute** in both directions. A 0-second call is free. A connected call has a one-minute minimum, then the actual duration, rounded up to the cent.

JavaScript examples call `https://api.agentline.cloud` with `fetch` and a
Bearer `al_live_...` key. The Node package is not on npm.

## Make an outbound call

<CodeGroup>
  ```python theme={null}
  call = client.calls.create(
      agent_id=agent.id,
      to_number="+12125557890",
      # optional per-call overrides:
      system_prompt="You are confirming an appointment.",
      initial_greeting="Hi, calling about your appointment tomorrow.",
  )
  ```

  ```javascript theme={null}
  const call = await fetch("https://api.agentline.cloud/v1/calls", {
    method: "POST",
    headers: {
      Authorization: "Bearer al_live_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      agent_id: agent.id,
      to_number: "+12125557890",
      system_prompt: "You are confirming an appointment.",
      initial_greeting: "Hi, calling about your appointment tomorrow.",
    }),
  }).then((res) => res.json());
  ```
</CodeGroup>

The call is placed from the agent's assigned number (or `from_number_id` if
provided). Returns a `call_id` you use to control and inspect the call.

Outbound calls **listen first**. The pipeline classifies what picked up:

| What it hears | What it does |
| - | - |
| Live human (*"Hello?"*) | Introduces itself from `initial_greeting` |
| Voicemail greeting (*"X is not available"*, *"leave a message"*) | Waits for the beep, leaves `voicemail_message`, hangs up |
| Voicemail key menu (*"press 2 to record"*) | Presses **2**, then leaves `voicemail_message` |
| IVR (*"Press 1 for sales"*) | Sends a real DTMF tone for a key the menu actually offered. `0` is used only if the menu listed it. |
| Call screening (*"State your name"*) | States name and purpose |

<Warning>
  The agent leaves a voicemail **only** if `voicemail_message` is set on the
  agent (`PATCH /v1/agents`). Without it, a mailbox greeting hangs up and a
  "press 2 to record" menu presses disconnect. See [Agents](/guides/agents).
</Warning>

## Control and inspect

<CodeGroup>
  ```python theme={null}
  client.calls.hangup(call.id)
  client.calls.get(call.id)
  transcript = client.calls.get_transcript(call.id)
  client.calls.list(status="completed")
  ```

  ```javascript theme={null}
  const headers = { Authorization: "Bearer al_live_..." };

  await fetch(`https://api.agentline.cloud/v1/calls/${call.id}/hangup`, {
    method: "POST",
    headers,
  });
  await fetch(`https://api.agentline.cloud/v1/calls/${call.id}`, { headers });
  const transcript = await fetch(
    `https://api.agentline.cloud/v1/calls/${call.id}/transcript`,
    { headers },
  ).then((res) => res.json());
  await fetch("https://api.agentline.cloud/v1/calls?status=completed", { headers });
  ```
</CodeGroup>

## Pushing context to a live call (relay mode)

If your backend (Hermes, OpenClaw, Claude Code, Codex, or another agent) needs
to answer a live caller after a `call.utterance` event, use the persistent
[Agent Relay](/guides/relay) or push context over HTTP. Every response is bound
to the exact `turn_id` from that event.

Send short facts, not a script. Include `disposition`:

| `disposition` | What happens |
| - | - |
| `progress` | Adds a note and keeps the caller on hold. They hear canned lines. The text is not spoken. The turn stays open. |
| `done` | Default. Closes the turn. The hosted voice rephrases the facts in one or two sentences. |
| `facts` | Closes the turn. The hosted voice rephrases the facts in one or two sentences. |
| `failed` | Closes the turn. The hosted voice rephrases the facts in one or two sentences. |
| `noop` | Closes the turn with no facts. |

<CodeGroup>
  ```python theme={null}
  client.calls.push_context(
      call.id,
      turn_id="turn_xxx",
      context="Order ships Tuesday.",
      disposition="done",
  )
  ```

  ```javascript theme={null}
  await fetch(`https://api.agentline.cloud/v1/calls/${call.id}/context?turn_id=turn_xxx`, {
    method: "POST",
    headers: {
      Authorization: "Bearer al_live_...",
      "Content-Type": "application/json",
    },
    body: JSON.stringify({
      turn_id: "turn_xxx",
      context: "Order ships Tuesday.",
      disposition: "done",
    }),
  });
  ```
</CodeGroup>

The hosted voice does not read `context` aloud. `done`, `facts`, and `failed`
close the turn and the voice rephrases those facts. `progress` only holds the
caller.

Returns `delivered=true` with `status: "live"` or `"duplicate"`. A **409** means
the turn is stale or cancelled; a **410** means the call has ended. Never reuse
context from one turn for another.

<Note>
  `GET /v1/calls/{id}/transcript` returns `{role, text, timestamp}` turns.
  `role` is `human` (caller) or `agent` (the AI agent). A `call.utterance`
  `conversation` field uses `user` and `assistant` instead.
</Note>


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.