> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.getdial.ai/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.getdial.ai/_mcp/server.

# Update a phone number

PATCH https://api.getdial.ai/api/v1/numbers/{id}
Content-Type: application/json

Update a number's properties. Send any subset of the fields below —
at least one is required; omitted fields are left unchanged.
A new `inboundInstruction` takes effect on the next inbound call;
in-progress calls are unaffected.

**iMessage display identity.** On numbers with the `imessage`
capability, `firstName`, `lastName`, and an avatar photo set the
identity shown beside the number's messages in recipients' Messages
apps. Sending any of these fields for a number without the `imessage`
capability is rejected with `400`.

**The avatar photo** is set either by uploading a file (the `avatar`
part, `multipart/form-data` only) or by passing a publicly reachable
image URL (`avatarUrl`, JSON or multipart) that Dial downloads
server-side. Accepted types: jpeg, png, gif, webp; max 5 MB. A square
image of 512×512 or larger is recommended — it is shown as a circle.
Dial mirrors the photo into its own storage and serves it from the
stable public URL returned as `avatarUrl`. The photo can be
**replaced but not removed** — `avatarUrl: null` is rejected with
`400`. Identity changes can take a few minutes to propagate to
recipients' devices.

**WhatsApp display identity.** On WhatsApp-ready numbers, `whatsappName`
and a `whatsappAvatar`/`whatsappAvatarUrl` set the display name and photo
shown to WhatsApp recipients. The name is 1–25 characters and cannot
contain the reserved verification marks (✔, ✅, ☑); the avatar must be a
square jpeg or png between 192×192 and 640×640 (Dial validates the
dimensions and does not resize). These fields apply only to
WhatsApp-ready numbers — rejected with `400` otherwise. Unlike the
iMessage identity, the request **blocks until WhatsApp confirms** the
change; if the WhatsApp line can't be driven, the call returns `503`.


Reference: https://docs.getdial.ai/api-reference/rest-api/phone-numbers/update-number

## Authentication

- `Authorization` header (bearer token, required) — Your Dial API key, sent as `Authorization: Bearer sk_live_...`

## Request

### Path parameters

- `id` (string, required)

### Body (application/json)

- `inboundInstruction` (string, optional) — New inbound voice-agent system prompt for this number.
- `inboundVoiceGender` (enum, optional) — Voice gender for the AI agent on inbound calls to this number. Send null to clear it (the voice reverts to the default, female). Takes effect on the next inbound call.
  - Allowed values: `male`, `female`
