From 0bef3a96dac0d0f2b5dcdeaf209defb1941e8ddf Mon Sep 17 00:00:00 2001 From: virgoone Date: Thu, 29 Oct 2026 16:30:50 +0900 Subject: [PATCH 1/2] docs(agents): document verified numbers for outbound calls before adding credit Explain that purchased numbers can only call verified numbers until the team adds API credit, how to verify a number in the console or over the API, and the new outbound_requires_credit error. Co-Authored-By: Claude Opus 5.5 (1M context) --- agents/telephony/outbound-calls.mdx | 125 ++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) diff --git a/agents/telephony/outbound-calls.mdx b/agents/telephony/outbound-calls.mdx index 056c51b9..6f159448 100644 --- a/agents/telephony/outbound-calls.mdx +++ b/agents/telephony/outbound-calls.mdx @@ -126,6 +126,130 @@ Calls from [imported BYO numbers](/agents/telephony/byo-sip) dial out through yo Numbers that live on the platform can never be dialed, so an agent cannot call another agent's number. +## Calls before you add credit + +Until your team adds API credit, purchased numbers can only call numbers your team has [verified](#verify-a-number). Calls to any other number are refused with `403 outbound_requires_credit`. + +- Your API credit must be above zero. The [trial balance](/agents/pricing#trial-balance) does not count. +- Teams billed by invoice under a contract are not restricted. +- [Imported BYO numbers](/agents/telephony/byo-sip) are not restricted. They dial out through your own trunk. +- Once your team has API credit, purchased numbers can call any [allowed destination](#allowed-destinations). + +### Verify a number + +Verifying proves that your team controls the number. You get a one-time code by text message or by phone call. Use a phone call for numbers that cannot receive texts, such as landlines. + + + + + + On the agent's **Phone** page, open **Outbound calls**. The **Verified numbers** card lists your team's verified numbers. + + + Click **Verify a number** and enter the number. Under **Get the code by**, pick **Text message** or **Phone call**. Click **Send code**. + + + Type the code you received and click **Verify**. + + + + + Request a code. `channel` is `sms` (the default) or `call`: + + ```bash + curl --request POST https://api.fish.audio/v1/agent/verified-phone-numbers/verifications \ + --header "Authorization: Bearer $FISH_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ "phone_number": "+14155550123", "channel": "sms" }' + ``` + + The request returns `202`: + + ```json + { + "phone_number": "+14155550123", + "channel": "sms", + "status": "pending", + "expires_at": "2026-01-15T10:10:00Z" + } + ``` + + Confirm the code: + + ```bash + curl --request POST https://api.fish.audio/v1/agent/verified-phone-numbers/verifications/confirm \ + --header "Authorization: Bearer $FISH_API_KEY" \ + --header "Content-Type: application/json" \ + --data '{ "phone_number": "+14155550123", "code": "123456" }' + ``` + + The request returns `201` with the verified number: + + ```json + { + "verified_phone_number_id": "3f9a1c0e7b2d4e8f9a6b5c4d3e2f1a0b", + "phone_number": "+14155550123", + "verified_by": "YOUR_USER_ID", + "verified_at": "2026-01-15T10:02:41Z" + } + ``` + + + + +- The code is valid for 10 minutes. +- Five wrong codes cancel the pending verification. Request a new code after that. +- Sending codes is rate limited per number and per team. +- The number must be an [allowed destination](#allowed-destinations). +- Verified numbers belong to the team. Every agent and number in the team can call them. +- A team can have up to 10 verified numbers. Remove one to add another. + +### Manage verified numbers + +List your team's verified numbers: + +```bash +curl https://api.fish.audio/v1/agent/verified-phone-numbers \ + --header "Authorization: Bearer $FISH_API_KEY" +``` + +```json +{ + "verified_phone_numbers": [ + { + "verified_phone_number_id": "3f9a1c0e7b2d4e8f9a6b5c4d3e2f1a0b", + "phone_number": "+14155550123", + "verified_by": "YOUR_USER_ID", + "verified_at": "2026-01-15T10:02:41Z" + } + ], + "third_party_calls_allowed": false +} +``` + +`third_party_calls_allowed` is `true` once your team can call numbers outside the list. While it is `false`, the restriction applies. + +Remove a number with `DELETE /v1/agent/verified-phone-numbers/{verified_phone_number_id}`. It returns `204`. In the console, team owners and admins can remove any verified number. Other members can remove the numbers they verified. + +### Verification errors + +Verification errors carry a `reason`, like phone-call errors: + +| Status | Reason | Cause | +| ------ | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | +| `404` | `verification_not_found` | No pending code for this number, or the code expired. Request a new one. | +| `404` | `verified_phone_number_not_found` | The verified number doesn't exist or isn't your team's. | +| `409` | `phone_already_verified` | The number is already on your team's list. | +| `409` | `verified_numbers_limit_reached` | Your team has 10 verified numbers. Remove one first. | +| `422` | `phone_number_invalid` | The number is not valid E.164, or codes cannot be delivered to it. | +| `422` | `destination_not_allowed`, `premium_destination_blocked` | The number is not an [allowed destination](#allowed-destinations). | +| `422` | `phone_number_cannot_receive_sms` | The number cannot receive texts. Request the code with `"channel": "call"`. | +| `422` | `phone_verification_blocked` | Codes cannot be sent to this number. | +| `422` | `verification_code_invalid` | The code is wrong. The message says how many attempts are left. | +| `429` | `verification_rate_limited` | Too many codes requested. Try again later. | +| `429` | `verification_attempts_exceeded` | Too many wrong codes. Request a new one. | +| `503` | `phone_verification_unavailable` | Phone verification is temporarily unavailable. Try again later. | + ## Errors Unlike most [Agents API errors](/api-reference/agent-errors), phone-call errors carry a machine-readable `reason` alongside the `message`: @@ -142,6 +266,7 @@ Unlike most [Agents API errors](/api-reference/agent-errors), phone-call errors | ------ | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `402` | `insufficient_credit` | Out of API credit; top up first. | | `403` | `outbound_disabled` | Outbound calling is switched off for this workspace. | +| `403` | `outbound_requires_credit` | Your team has no API credit yet and the destination is not verified. See [calls before you add credit](#calls-before-you-add-credit). | | `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. | From 0e1b900d8fe1e6cfb7e65e6466fb331ad709abd6 Mon Sep 17 00:00:00 2001 From: virgoone Date: Fri, 30 Oct 2026 18:18:44 +0900 Subject: [PATCH 2/2] docs(agents): verify numbers in the console, paid teams call any number Teams that have paid (bought API credit once, a paid subscription, or an invoice contract) can call any allowed destination. Until then, numbers are verified from the call window on the Outbound calls page. Sending a code needs reCAPTCHA, so the API section keeps list and delete only. Adds the recaptcha and self_call_blocked verification errors. Co-Authored-By: Claude Opus 5.5 (1M context) --- agents/telephony/outbound-calls.mdx | 138 ++++++++++++---------------- 1 file changed, 59 insertions(+), 79 deletions(-) diff --git a/agents/telephony/outbound-calls.mdx b/agents/telephony/outbound-calls.mdx index 6f159448..7ce0b862 100644 --- a/agents/telephony/outbound-calls.mdx +++ b/agents/telephony/outbound-calls.mdx @@ -126,86 +126,56 @@ Calls from [imported BYO numbers](/agents/telephony/byo-sip) dial out through yo Numbers that live on the platform can never be dialed, so an agent cannot call another agent's number. -## Calls before you add credit +## Calls before your team has paid -Until your team adds API credit, purchased numbers can only call numbers your team has [verified](#verify-a-number). Calls to any other number are refused with `403 outbound_requires_credit`. +Until your team has paid for Fish Audio, purchased numbers can only call numbers your team has [verified](#verify-a-number). Calls to any other number are refused with `403 outbound_requires_credit`. -- Your API credit must be above zero. The [trial balance](/agents/pricing#trial-balance) does not count. -- Teams billed by invoice under a contract are not restricted. -- [Imported BYO numbers](/agents/telephony/byo-sip) are not restricted. They dial out through your own trunk. -- Once your team has API credit, purchased numbers can call any [allowed destination](#allowed-destinations). - -### Verify a number +Your team counts as paid once any of these is true: -Verifying proves that your team controls the number. You get a one-time code by text message or by phone call. Use a phone call for numbers that cannot receive texts, such as landlines. +- You have bought API credit at least once. This still counts after the balance is spent. +- You have a paid subscription. +- Your team is billed by invoice under a contract. - - - - - On the agent's **Phone** page, open **Outbound calls**. The **Verified numbers** card lists your team's verified numbers. - - - Click **Verify a number** and enter the number. Under **Get the code by**, pick **Text message** or **Phone call**. Click **Send code**. - - - Type the code you received and click **Verify**. - - - - - Request a code. `channel` is `sms` (the default) or `call`: +Free credit and trials do not count. - ```bash - curl --request POST https://api.fish.audio/v1/agent/verified-phone-numbers/verifications \ - --header "Authorization: Bearer $FISH_API_KEY" \ - --header "Content-Type: application/json" \ - --data '{ "phone_number": "+14155550123", "channel": "sms" }' - ``` - - The request returns `202`: - - ```json - { - "phone_number": "+14155550123", - "channel": "sms", - "status": "pending", - "expires_at": "2026-01-15T10:10:00Z" - } - ``` +- [Imported BYO numbers](/agents/telephony/byo-sip) are not restricted. They dial out through your own trunk. +- Once your team has paid, purchased numbers can call any [allowed destination](#allowed-destinations). - Confirm the code: +### Verify a number - ```bash - curl --request POST https://api.fish.audio/v1/agent/verified-phone-numbers/verifications/confirm \ - --header "Authorization: Bearer $FISH_API_KEY" \ - --header "Content-Type: application/json" \ - --data '{ "phone_number": "+14155550123", "code": "123456" }' - ``` +Verifying proves that your team controls the number. You get a one-time code by text message or by phone call. Use a phone call for numbers that cannot receive texts, such as landlines. - The request returns `201` with the verified number: +Verify numbers in the console. Sending a code needs a reCAPTCHA check in the browser, so you cannot request codes with an API key alone. - ```json - { - "verified_phone_number_id": "3f9a1c0e7b2d4e8f9a6b5c4d3e2f1a0b", - "phone_number": "+14155550123", - "verified_by": "YOUR_USER_ID", - "verified_at": "2026-01-15T10:02:41Z" - } - ``` + + + On the agent's **Phone** page, open **Outbound calls** and place a call to the number. If the number is not verified yet, a window opens and asks you to verify it. + + + Under **Get the code by**, pick **Text message** or **Phone call**. Click **Verify this number**. + + + Type the code you received. For a phone call, answer and press a key when the call asks you to. The call then reads out the code. + + + Once the code is accepted, the console places your call again. + + - - +The window also links to adding credits or subscribing. Do that to call any number without verifying it. - The code is valid for 10 minutes. -- Five wrong codes cancel the pending verification. Request a new code after that. +- Five wrong codes cancel the pending code. Request a new one after that. - Sending codes is rate limited per number and per team. - The number must be an [allowed destination](#allowed-destinations). +- Numbers that live on the platform cannot be verified. - Verified numbers belong to the team. Every agent and number in the team can call them. -- A team can have up to 10 verified numbers. Remove one to add another. +- A team can have up to 10 verified numbers. [Remove one](#manage-verified-numbers) to add another. ### Manage verified numbers +List and remove verified numbers over the API. + List your team's verified numbers: ```bash @@ -227,28 +197,38 @@ curl https://api.fish.audio/v1/agent/verified-phone-numbers \ } ``` -`third_party_calls_allowed` is `true` once your team can call numbers outside the list. While it is `false`, the restriction applies. +`third_party_calls_allowed` is `true` once your team has paid. Then you can call numbers outside the list. While it is `false`, the restriction applies. + +Remove a number: + +```bash +curl --request DELETE https://api.fish.audio/v1/agent/verified-phone-numbers/3f9a1c0e7b2d4e8f9a6b5c4d3e2f1a0b \ + --header "Authorization: Bearer $FISH_API_KEY" +``` -Remove a number with `DELETE /v1/agent/verified-phone-numbers/{verified_phone_number_id}`. It returns `204`. In the console, team owners and admins can remove any verified number. Other members can remove the numbers they verified. +The request returns `204`. ### Verification errors Verification errors carry a `reason`, like phone-call errors: -| Status | Reason | Cause | -| ------ | -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | -| `404` | `verification_not_found` | No pending code for this number, or the code expired. Request a new one. | -| `404` | `verified_phone_number_not_found` | The verified number doesn't exist or isn't your team's. | -| `409` | `phone_already_verified` | The number is already on your team's list. | -| `409` | `verified_numbers_limit_reached` | Your team has 10 verified numbers. Remove one first. | -| `422` | `phone_number_invalid` | The number is not valid E.164, or codes cannot be delivered to it. | -| `422` | `destination_not_allowed`, `premium_destination_blocked` | The number is not an [allowed destination](#allowed-destinations). | -| `422` | `phone_number_cannot_receive_sms` | The number cannot receive texts. Request the code with `"channel": "call"`. | -| `422` | `phone_verification_blocked` | Codes cannot be sent to this number. | -| `422` | `verification_code_invalid` | The code is wrong. The message says how many attempts are left. | -| `429` | `verification_rate_limited` | Too many codes requested. Try again later. | -| `429` | `verification_attempts_exceeded` | Too many wrong codes. Request a new one. | -| `503` | `phone_verification_unavailable` | Phone verification is temporarily unavailable. Try again later. | +| Status | Reason | Cause | +| ------ | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------ | +| `400` | `recaptcha_failed` | The reCAPTCHA check failed or no token was sent. Request the code in the console. | +| `404` | `verification_not_found` | No pending code for this number, or the code expired. Request a new one. | +| `404` | `verified_phone_number_not_found` | The verified number doesn't exist or isn't your team's. | +| `409` | `phone_already_verified` | The number is already on your team's list. | +| `409` | `verified_numbers_limit_reached` | Your team has 10 verified numbers. Remove one first. | +| `422` | `phone_number_invalid` | The number is not valid E.164, or codes cannot be delivered to it. | +| `422` | `destination_invalid`, `destination_not_allowed`, `premium_destination_blocked` | The number is not an [allowed destination](#allowed-destinations). | +| `422` | `self_call_blocked` | The number lives on the platform. It cannot be verified. | +| `422` | `phone_number_cannot_receive_sms` | The number cannot receive texts. Get the code by phone call instead. | +| `422` | `phone_verification_blocked` | Codes cannot be sent to this number. | +| `422` | `verification_code_invalid` | The code is wrong. The message says how many attempts are left. | +| `429` | `verification_rate_limited` | Too many codes requested. Try again later. | +| `429` | `verification_attempts_exceeded` | Too many wrong codes. Request a new one. | +| `502` | `recaptcha_unavailable` | The reCAPTCHA check is temporarily unavailable. No code was sent. Try again shortly. | +| `503` | `phone_verification_unavailable` | Phone verification is temporarily unavailable. Try again later. | ## Errors @@ -266,7 +246,7 @@ Unlike most [Agents API errors](/api-reference/agent-errors), phone-call errors | ------ | ---------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | `402` | `insufficient_credit` | Out of API credit; top up first. | | `403` | `outbound_disabled` | Outbound calling is switched off for this workspace. | -| `403` | `outbound_requires_credit` | Your team has no API credit yet and the destination is not verified. See [calls before you add credit](#calls-before-you-add-credit). | +| `403` | `outbound_requires_credit` | Your team has not paid yet and the destination is not verified. See [calls before your team has paid](#calls-before-your-team-has-paid). | | `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. |