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

# Buy and release phone numbers through the API

> Search, buy, attach and release Brilo phone numbers with the API or MCP tools: price consent, the daily limit, owner-only purchases, release at period end and refunds.

Buy a phone number for an agent in two Brilo API calls: search for one and show the owner its
monthly price, then buy it at that price. Releasing a number keeps it working until the end of
the month already paid for, and you can change your mind until then.

## Before you start

* A Brilo API key that belongs to a person, from **Settings**, then **Developer**. A paired
  assistant's key can search and attach numbers but cannot buy one.
* A card on file for the workspace, added by the owner in the dashboard's billing settings.
* The Agents API turned on for your workspace. While it is off, these routes answer 404.

## Steps

**1. Search for a number and show the owner its price**

```bash theme={null}
curl "https://api.brilo.ai/v1/phone_numbers/available?country=US&area_code=512&limit=5" \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Each result has `monthly_price` and `currency`. When your plan includes free numbers and one is
left, `within_free_allowance` is true and the price is 0. Over MCP, call
`search_available_phone_numbers`. An AI agent should show the owner the price and wait for a yes.

**2. Buy it at the price the owner accepted**

```bash theme={null}
curl -X POST "https://api.brilo.ai/v1/phone_numbers?wait=20" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Idempotency-Key: 6f1c2b7e-buy-512-555-0142" \
  -H "Content-Type: application/json" \
  -d '{"phone_number": "+15125550142", "accept_monthly_price": 20, "agent_id": "AGENT_ID"}'
```

The `Idempotency-Key` header is required. Send the same key if you retry, and you get the same
number back instead of buying a second one. The response is 202 with `status: provisioning` and
an `id` that stays the number's id once it is active. With `agent_id`, the number answers for
that agent as soon as it is ready. Over MCP, `buy_phone_number` waits up to 25 seconds for you.

**3. Check that it is active**

```bash theme={null}
curl https://api.brilo.ai/v1/phone_numbers/NUMBER_ID \
  -H "Authorization: Bearer YOUR_API_KEY"
```

Most purchases are active within a few seconds. If `status` is still `provisioning`, wait a few
seconds and ask again.

## You will know it worked when

* `GET /v1/phone_numbers/NUMBER_ID` shows `status: active` and your `agent_id`.
* A call to the number is answered by the agent.

## Price consent

The Brilo API never charges a price nobody saw. `accept_monthly_price` must equal the number's
current monthly price, which is 0 inside your plan's allowance. If the price changed since you
searched, for example because another purchase used the last free number, the purchase is refused
with 409 `price_not_accepted`. Its `details` carry the new `monthly_price` and `currency`, and its
`next_action` is the same purchase at that price, to send once the owner agrees.

## Limits and who can buy

* **5 a day.** A workspace can buy at most 5 numbers through the API in any 24 hours. Purchases
  that failed do not count. The sixth gets 429 `phone_number_purchase_limit` with
  `details.retry_after` in seconds. The dashboard has no such limit.
* **People buy, assistants ask.** A paired assistant's key gets 403 `owner_approval_required`:
  an assistant may not start a charge on its own. The owner buys in the dashboard or with their own key.
* **A card on file.** Without one, the purchase gets 402 `payment_method_required` with
  `details.billing_url`, the page where the owner adds a card. Never enter card details yourself.

## Releasing a number

`DELETE /v1/phone_numbers/NUMBER_ID`, or `release_phone_number` over MCP, schedules the release.
The number keeps working until the end of the period already paid for and then goes. The response
has `status: releasing` and `release_at`. To keep the number, send
`PATCH /v1/phone_numbers/NUMBER_ID` with `{"release_at": null}` any time before then. Releasing a
number that is already releasing changes nothing and returns the warning `already_releasing`.

An imported number, one you brought from your own carrier, has no Brilo subscription. It is detached
and removed straight away. A number that is part of an Agent Phone Plan is refused with 409
`number_managed_by_plan`: the owner gives it up by cancelling the plan.

## Attaching numbers to agents

`POST /v1/agents/AGENT_ID/phone_numbers/attach` with `{"phone_numbers": ["+15125550142"]}` makes
the agent answer those numbers. Ids and E.164 numbers both work. Either every number is attached or
none is. A number that answered for another agent moves, and `moved_from_agent_id` says which.
`.../detach` stops the agent answering; calls then go unanswered until you attach the number again.

## If it did not work

**The purchase says `failed`.** Brilo cancels the subscription and refunds any payment in full, and
`refunded: true` says so. Pick another number and buy it with a new Idempotency-Key.
`failure.error_code` says why:

| `error_code` | What happened |
| - | - |
| `carrier_purchase_failed` | The carrier could not sell that number. |
| `phone_number_unavailable` | Someone else took the number before the purchase finished. |
| `provisioning_failed` | The number could not be set up after it was bought. |
| `stripe_error` | Billing could not start, so nothing was charged. |
| `provisioning_timeout` | The number was not ready within about 15 minutes. |

`refunded: false` on a failed purchase means nothing was charged, or the refund is still being
retried.

**409 `price_not_accepted`.** The price is not the one you sent. Show the owner `details.monthly_price`
and resend with it.

**409 `phone_number_unavailable`.** Someone else bought the number, or a purchase of it is already
running. Search again.

**402 `payment_failed`.** The card on file was declined and nothing was charged. The owner updates it
at `details.billing_url`.

**502 or 503 `billing_unavailable`.** On 503 billing is not set up and nothing happened; try again
later. On 502, check `details.id` with `get_phone_number` before buying again: `failed` means billing
refused the purchase and nothing was charged; `provisioning` means billing did not answer and the
purchase may still complete.

## FAQ

> **Can an AI agent buy a phone number on its own?**
>
> Not without the owner. Every purchase needs `accept_monthly_price`, the price the owner agreed
> to, and a paired assistant's key cannot buy at all: it gets `owner_approval_required`. An agent
> using a person's key should still show the price and wait for a yes before buying.

> **What happens to my money if a purchase fails?**
>
> Brilo refunds it in full. If the carrier cannot sell the number, or it is not ready within about
> 15 minutes, Brilo cancels the subscription and refunds the payment. The number then shows
> `status: failed` with `refunded: true`. A refund can take 5 to 10 business days to appear.

> **Why is the Idempotency-Key header required to buy a number?**
>
> Buying starts a monthly charge, so a retried request must never buy twice. With the same key,
> a retry returns the first purchase instead of making a new one. Use a new key only for a new
> purchase, for example after one failed.

> **Does releasing a number stop it working straight away?**
>
> No. A bought number keeps answering until the end of the period you already paid for, shown as
> `release_at`. Until then you can keep it with `PATCH` and `{"release_at": null}`. Imported numbers
> are the exception: they are removed at once.

> **How many numbers can I buy through the API?**
>
> Up to 5 a day per workspace, counted over the last 24 hours. Purchases that failed do not count.
> The owner can buy more in the Brilo dashboard, which has no daily limit.

> **Which countries and kinds of number can I buy?**
>
> Local numbers in the United States and Canada. Toll-free numbers are not sold and return
> `toll_free_not_supported`; other countries return `country_not_supported`.

## Related

* [Change an agent through the API](https://docs.brilo.ai/api-reference/agents/quickstart.md), from first change to a number callers can ring
* [API introduction](https://docs.brilo.ai/api-reference/introduction.md), for errors, retries and rate limits
* [MCP tools](https://docs.brilo.ai/api-reference/mcp/tools.md), every phone number tool and its parameters


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