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

# Buying a Phone Number

> Purchase Truedy-managed phone numbers for outbound and inbound calling

# Buying a Phone Number

Truedy-managed numbers are the fastest way to get a phone number ready for your agent. Truedy purchases the number from its carrier partner, configures all routing automatically, and adds the number to your account — no external provider dashboard required.

This guide covers searching for available numbers, purchasing via the dashboard or API, assigning to an agent, and releasing numbers you no longer need.

## Prerequisites

* A Truedy account with an active subscription.
* An API key (for API-based provisioning) — see [Authentication](/authentication).
* At least one agent created — see [Creating an Agent](/guides/creating-an-agent).

## Dashboard flow

<Steps>
  <Step title="Open Phone Numbers">
    In the Truedy dashboard, navigate to **Settings → Phone Numbers**.
  </Step>

  <Step title="Click Buy Number">
    Click the **Buy Number** button in the top-right corner of the Phone Numbers page.
  </Step>

  <Step title="Select country and area code">
    Choose the **country** from the dropdown. For US/Canada numbers, optionally enter a preferred **area code** to narrow results. Select a **number type** (local, toll-free, or mobile where available).
  </Step>

  <Step title="Review available numbers">
    Truedy returns a list of available numbers matching your criteria. Each row shows the full number, type, and monthly cost.
  </Step>

  <Step title="Purchase">
    Click **Buy** next to the number you want. Confirm the purchase in the dialog. The number appears in your Phone Numbers list immediately.
  </Step>

  <Step title="Assign to an agent">
    Click the number in the list, then select an agent from the **Assigned Agent** dropdown and save. The number is now active for outbound and inbound calls on that agent.
  </Step>
</Steps>

## API flow

### Step 1 — Search available numbers

