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

# Buy and provision numbers: single purchases, bulk orders, and post-purchase wiring

> Search inventory, buy a single DID or up to 50 in one bulk order, poll the order record for per-line outcomes, and wire routing, emergency address, and caller ID after purchase.

# Buy and provision numbers

Buying a number on Orbit is a four-step loop: **search → buy → audit the order → wire the number up**. This guide walks the whole loop — single purchases, bulk orders of up to 50 DIDs, the pollable order record, and the provisioning steps that turn an owned DID into one that actually answers calls and messages.

Reads (`available`, `country-capabilities`, `orders`) need the `numbers:read` scope; purchases and post-purchase wiring need `numbers:write`. The full endpoint surface is at [Phone Numbers](/numbers/overview); the API reference is at [Numbers](/api-reference/numbers). Outbound termination never touches a third-party carrier — buying a DID provisions inbound routing only, and outbound voice and SMS exit through Orbit's own network.

## 1. Number basics

A phone number on Orbit is a **DID** identified in **E.164** format — a leading `+`, country code, then digits, with no spaces or punctuation (`+14155550100`). Every endpoint in this guide accepts and returns E.164.

Three number types cover different use cases:

| Type          | Best for                                                             | Notes                                                                                               |
| ------------- | -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| **Local**     | A geographic presence — a local presence dialer, a city support line | Tied to a city or region. US local numbers can carry two-way SMS under a registered 10DLC campaign. |
| **Toll-free** | National inbound lines, high-volume outbound SMS                     | Callers pay nothing; you absorb the cost. Toll-free SMS is **send-only** — it is never two-way.     |
| **Mobile**    | Markets where locals expect a mobile-format sender                   | Availability is country-dependent.                                                                  |

Capabilities are per-number flags for the channels the DID supports. The **search filter** accepts `sms`, `mms`, `voice`, `fax`; the **purchase-time request** accepts `sms`, `voice`, `whatsapp`, `rcs`. The two enums are deliberately different — a purchase-time OTT registration (`whatsapp`, `rcs`) is an add-on requested at provisioning, not something inventory search filters on. Passing a value from the wrong enum returns `422`.

## 2. Search inventory first

Never buy blind. Query live inventory before you construct an order:

```bash theme={null}
curl "https://api.orbit.devotel.io/api/v1/numbers/available?country=US&type=local&capabilities=sms,voice" \
  -H "X-API-Key: dv_live_sk_..."
```

Each returned row carries an `id` you should forward into the purchase call (see below), plus `monthly_cost` and `setup_cost` as decimal strings, `requires_registration`, and `expected_activation`. A row flagged `requires_registration: true` lands in a regulatory hold unless you attach an approved compliance profile at purchase time.

Two discovery helpers narrow the search before you run it:

```bash theme={null}
# Which countries currently have searchable stock
curl "https://api.orbit.devotel.io/api/v1/numbers/available/countries" \
  -H "X-API-Key: dv_live_sk_..."

# Per-country line-type × capability counts (local/mobile/toll-free × SMS/voice)
curl "https://api.orbit.devotel.io/api/v1/numbers/country-capabilities?country=GB" \
  -H "X-API-Key: dv_live_sk_..."
```

After purchase, audit what you own with the [Inventory & Export](/numbers/inventory-export) endpoints — page your inventory, export it to CSV/JSON for finance reconciliation, and subscribe to low-stock alerts.

If the country you want is empty, see the [Troubleshooting](#8-troubleshooting) section — and for new inventory programs, the *retro* order of operations is: preview requirements, then search, then buy.

## 3. Buy a single DID

In the dashboard, go to **Numbers → Buy**, search, and check out — the wizard runs the same endpoints below. By API:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/numbers/purchase \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "phone_number": "+14155550100",
    "country_code": "US",
    "capabilities": ["sms", "voice"],
    "id": "did_8f2a91c4"
  }'
```

| Field                   | Required | Description                                                                                                                                                                                                                                                                                                  |
| ----------------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `phone_number`          | yes      | E.164 number to buy.                                                                                                                                                                                                                                                                                         |
| `country_code`          | no       | ISO 3166-1 alpha-2. Defaults to `US`.                                                                                                                                                                                                                                                                        |
| `capabilities`          | no       | Subset of `sms`, `voice`, `whatsapp`, `rcs` to provision. When omitted, Orbit provisions what the carrier advertises — pass an explicit set so a voice-only selection on a multi-capability DID does not write a phantom SMS flag onto the record.                                                           |
| `id`                    | no       | The provider-issued row id from `GET /numbers/available`. Forward it: it lets Orbit pass the canonical row straight to the carrier instead of re-parsing the number, and it flags placeholder rows (a DID-group prefix rather than a concrete number) so a compliance gate applies before the carrier order. |
| `compliance_profile_id` | no       | An approved compliance profile covering the target country. Attaching one lets a registration-required number activate immediately instead of entering a regulatory hold. Rejected with `422` if the profile is not approved or does not cover the country.                                                  |

Pricing is resolved server-side against live inventory — a client-supplied price field is never honoured. The wallet is checked up front; insufficient balance returns `402` with the required and available amounts.

## 4. Bulk-provision up to 50 numbers

When you already have the exact E.164 list — from `GET /numbers/available` or your own selection — submit it in one call instead of fifty:

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/numbers/buy-bulk \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "phone_number": "+14155550100", "country_code": "US", "id": "did_8f2a91c4" },
      { "phone_number": "+14155550101", "country_code": "US" }
    ],
    "compliance_profile_id": "cmpl_abc123"
  }'
```

