Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion agents/monitor/webhooks.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
icon: "bell"
---

Point your agent at one or more endpoints on your server and Fish Audio calls them when things happen: `call.ended` the moment a session reaches a terminal state, `call.analyzed` when [post-call analysis](/agents/monitor/post-call-analysis) settles, and, on outbound phone calls, `phone_call.dial_finished` as soon as the dial attempt resolves. Use them to write results into your CRM, ticketing system, or data warehouse without polling the sessions API.
Point your agent at one or more endpoints on your server and Fish Audio calls them when things happen: `call.ended` the moment a session reaches a terminal state, `call.analyzed` when [post-call analysis](/agents/monitor/post-call-analysis) settles, and, on [outbound phone calls](/agents/telephony/outbound-calls), `phone_call.dial_finished` as soon as the dial attempt resolves. Use them to write results into your CRM, ticketing system, or data warehouse without polling the sessions API.

## Events

Expand Down Expand Up @@ -108,10 +108,10 @@
"duration_seconds": 184,
"end_user_id": "customer-42",
"metadata": { "order_ref": "SO-1042" },
"agent_name": "Support agent",

Check warning on line 111 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L111

Did you really mean 'agent_name'?
"config_hash": "sha256:9c41…"

Check warning on line 112 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L112

Did you really mean 'config_hash'?
},
"ended_reason": "hangup"

Check warning on line 114 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L114

