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

# Numbers

## Worked sequences

The endpoint list below documents each operation with its parameters, but the
two flows that integrate against this surface — renting a number and porting
one in — span several calls, and their response bodies are what you branch on.
These two sequences show every call in order with the body each one returns.

### Sequence 1 — rent a number

Go from inventory search to an active, capability-checked number in three
calls.

**Step 1 — search inventory.** Filter by country, line type, capability, and
area code. Each result carries the per-number capability list and monthly
price, so you can filter before you buy.

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

```json 200 theme={null}
{
  "data": [
    {
      "number": "+14155550100",
      "country": "US",
      "type": "local",
      "region": "California",
      "capabilities": ["sms", "voice", "mms"],
      "monthly_cost": "1.50",
      "currency": "USD"
    },
    {
      "number": "+14155550101",
      "country": "US",
      "type": "local",
      "region": "California",
      "capabilities": ["sms", "voice", "mms"],
      "monthly_cost": "1.50",
      "currency": "USD"
    }
  ],
  "meta": {
    "request_id": "req_num_001",
    "timestamp": "2026-08-27T12:00:00Z"
  }
}
```

<Note>
  For a regulated country (most of the EU/EEA, GB, and several others), run
  `GET /api/v1/numbers/regulatory-preview?country…` before this step — it
  returns the documents and data fields the carrier requires, and whether a
  compliance profile you already hold satisfies them.
</Note>

**Step 2 — purchase the number.** Submit the E.164 you picked. The `201` body
returns the owned-number record — save the `id`, because every follow-up
operation (configure, suspend, release) addresses the number by it. Billing
starts immediately.

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

```json 201 theme={null}
{
  "data": {
    "id": "num_abc123",
    "number": "+14155550100",
    "country": "US",
    "type": "local",
    "capabilities": ["sms", "voice", "mms"],
    "status": "active",
    "monthly_cost": "1.50",
    "currency": "USD",
    "created_at": "2026-08-27T12:00:00Z"
  },
  "meta": {
    "request_id": "req_num_002",
    "timestamp": "2026-08-27T12:00:00Z"
  }
}
```

**Step 3 — verify the provisioned number.** Read the number back by its `id`
to confirm it is `active` and that the capabilities you ordered are the ones
the carrier actually provisioned — a regulated country can hold the number at
`pending_compliance` until the required documents clear.

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/numbers/num_abc123 \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

```json 200 theme={null}
{
  "data": {
    "id": "num_abc123",
    "number": "+14155550100",
    "country": "US",
    "type": "local",
    "label": "Support line",
    "capabilities": ["sms", "voice", "mms"],
    "status": "active",
    "liveness": "healthy",
    "monthly_cost": "1.50",
    "currency": "USD",
    "created_at": "2026-08-27T12:00:00Z"
  },
  "meta": {
    "request_id": "req_num_003",
    "timestamp": "2026-08-27T12:00:00Z"
  }
}
```

### Sequence 2 — port a number in

Move an existing number from a losing carrier onto the platform. A full port
runs `eligibility check → LOA upload → submit → poll status`; the check step
is optional but cheap, and it turns a multi-day carrier rejection into an
instant answer.

**Step 1 — check eligibility (recommended).** Run a live pre-flight against
the losing carrier's database. The response tells you in seconds whether the
number can port; US and Canadian numbers are checked live, other countries
return `check-not-supported` and proceed straight to submission.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/numbers/porting/check \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{ "phoneNumber": "+14155551234", "currentCarrier": "Acme Telecom" }'
```

```json 200 theme={null}
{
  "data": {
    "phoneNumber": "+14155551234",
    "check_status": "portable",
    "carrier": "Acme Telecom"
  },
  "meta": {
    "request_id": "req_port_check_001",
    "timestamp": "2026-08-27T12:00:00Z"
  }
}
```

**Step 2 — submit the port-in request.** Send the numbers, the losing
carrier, and the account details the carrier will verify. The `201` body
returns the request id and the starting status — porting requests move
`submitted → reviewing → approved → completed`, with `rejected` as the
carrier-declined terminal state. Branch on these values; there is no
`pending` state.

```bash theme={null}
curl -X POST https://api.orbit.devotel.io/api/v1/numbers/porting \
  -H "X-API-Key: dv_live_sk_your_key_here" \
  -H "Content-Type: application/json" \
  -d '{
    "numbers": ["+14155551234"],
    "currentCarrier": "Acme Telecom",
    "authorizedSigner": "John Doe",
    "accountNumber": "ACC-12345",
    "accountPin": "4821",
    "country": "US",
    "contactEmail": "ops@example.com"
  }'
