Release a dedicated IP
Release the dedicated IP to Telnyx. The IP stops carrying mail immediately, leaves its pool, and moves to released. Telnyx sets quarantine_until to 30 days after release. Release requests that the MRC stop asynchronously. Check billing: stopping means the stop is pending, stopped means it completed, and stop_failed means the charge remains. If the charge was never created or its creation has not completed, billing keeps showing the creation status (not_started, pending, in_progress, or failed). Any status except released can be released. Releasing the last IP in a pool requires force=true and drain=true.
curl --request DELETE \
--url https://api.telnyx.com/v2/email/dedicated_ips/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"reason": "No longer needed"
}
'import requests
url = "https://api.telnyx.com/v2/email/dedicated_ips/{id}"
payload = { "reason": "No longer needed" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.delete(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'DELETE',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({reason: 'No longer needed'})
};
fetch('https://api.telnyx.com/v2/email/dedicated_ips/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.telnyx.com/v2/email/dedicated_ips/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_POSTFIELDS => json_encode([
'reason' => 'No longer needed'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.telnyx.com/v2/email/dedicated_ips/{id}"
payload := strings.NewReader("{\n \"reason\": \"No longer needed\"\n}")
req, _ := http.NewRequest("DELETE", 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(string(body))
}HttpResponse<String> response = Unirest.delete("https://api.telnyx.com/v2/email/dedicated_ips/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"No longer needed\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.telnyx.com/v2/email/dedicated_ips/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Delete.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"No longer needed\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "6a7f9a30-1234-4b5c-8d9e-0f1a2b3c4d5e",
"record_type": "dedicated_ip",
"ip_address": "64.16.239.170",
"ip_version": "ipv4",
"pool_id": null,
"region": "ewr-nj1",
"status": "released",
"warmup": {
"started_at": null,
"progress": 0,
"daily_cap": null,
"paused": false,
"paused_at": null,
"today": null
},
"billing": {
"status": "stopping",
"charged": true
},
"provisioning_status": "not_applicable",
"provisioning": {
"dns_status": "not_applicable",
"ptr_request_state": "confirmed",
"ptr_request_pr_url": null,
"checklist": {
"ptr_requested": true,
"ptr_authored": false,
"ptr_merged": true,
"forward_confirmed": true
}
},
"ptr_hostname": "mta-64-16-239-170.msgtelnyx.com",
"dns_confirmed_at": "2026-10-14T20:12:41.552310Z",
"quarantine_until": "2026-11-23T22:00:00.000000Z",
"released_at": "2026-10-24T22:00:00.000000Z",
"suspension_reason": null,
"created_at": "2026-09-30T02:03:09.474123Z",
"updated_at": "2026-10-24T22:00:00.000000Z"
}
}{
"errors": [
{
"code": "<string>",
"title": "<string>",
"detail": "<string>",
"source": {
"pointer": "<string>",
"parameter": "<string>"
}
}
]
}{
"errors": [
{
"code": "<string>",
"title": "<string>",
"detail": "<string>",
"source": {
"pointer": "<string>",
"parameter": "<string>"
}
}
]
}{
"errors": [
{
"code": "10001",
"title": "Not Found",
"detail": "The requested dedicated IP was not found"
}
]
}{
"errors": [
{
"code": "40901",
"title": "Conflict",
"detail": "cannot release the last IP in a pool without force: true and drain: true (in-flight messages need a routable source)"
}
]
}{
"errors": [
{
"code": "10015",
"title": "Validation Failed",
"detail": "cannot transition dedicated IP from released to released",
"source": {
"pointer": "/data/attributes/status"
}
}
]
}{
"errors": [
{
"code": "10031",
"title": "Service Unavailable",
"detail": "Dedicated IP Billing is unavailable — the purchase was not allocated; retry shortly"
}
]
}Authorizations
Telnyx API key supplied as Authorization: Bearer <token>. In production, auth may be validated by the API gateway and forwarded via Telnyx auth headers.
Path Parameters
The dedicated IP identifier (UUID).
Query Parameters
Set together with drain=true to release the last IP in a pool. Either flag alone has no effect. Also accepted in the JSON body.
Set together with force=true to release the last IP in a pool. Acknowledges that mail routed to the emptied pool is held until the pool has a sendable IP again. Also accepted in the JSON body.
Free-text reason recorded with the release. Also accepted in the JSON body.
Body
Optional release options. The same fields are accepted as query parameters.
Set together with drain: true to release the last IP in a pool. Either flag alone has no effect.
Set together with force: true to release the last IP in a pool. Acknowledges that mail routed to the emptied pool is held until the pool has a sendable IP again.
Free-text reason recorded with the release.
Response
Released dedicated IP
A dedicated sending IP address owned by the account.
Show child attributes
Show child attributes
Was this page helpful?
curl --request DELETE \
--url https://api.telnyx.com/v2/email/dedicated_ips/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"reason": "No longer needed"
}
'import requests
url = "https://api.telnyx.com/v2/email/dedicated_ips/{id}"
payload = { "reason": "No longer needed" }
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.delete(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'DELETE',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({reason: 'No longer needed'})
};
fetch('https://api.telnyx.com/v2/email/dedicated_ips/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.telnyx.com/v2/email/dedicated_ips/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_POSTFIELDS => json_encode([
'reason' => 'No longer needed'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.telnyx.com/v2/email/dedicated_ips/{id}"
payload := strings.NewReader("{\n \"reason\": \"No longer needed\"\n}")
req, _ := http.NewRequest("DELETE", 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(string(body))
}HttpResponse<String> response = Unirest.delete("https://api.telnyx.com/v2/email/dedicated_ips/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"reason\": \"No longer needed\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.telnyx.com/v2/email/dedicated_ips/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Delete.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"reason\": \"No longer needed\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "6a7f9a30-1234-4b5c-8d9e-0f1a2b3c4d5e",
"record_type": "dedicated_ip",
"ip_address": "64.16.239.170",
"ip_version": "ipv4",
"pool_id": null,
"region": "ewr-nj1",
"status": "released",
"warmup": {
"started_at": null,
"progress": 0,
"daily_cap": null,
"paused": false,
"paused_at": null,
"today": null
},
"billing": {
"status": "stopping",
"charged": true
},
"provisioning_status": "not_applicable",
"provisioning": {
"dns_status": "not_applicable",
"ptr_request_state": "confirmed",
"ptr_request_pr_url": null,
"checklist": {
"ptr_requested": true,
"ptr_authored": false,
"ptr_merged": true,
"forward_confirmed": true
}
},
"ptr_hostname": "mta-64-16-239-170.msgtelnyx.com",
"dns_confirmed_at": "2026-10-14T20:12:41.552310Z",
"quarantine_until": "2026-11-23T22:00:00.000000Z",
"released_at": "2026-10-24T22:00:00.000000Z",
"suspension_reason": null,
"created_at": "2026-09-30T02:03:09.474123Z",
"updated_at": "2026-10-24T22:00:00.000000Z"
}
}{
"errors": [
{
"code": "<string>",
"title": "<string>",
"detail": "<string>",
"source": {
"pointer": "<string>",
"parameter": "<string>"
}
}
]
}{
"errors": [
{
"code": "<string>",
"title": "<string>",
"detail": "<string>",
"source": {
"pointer": "<string>",
"parameter": "<string>"
}
}
]
}{
"errors": [
{
"code": "10001",
"title": "Not Found",
"detail": "The requested dedicated IP was not found"
}
]
}{
"errors": [
{
"code": "40901",
"title": "Conflict",
"detail": "cannot release the last IP in a pool without force: true and drain: true (in-flight messages need a routable source)"
}
]
}{
"errors": [
{
"code": "10015",
"title": "Validation Failed",
"detail": "cannot transition dedicated IP from released to released",
"source": {
"pointer": "/data/attributes/status"
}
}
]
}{
"errors": [
{
"code": "10031",
"title": "Service Unavailable",
"detail": "Dedicated IP Billing is unavailable — the purchase was not allocated; retry shortly"
}
]
}