Did you really mean 'ended_reason'?
}
```

Expand Down Expand Up @@ -272,14 +272,14 @@
| Fan-out | Every configured endpoint receives every event |
| Guarantee | At-least-once, per endpoint |
| Timeout | 10 seconds per attempt |
| Retries | 2 after the first attempt (3 attempts total) per endpoint, with backoff of 1s / 5s, then that delivery is dropped |

Check warning on line 275 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L275

Did you really mean 'backoff'?
| Ordering | `phone_call.dial_finished` (outbound only) before `call.ended` before `call.analyzed` for the same session |

Endpoints are delivered in parallel and independently: each gets its own attempts, its own retry budget, and its own signature keyed with its own secret. An endpoint that is down and exhausts all three attempts has no effect on the others.

Respond with a `2xx` status within the timeout; a `500` response or a timed-out request counts as a failed attempt. Acknowledge first and process asynchronously. Slow handlers burn their own retry budget.

**Idempotency.** At-least-once delivery means the same event can arrive more than once. Retries of one delivery carry an identical body, so dedupe `call.ended` and `phone_call.dial_finished` on (`event`, `session.id`), and `call.analyzed` on (`event`, `session.id`, `analysis.finished_at`). The extra element matters because a skipped or failed analysis can be re-run from the console: the recovered result arrives as a fresh `call.analyzed` with a newer `finished_at`, superseding the earlier one.

Check warning on line 282 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L282

Did you really mean 'Idempotency'?

Check warning on line 282 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L282

Did you really mean 'dedupe'?

<Note>
[Preview calls](/agents/test/preview-calls) made from the Builder never
Expand All @@ -289,7 +289,7 @@

## Auto-ticket unresolved calls

`call.analyzed` closes the loop on conversations the agent couldn't: judge every call with a success criterion, and open a ticket in your helpdesk whenever the verdict isn't `success`.

Check warning on line 292 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L292

Did you really mean 'helpdesk'?

First give the agent's [analysis configuration](/agents/monitor/post-call-analysis) a criterion that captures resolution:

Expand Down Expand Up @@ -410,11 +410,11 @@

</CodeGroup>

`verifyWebhook` is the function from [Verify the signature](#verify-the-signature); `openTicket` stands in for your helpdesk's API. Escalating on anything but `success` includes `unknown` verdicts: the model couldn't judge the call, which usually deserves human eyes too. Tighten the check to `failure` only if unknowns prove noisy.

Check warning on line 413 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L413

Did you really mean 'helpdesk's'?

Edges worth handling:

- Calls with nothing to analyze arrive with `analysis.status: "skipped"`. The handler above tickets them as unjudged, so every call reaches the helpdesk without also watching `call.ended`. Drop that branch if silent calls don't belong in your queue.

Check warning on line 417 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L417

Did you really mean 'unjudged'?

Check warning on line 417 in agents/monitor/webhooks.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/monitor/webhooks.mdx#L417

Did you really mean 'helpdesk'?
- Payloads carry no transcript. To include one in the ticket, fetch `GET /v1/agent/sessions/{session_id}` from your handler. See [conversation history](/agents/monitor/conversation-history).
- Set `end_user_id` and `metadata` when creating sessions so tickets attach to the right customer record without a lookup.

Expand Down
2 changes: 1 addition & 1 deletion agents/telephony/byo-sip.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

If your numbers already live at a carrier, you can connect them to your agents without porting anything. Point the carrier's SIP trunk at Fish Audio and import the number: it stays with your carrier, who keeps billing you for the telephone-network legs, and on Fish Audio the calls bill as ordinary agent sessions. Imported numbers carry no monthly rental and no telephony charges of any kind: no phone surcharge, no transfer fees, agent minutes only.

This works with any carrier or PBX that speaks SIP trunking: Twilio Elastic SIP Trunking, Asterisk or FreePBX, and most SIP providers. It is also the only way to use non-US/CA numbers, which the purchasable inventory does not cover.

Check warning on line 9 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L9

Did you really mean 'Twilio'?

## How it works

Expand Down Expand Up @@ -80,30 +80,30 @@
The SIP endpoint is shared, so an import must prove that calls really come from your trunk:

- **Digest credentials**: the platform challenges your trunk and verifies the username and password. Use this whenever your carrier or PBX answers digest challenges (Asterisk, FreePBX, most SIP providers).
- **Allowed source addresses**: calls are only accepted from the listed IPs or CIDR ranges. Use this for carriers that do not authenticate their origination traffic; Twilio Elastic SIP Trunking is one, so for Twilio this is the required factor.

Check warning on line 83 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L83

Did you really mean 'IPs'?

Check warning on line 83 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L83

Did you really mean 'Twilio'?

Check warning on line 83 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L83

Did you really mean 'Twilio'?

Set both when your carrier supports it.

## Carrier walkthroughs

Check warning on line 87 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L87

Did you really mean 'walkthroughs'?

### Twilio Elastic SIP Trunking

Check warning on line 89 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L89

Did you really mean 'Twilio'?

<Steps>
<Step title="Create a trunk">
In the Twilio console, under **Elastic SIP Trunking**, create a trunk (or

Check warning on line 93 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L93

Did you really mean 'Twilio'?
reuse an existing one).
</Step>
<Step title="Point origination at Fish Audio">
Add an origination URI: `sip:1pv316az391.sip.livekit.cloud;transport=tcp`.
</Step>
<Step title="Attach your number">
On the trunk's **Numbers** tab, add the phone number. Twilio routes its

Check warning on line 100 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L100

Did you really mean 'Twilio'?
calls through the trunk from then on.
</Step>
<Step title="Import on Fish Audio">
Twilio's origination does not answer digest challenges, so authenticate by

Check warning on line 104 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L104

Did you really mean 'Twilio's'?
source address: allow Twilio's published signaling IP ranges for the regions

Check warning on line 105 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L105

Did you really mean 'Twilio's'?
you use (see [Twilio's IP address

Check warning on line 106 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L106

Did you really mean 'Twilio's'?
list](https://www.twilio.com/docs/sip-trunking/ip-addresses)). In the
console, the **Twilio Elastic SIP Trunking preset** button fills the ranges
and sets the transport for you.
Expand All @@ -113,19 +113,19 @@
(`yourprefix.pstn.twilio.com`) and attach a **Credential List**. Pass the
host as `termination_uri` and the credentials as `termination_auth_username`
and `termination_auth_password`. Credentials are required here: Fish Audio's
outbound traffic does not come from fixed IPs, so Twilio IP access control

Check warning on line 116 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L116

Did you really mean 'IPs'?

Check warning on line 116 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L116

Did you really mean 'Twilio'?
lists cannot authorize it.
</Step>
<Step title="Allow transfers (optional)">
For [cold transfers](/agents/telephony/transfers), enable **Call Transfer
(SIP REFER)** in the trunk's settings so Twilio honors the handoff.

Check warning on line 121 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L121

Did you really mean 'Twilio'?
</Step>
</Steps>

### Asterisk, FreePBX, and other SIP platforms

- Route the number's inbound calls to `sip:1pv316az391.sip.livekit.cloud;transport=tcp`.
- Configure digest credentials on the trunk and pass the same pair as `inbound_auth_username` and `inbound_auth_password`; add your PBX's public IPs to `inbound_allowed_addresses` for defense in depth.

Check warning on line 128 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L128

Did you really mean 'PBX's'?

Check warning on line 128 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L128

Did you really mean 'IPs'?
- For outbound, expose a termination host reachable from the internet and pass it as `termination_uri`, with digest credentials if your PBX requires registration or authentication.

## Outbound calls and transfers
Expand All @@ -139,7 +139,7 @@
| **Warm transfers** | No | Yes; the consult leg dials through your trunk |
| **Outbound calls** | No | Yes; caller ID is the imported number |

The number object reports this as `supports_outbound`.
The number object reports this as `supports_outbound`. Place calls with the same API as purchased numbers; see [Outbound calls](/agents/telephony/outbound-calls).

## Update the configuration

Expand All @@ -160,7 +160,7 @@
}'
```