- `inboundLanguage` (string, optional, nullable) — BCP-47 language tag for the AI voice agent on inbound calls to this number. Send null to clear it — the language is then detected from the caller's country prefix on each call, with the agent handling both that language and `en-US`. Takes effect on the next inbound call.
- `nickname` (string, optional, nullable) — Human-readable label for the number. Trimmed; at most 100 characters. Send null or an empty string to clear it.
- `firstName` (string, optional, nullable) — iMessage display first name shown beside this number's messages in recipients' Messages apps. Trimmed; at most 30 characters. Send null or an empty string to clear it. Only valid on numbers with the `imessage` capability — rejected with `400` otherwise.
- `lastName` (string, optional, nullable) — iMessage display last name. Trimmed; at most 30 characters. Send null or an empty string to clear it. Only valid on numbers with the `imessage` capability — rejected with `400` otherwise.
- `avatarUrl` (string, optional) — Publicly reachable http(s) URL of an image to set as the number's iMessage avatar photo. Dial downloads it server-side, mirrors it into its own storage, and serves it from the `avatarUrl` returned on the number. jpeg, png, gif, or webp; max 5 MB. The photo can be replaced but not removed — null is rejected with `400`. Only valid on numbers with the `imessage` capability.
- `whatsappName` (string, optional) — WhatsApp display name for this number's WhatsApp line, shown to recipients as the sender name. Trimmed; 1–25 characters. Cannot be cleared, and cannot contain the reserved verification marks (✔, ✅, ☑). Only valid on WhatsApp-ready numbers — rejected with `400` otherwise. The request blocks until WhatsApp applies the change; a failure returns `503`.
- `whatsappAvatarUrl` (string, optional) — Publicly reachable http(s) URL of an image to set as the number's WhatsApp avatar. Dial downloads it server-side, mirrors it into its own storage, and serves it from the `whatsappAvatarUrl` returned on the number. jpeg or png; the image must be square, between 192×192 and 640×640 — any other dimensions are rejected with `400` (Dial does not resize). Only valid on WhatsApp-ready numbers.
- `maxCallDurationSeconds` (integer, optional, nullable) — Cap on the length of calls on this number, in seconds, for both inbound calls to the number and outbound calls placed from it. The effective cap on a call is the first one set in priority order — the per-call cap, then this number cap, then the account cap — falling back to the global default. This number cap overrides the account cap (raising or lowering the limit) but is itself overridden by a per-call cap. Must be between 60 and 3600 seconds (1 minute to 1 hour); a value outside that range returns 400. Send null to clear it (falls back to the account cap or global default). Free accounts — accounts that have never added credit and never subscribed — are capped at 300 seconds (5 minutes), reported as `limits.maxCallDurationSeconds` on the account: a higher value sent here returns 400, and a cap inherited from another level is clamped to 300. When a cap is active, Dial automatically injects a warning to the agent ~40 seconds before the hard cut, prompting it to wrap up naturally.
- `callingEnabled` (boolean, optional) — Switch calling on or off for this number, in both directions. `false` stops inbound calls from being connected and makes Place a call from this number return `409 calling_disabled`; messaging is unaffected. Takes effect on the next call — a call already in progress is not terminated. `capabilities` does not change.

## Response

### 200

Updated.

