Phone numbers

Search live inventory, buy a number in one call, bind it to an inbox and an agent, and release it when you no longer need it.

Every call needs a from — a number your account owns. You search live inventory, buy a number in one call, and it becomes the caller id your agent dials from and the line that answers incoming calls into your inbox.

OperationMethod & pathScope
Search inventoryGET /v1/phone/numbers/availablephone:read
List your numbersGET /v1/phone/numbersphone:read
BuyPOST /v1/phone/numbersphone:write
Get oneGET /v1/phone/numbers/{id}phone:read
ConfigurePATCH /v1/phone/numbers/{id}phone:write
ReleaseDELETE /v1/phone/numbers/{id}phone:write

Search available numbers

Filter by country (ISO 3166-1 alpha-2, default US), areaCode, a contains digit sequence, and type (local, toll_free, national, mobile). limit is 1–100 and defaults to 10.

curl "https://api.dairo.app/v1/phone/numbers/available?country=US&areaCode=415&limit=5" \
  -H "Authorization: Bearer $DAIRO_API_KEY"
{
  "object": "list",
  "data": [
    {
      "object": "phone_number.available",
      "phoneNumber": "+14155550123",
      "countryCode": "US",
      "numberType": "local",
      "locality": "SAN FRANCISCO",
      "region": "CA",
      "capabilities": ["voice", "sms"],
      "monthlyCostUsd": 1.0,
      "setupCostUsd": 1.0,
      "purchasable": true
    }
  ]
}

capabilities lists what the carrier supports on the number (voice, sms); Dairo uses it for calls. monthlyCostUsd and setupCostUsd are the recurring and one-time cost of owning it.

A result with purchasable: false and a masked number like +16313------ is real inventory your account can't buy yet: additional identity verification is required before those numbers unlock. It isn't an error and it isn't hidden from you — pick a purchasable: true number instead.

Buy a number

Pass the exact E.164 number from a search result. You get back a phone_number record; when the country requires no paperwork it arrives with status: "active", immediately usable as a caller id. Buying a number you already own returns 409, and so does a number that is no longer available.

curl -X POST https://api.dairo.app/v1/phone/numbers \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "phoneNumber": "+14155550123" }'
{
  "object": "phone_number",
  "id": "b4e7d9f0-2a1b-4c8e-9f3a-7d0a1f2c5b6e",
  "phoneNumber": "+14155550123",
  "countryCode": "US",
  "numberType": "local",
  "capabilities": ["voice", "sms"],
  "status": "active",
  "inboxId": null,
  "agentId": null,
  "inboundInstructions": null,
  "inboundGreeting": null,
  "inboundVoice": null,
  "inboundLanguage": null,
  "monthlyCostUsd": 1.0,
  "setupCostUsd": 1.0,
  "requirements": { "status": null, "items": [] },
  "metadata": {},
  "purchasedAt": "2026-07-09T13:58:02Z",
  "createdAt": "2026-07-09T13:58:02Z"
}

With an active number in hand, use it as the from on Making calls.

Regulated countries: pending is not an error

Some countries regulate who may hold a local number. Germany, for example, requires proof of a local address before a number activates. Buying a number there succeeds, but the order settles at status: "pending" with a requirements object listing exactly which documents are outstanding:

{
  "object": "phone_number",
  "phoneNumber": "+4930XXXXXXXX",
  "countryCode": "DE",
  "status": "pending",
  "requirements": {
    "status": "pending",
    "items": [
      { "name": "proof_of_address", "description": "A utility bill or registration certificate showing a German address" }
    ]
  }
}

The purchase is reserved for you. Poll GET /v1/phone/numbers/{id} to watch the status: once the listed requirements are met, the number turns active. A number's status is one of active, pending, or released — only an active number can be a call's from.

Configure a number

Two bindings turn a bare number into part of your fleet — set either, both, or clear them with an explicit null:

  • inboxId — every call the number answers lands in that inbox's mailbox as a message, next to your email and other channels.
  • agentId — attribute the number to one of your agents, so its calls carry clear provenance.
curl -X PATCH https://api.dairo.app/v1/phone/numbers/b4e7d9f0-2a1b-4c8e-9f3a-7d0a1f2c5b6e \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "inboxId": "inbox_123", "agentId": "agt_456" }'

The same call configures the agent that answers when someone dials the number — inboundInstructions, inboundGreeting, inboundVoice, and inboundLanguage; Inbound calls covers them. You can replace the number's metadata there too — a JSON object of at most 8 KiB (null clears it); the request must carry at least one field. Binding an inbox or agent you don't own is rejected. List everything you own with GET /v1/phone/numbers — add includeReleased=true to include released numbers, which stay on your account for the audit trail.

Release a number

Releasing returns the number to the public pool — anyone can buy it afterwards, and whoever does receives the calls meant for you. Because that is irreversible, the API refuses to release without an explicit confirm: true in the body (400 without it), and releasing an already-released number returns 409. A successful release returns the number's final record with status: "released" and releasedAt set.

curl -X DELETE https://api.dairo.app/v1/phone/numbers/b4e7d9f0-2a1b-4c8e-9f3a-7d0a1f2c5b6e \
  -H "Authorization: Bearer $DAIRO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "confirm": true }'

Release is irreversible. A released number stops receiving calls for you, monthly charges end, and the number returns to the pool for anyone to claim. If a number is printed on letterheads or saved in customers' contacts, keep it.

On this page