Skip to main content
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

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

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

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.
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: 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

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.
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.
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.
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.
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.
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.