```

```json 201 theme={null}
{
  "data": {
    "id": "port_abc123",
    "numbers": ["+14155551234"],
    "status": "submitted",
    "submittedAt": "2026-08-27T12:00:00Z"
  },
  "meta": {
    "request_id": "req_port_001",
    "timestamp": "2026-08-27T12:00:00Z"
  }
}
```

**Step 3 — poll status until complete.** Read the request's status timeline;
each stage transition appends an entry with the stage name and a
`recommendedAction` when the port is waiting on you (for example, a
supplement on a rejection). Porting typically takes 7–14 business days
depending on the country and carrier — subscribe to the `number.ported`
webhook instead of polling once you are past submission.

```bash theme={null}
curl https://api.orbit.devotel.io/api/v1/numbers/porting/port_abc123/timeline \
  -H "X-API-Key: dv_live_sk_your_key_here"
```

```json 200 theme={null}
{
  "data": {
    "id": "port_abc123",
    "status": "approved",
    "timeline": [
      {
        "stage": "submitted",
        "at": "2026-08-27T12:00:00Z"
      },
      {
        "stage": "validating_loa",
        "at": "2026-08-27T14:20:00Z"
      },
      {
        "stage": "carrier_review",
        "at": "2026-08-28T09:05:00Z"
      },
      {
        "stage": "foc_scheduled",
        "at": "2026-08-30T11:00:00Z",
        "focDate": "2026-09-03",
        "recommendedAction": "none"
      }
    ]
  },
  "meta": {
    "request_id": "req_port_timeline_001",
    "timestamp": "2026-09-01T12:00:00Z"
  }
}
```

When the timeline reaches `completed`, the numbers appear in your
`GET /api/v1/numbers/` inventory as `active`.

### Error samples

Two purchase-time rejections account for most failed buys; both return the
standard error envelope with a stable `code` you can branch on.

**Regulated country without a compliance profile** — buying a number in a
country that requires verified end-user documents before the carrier will
activate it:

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

```json 422 theme={null}
{
  "error": {
    "code": "COMPLIANCE_PROFILE_REQUIRED",
    "status": 422,
    "message": "DE is a regulated country — the carrier won't activate a number without an approved compliance profile. Create / approve a profile that covers DE in Settings → Compliance, then retry the purchase. No wallet debit was attempted.",
    "details": { "country": "DE" }
  },
  "meta": {
    "request_id": "req_num_004",
    "timestamp": "2026-08-27T12:01:00Z"
  }
}
```

Fix it by creating and approving a compliance profile that covers the country
(under **Settings → Compliance** in the dashboard), then passing its id as
`compliance_profile_id` on the retry. No billing happens on this rejection —
your balance is untouched.

**Number already owned** — the number sold between your search and your
purchase, or is already on an account:

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

```json 409 theme={null}
{
  "error": {
    "code": "NUMBER_ALREADY_TAKEN",
    "status": 409,
    "message": "This number was just reserved by another user. Please select a different number.",
    "details": { "phone_number": "+1415****" }
  },
  "meta": {
    "request_id": "req_num_005",
    "timestamp": "2026-08-27T12:02:00Z"
  }
}
```

Fix it by re-running the search and submitting another candidate. Search
results are live inventory, not holds — treat a purchase attempt as a claim
race and retry with the next match.
