Removing extra numbers
Remove extra numbers you no longer need to free up room in your plan and stop the matching charge. You can remove a number at any time, whether it is connected or not. Disconnecting does not stop billing; only removal does.
What happens on the phone
When the removal completes (right away, or on the scheduled date), Turbo Notify disconnects the number from WhatsApp and deletes the number’s access data from your account. On the number’s phone, the entry under Linked devices can stay in the list as Disconnected, and it still counts toward the devices WhatsApp lets you connect (up to 4). To clear it, whoever has the phone opens Linked devices, taps the entry and chooses Remove device. If you resell numbers, pass this on to your customer.
Billing
The effect on the invoice depends on which of the two removal paths was taken:
- Immediate removal: removing an extra number right after adding it, before using it, may delete it on the spot and automatically refund the pro-rata charge made at activation. It is not included in the next period’s invoice.
- Scheduled removal: in every other case, the number is removed at the end of the period already paid (see
scheduled_deletion_atin the response) and there is no refund. Until that date it keeps working normally: it keeps the status it had, sends and receives messages, and you can connect and disconnect it as usual. It is not included in the next period’s invoice: billing stops with the removal. A number that is only disconnected, by contrast, keeps being billed. Until the date, you can cancel the deletion and keep the number.
The DELETE response tells you what happened, in refund_eligible, refund_amount_cents, refund_status and scheduled_deletion_at. Questions about a refund: write to billing@turbonotify.com. For more details, see Extra number billing.
Removing in the dashboard
Open the Numbers (opens in a new tab) page in the dashboard, open the number and click Remove number. Before you confirm, the panel shows what will happen: immediate removal, with the activation amount that will be refunded when there is one (Remove button), or a deletion scheduled for the end of the period already paid, with no refund (Schedule deletion button). While the deletion is pending, the number shows its usual connection status, plus a “Deletion on” notice with the date and a Keep number button.
Removing through the API
curl -X DELETE \ https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS \ -H "Authorization: Bearer YOUR_KEY"const response = await fetch('https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS', { method: 'DELETE', headers: { 'Authorization': 'Bearer YOUR_KEY' }});
const result = await response.json();console.log(result);import requests
url = "https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS"headers = { "Authorization": "Bearer YOUR_KEY"}
response = requests.delete(url, headers=headers)result = response.json()print(result)package main
import ( "fmt" "io" "net/http")
func main() { req, _ := http.NewRequest("DELETE", "https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS", nil) req.Header.Set("Authorization", "Bearer YOUR_KEY") resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body))}<?php$url = 'https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS';
$options = [ 'http' => [ 'header' => [ 'Authorization: Bearer YOUR_KEY' ], 'method' => 'DELETE' ]];
$context = stream_context_create($options);$result = file_get_contents($url, false, $context);$response = json_decode($result, true);var_dump($response);?>var client = new HttpClient();client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_KEY");
var response = await client.DeleteAsync( "https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS");var result = await response.Content.ReadAsStringAsync();Console.WriteLine(result);import java.net.http.*;import java.net.URI;
public class TurboNotify { public static void main(String[] args) throws Exception { var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder() .uri(URI.create("https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS")) .header("Authorization", "Bearer YOUR_KEY") .DELETE() .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}{
"scheduled_deletion_at": "2025-07-16T10:00:00Z",
"refund_eligible": true,
"refund_amount_cents": 2252,
"refund_status": "succeeded"
} Required scope: numbers:write
The response describes the outcome of the deletion, not the number itself:
| Field | Type | Description |
|---|---|---|
scheduled_deletion_at | string | ISO 8601 timestamp of when the number is removed from the account. |
refund_eligible | boolean | true when the removal was immediate and the activation charge is refunded; in that case scheduled_deletion_at is the current time. false when the deletion was scheduled; in that case scheduled_deletion_at is at the end of the period already paid and the number keeps working until then. |
refund_amount_cents | integer | Refunded amount in cents: the same amount as the pro-rata charge made when this number was activated. 0 when refund_eligible is false, or when refund_status is not_applicable or failed (see below). |
refund_status | string | null | The outcome of the refund attempt: succeeded (refund processed; refund_amount_cents has the refunded amount), not_applicable (nothing to refund in this response: there was no activation charge for this number, or another simultaneous request for the same number is already handling the refund; not an error) or failed (there was a charge and the refund could not be processed; the deletion of the number is not blocked by this. Write to billing@turbonotify.com to get the refund). null when refund_eligible is false (no refund was attempted). |
The call is idempotent: repeating the request for a number already scheduled for deletion returns the same schedule (without a new refund).
Cancel a scheduled deletion
While the deletion has not been carried out (the number has a
scheduled_deletion_at), you can cancel it and keep the number. This is the
only way to keep it: connecting or disconnecting the number does not change a
scheduled deletion.
curl -X POST \ https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/cancel-deletion \ -H "Authorization: Bearer YOUR_KEY"const response = await fetch('https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/cancel-deletion', { method: 'POST', headers: { 'Authorization': 'Bearer YOUR_KEY' }});
const result = await response.json();console.log(result);import requests
url = "https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/cancel-deletion"headers = {"Authorization": "Bearer YOUR_KEY"}
response = requests.post(url, headers=headers)result = response.json()print(result)package main
import ( "fmt" "io" "net/http")
func main() { req, _ := http.NewRequest("POST", "https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/cancel-deletion", nil) req.Header.Set("Authorization", "Bearer YOUR_KEY") resp, _ := http.DefaultClient.Do(req) defer resp.Body.Close() body, _ := io.ReadAll(resp.Body) fmt.Println(string(body))}<?php$url = 'https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/cancel-deletion';
$options = [ 'http' => [ 'header' => ['Authorization: Bearer YOUR_KEY'], 'method' => 'POST' ]];
$context = stream_context_create($options);$result = file_get_contents($url, false, $context);$response = json_decode($result, true);var_dump($response);?>var client = new HttpClient();client.DefaultRequestHeaders.Add("Authorization", "Bearer YOUR_KEY");
var response = await client.PostAsync( "https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/cancel-deletion", null);var result = await response.Content.ReadAsStringAsync();Console.WriteLine(result);import java.net.http.*;import java.net.URI;
public class TurboNotify { public static void main(String[] args) throws Exception { var client = HttpClient.newHttpClient();
var request = HttpRequest.newBuilder() .uri(URI.create("https://api.turbonotify.com/v1/numbers/NUMBER_ALIAS/cancel-deletion")) .header("Authorization", "Bearer YOUR_KEY") .POST(HttpRequest.BodyPublishers.noBody()) .build();
var response = client.send(request, HttpResponse.BodyHandlers.ofString()); System.out.println(response.body()); }}{
"status": "connected",
"at": "2025-07-16T10:05:00Z"
} The response carries the number’s connection status (one of the values in the
Status table) and, in at, the moment it
entered that status (null when there is no record). Since a scheduled
deletion does not change the number, the status is the same as before the
cancellation. To follow the status afterwards, check
Extra number status.
Possible errors
Remove (DELETE /v1/numbers/{ref})
| Status | Error code | Description |
|---|---|---|
402 | feature_not_available | The current plan does not support extra numbers. |
401 | not_authenticated | The API key is invalid or missing. |
403 | insufficient_scope | The API key does not have the numbers:write scope (the response includes required_scope). |
404 | number_not_found | The alias or id was not found in the account. |
500 | internal_error | Unexpected internal server error. |
Cancel deletion (POST /v1/numbers/{ref}/cancel-deletion)
| Status | Error code | Description |
|---|---|---|
400 | not_pending_deletion | The number does not have a scheduled deletion. |
400 | no_payment_method | Canceling requires charging the rest of the paid period, but the organization has no payment method on file. The deletion stays scheduled. |
402 | feature_not_available | The current plan does not support extra numbers. |
402 | payment_declined | The charge for the rest of the paid period was declined. The deletion stays scheduled. |
402 | payment_requires_authentication | The payment method requires re-authentication (3DS). The deletion stays scheduled. |
401 | not_authenticated | The API key is invalid or missing. |
403 | insufficient_scope | The API key does not have the numbers:write scope (the response includes required_scope). |
404 | number_not_found | The alias or id was not found in the account. |
500 | internal_error | Unexpected internal server error. |
503 | payment_gateway_unavailable | The charge for the rest of the paid period could not be confirmed in time. Try again. |