The body is the import payload without `phone_number`, `label`, and `agent_id`, and it replaces the whole configuration. Two conveniences:

Check warning on line 163 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L163

Did you really mean 'phone_number'?

Check warning on line 163 in agents/telephony/byo-sip.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/byo-sip.mdx#L163

Did you really mean 'agent_id'?

- An empty password next to a set username keeps the stored password, so you can edit other fields without re-entering secrets. Setting a username for the first time requires a password.
- An empty `termination_uri` removes the termination and makes the number inbound-only again.
Expand Down
170 changes: 170 additions & 0 deletions agents/telephony/outbound-calls.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
---
title: "Outbound Calls"
description: "Place calls from your phone numbers over the API; the agent speaks when the callee answers"

Check warning on line 3 in agents/telephony/outbound-calls.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/outbound-calls.mdx#L3

Did you really mean 'callee'?
icon: "phone-arrow-up-right"
---

Dial any allowed number from one of your workspace numbers and the agent takes the call the moment the callee picks up. Outbound calls are ordinary agent sessions with `direction: "outbound"`: they appear in session history, they are [stored](/agents/monitor/conversation-history#what-gets-stored) and analyzed under the same per-agent settings as any other conversation, and they trigger the same webhooks plus one extra, [`phone_call.dial_finished`](/agents/monitor/webhooks), that reports how the dial attempt ended.

Check warning on line 7 in agents/telephony/outbound-calls.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/outbound-calls.mdx#L7

Did you really mean 'callee'?

<CardGroup cols={3}>
<Card
title="Phone numbers"
icon="hashtag"
href="/agents/telephony/phone-numbers"
>
Get a number that can place calls.
</Card>
<Card title="Webhooks" icon="webhook" href="/agents/monitor/webhooks">
Get the dial outcome pushed to your backend.
</Card>
<Card
title="Dynamic variables"
icon="brackets-curly"
href="/agents/build/dynamic-variables"
>
Personalize the call with per-call values.
</Card>
</CardGroup>

## Place a call

<Steps>
<Step title="Get a number that supports outbound">
Any [purchased number](/agents/telephony/phone-numbers) can place calls. An [imported BYO number](/agents/telephony/byo-sip) can too, once its termination is configured; the number object reports this as `supports_outbound`. The number you dial from is the caller ID the callee sees.

Check warning on line 33 in agents/telephony/outbound-calls.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/outbound-calls.mdx#L33

Did you really mean 'callee'?
</Step>
<Step title="Publish your agent">
Outbound calls run the agent's published configuration, not the draft. [Publish](/agents/deploy/versions-publishing) before dialing.
</Step>
<Step title="Create the phone call">
```bash
curl --request POST https://api.fish.audio/v1/agent/phone-calls \
--header "Authorization: Bearer $FISH_API_KEY" \
--header "Content-Type: application/json" \
--header "Idempotency-Key: order-4711-reminder-1" \
--data '{
"agent_id": "YOUR_AGENT_ID",
"phone_number_id": "YOUR_PHONE_NUMBER_ID",
"to_number": "+14155550123"
}'
```

The request returns `201` as soon as the dial is dispatched:

```json
{ "session_id": "9c41f0d2e8a34b7f", "status": "queued" }
```

</Step>
</Steps>

This endpoint requires an API key; there is no anonymous variant. See the [API reference](/api-reference/endpoint/agent/create-phone-call) for the full schema.

### Request fields

| Field | Description |
| ------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `agent_id` | Required: the agent that speaks on the call. Must have a published version. |
| `phone_number_id` | Required: the workspace number to dial from. |
| `to_number` | Required: the destination in E.164, for example `+14155550123`. |
| `dynamic_variables` | Optional: per-call values for `{{placeholders}}` in the agent's configured text, same rules as [session creation](/agents/build/dynamic-variables). Up to 50 entries. |
| `overrides` | Optional: replace whole configuration fields for this call, subject to the agent's [override allowlist](/agents/deploy/authenticated-sessions#overrides). |
| `metadata` | Optional: your own JSON object, returned verbatim on session reads and in webhook payloads. Never interpreted. |

The session's [time and timezone context](/agents/build/time-timezone) resolves from the destination number when the agent has no fixed timezone configured, so "tomorrow morning" means the callee's morning.

Check warning on line 73 in agents/telephony/outbound-calls.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/outbound-calls.mdx#L73

Did you really mean 'callee's'?

### Retry safely with an Idempotency-Key

Outbound dials spend money and ring real phones, so put an `Idempotency-Key` header on every create. For 24 hours, repeating the same key with the same body returns the call already placed instead of dialing again. The same key with a **different** body is refused with `422 idempotency_key_reuse`, and a retry that races an in-flight first attempt gets `409 idempotency_key_conflict`; back off and retry the same request. If the create fails with an ambiguous network error, retry with the same key: you get the placed session back if the first attempt went through.

## The dial outcome

Ringing is never billed; metering starts when the callee answers. A call that is never answered is not billed and not analyzed.

Check warning on line 81 in agents/telephony/outbound-calls.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/outbound-calls.mdx#L81

Did you really mean 'callee'?

You learn how the dial ended in either of two ways:

- **Push**: subscribe to the [`phone_call.dial_finished` webhook](/agents/monitor/webhooks). It fires exactly once per outbound call, whether or not anyone picked up, before `call.ended`.
- **Poll**: read `GET /v1/agent/sessions/{session_id}` until `dial_status` is set.

```bash
curl https://api.fish.audio/v1/agent/sessions/9c41f0d2e8a34b7f \
--header "Authorization: Bearer $FISH_API_KEY"
```

Two session fields carry the outcome:

| Field | Values |
| ------------- | ----------------------------------------------------------------------------------------------------------- |
| `dial_status` | `answered`, `busy`, `no_answer`, or `failed`. `null` while the call is still ringing, and on inbound calls. |
| `answered_by` | What answering-machine detection heard: `human`, `voicemail`, or `unknown`. `null` unless answered. |

On outbound sessions the attribution fields are person-centric: `caller_number` is the human you dialed and `dialed_number` is your workspace number. Everything else about the session (transcript, recording, [post-call analysis](/agents/monitor/post-call-analysis), `call.ended` and `call.analyzed` webhooks, hang-up via `POST /v1/agent/sessions/{session_id}/end`) works exactly as for [inbound calls](/agents/telephony/inbound-calls).

## Allowed destinations

Calls from purchased numbers can reach US, Canada, and Japan numbers. Japanese destinations may keep the domestic trunk zero (`+81080...` is accepted and normalized to `+8180...`), and premium-rate segments (such as `0570` Navi Dial and `0990`) are always refused. Calls from [imported BYO numbers](/agents/telephony/byo-sip) dial out through your own trunk, so the country allowlist does not apply; the destination only has to be valid E.164.

Check warning on line 104 in agents/telephony/outbound-calls.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/outbound-calls.mdx#L104

Did you really mean 'Navi'?

Check warning on line 104 in agents/telephony/outbound-calls.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

agents/telephony/outbound-calls.mdx#L104

Did you really mean 'allowlist'?

Numbers that live on the platform can never be dialed, so an agent cannot call another agent's number.

## Limits

| Limit | Default |
| ---------------- | -------------------------------------------------------------------------------- |
| Calls per day | 200 per workspace, on a fixed UTC day. Rejected attempts count toward the quota. |
| Concurrent calls | 10 per workspace, counting calls that are still ringing or in conversation. |

Exceeding either returns `429` with a machine-readable reason (`daily_limit_exceeded`, `concurrency_limit_exceeded`). These are per-workspace defaults; contact support if you need more.

## Errors

Unlike most [Agents API errors](/api-reference/agent-errors), phone-call errors carry a machine-readable `reason` alongside the `message`:

```json
{
"status": 422,
"reason": "destination_not_allowed",
"message": "Outbound calls are limited to US, Canada and Japan numbers"
}
```

| Status | Reason | Cause |
| ------ | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| `402` | `insufficient_credit` | Out of API credit; top up first. |
| `403` | `outbound_disabled` | Outbound calling is switched off for this workspace. |
| `404` | `number_not_found`, `agent_not_found` | The id doesn't exist, isn't yours, or the number was released. |
| `409` | `agent_not_published` | [Publish](/agents/deploy/versions-publishing) the agent first. |
| `409` | `idempotency_key_conflict` | A request with this key is still in flight; back off and retry the same request. |
| `422` | `number_provider_unsupported`, `number_termination_missing`, `number_inactive` | The from-number can't place calls; see [which numbers support outbound](/agents/telephony/byo-sip#outbound-calls-and-transfers). |
| `422` | `destination_invalid`, `destination_not_allowed`, `premium_destination_blocked`, `self_call_blocked` | The destination is refused; see [allowed destinations](#allowed-destinations). |
| `422` | `idempotency_key_reuse` | The key was already used with a different body; mint a fresh key per distinct call. |
| `429` | `daily_limit_exceeded`, `concurrency_limit_exceeded` | A workspace [limit](#limits) was hit. |

`502` and `503` follow the [general guidance](/api-reference/agent-errors#5xx): retrying is safe, especially with an `Idempotency-Key`.

## Going further

<CardGroup cols={2}>
<Card title="Webhooks" icon="webhook" href="/agents/monitor/webhooks">
The `phone_call.dial_finished` payload in full.
</Card>
<Card
title="Transfers"
icon="arrow-right-arrow-left"
href="/agents/telephony/transfers"
>
Hand an answered call to a human; consult legs dial from the same number.
</Card>
<Card
title="Bring your own SIP numbers"
icon="server"
href="/agents/telephony/byo-sip"
>
Place calls through your own trunk with your number as caller ID.
</Card>
<Card
title="Conversation history"
icon="clock-rotate-left"
href="/agents/monitor/conversation-history"
>
Transcripts, recordings, and session listing filters.
</Card>
</CardGroup>
1 change: 1 addition & 0 deletions api-reference/agent-errors.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
]
```

- **Phone-call creation** ([`POST /v1/agent/phone-calls`](/api-reference/endpoint/agent/create-phone-call)) adds a machine-readable `reason` field to its errors; see [Outbound calls](/agents/telephony/outbound-calls#errors) for the full list.
- A request body that isn't valid JSON returns `400` with `"Malformed JSON"`; a missing body or wrong `Content-Type` returns a bare `415`.
- A missing or malformed `Authorization` header returns a bare `401` with a `WWW-Authenticate: Bearer` header; a present-but-bad credential returns the JSON shape (`"Invalid token"`, `"Token expired"`).

Expand All @@ -42,11 +43,11 @@
| `422` | Field-level validation failed | Fix the fields listed in the error array. |
| `429` | Public session creation is rate limited | Back off and retry; per-agent and per-IP windows apply to [public agents](/agents/deploy/public-agents) only. |
| `502` | An upstream dependency (conversation gateway, telephony provider) failed | Retry; for a failed phone-number purchase the row stays visible with status `error` and is safe to release. |
| `503` | A platform dependency is temporarily unavailable | Retry with backoff. |

Check warning on line 46 in api-reference/agent-errors.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

api-reference/agent-errors.mdx#L46

Did you really mean 'backoff'?

## 400 vs 422

`422` is field-level validation: unknown fields (the public surface rejects them), length caps, enum values, invalid IANA timezones, dynamic-variable naming. `400` is semantic: an [override](/agents/deploy/authenticated-sessions#overrides) not enabled for the agent, mutually exclusive pagination parameters (`page` + `cursor`), an undecodable cursor, a page offset past 100,000 rows, or a knowledge upload that isn't UTF-8 plain text.

Check warning on line 50 in api-reference/agent-errors.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

api-reference/agent-errors.mdx#L50

Did you really mean 'undecodable'?

Two quirks worth coding around:

Expand Down Expand Up @@ -87,7 +88,7 @@

## 5xx

`502` names the failing upstream in the message: the conversation gateway (`Agent gateway is unreachable`) or the telephony provider (`Twilio refused the request: …`). Retrying is safe. A failed phone-number purchase leaves the row visible with status `error`, refunds the day charge, and can be released; a failed release keeps the number live so releasing again retries. `503` means a platform dependency was briefly unreachable; retry with backoff.

Check warning on line 91 in api-reference/agent-errors.mdx

View check run for this annotation

Mintlify / Mintlify Validation (hanabiaiinc) - vale-spellcheck

api-reference/agent-errors.mdx#L91

Did you really mean 'backoff'?

## Going further

Expand Down
7 changes: 7 additions & 0 deletions api-reference/endpoint/agent/create-phone-call.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
openapi: post /v1/agent/phone-calls
title: "Create Phone Call"
description: "Place an outbound call from one of your phone numbers; the agent speaks when\nthe callee answers."
icon: "phone-arrow-up-right"
iconType: "solid"
---
Loading
Loading