curl --request PATCH \
--url https://app.thinnest.ai/api/v1/phone-numbers/{number} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"label": "Front desk",
"agent": "ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34",
"callingAgent": "ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15"
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
label: 'Front desk',
agent: 'ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34',
callingAgent: 'ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15'
})
};
fetch('https://app.thinnest.ai/api/v1/phone-numbers/{number}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.thinnest.ai/api/v1/phone-numbers/{number}"
payload = {
"label": "Front desk",
"agent": "ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34",
"callingAgent": "ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"number": "918041234567",
"label": "Front desk",
"source": "rented",
"agent": "ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34",
"since": "2026-09-02T07:15:40.118Z",
"provider": null,
"callingAgent": "ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15"
}{
"error": "Nothing to change — send `label`, `agent` or `callingAgent`."
}{
"error": "Send a valid API key as `Authorization: Bearer <key>`."
}{
"error": "This API key is read-only: it can read everything but change nothing."
}{
"error": "Agent not found."
}{
"error": "Turn voice on for that agent first, then move the number to it."
}{
"error": "Over 240 requests a minute. Slow down and retry."
}Update Phone Number
Points a number at an agent, lends it to one for calling out, or names it — any of the three. agent makes the number that agent’s line (it stops being any other agent’s; the agent must have voice switched on); callingAgent lets an agent call out on it without answering it (a brought number needs its carrier account’s keys saved first). They are applied in the order label, agent, callingAgent, and a refusal stops there with the earlier changes kept. Needs a full key.
curl --request PATCH \
--url https://app.thinnest.ai/api/v1/phone-numbers/{number} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"label": "Front desk",
"agent": "ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34",
"callingAgent": "ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15"
}
'const options = {
method: 'PATCH',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
label: 'Front desk',
agent: 'ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34',
callingAgent: 'ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15'
})
};
fetch('https://app.thinnest.ai/api/v1/phone-numbers/{number}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));import requests
url = "https://app.thinnest.ai/api/v1/phone-numbers/{number}"
payload = {
"label": "Front desk",
"agent": "ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34",
"callingAgent": "ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text){
"number": "918041234567",
"label": "Front desk",
"source": "rented",
"agent": "ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34",
"since": "2026-09-02T07:15:40.118Z",
"provider": null,
"callingAgent": "ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15"
}{
"error": "Nothing to change — send `label`, `agent` or `callingAgent`."
}{
"error": "Send a valid API key as `Authorization: Bearer <key>`."
}{
"error": "This API key is read-only: it can read everything but change nothing."
}{
"error": "Agent not found."
}{
"error": "Turn voice on for that agent first, then move the number to it."
}{
"error": "Over 240 requests a minute. Slow down and retry."
}Authorizations
Your API key (ta_live_…) from Settings → API keys, sent as Authorization: Bearer <key>. Keep it on a server: it can message every customer you have. A key is full, build or read-only; a request its level does not allow is refused with 403.
Headers
Developers only: the customer workspace this request acts in — its org_… id from POST /customers. Leave it out to act in your own workspace.
"org_3fKq9TzQ1mN8vB2xR7cLpA"
Path Parameters
The number, in any spelling — compared on its digits (8 to 15 of them). Encode a leading + as %2B, or leave it out.
Body
Send any of the three; at least one.
A name for the number. null or "" removes it.
60"Front desk"
The agent that answers the number (ag_…): it becomes that agent's line and stops being any other's. The agent must have voice switched on. null makes nothing answer it.
"ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34"
The agent that calls out on the number without answering it (ag_…) — campaigns spread their calls over an agent's numbers. null takes it back. Where the number answers is unchanged.
"ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15"
Response
The number as it now is.
A number, with the agent it is lent to for calling out.
The number. A rented number reads as digits with its country code (918041234567); a brought one as you brought it, usually E.164.
"918041234567"
Its name, or null. Always null for a brought number in List Phone Numbers.
60"Front desk"
rented here and charged monthly, or brought from your own carrier account and never billed by us.
rented, brought "rented"
The agent that answers it (ag_…), or null for nobody.
"ag_3f6a9c21-7d4e-4b58-9a1f-0c2e8b7d5a34"
When a rented number was rented; null for a brought one.
"2026-09-02T07:15:40.118Z"
Your own carrier account a brought number is on (plivo, vobiz, twilio or telnyx); null for a number rented here.
"twilio"
The agent lent this number to call out on (ag_…), or null. May differ from agent.
"ag_9b0e4d17-5a2c-4e6f-b381-7c4d2a0f9e15"