- `number` (object, optional)
  - `id` (string, optional)
  - `number` (string, optional) — The number in E.164 format.
  - `nickname` (string, optional, nullable) — Optional human-readable label for the number, e.g. "Support line". Free text, at most 100 characters, not required to be unique. Null when unset. Set and cleared with Update a phone number.
  - `firstName` (string, optional, nullable) — iMessage display first name — with `lastName` and the avatar photo, the identity shown beside this number's messages in recipients' Messages apps. At most 30 characters. Null when unset, and always null on numbers without the `imessage` capability. Set and cleared with Update a phone number.
  - `lastName` (string, optional, nullable) — iMessage display last name. At most 30 characters. Null when unset, and always null on numbers without the `imessage` capability. Set and cleared with Update a phone number.
  - `avatarUrl` (string, optional, nullable) — Public URL of the number's current iMessage avatar photo, hosted by Dial. Null when no photo has been set, and always null on numbers without the `imessage` capability. Set with Update a phone number; the photo can be replaced but not removed.
  - `whatsappName` (string, optional, nullable) — The number's current WhatsApp display name. Null when none is set, and always null on numbers without a working `whatsapp` capability. Set with Update a phone number.
  - `whatsappAvatarUrl` (string, optional, nullable) — Public URL of the number's current WhatsApp avatar, hosted by Dial. Null when no photo has been set, and always null on numbers without a working `whatsapp` capability. Set with Update a phone number.
  - `country` (string, optional) — ISO-3166-1 alpha-2 country code of the number. Always `US` — only US numbers can be provisioned at this time.
  - `capabilities` (list of enum, optional) — Channels the number supports. `["sms","call"]` for a standard number; `["sms","call","imessage"]` for an iMessage number (which sends iMessage with automatic fallback to RCS/SMS); that plus `whatsapp` once a WhatsApp registration on the line is live. `whatsapp` appears only when the channel actually works — while it is still being set up the line reports the iMessage list, and `whatsapp.status` is where the progress shows. Mirrors the `capabilities` accepted when provisioning, plus `whatsapp`, which is requested with the separate `whatsapp` flag rather than in this array.
    - Allowed values: `sms`, `call`, `imessage`, `whatsapp`
  - `callingEnabled` (boolean, optional, default: true) — Whether calling is switched on for this number, in both directions. `true` (the default) is normal operation. When `false`, inbound calls to the number are not connected — the caller is not answered, no AI agent runs, and no minute is billed — and Place a call from this number is refused with `409 calling_disabled`. Messaging on the number (SMS, iMessage, RCS, WhatsApp) is unaffected either way. Set at provisioning time and changeable with Update a phone number; takes effect on the next call, never on one already in progress. Distinct from `capabilities`, which reports what the line was provisioned to do and never moves when this switch is flipped. To decide whether a call can be placed from this number right now, read all three: `capabilities` contains `call`, `setupStatus` is `ready`, and `callingEnabled` is `true`.
  - `setupStatus` (enum, optional) — Whether the number is ready to use. An SMS/call number is always `ready`. An `imessage` number is `provisioning` while it's being set up and only becomes usable for sending or calling once `ready` (`failed` on a setup error). Every change to this field emits a `number.status_changed` event — wait for that rather than polling. That event reports per-capability statuses rather than this single field, so it can also tell you about the WhatsApp channel, which settles independently of this one.
    - Allowed values: `provisioning`, `ready`, `failed`
  - `setupError` (string, optional, nullable) — Human-readable reason when `setupStatus` is `failed`; null otherwise.
  - `inboundInstruction` (string, optional, nullable) — System prompt the AI voice agent uses on inbound calls to this number. Set at provisioning time and changeable with Update a phone number. Null for numbers provisioned before this field existed — those reject inbound calls until an instruction is set.
  - `inboundVoiceGender` (enum, optional) — Voice gender the AI agent uses on inbound calls to this number. Null when unset — the voice then uses the default, female. Set and cleared with Update a phone number.
    - Allowed values: `male`, `female`
  - `inboundLanguage` (string, optional, nullable) — BCP-47 language tag the AI voice agent uses on inbound calls to this number. Null when unset — the language is then detected from the caller's country prefix on each call, with the agent handling both that language and `en-US`. Set and cleared with Update a phone number.
  - `accountId` (string, optional)
  - `createdAt` (datetime, optional)
  - `maxCallDurationSeconds` (integer, optional, nullable) — Call-length cap in seconds; the effective cap on a call is the first one set in priority order — per-call, then number, then account — falling back to the global default. A higher-priority level overrides a lower one. Null means this level sets no cap. Free accounts (never added credit, never subscribed) are additionally hard-capped at 300 seconds regardless of any configured cap.
  - `whatsapp` (object, optional, nullable) — The WhatsApp channel's own setup state, or null when the number has no WhatsApp registration at all — which is every number unless the beta was enabled and WhatsApp was requested for this line. **Independent of `setupStatus`.** They are separate tracks on one line: voice caller-ID can be `ready` while WhatsApp is `failed`, and the other way round, so one status field could not carry both. See WhatsApp lines.
    - `status` (enum, optional) — Where WhatsApp setup stands for this line. Sending with `channel: "whatsapp"` is rejected until `ready`.
      - Allowed values: `provisioning`, `ready`, `failed`
    - `error` (string, optional, nullable) — Human-readable reason when `status` is `failed`; null otherwise.
    - `retryAvailableAt` (datetime, optional, nullable) — When WhatsApp will accept another verification attempt for this number, or null. Only ever set on a `failed` track, and only while still in the future. It is the one failure that can be neither fixed nor retried around — enforced per number by WhatsApp itself — so a retry is refused until it lifts. Show the time rather than a button that cannot work.
  - `tenDlc` (object, optional, nullable) — US 10DLC carrier registration for this number. Null when 10DLC does not apply to it — a non-US number, a number with the `imessage` capability (those send over Apple Messages for Business, not carrier SMS), or a number on an account that isn't pay-as-you-go and has no registration yet. Otherwise an object whose `status` says where the registration stands, starting at `not_registered`. US carriers block outbound SMS and MMS sent from an unregistered 10-digit number to US phone numbers. Registering lifts that block for this number. Inbound texts, voice calls in either direction, and messaging to numbers outside the US are unaffected.
    - `status` (enum, required) — Where this number's registration stands. - `not_registered` — 10DLC applies to this number but nothing has been submitted. Outbound US SMS/MMS is blocked by carriers. - `in_review` — submitted; Dial is checking the details before filing them with the carrier registry. - `with_carrier` — filed with the carrier registry; a decision usually lands within 3–5 business days. - `approved` — registered. The number can send outbound SMS and MMS to US phone numbers. - `rejected` — changes are needed before it can be registered. See `reason`, then resubmit (no additional fee). The brand and the campaign are vetted separately, and this is the combined outcome: `approved` means both cleared, and `rejected` means either was turned down.
      - Allowed values: `not_registered`, `in_review`, `with_carrier`, `approved`, `rejected`
    - `kind` (enum, required) — Who the number was registered as. Null while `status` is `not_registered`.
      - Allowed values: `sole_proprietor`, `business`
    - `submittedAt` (datetime, required, nullable) — When the current submission was sent. Null while `status` is `not_registered`. A resubmission after a rejection updates this.
    - `reviewedAt` (datetime, required, nullable) — When the registration was approved or rejected. Null until then.
    - `reason` (string, required, nullable) — What needs to change, verbatim as shown to the account owner. Non-null only when `status` is `rejected`.

