# Numbers

Search and buy phone numbers, route their inbound calls, release them, and manage verified numbers (numbers
you own elsewhere and may call from). Paths are relative to
`https://api.contactivity.io/v1/projects/{project_id}`; see the [overview](/guides/overview.md). Numbers are sold for
voice only today (`capabilities.sms` and `mms` are false).

| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | `/available-numbers` | `numbers:read` | Search numbers to buy (one page) |
| POST | `/numbers` | `numbers:write` | Order a number (`Idempotency-Key` required) |
| GET | `/numbers` | `numbers:read` | List the project's numbers (paged) |
| GET | `/numbers/{phone_number}` | `numbers:read` | Fetch a number |
| PATCH | `/numbers/{phone_number}` | `numbers:write` | Route a number |
| DELETE | `/numbers/{phone_number}` | `numbers:write` | Release a number |
| GET | `/verified-numbers` | `verified_numbers:read` | List verified numbers (one page, up to 1000) |
| GET | `/verified-numbers/{verified_number}` | `verified_numbers:read` | Fetch by E.164 or id |
| DELETE | `/verified-numbers/{verified_number}` | `verified_numbers:write` | Archive a verified number |
| POST | `/verified-numbers/verifications` | `verified_numbers:write` | Verify a number by phone call |
| GET | `/verified-numbers/verifications/{verification_id}` | `verified_numbers:write` | Verification state |

Phone numbers in paths are URL-encoded: `/numbers/%2B14155551234`.

## Search

`GET /available-numbers` query: `country` (ISO alpha-2, default `US`), `type` (`local` default, `mobile`,
`toll_free`), `area_code` (3 digits), `contains` (digits, `*` only at the start or end), `region` (state or
region code), `limit` (1-200, default 50). Each result: `phone_number`, `country`, `type`, `region`,
`capabilities`, `setup_price`, `monthly_price`, `inbound_per_minute_price` (money or null). Errors:
`400 invalid_parameter`, `503 search_unavailable`.

```sh
curl "https://api.contactivity.io/v1/projects/$PROJECT_ID/available-numbers?area_code=415&limit=5" \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY"
```

## Order

`POST /numbers` with `phone_number` (E.164) or `area_code` (the first available number there), and optionally
`route_id` (a route of the project). `Idempotency-Key` is required, so a retry never buys twice. The setup fee
and first month are charged from the balance. Returns `201` and the number; `status` is `pending` while the
carrier provisions it, then `active`.

```sh
curl https://api.contactivity.io/v1/projects/$PROJECT_ID/numbers \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY" \
  -H "Content-Type: application/json" -H "Idempotency-Key: $(uuidgen)" \
  -d '{"phone_number": "+14155551234", "route_id": "rt_us1_…"}'
```

Errors: `400 missing_parameter` (param `Idempotency-Key`), `400 invalid_parameter` (param `phone_number`,
`area_code`, `route_id`), `402 insufficient_balance` (the message gives the amount needed and the balance),
`403 permission_denied`, `403 account_suspended`, `403 verification_required`, `403 regulatory_bundle_required`,
`409 number_not_available`, `502 carrier_error`, `503 service_unavailable`.

## The number object

| Field | Type | Description |
|---|---|---|
| `id`, `phone_number` | string | The E.164 number |
| `country` | string | |
| `type` | string | `local`, `mobile`, `toll_free` |
| `status` | string | `active` or `pending` |
| `capabilities` | object | `voice`, `sms`, `mms` booleans |
| `route_id` | string or null | Where inbound calls go |
| `setup_price`, `monthly_price`, `inbound_per_minute_price` | money or null | |
| `created_at` | timestamp | When provisioned |

`GET /numbers` filters by `status` (`active`, `pending`).

`PATCH /numbers/{phone_number}` takes only `route_id` (required; `null` unroutes). Errors:
`400 missing_parameter`, `400 invalid_parameter` (param `route_id`), `404 not_found`.

```sh
curl -X PATCH https://api.contactivity.io/v1/projects/$PROJECT_ID/numbers/%2B14155551234 \
  -H "Authorization: Bearer $CONTACTIVITY_API_KEY" -H "Content-Type: application/json" \
  -d '{"route_id": "rt_us1_…"}'
```

`DELETE /numbers/{phone_number}` releases it: `204`; `404 not_found`; `409 number_pending` (wait until it is
active).

## Verified numbers

A verified number object is `{id, phone_number}`. To add one, start a verification: Contactivity calls the number and
the person who answers keys in the code you show them.

`POST /verified-numbers/verifications` with `{"phone_number": "+14155550100"}` returns `201`:

```json
{"id": "CA…", "call_id": "CA…", "phone_number": "+14155550100", "status": "calling", "reason": null, "validation_code": "482913"}
```

Poll `GET /verified-numbers/verifications/{id}` until `status` is `verified` or `failed` (`reason` says why). A
verification is kept for 10 minutes after it ends (then `404 not_found`).

Errors on start: `400 invalid_parameter` (param `phone_number`), `403 kyc_required` (the project must pass
identity verification first), `403 verified_number_blocked`, `403 number_owned_elsewhere`, `403 account_inactive`,
`403 permission_denied`, `409 verified_number_exists`, `429 too_many_verifications`, `503 verification_unavailable`.

`GET` / `DELETE /verified-numbers/{verified_number}` take the E.164 number or the id: `404 not_found` when absent; delete
archives it (it can no longer be used as caller ID; verify the number again to use it) and returns `204`.