```json theme={null}
{
  "data": {
    "order_id": "numOrder_01J9Z8ABCDEF",
    "succeeded": [
      { "id": "num_abc123", "phone_number": "+14155550100", "status": "active" }
    ],
    "failed": [
      {
        "phone_number": "+14155550101",
        "error": { "code": "NUMBER_UNAVAILABLE", "message": "Number no longer available" }
      }
    ],
    "total_cost_cents": 300,
    "debited_cents": 150
  }
}
```

Read the response with partial success in mind:

* **`200` even when every row fails.** The status code tells you the request was processed, not the outcome — inspect `succeeded.length` to decide your UI state.
* **Failed rows are never charged.** `total_cost_cents` sums every requested item; `debited_cents` is what was actually charged — only for `succeeded`. There is no partial-batch debit.
* **`compliance_profile_id` applies to every item** in the batch — pick one profile per order. The wallet is checked up front against the summed per-number cost, and each item can carry the same `provider` hint enum as the single purchase.
* **Rate-limited to 2 requests/minute** per tenant, because one call fans out to up to 50 upstream carrier calls.

Need more than 50, or want the platform to pick the block for you instead of posting a pre-built list? Use the bulk-reservation lifecycle — hold up to 1000 DIDs matching a country / area-code / capability filter for 15 minutes, then finalize (purchase, bill, and route) or cancel. It's documented under [Bulk Reserve](/numbers/overview#bulk-reserve).

## 5. Poll and audit the order

Every `buy-bulk` response carries an `order_id` — a stable, pollable record of the batch, persisted so partial fulfillment can be audited long after the request returned.

```bash theme={null}
# List recent bulk orders (summaries)
curl "https://api.orbit.devotel.io/api/v1/numbers/orders?limit=20" \
  -H "X-API-Key: dv_live_sk_..."

# Fetch one order with per-line outcomes
curl "https://api.orbit.devotel.io/api/v1/numbers/orders/numOrder_01J9Z8ABCDEF" \
  -H "X-API-Key: dv_live_sk_..."
```

```json theme={null}
{
  "data": {
    "order_id": "numOrder_01J9Z8ABCDEF",
    "status": "partial",
    "requested_count": 2,
    "delivered_count": 1,
    "failed_count": 1,
    "total_cost_cents": 300,
    "debited_cents": 150,
    "created_at": "2026-08-24T12:00:00.000Z",
    "lines": [
      {
        "phone_number": "+14155550100",
        "line_status": "delivered",
        "provider": "devotel",
        "country_code": "US",
        "capabilities": ["sms", "voice"],
        "monthly_cost_cents": 150
      },
      {
        "phone_number": "+14155550101",
        "line_status": "failed",
        "error": { "code": "NUMBER_UNAVAILABLE", "message": "Number no longer available" }
      }
    ]
  }
}
```

The order `status` is the aggregate across its lines: `delivered` (all succeeded), `partial` (some succeeded), or `failed` (none succeeded). Per line you get the E.164, country, capabilities, monthly cost, and the carrier error for failures — enough to reconcile a bulk provisioning run against finance records without replaying the batch. Orders are org-scoped: an unknown or not-owned id returns `404`, not an exists-but-not-yours leak.

## 6. Wire the number up after purchase

A purchased DID with no route answers with silence. Do these immediately after the buy:

### Set the voice route

Pick where inbound calls terminate — an AI agent, IVR, queue, ring group, voicemail, SIP forward, or your own webhook — via the inbound-routing surface, keyed by the number in E.164 form:

```bash theme={null}
curl -X PUT "https://api.orbit.devotel.io/api/v1/numbers/+14155550100/routing" \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "type": "queue",
    "config": { "queueId": "que_support" },
    "sms_route_type": "webhook",
    "sms_route_config": { "url": "https://yourapp.com/webhooks/inbound-sms" }
  }'
```