## Examples

**Request**

```json
{}
```

**Response**

```json
{
  "number": {
    "id": "string",
    "number": "+14155550123",
    "nickname": "Support line",
    "firstName": "Maya",
    "lastName": "Chen",
    "avatarUrl": "https://getdial.ai/public-media/9f2c47a1b8d3e6f0a1b2c3d4.png",
    "whatsappName": "Maya from ACME",
    "whatsappAvatarUrl": "https://getdial.ai/public-media/7a1b2c3d4e5f60718293a4b5.png",
    "country": "US",
    "capabilities": [
      "sms",
      "call"
    ],
    "callingEnabled": true,
    "setupStatus": "ready",
    "setupError": "string",
    "inboundInstruction": "You are Dial's receptionist. Greet the caller and find out what they need.",
    "inboundVoiceGender": "female",
    "inboundLanguage": "es-ES",
    "accountId": "string",
    "createdAt": "2024-01-15T09:30:00Z",
    "maxCallDurationSeconds": 1,
    "whatsapp": {
      "status": "ready",
      "error": null,
      "retryAvailableAt": null
    },
    "tenDlc": {
      "status": "in_review",
      "kind": "business",
      "submittedAt": "2024-01-15T09:30:00Z",
      "reviewedAt": "2024-01-15T09:30:00Z",
      "reason": "The message flow describes a checkout page rather than the SMS consent step. Say where the consent wording and the checkbox appear, and that the box starts unchecked."
    }
  }
}
```

**SDK Code**

```python
import requests

url = "https://api.getdial.ai/api/v1/numbers/id"

payload = {}
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.patch(url, json=payload, headers=headers)

print(response.json())
```

```javascript
const url = 'https://api.getdial.ai/api/v1/numbers/id';
const options = {
  method: 'PATCH',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://api.getdial.ai/api/v1/numbers/id"

	payload := strings.NewReader("{}")

	req, _ := http.NewRequest("PATCH", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby
require 'uri'
require 'net/http'

url = URI("https://api.getdial.ai/api/v1/numbers/id")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Patch.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{}"

response = http.request(request)
puts response.read_body
```

```java
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.patch("https://api.getdial.ai/api/v1/numbers/id")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{}")
  .asString();
```

```php
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PATCH', 'https://api.getdial.ai/api/v1/numbers/id', [
  'body' => '{}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp
using RestSharp;

var client = new RestClient("https://api.getdial.ai/api/v1/numbers/id");
var request = new RestRequest(Method.PATCH);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = [] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://api.getdial.ai/api/v1/numbers/id")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PATCH"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```