# Phone

Part of AppEngine API Documentation. Full index: https://appengine.appmint.io/documentation.md
## GET /phone/numbers

**List phone numbers**

`operationId: PhoneController_getPhoneNumbers`

Every phone number configured for the organization, with its capabilities and purpose.

#### Signature

```http
GET /phone/numbers () -> Phone numbers
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/available`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Phone numbers |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/numbers

**Purchase a phone number**

`operationId: PhoneController_purchasePhoneNumber`

Buys a number from the provider and adds it to the organization.

**This incurs a real, recurring charge.** Numbers bill monthly until released, so provision deliberately rather than as a side effect of a setup flow.

#### Signature

```http
POST /phone/numbers (body) -> The purchased number
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Recurring cost from the moment of purchase. Release numbers you stop using.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /phone/numbers/{phoneId}`
- `POST /phone/numbers/add`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

Which number to buy.

```json
{
  "phoneNumber": "+14155552600",
  "friendlyName": "Support line",
  "purpose": "support"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The purchased number |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/numbers/{phoneId}

**Get a phone number**

`operationId: PhoneController_getPhoneNumberById`

Fetches one number with its routing, capabilities and SMS registration state.

#### Signature

```http
GET /phone/numbers/{phoneId} (phoneId: string) -> The phone number
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | PHONE_NOT_FOUND | Phone number not found | No phone number in the org has that id. | List them with `GET /phone/numbers`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/numbers/{phoneId}/sms-requirements`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | path | string | yes | Phone number id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The phone number |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Phone number not found — No phone number in the org has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## PUT /phone/numbers/{phoneId}

**Update a phone number**

`operationId: PhoneController_updatePhoneConfiguration`

Updates a number's friendly name or purpose. Routing has its own endpoint.

#### Signature

```http
PUT /phone/numbers/{phoneId} (phoneId: string, body) -> The updated number
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | PHONE_NOT_FOUND | Phone number not found | No phone number in the org has that id. | List them with `GET /phone/numbers`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/numbers/{phoneId}/routing`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | path | string | yes | Phone number id. |

### Request body

Fields to change.

```json
{
  "friendlyName": "Sales line"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The updated number |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Phone number not found — No phone number in the org has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /phone/numbers/{phoneId}

**Release a phone number**

`operationId: PhoneController_releasePhoneNumber`

Releases a number back to the provider, ending the recurring charge.

**Releasing is not reversible.** The number returns to the provider's pool and may be reassigned to someone else — anyone who calls or texts it afterwards reaches a stranger. Check nothing published still lists it.

#### Signature

```http
DELETE /phone/numbers/{phoneId} (phoneId: string) -> Release result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- You cannot get the number back. Verify it is not in print, on a website, or in a customer record first.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | PHONE_NOT_FOUND | Phone number not found | No phone number in the org has that id. | List them with `GET /phone/numbers`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/numbers`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | path | string | yes | Phone number id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Release result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Phone number not found — No phone number in the org has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/available

**Search available numbers**

`operationId: PhoneController_getAvailableNumbers`

Searches the provider for numbers available to buy. Listing is free and reserves nothing — a number shown here can be taken by someone else before you purchase it.

#### Signature

```http
GET /phone/available (areaCode?: string, region?: string, contains?: string, smsEnabled?: boolean, voiceEnabled?: boolean, limit?: integer) -> Available numbers
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Search results are not held. Purchase promptly or re-search.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/numbers`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `limit` | query | integer | — | How many results. |
| `voiceEnabled` | query | boolean | — | Only voice-capable numbers. |
| `smsEnabled` | query | boolean | — | Only SMS-capable numbers. |
| `contains` | query | string | — | Digits the number should contain. |
| `region` | query | string | — | Region or state. |
| `areaCode` | query | string | — | Area code to search within. |
| `countryCode` | query | any | — | Country code (default: US) |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Available numbers |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/numbers/add

**Add an existing number**

`operationId: PhoneController_addExistingPhoneNumber`

Registers a number you already own with the platform, rather than buying a new one. Use this when porting in or when the number was bought directly with the provider — it adds no cost of its own.

#### Signature

```http
POST /phone/numbers/add (body) -> The added number
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- E.164 format is required — `+` and country code, no spaces or punctuation.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/numbers`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The number to add.

```json
{
  "phoneNumber": "+14155552600",
  "friendlyName": "Support line",
  "purpose": "support"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The added number |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/numbers/{phoneId}/routing

**Configure number routing**

`operationId: PhoneController_configurePhoneRouting`

Sets where calls and messages to a number go — an IVR, a queue, a forwarding destination. Misrouting silently sends customers nowhere, so verify with a test call after changing it.

#### Signature

```http
POST /phone/numbers/{phoneId}/routing (phoneId: string, body) -> The updated routing
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | PHONE_NOT_FOUND | Phone number not found | No phone number in the org has that id. | List them with `GET /phone/numbers`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/numbers/{phoneId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | path | string | yes | Phone number id. |

### Request body

The routing configuration.

```json
{
  "voice": {
    "type": "queue",
    "target": "support"
  },
  "sms": {
    "type": "inbox"
  }
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated routing |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Phone number not found — No phone number in the org has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/numbers/sms-status/{phoneId}

**Get SMS registration status**

`operationId: PhoneController_checkSmsRegistrationStatus`

Where a number stands in A2P registration. Registration takes days and can be rejected, so check status rather than assuming a submitted registration is a working one.

#### Signature

```http
GET /phone/numbers/sms-status/{phoneId} (phoneId: string) -> Registration status
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | PHONE_NOT_FOUND | Phone number not found | No phone number in the org has that id. | List them with `GET /phone/numbers`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/a2p/brand`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | path | string | yes | Phone number id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Registration status |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Phone number not found — No phone number in the org has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/numbers/register-sms/{phoneId}

**Register a number for SMS**

`operationId: PhoneController_registerForSms`

Submits a number for A2P messaging registration. Asynchronous and subject to carrier approval — poll the status endpoint rather than treating a `200` as registration.

#### Signature

```http
POST /phone/numbers/register-sms/{phoneId} (phoneId: string, body) -> The submission result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Submission is not approval. Carriers can reject a campaign days later.

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | PHONE_NOT_FOUND | Phone number not found | No phone number in the org has that id. | List them with `GET /phone/numbers`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/numbers/sms-status/{phoneId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | path | string | yes | Phone number id. |

### Request body

Registration details.

```json
{
  "campaignUseCase": "customer_care"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The submission result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Phone number not found — No phone number in the org has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/a2p/site-pages

**Publish SMS terms and a privacy policy**

`operationId: PhoneController_publishA2PSitePages`

Publishes the SMS Terms and Privacy Policy pages carriers look for on the org's site, filled with its details. Pages the site already has are kept. Returns the page links and a suggested opt-in description.

#### Signature

```http
POST /phone/a2p/site-pages (body) -> { site, siteUrl, pages, suggestedMessageFlow }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

Optional business details to use.

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { site, siteUrl, pages, suggestedMessageFlow } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/calls/ai

**Make an AI phone call (call someone)**

`operationId: PhoneController_placeAICall`

Dials a person from the organization's number and connects its AI voice assistant, which talks to them — you do not speak on the call. Give `to` (the number to call; 10-digit US numbers are fine), `reason` (what the call is for — the voice assistant works from it) and optionally `greeting` (its opening line), `assistantId` (which voice assistant; default: the one that answers the calling number) and `from` (which of the organization's numbers to call from — by default your own assigned number, else the default number, else a free one, else the system phone). Use it to call a customer back, confirm an appointment, or follow up.

#### Signature

```http
POST /phone/calls/ai (body) -> { sid, status, to, from, assistantId } — the call is placed; the voice assistant takes over when they answer.
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Premium-rate and international numbers are refused.
- The call is billed to the organization like any call.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /crm/communications/calls`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

Who to call and why.

```json
{
  "to": "+16823470647",
  "reason": "Call back about their website setup question and offer to book a walkthrough.",
  "greeting": "Hi, this is Appmint calling about your website question."
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { sid, status, to, from, assistantId } — the call is placed; the voice assistant takes over when they answer. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/a2p/draft

**The SMS registration, pre-filled**

`operationId: PhoneController_a2pDraft`

The registration form filled from what the platform knows: the registered brand, business profile, org settings (address, email, phone), the signed-in user as representative, the website and its SMS pages, and this number's previous submission. Includes `platform.ready` — false until the platform's own Twilio profile is approved.

#### Signature

```http
GET /phone/a2p/draft (phoneId?: string) -> The pre-filled submission
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/a2p/check`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | query | string | — | The number being registered. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The pre-filled submission |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/a2p/check

**Check an SMS registration before submitting**

`operationId: PhoneController_checkA2P`

Runs the checks that catch the usual rejection reasons. Returns { ok, problems: [{ field, severity: block|warn, message }] } — registration refuses a submission with block problems.

#### Signature

```http
POST /phone/a2p/check (body) -> { ok, problems, brandExists }
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/numbers/register-sms/{phoneId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The submission.

### Responses

| Status | Meaning |
| --- | --- |
| `201` | { ok, problems, brandExists } |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/a2p/brand

**Get the A2P brand**

`operationId: PhoneController_getA2PBrand`

The organization's A2P brand registration — the business identity carriers approve campaigns against. Numbers cannot be registered until the brand is.

#### Signature

```http
GET /phone/a2p/brand () -> The A2P brand
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/numbers/register-sms/{phoneId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The A2P brand |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/numbers/{phoneId}/sms-requirements

**Get SMS requirements for a number**

`operationId: PhoneController_getSmsRegistrationRequirements`

What still has to be done before this number can send SMS reliably — brand registration, campaign approval, and the rest of A2P 10DLC.

Read this before relying on a number for messaging. An unregistered number does not fail loudly; carriers simply filter its traffic.

#### Signature

```http
GET /phone/numbers/{phoneId}/sms-requirements (phoneId: string) -> Outstanding requirements
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `404` | PHONE_NOT_FOUND | Phone number not found | No phone number in the org has that id. | List them with `GET /phone/numbers`. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/numbers/register-sms/{phoneId}`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | path | string | yes | Phone number id. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Outstanding requirements |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `404` | Phone number not found — No phone number in the org has that id. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/setup

**Set up phone**

`operationId: PhoneController_setupPhone`

Configures phone service for the organization — provider credentials and defaults. Run `GET /phone/verify` afterwards to confirm it works before depending on it.

#### Signature

```http
POST /phone/setup (body) -> The setup result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- The body carries provider credentials — do not log it.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/verify`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

Setup details.

```json
{
  "provider": "twilio",
  "accountSid": "AC…",
  "authToken": "…"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The setup result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/verify

**Verify phone setup**

`operationId: PhoneController_verifySetup`

Checks the phone configuration is complete and the provider reachable. The first thing to run when calls or messages stop arriving.

#### Signature

```http
GET /phone/verify () -> Verification result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/setup`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |
| `phoneId` | query | string | — | Specific phone to verify (optional) |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Verification result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/token

**Get a phone access token**

`operationId: PhoneController_generateVoiceToken`

Issues a short-lived token for a softphone or browser client to connect to the voice service. Tokens expire — fetch one per session rather than caching.

#### Signature

```http
POST /phone/token (body) -> The access token
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- The token permits placing calls. Treat it as a credential.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/voice/register-device`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

Token request.

```json
{
  "identity": "ada@example.com"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Voice access token |
| `201` | The access token |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/user-phones

**Get user phone assignments**

`operationId: PhoneController_getUserPhones`

Which numbers are assigned to which users — who receives calls to what.

#### Signature

```http
GET /phone/user-phones () -> User phone assignments
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/numbers`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | User phone assignments |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/voice/app

**Get the voice application**

`operationId: PhoneController_getVoiceApp`

The voice application configuration — how inbound calls are handled before any per-number routing applies.

#### Signature

```http
GET /phone/voice/app () -> The voice application
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/voice/app`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The voice application |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/voice/app

**Update the voice application**

`operationId: PhoneController_createVoiceApp`

Updates the voice application configuration. This affects call handling org-wide, so a mistake here takes out every number at once — test with a call afterwards.

#### Signature

```http
POST /phone/voice/app (body) -> The updated application
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Org-wide effect. Verify with a real call.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/voice/app`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The configuration.

```json
{
  "greeting": "Thanks for calling Acme",
  "fallbackNumber": "+14155552601"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated application |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/voice/voices

**List available AI voices**

`operationId: PhoneController_getAiVoices`

Every AI voice the org can put on a call, from every engine, as `[{ name, info, platform, previewUrl? }]`. `previewUrl` is a short sample to play before choosing: ElevenLabs' own hosted sample, or for OpenAI a sample rendered once and stored. A voice whose sample does not exist yet is returned without it (the render starts in the background) — the list never waits or fails on previews.

#### Signature

```http
GET /phone/voice/voices () -> Available voices
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/voice/preview`
- `POST /phone/voice/app`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Available voices |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/voice/preview

**Preview a line in an AI voice**

`operationId: PhoneController_previewVoice`

Renders a specific line — usually the assistant's greeting — in the chosen voice and returns a URL to the mp3. ElevenLabs voices render on ElevenLabs, OpenAI voices on OpenAI TTS; the caller does not care which.

Rendered once per (platform, voice, text) and stored, so previewing the same greeting again is instant and free. New lines are capped per org per hour.

#### Signature

```http
POST /phone/voice/preview (body) -> `{ url }` — a public mp3 URL
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- 400 with a plain message for an unknown platform, a voice that is not on that platform, or empty / over-300-character text.
- 429 when the org has rendered too many new lines this hour; cached lines are never counted.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/voice/voices`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The voice and the line.

```json
{
  "voice": "marin",
  "platform": "openai-realtime",
  "text": "Thanks for calling Acme, how can I help?"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | `{ url }` — a public mp3 URL |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/voice/register-device

**Register a voice device**

`operationId: PhoneController_registerVoiceDevice`

Registers a device to receive calls — a softphone, a mobile app. Until registered, calls routed to that user will not ring anywhere.

#### Signature

```http
POST /phone/voice/register-device (body) -> The registered device
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/voice/heartbeat`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The device to register.

```json
{
  "identity": "ada@example.com",
  "deviceToken": "apns_…",
  "platform": "ios"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The registered device |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/voice/heartbeat

**Send a device heartbeat**

`operationId: PhoneController_heartbeatVoiceDevice`

Keeps a registered device marked as available. A device that stops sending heartbeats is treated as offline and calls route past it — which is what stops a dead app silently swallowing calls.

#### Signature

```http
POST /phone/voice/heartbeat (body) -> The result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/voice/devices`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The device.

```json
{
  "identity": "ada@example.com",
  "deviceId": "DEV-4821"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/voice/unregister-device

**Unregister a voice device**

`operationId: PhoneController_unregisterVoiceDevice`

Removes a device so it stops receiving calls. Do this when someone changes phone, or their old handset keeps ringing for calls they should not get.

#### Signature

```http
POST /phone/voice/unregister-device (body) -> The result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/voice/register-device`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The device to remove.

```json
{
  "identity": "ada@example.com",
  "deviceId": "DEV-4821"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/voice/devices

**List registered voice devices**

`operationId: PhoneController_listVoiceDevices`

Devices currently registered to receive calls, and whether each is live. Where a "why did nobody answer" investigation starts.

#### Signature

```http
GET /phone/voice/devices () -> Registered devices
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/voice/heartbeat`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Registered devices |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/system

**Get the system phone configuration**

`operationId: PhoneController_getSystemPhone`

The platform-level phone configuration, as opposed to the org's own numbers.

#### Signature

```http
GET /phone/system () -> System phone configuration
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/system`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | System phone configuration |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/system

**Update the system phone configuration**

`operationId: PhoneController_setSystemPhone`

Updates the platform-level phone configuration.

#### Signature

```http
POST /phone/system (body) -> The updated configuration
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `DELETE /phone/system`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The configuration.

```json
{
  "phoneNumber": "+14155552600"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated configuration |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /phone/system

**Remove the system phone configuration**

`operationId: PhoneController_clearSystemPhone`

Clears the platform-level phone configuration. Anything relying on a system number stops working.

#### Signature

```http
DELETE /phone/system () -> Removal result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/system`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Removal result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/sms-number

**Get the default SMS number**

`operationId: PhoneController_getSmsPhone`

The number outbound SMS is sent from by default.

#### Signature

```http
GET /phone/sms-number () -> The default SMS number
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/sms-number`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | The default SMS number |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/sms-number

**Set the default SMS number**

`operationId: PhoneController_setSmsPhone`

Sets the number outbound SMS is sent from.

The number is **checked for sendability first**: it must exist in the org and be capable of sending, and the refusal names the specific reason — usually incomplete A2P registration. That check is what stops the org silently defaulting to a number whose messages carriers drop.

#### Signature

```http
POST /phone/sms-number (body) -> The updated default
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

| Status | Code | Message | When | What to do |
| --- | --- | --- | --- | --- |
| `400` | PHONE_NUMBER_REQUIRED | phoneNumber is required | `phoneNumber` is missing. | Supply the number in E.164 format. |

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/numbers/{phoneId}/sms-requirements`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

The number to use.

```json
{
  "phoneNumber": "+14155552600"
}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The updated default |
| `400` | phoneNumber is required — `phoneNumber` is missing. |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## DELETE /phone/sms-number

**Clear the default SMS number**

`operationId: PhoneController_clearSmsPhone`

Removes the default SMS number. Outbound SMS with no explicit sender then has nowhere to send from.

#### Signature

```http
DELETE /phone/sms-number () -> Removal result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/sms-number`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Removal result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## GET /phone/migration/status

**Get phone migration status**

`operationId: PhoneController_checkMigrationStatus`

Progress of a phone configuration migration.

#### Signature

```http
GET /phone/migration/status () -> Migration status
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `POST /phone/migration/run`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Responses

| Status | Meaning |
| --- | --- |
| `200` | Migration status |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

## POST /phone/migration/run

**Run the phone migration**

`operationId: PhoneController_runMigration`

Runs the phone configuration migration. An administrative operation that rewrites phone configuration — run it once, deliberately, and check the status afterwards.

#### Signature

```http
POST /phone/migration/run (body) -> The migration result
```

#### Access

Requires a bearer JWT (`Authorization: Bearer <token>`).

#### Notes

- Rewrites configuration across the org's numbers.

#### Errors

Plus the standard platform errors: `401`, `403`, `429`, `500`.

#### See also

- `GET /phone/migration/status`

### Parameters

| Name | In | Type | Required | Description |
| --- | --- | --- | --- | --- |
| `orgid` | header | string | yes | Organization (tenant) identifier. Every request is scoped to this org; data from other orgs is never visible. Issued with your API credentials. |

### Request body

Optional options.

```json
{}
```

### Responses

| Status | Meaning |
| --- | --- |
| `201` | The migration result |
| `401` | Authentication failed: Invalid or expired token — The `Authorization` header is missing, malformed, or the JWT has expired. |
| `403` | You do not have permission to perform this action — The caller is authenticated but lacks the role required by the endpoint, or is acting on another org. |
| `429` | Too Many Requests — More than 100,000 requests from one IP within 5 minutes (configurable per deployment). CORS preflights and requests from inside the platform cluster are not counted. The limiter answers before the error filter, so the body is `{ statusCode, error, message }` with no `path`, `method` or `timeStamp`; the `RateLimit-*` response headers say when the window resets. |
| `500` | An unexpected error occurred. Our team has been notified. — An unhandled server-side failure. |

