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

# AI voice calls

> Collect by voice, over phone or WhatsApp, through the API.

Payable can **call the debtor** with a voice assistant that confirms identity, presents the debt and negotiates within your collection flow's limits (discount, installments, rescheduling). During the call it can send the PIX or payment link, record a promise to pay, and transfer to a human when asked.

There are two ways to reach the client (`medium`):

| `medium` | What happens |
| - | - |
| `pstn` | A regular phone call to the client's mobile. Default. |
| `whatsapp` | A WhatsApp voice call. Meta requires the client to **accept a call permission** first, so the call waits in `awaiting_permission`. If they decline or do not answer, it falls back to `pstn` when `fallbackToPstn` is `true` (default). |

API key scopes needed: `voice-calls:read` and `voice-calls:write`.

## Start a call

```bash theme={null}
curl -X POST "https://api.payable.run/api/v1/voice-calls" \
  -H "Authorization: Bearer esk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "clientId": "client_uuid",
    "debtId": "debt_uuid",
    "medium": "pstn"
  }'
```

`clientId` and `debtId` are required: every call is about one of the client's open debts.

The response is the call with `status: "queued"` (or `"awaiting_permission"` on WhatsApp) and a `warnings` array of non-blocking notices, for example when you set `allowOutsideWindow: true` to call outside the flow's time window.

### Errors

All follow [RFC 9457](https://docs.payable.run/errors.md). Decide by `code`:

| `code` | Meaning | Retry? |
| - | - | - |
| `VOICE_CALLS_DISABLED` | Calls are not enabled on the platform or in the flow | No |
| `CLIENT_HAS_NO_OPEN_DEBT` | The debt is not open for this client | No |
| `VOICE_MEDIUM_UNAVAILABLE` | The requested `medium` is not configured | No (try the other medium) |
| `VOICE_INVALID_PHONE` | The client has no valid mobile number | After fixing the record |
| `CHANNEL_OPTED_OUT` | The client asked not to be called (or unsubscribed from WhatsApp) | No |
| `CALL_IN_PROGRESS` | A call is already queued or running for this client | After it ends |
| `OUTSIDE_CALL_WINDOW` | Outside the flow's allowed hours | With `allowOutsideWindow: true`, or later |
| `VOICE_DAILY_ATTEMPTS_REACHED` | Daily attempt limit for this client | Next day |
| `INSUFFICIENT_BALANCE` | Not enough balance | After a top-up |

## Track a call

```bash theme={null}
curl "https://api.payable.run/api/v1/voice-calls/{id}" -H "Authorization: Bearer esk_live_..."
curl "https://api.payable.run/api/v1/voice-calls?debtId=debt_uuid&status=completed" -H "Authorization: Bearer esk_live_..."
```

`status` lifecycle: `queued` → (`awaiting_permission` →) `dialing` → `in_progress` → `completed` | `failed`. `cancelled` is only possible before dialing (`POST /voice-calls/{id}/cancel`).

When a call ends it gets an `outcome`:

| `outcome` | Description |
| - | - |
| `negotiated` | Client accepted installments or a new due date |
| `promise_to_pay` | Client promised to pay on a date (`promiseToPayDate`) |
| `paid_during_call` | Payment confirmed during the call |
| `callback_requested` | Client asked to be called back |
| `refused` | Answered, but nothing was agreed |
| `no_answer` / `busy` / `voicemail` | Not reached (the flow tries again within its limits) |
| `wrong_number` | The person answering does not know the client |
| `transferred_to_human` | Transferred to the support phone |
| `permission_denied` | WhatsApp: client did not allow the call |
| `failed` | Technical failure |

`summary` and `transcript` are in Portuguese. `analysis.source` tells you whether the outcome came from recorded tool actions (deterministic), from the provider, or was inferred by AI from the transcript.

## Recording

`GET /voice-calls/{id}/recording` returns `{ "url": "...", "expiresInSeconds": 86400 }` with a signed URL. Use `?redirect=1` for a direct 302 to the file. Recordings are kept for up to 180 days.

## Webhook

`voice_call.completed` fires when each call ends (see [Webhooks](https://docs.payable.run/webhooks.md)):

```json theme={null}
{
  "type": "voice_call.completed",
  "data": {
    "id": "vc_uuid",
    "clientId": "client_uuid",
    "debtId": "debt_uuid",
    "medium": "pstn",
    "trigger": "flow",
    "status": "completed",
    "outcome": "promise_to_pay",
    "answered": true,
    "durationSeconds": 95,
    "billedAmountCents": 298,
    "promiseToPayDate": "2026-10-01",
    "recordingUrl": "https://...(24h)",
    "summary": "O cliente prometeu pagar em 01/10/2026."
  }
}
```

## Pricing

Charged per started minute of answered calls (`voice_call_minute`) plus a fixed fee per unanswered attempt (`voice_call_attempt`). Current values are in `GET /voice-calls/config`.

## In the collection flow

Under **Flows → AI voice calls** in the dashboard you enable the channel and set the call window (default 8am–8pm, Monday to Saturday), attempts per day and per step, the voice, and the transfer phone. Then turn on "Call (AI)" on the steps you want. Outside the window the flow holds the step until the next opening; with no answer it retries within the limits.


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