Search for numbers matching your requirements. This is a `POST` with a JSON body.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.truedy.ai/api/public/v1/telephony/numbers/search \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "country_code": "US",
      "area_code": "415",
      "phone_number_type": "local",
      "page_size": 10
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.truedy.ai/api/public/v1/telephony/numbers/search",
      headers={
          "Authorization": "Bearer YOUR_API_KEY",
          "Content-Type": "application/json",
      },
      json={
          "country_code": "US",
          "area_code": "415",
          "phone_number_type": "local",
          "page_size": 10,
      },
  )
  response.raise_for_status()
  numbers = response.json()["data"]
  for n in numbers:
      print(n["phone_number"], n.get("cost_information", {}).get("monthly_cost"))
  ```

  ```typescript TypeScript theme={null}
  const response = await fetch(
    'https://api.truedy.ai/api/public/v1/telephony/numbers/search',
    {
      method: 'POST',
      headers: {
        Authorization: `Bearer ${process.env.TRUEDY_API_KEY}`,
        'Content-Type': 'application/json',
      },
      body: JSON.stringify({
        country_code: 'US',
        area_code: '415',
        phone_number_type: 'local',
        page_size: 10,
      }),
    }
  )
  const { data: numbers } = await response.json()
  numbers.forEach((n: { phone_number: string }) => console.log(n.phone_number))
  ```
</CodeGroup>

**Request body:**

| Field                 | Type    | Required | Description                                    |
| --------------------- | ------- | -------- | ---------------------------------------------- |
| `country_code`        | string  | No       | ISO 3166-1 alpha-2 country code. Default: `US` |
| `area_code`           | string  | No       | Preferred area code / NPA (US/Canada only)     |
| `administrative_area` | string  | No       | State or province abbreviation (e.g. `CA`)     |
| `locality`            | string  | No       | City name to narrow results                    |
| `phone_number_type`   | string  | No       | `local` (default), `toll-free`, or `mobile`    |
| `page`                | integer | No       | Page number for pagination. Default: `1`       |
| `page_size`           | integer | No       | Results per page. Default: `20`, max: `50`     |

**Response** includes a `data` array of available numbers, each with `phone_number` (E.164), `phone_number_type`, `features`, and `cost_information`.

<Tip>
  If your preferred area code shows no results, try searching without `area_code` to see all available numbers in that country, then pick the closest match.
</Tip>

***

### Step 2 — Purchase a number

Pass the exact `phone_number` from the search results to purchase it.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://api.truedy.ai/api/public/v1/telephony/numbers/purchase \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "phone_number": "+14155551234"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      "https://api.truedy.ai/api/public/v1/telephony/numbers/purchase",
      headers={
          "Authorization": "Bearer YOUR_API_KEY",
          "Content-Type": "application/json",
      },
      json={"phone_number": "+14155551234"},  # E.164 number from search results
  )
  response.raise_for_status()
  purchased = response.json()["data"]
  number_id = purchased["id"]
  print(f"Purchased: {purchased['phone_number']}  (id: {number_id})")
  ```

  ```typescript TypeScript theme={null}
  const res = await fetch('https://api.truedy.ai/api/public/v1/telephony/numbers/purchase', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${process.env.TRUEDY_API_KEY}`,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ phone_number: '+14155551234' }),
  })
  const { data: purchased } = await res.json()
  const numberId = purchased.id
  ```
</CodeGroup>

**Request body:**

| Field          | Type   | Required | Description                                                         |
| -------------- | ------ | -------- | ------------------------------------------------------------------- |
| `phone_number` | string | Yes      | E.164 number to purchase (from search results, e.g. `+14155551234`) |

**Response** returns the created phone number object including `id`, `phone_number`, `status`, and `is_truedy_managed: true`.

***

### Step 3 — Assign the number to an agent

After purchasing, assign the number to an agent. Specify whether it's for **inbound**, **outbound**, or both (run the request twice).

<CodeGroup>
  ```bash cURL theme={null}
  # Assign for outbound (agent places calls from this number)
  curl -X POST https://api.truedy.ai/api/public/v1/telephony/numbers/assign \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "number_id": "NUMBER_UUID",
      "agent_id": "AGENT_UUID",
      "assignment_type": "outbound"
    }'

  # Also assign for inbound (agent receives calls on this number)
  curl -X POST https://api.truedy.ai/api/public/v1/telephony/numbers/assign \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "number_id": "NUMBER_UUID",
      "agent_id": "AGENT_UUID",
      "assignment_type": "inbound"
    }'
  ```

  ```python Python theme={null}
  import requests

  BASE = "https://api.truedy.ai/api/public/v1"
  HEADERS = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
  }

  def assign_number(number_id: str, agent_id: str, assignment_type: str):
      resp = requests.post(
          f"{BASE}/telephony/numbers/assign",
          headers=HEADERS,
          json={
              "number_id": number_id,
              "agent_id": agent_id,
              "assignment_type": assignment_type,  # "inbound" or "outbound"
          },
      )
      resp.raise_for_status()
      return resp.json()["data"]

  # Assign for outbound calling
  assign_number(number_id, agent_id, "outbound")

  # Assign for inbound calling (same number can handle both)
  assign_number(number_id, agent_id, "inbound")
  print("Number assigned for inbound and outbound.")
  ```

  ```typescript TypeScript theme={null}
  const BASE = 'https://api.truedy.ai/api/public/v1'
  const headers = {
    Authorization: `Bearer ${process.env.TRUEDY_API_KEY}`,
    'Content-Type': 'application/json',
  }

  async function assignNumber(numberId: string, agentId: string, assignmentType: 'inbound' | 'outbound') {
    const res = await fetch(`${BASE}/telephony/numbers/assign`, {
      method: 'POST',
      headers,
      body: JSON.stringify({ number_id: numberId, agent_id: agentId, assignment_type: assignmentType }),
    })
    if (!res.ok) throw new Error(`Assign failed: ${res.status}`)
    return res.json()
  }

  await assignNumber(numberId, agentId, 'outbound')
  await assignNumber(numberId, agentId, 'inbound')
  ```
</CodeGroup>

**Assign request body:**

| Field             | Type   | Required | Description                                                                        |
| ----------------- | ------ | -------- | ---------------------------------------------------------------------------------- |
| `number_id`       | string | Yes      | ID of the phone number to assign                                                   |
| `agent_id`        | string | Yes      | ID of the agent to assign the number to                                            |
| `assignment_type` | string | Yes      | `inbound` — agent receives calls; `outbound` — agent places calls from this number |

<Note>
  Inbound and outbound are **separate assignments**. A single number can be assigned to the same (or different) agents for each direction. Run the assign request twice with `"inbound"` and `"outbound"` to enable both.
</Note>

To unassign: `POST /telephony/numbers/unassign` with `{number_id, assignment_type}`.

***

### Full end-to-end example

<CodeGroup>
  ```bash cURL theme={null}
  BASE="https://api.truedy.ai/api/public/v1"
  KEY="YOUR_API_KEY"

  # 1. Search
  curl -s -X POST "$BASE/telephony/numbers/search" \
    -H "Authorization: Bearer $KEY" \
    -H "Content-Type: application/json" \
    -d '{"country_code":"US","area_code":"212","phone_number_type":"local","page_size":5}'

  # 2. Purchase (use a phone_number from step 1)
  curl -s -X POST "$BASE/telephony/numbers/purchase" \
    -H "Authorization: Bearer $KEY" \
    -H "Content-Type: application/json" \
    -d '{"phone_number":"+12125550123"}'

  # 3. Assign for outbound (use number id from step 2)
  curl -s -X POST "$BASE/telephony/numbers/assign" \
    -H "Authorization: Bearer $KEY" \
    -H "Content-Type: application/json" \
    -d '{"number_id":"NUMBER_UUID","agent_id":"AGENT_UUID","assignment_type":"outbound"}'
  ```

  ```python Python theme={null}
  import requests

  BASE = "https://api.truedy.ai/api/public/v1"
  HEADERS = {
      "Authorization": "Bearer YOUR_API_KEY",
      "Content-Type": "application/json",
  }
  AGENT_ID = "AGENT_UUID"

  # 1. Search for available numbers
  search = requests.post(
      f"{BASE}/telephony/numbers/search",
      headers=HEADERS,
      json={"country_code": "US", "area_code": "212", "phone_number_type": "local"},
  )
  search.raise_for_status()
  available = search.json()["data"]
  phone_to_buy = available[0]["phone_number"]
  print(f"Buying: {phone_to_buy}")

  # 2. Purchase the number
  purchase = requests.post(
      f"{BASE}/telephony/numbers/purchase",
      headers=HEADERS,
      json={"phone_number": phone_to_buy},
  )
  purchase.raise_for_status()
  number_id = purchase.json()["data"]["id"]
  print(f"Purchased number ID: {number_id}")

  # 3. Assign for outbound
  requests.post(
      f"{BASE}/telephony/numbers/assign",
      headers=HEADERS,
      json={"number_id": number_id, "agent_id": AGENT_ID, "assignment_type": "outbound"},
  ).raise_for_status()
  print("Number ready for outbound calls.")
  ```
</CodeGroup>

***

## Billing

* Numbers are billed on a **monthly flat fee** from the date of purchase.
* The monthly fee renews automatically and is charged to your Truedy subscription.
* Per-minute charges for calls placed or received on the number are billed separately.
* All charges appear on your Truedy invoice — there is no separate carrier invoice for Truedy-managed numbers.

<Note>
  You can see current number pricing in the dashboard when browsing available numbers, or via the `cost_information.monthly_cost` field in the search API response.
</Note>

***

## US and Canada vs international availability

* **US and Canada** have the broadest inventory. Local numbers are available in virtually all area codes. Toll-free (800, 888, 877, 866, 855, 844, 833) numbers are widely available.
* **UK, Australia, and major EU markets** have good availability for local numbers.
* **Other countries** vary significantly. Run a search against the API to confirm availability before building a workflow that depends on a specific country or region.

***

## Releasing a number

When you no longer need a number, release it to stop billing.

**Dashboard:** Settings → Phone Numbers → select the number → **Release Number**.

**API:**

```bash theme={null}
curl -X DELETE https://api.truedy.ai/api/public/v1/telephony/numbers/NUMBER_UUID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

<Warning>
  Releasing a number is **immediate and irreversible**. The number is returned to carrier inventory and may be reassigned to another customer. Unassign the number from all agents and campaigns before releasing it.
</Warning>

***

## Next steps

<Columns>
  <Card title="Importing Phone Numbers" icon="arrow-down-to-line" href="/guides/importing-phone-numbers">
    Bring your own Twilio or Telnyx number
  </Card>

  <Card title="Telephony Overview" icon="phone" href="/guides/telephony-overview">
    Understand the full telephony model
  </Card>

  <Card title="Making Outbound Calls" icon="phone-outgoing" href="/guides/making-outbound-calls">
    Place your first call with the new number
  </Card>

  <Card title="Setting Up Inbound" icon="phone-incoming" href="/guides/setting-up-inbound-calls">
    Route inbound calls to your agent
  </Card>
</Columns>