Voice `type` and SMS routing (`webhook`, `agent`, `auto_reply`, `disabled`) are configured independently — set both if the number carries both capabilities. The full route-type catalog is in [Phone Numbers](/numbers/overview#configure-routing).

### Register the emergency address

If the number's users can place calls to emergency services, register a validated dispatchable address per number:

```bash theme={null}
curl -X POST "https://api.orbit.devotel.io/api/v1/numbers/num_abc123/emergency-address" \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{
    "address_line1": "1 Market St",
    "city": "San Francisco",
    "state": "CA",
    "postal_code": "94105",
    "country_code": "US"
  }'
```

The address records and validates the dispatchable location for compliance — treat E911 as record-keeping, not a live emergency-calling guarantee. Full surface: [Emergency Address](/numbers/emergency-address).

### Set the caller name

Outbound callers see what the carrier CNAM database says. Register your brand per number:

```bash theme={null}
curl -X PUT "https://api.orbit.devotel.io/api/v1/numbers/num_abc123/cnam" \
  -H "X-API-Key: dv_live_sk_..." \
  -H "Content-Type: application/json" \
  -d '{ "caller_name": "ACME SUPPORT" }'
```

Registrations are captured and dispatched on Orbit's network; propagation to carrier CNAM databases is carrier-paced. Details and spam-label remediation: [CNAM & Caller ID](/numbers/cnam).

Finally, enable [auto-renew](/numbers/lifecycle) so the number never lapses: `PATCH /api/v1/numbers/{id}/auto-renew` with `{ "auto_renew": true }`.

## 7. Trial numbers — and when to upgrade

A new organization can claim **one free trial number** from the shared pool, leased for 24 hours as a one-time lifetime claim — enough to test inbound calls and SMS before committing:

```bash theme={null}
# Claim from the pool (no body)
curl -X POST https://api.orbit.devotel.io/api/v1/numbers/claim-trial \
  -H "X-API-Key: dv_live_sk_..."

# Keep it permanently
curl -X POST https://api.orbit.devotel.io/api/v1/numbers/purchase-trial \
  -H "X-API-Key: dv_live_sk_..."

# Or hand it back
curl -X DELETE https://api.orbit.devotel.io/api/v1/numbers/release-trial \
  -H "X-API-Key: dv_live_sk_..."
```

Claim returns `409` if your org already holds an active trial or already owns purchased numbers. Upgrade the moment you need the number to survive past 24 hours, want a specific area code, or need capabilities the shared pool doesn't guarantee — convert with `purchase-trial` to keep the exact number, or release it and buy a DID that matches your requirements. The full trial lifecycle is in [Number Lifecycle](/numbers/lifecycle).

## 8. Troubleshooting

| Symptom                                                           | Likely cause                                                                                                      | Fix                                                                                                                                                                                                                                                                  |
| ----------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `GET /numbers/available` returns no rows                          | Inventory is provider-driven and rotates; a filter may be too narrow, or the country has no current stock         | Drop the capability filter and retry; check `GET /numbers/available/countries` for countries with live stock and `GET /numbers/country-capabilities` for per-type counts. For a block, use `POST /numbers/bulk-reserve` and let the platform find inventory for you. |
| Purchased number can't receive calls                              | No route was set, or the DID was bought without the `voice` capability                                            | Pull `GET /numbers/{id}` and check `capabilities` includes `voice`; then set an inbound route. If capability is genuinely missing, release the DID and rebuy with `capabilities: ["voice", ...]`.                                                                    |
| SMS fails on a voice-only DID                                     | Capability mismatch at purchase — an explicit `capabilities` request intersects with the carrier's advertised set | Pass the full set you need at purchase. A toll-free number's SMS is send-only — if you need two-way SMS, buy a local or mobile DID instead.                                                                                                                          |
| Bulk row failed with `NUMBER_UNAVAILABLE`                         | Inventory turnover — another buyer took the number between your search and checkout                               | Re-run the search and retry only the failed rows; failed rows are never charged, so retrying is safe.                                                                                                                                                                |
| Purchase blocked on a regulated country (`requires_registration`) | The country gates activation on identity/address documents                                                        | Preview exact requirements with [Regulatory Preview](/numbers/regulatory-preview), complete the compliance profile, and pass its id at purchase time so the number activates immediately instead of entering a hold.                                                 |
| `402 INSUFFICIENT_BALANCE` on buy                                 | Wallet checked up front against the full (summed, for bulk) cost                                                  | Top up the wallet; the response names the required and available cents.                                                                                                                                                                                              |

Most post-purchase oddities trace to one of: capability mismatch (bought without the channel you need), a missing inbound route, or a regulatory hold still pending a compliance profile.

## See Also

* [Phone Numbers](/numbers/overview) — search filters, purchase fields, number types, routing catalog, and bulk reserve.
* [Number Lifecycle](/numbers/lifecycle) — auto-renew, scheduled release, reassign, reclaim, and the trial pool.
* [Inventory & Export](/numbers/inventory-export) — list and export what you own.
* [Regulatory Preview](/numbers/regulatory-preview) — document requirements before checkout.
* [Emergency Address (E911)](/numbers/emergency-address) and [CNAM & Caller ID](/numbers/cnam) — post-purchase provisioning.
* [Send & Receive Messages](/guides/send-receive-messages) — the first-message walkthrough once a route is set.
