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

# Bring your own carrier

> Let agents call from the numbers you already own at Telnyx. The calls run on your Telnyx account, which bills the phone minutes; Yappr bills the agent minutes.

If your numbers already live at Telnyx, your agents can call from them. You connect
your Telnyx account once, add the numbers, and pick them as the number an agent calls
from: in the dashboard (**Phone numbers → Your carrier**) or with the
[carrier accounts API](/api-reference/carrier-accounts/create). The numbers stay where
they are: nothing is ported or moved.

<Note>
  Available in every workspace. If you use the API, tick the `carrier_accounts:read` and
  `carrier_accounts:manage` scopes on your API key. Only if Yappr ever has to switch it
  off for a workspace does every carrier-accounts route answer
  `403 CARRIER_ACCOUNTS_NOT_ENABLED` and the dashboard hide the **Your carrier** tab;
  [GET /carrier-accounts/status](/api-reference/carrier-accounts/status) tells you which.
</Note>

## How a call goes out

Yappr places each call **on your Telnyx account**: through a Call Control App in your
account, with an API key you gave Yappr. The agent, the recording, the transcript and
the webhooks are exactly the same as on any other call. So:

* **Telnyx bills your account** for the call: the phone minutes at your rates, plus
  Telnyx's own fees for call control, media streaming, recording and noise
  suppression ([Telnyx pricing](https://telnyx.com/pricing/voice-api)). They never
  appear on your Yappr bill.
* **Yappr bills the agent minutes** at the same per-minute rate as any other call.
* **Caller ID** is your own number, on your own account. Yappr checks with Telnyx that
  every number you add is an active number in that account.
* **Recordings** are copied into Yappr when the call ends, so they keep playing even
  if you later disconnect the account.

This works with **Telnyx**.

## Set it up in Telnyx

1. **Verify your account to Level 2.** Level 1 allows calls inside the US only; Level
   2 turns on international calling, including Israel.
2. **Create an outbound voice profile.** A new profile allows only the US and Canada:
   add every country your agents call, or those calls are refused (Telnyx code D13).
   Set a **channel limit** and a **daily spend limit**: they cap what anyone could
   spend if the key ever leaked.
3. **Create an API key just for Yappr** (Account Settings → API Keys → Create API
   Key) and copy it: Telnyx shows it only once. Telnyx keys cannot be limited to
   certain actions, so keep this one for Yappr alone. Switching it off in Telnyx stops
   Yappr's calls from your account at once.
4. **Copy your public key** (Keys & Credentials → Public Key). Recommended: Yappr uses
   it to check that call events really come from your account.

Then connect it:

5. **Phone numbers → Your carrier → Connect your Telnyx account**, or
   [POST /carrier-accounts](/api-reference/carrier-accounts/create). Paste the key and
   the public key.
6. **Choose the Call Control App.** Pick **Create one for me** and your outbound voice
   profile, and Yappr creates an app named "Yappr outbound" in your account. Or pick
   an app you made just for Yappr, whose webhook URL is exactly the one Yappr shows
   ([POST /carrier-accounts/{id}/connection](/api-reference/carrier-accounts/connection)).
   Yappr never creates or changes an outbound voice profile.
7. **Add the numbers** agents should call from
   ([POST /carrier-accounts/{id}/numbers](/api-reference/carrier-accounts/add-number)).
   They must be active numbers in this Telnyx account. Leave their settings in Telnyx
   as they are: calls *to* them keep going where they go today.
8. **Use them**: as an agent's outbound number, a campaign's number, or `from` on
   [POST /calls](/api-reference/calls/create).

## Status and Turn back on

| `status`   | Meaning                                                                                                                                                          |
| ---------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `untested` | No call has been answered on your app since you connected or turned it back on.                                                                                  |
| `active`   | The last answered call ran on your app.                                                                                                                          |
| `paused`   | Calls from the account's numbers are paused, so campaigns stop instead of burning through leads. `POST /calls` from those numbers answers `INVALID_FROM_NUMBER`. |

An account pauses when Telnyx refuses the API key (`key_rejected`, on a call or on a
[test](/api-reference/carrier-accounts/test)), when the Call Control App is gone or
switched off (`connection_invalid`), or after Telnyx refuses **5 calls in a row**
(`carrier_rejections`). Fix the cause in Telnyx, then press
**Turn back on** in the dashboard or call
[POST /carrier-accounts/{id}/reactivate](/api-reference/carrier-accounts/reactivate).
Yappr runs a [test](/api-reference/carrier-accounts/test) first (it places no call)
and turns the numbers back on only if it passes.

## When Telnyx refuses a call

Telnyx can refuse a call at two moments.

**Before it rings.** Telnyx turns the dial itself down, refuses the API key, or
cannot find the account's Call Control App. The call is recorded as `failed`. If
[POST /calls](/api-reference/calls/create) was placing it right away, it answers
`422` and its `error` says why; no webhook is sent, so that answer is the only
notice. A queued or campaign call refused this way sends `call.failed` with the
reason in `data.error_reason` and no `data.hangup_cause`. A refused key or a missing
app also pauses the account; any other refusal counts toward the 5.

**While it rings.** The call ends as `failed`, and its `disconnect_reason` says so.
If the agent has a webhook, the `call.failed` event carries the verdict in
`data.hangup_cause`:

| `data.hangup_cause`      | SIP codes     | Meaning                                                       |
| ------------------------ | ------------- | ------------------------------------------------------------- |
| `carrier_rejected`       | 401, 403, 407 | Telnyx refused the call. Counts toward the 5 refusals.        |
| `carrier_number_invalid` | 404, 484, 604 | Telnyx could not route the number you called. Does not count. |

| SIP code      | Check in Telnyx                                                                                                                                                                                                      |
| ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 401, 403, 407 | The outbound voice profile is attached to the app (D38) and allows the destination country (D13); the caller ID is a number in this account (D36, D51); the account has balance and Level 2 for international calls. |
| 404, 484, 604 | The destination number.                                                                                                                                                                                              |

The SIP code itself is not in the webhook: the account keeps the last one in
`last_error.sip_code` on [GET /carrier-accounts/{id}](/api-reference/carrier-accounts/get).
The exact Telnyx reason (the D-code) is only in your Telnyx portal's call debugging.

## Numbers that leave your account

Every [test](/api-reference/carrier-accounts/test) asks Telnyx again whether each
number is still in your account. A number it no longer lists shows **Not verified**
(`ownership_verified_at: null`) and cannot make calls until a later test finds it
again.

A number is in Yappr once. If another workspace registered your number but its own
Telnyx key no longer proves it, Yappr releases that claim when you add the number. If
that workspace still uses the number (a campaign calls from it, or past calls were
made from it), its claim is switched off instead of removed, so its history stays
intact, and adding the number answers `409 NUMBER_ALREADY_REGISTERED`: contact Yappr
support to move it.

## Calls to your numbers

This is outbound only. Calls **to** your numbers keep going where they go today. To
have an agent answer them, route the number in Telnyx to a
[SIP endpoint](/api-reference/sip-endpoints/create). If a call to one of your numbers
reaches the "Yappr outbound" app, Yappr refuses it.

## Security

* The API key is stored encrypted and is never returned, not by the API and not in
  the dashboard: only its last four characters. You can only replace it.
* Yappr uses the key only to check your account, create the app it calls through,
  place and control your calls, and fetch their recordings.
* Call events from Telnyx for your calls are accepted only on your account's secret
  webhook URL, and, once your public key has verified one, only with a valid Telnyx
  signature. Events for another app in your account are ignored.
* Only workspace owners and admins can connect, update, test or disconnect an
  account, or add and remove its numbers. API keys need the `carrier_accounts:manage`
  scope (`carrier_accounts:read` to list them). Neither is on by default: create a key
  with them.
* A dedicated key, plus your outbound voice profile's channel and daily spend limits,
  keep what a leaked key could do small, and you can switch it off on its own.
