Skip to main content
Dedicated IPs give your email traffic its own sending IP address, isolated from other Telnyx customers. Use them when your sending reputation requirements demand full control of the IP’s history — deliverability-critical workloads, shared-pool reputation sensitivity, or compliance needs that name a specific IP.

Pricing and eligibility

  • Pricing: $14 per IP per month, charged as a monthly recurring charge (MRC) that starts at purchase.
  • Billing: the charge continues while the IP is provisioning, warming_up, active, or suspended. It stops only when you release the IP. The billing object on the IP reports the charge state.
  • Eligibility: purchases require a verified or enterprise account. Other accounts receive 403.
  • Selection: the optional region (supported value: ewr-nj1) and ip_version (supported value: ipv4) fields on POST /email/dedicated_ips each restrict which stock IP is allocated; they never change the allocated IP’s metadata. An omitted field applies no restriction for that field.

Lifecycle

A dedicated IP moves through these statuses:

Provisioning and reverse DNS

Dedicated IPs ship with a Telnyx-managed reverse DNS (PTR) record, mta-<a-b-c-d>.msgtelnyx.com — for example, mta-64-16-239-165.msgtelnyx.com for 64.16.239.165. The hostname already resolves forward to the IP, and Telnyx uses it as the EHLO hostname when sending from the IP. There is no customer step to request or author the PTR record, and the hostname cannot be changed: a PATCH /email/dedicated_ips/{id} request that includes ptr_hostname (including null) returns 422 (code 10015), and the IP’s hostname and DNS confirmation are unchanged. When the same request carries pool_id or a warm-up pause field, that change applies and ptr_hostname is ignored. A purchased IP stays provisioning until you call POST /email/dedicated_ips/{id}/actions/start_warmup. That call requires the IP to be in provisioning status; warming_up, active, and released IPs return 422. A suspended IP returns 409 (code 40901): only Telnyx can lift a suspension. The call does not check DNS or pool membership. The provisioning object is read-only status information: An IP sends only while dns_confirmed_at is set. Without it, the IP is excluded from sending, and mail that depends on it is held — it never spills over to the shared pool.

DNS for your sending domains

Dedicated IPs need no SPF change for domains whose SPF record already uses include:spf.telnyx.com, the record Telnyx asks you to publish for every sending domain. Telnyx lists its dedicated sending IPs in spf.telnyx.com. See Domains for the required records.

Warm-up

Every dedicated IP follows an automated warm-up ramp before reaching its full daily volume — the same principle as sender-domain graduation, applied per-IP. One warm-up engine per IP: per-IP and per-domain scopes never stack.
  • Start: the ramp starts only when you call POST /email/dedicated_ips/{id}/actions/start_warmup. It never starts automatically, including after DNS is confirmed.
  • Progression: the ramp advances one stage for each UTC day on which the IP sent mail. Days without sends do not count, so an idle IP holds its stage.
  • Completion: after 28 send-days, the IP moves to active automatically.
  • Pause/resume: POST /email/dedicated_ips/{id}/actions/pause_warmup and .../resume_warmup hold the ramp at its current stage and continue it. You can also PATCH the resource with warmup_paused: true|false or warmup.paused; a Boolean warmup_paused takes precedence. Pausing stops sending, not just progression: while paused, the IP releases no first-attempt sends from hold (see below) until you resume. Pause and resume apply only to warming_up IPs; other statuses return 409.
  • Manual completion: POST /email/dedicated_ips/{id}/actions/complete_warmup moves a warming_up IP to active immediately, bypassing the schedule — use only when you have independently warmed the IP elsewhere. Suspended IPs return 409; other statuses return 422. Completion sets warmup.progress to 100, clears warmup.daily_cap, and applies the ramp-complete allowance to the current UTC day: today.cap becomes 100000000, today.granted keeps the sends already released today, and today.remaining becomes cap − granted. Once completion applies this allowance, an exhausted stage allowance does not block the next eligible first-attempt send. On an active IP, warmup.progress and warmup.daily_cap are informational: they can keep earlier values after a suspension is lifted and do not limit sending.
The default schedule sets these daily caps: An IP under warm-up sends only up to its current stage cap. Do not attempt to send around the cap: once the day’s allowance is spent, further first-attempt sends are held in queue, not rejected, and retried about once a minute until allowance is available — normally when the next UTC day arms a new allowance. A held message waits at most 7 days: if it is still held after 7 days, it expires and is not delivered. Once released from hold, a message gets the standard 72-hour delivery-retry window.

Checking today’s allowance

The warmup object on every dedicated IP carries a today block — the live report card for the current UTC day (caps reset at UTC midnight): today is null outside the warm-up window: before start_warmup, and after release or suspension. A spent day reports the cap with remaining: 0 — that combination is the deliberate “your mail is held for today” signal, distinct from day-0’s cap: null (ramp not yet opened). The exception is an active IP whose cap is below 100000000: that is a stored allowance awaiting refresh, and it does not block the next eligible first-attempt send.

Failure semantics

  • Unsupported purchase selector (422): a region or ip_version value other than the supported one — including ipv6, an empty string, or null — returns 422 (code 10015). source.pointer names the field and detail lists the supported values. Nothing is allocated or waitlisted.
  • Out of stock / over capacity (429): when no dedicated IPs are available for purchase (including none matching your region and ip_version), or your account’s holding capacity is exceeded, the API returns 429 with a meta object carrying retry_after_seconds (and waitlist: true when your request was recorded on the waitlist). Nothing was allocated — retry after the indicated interval.
  • Billing unavailable (503): if billing could not be verified at purchase time — or its admission decision could not be read — the API returns 503 and nothing is allocated. A release returns 503 when billing is unavailable, and the IP is not released. Retry shortly.
  • No sendable IP holds traffic (no spillover): mail routed to a dedicated pool is held when no IP in that pool can send — for example, when every member is provisioning, suspended, or not DNS-confirmed, or the pool is empty. Held mail never spills over to the shared pool, and it expires undelivered if it is still held after the 7-day limit described in Warm-up.

IP pools

Group dedicated IPs into pools to control which addresses carry your traffic:
  • Pools are account-scoped; optionally scope one to a specific email domain (domain_id). An account has at most one default pool (is_default: true).
  • Add/remove members with POST /email/ip_pools/{id}/ips and DELETE /email/ip_pools/{id}/ips/{ip_id}; each membership carries a weight (positive integer, default 100) for traffic distribution.
  • An IP belongs to at most one pool; moving it (PATCH /email/dedicated_ips/{id} with pool_id) removes it from the previous pool’s memberships.
  • Last-member protection: removing a pool’s last IP, moving it to another pool, releasing it, or deleting a pool that still has IPs returns 409 (code 40901) unless you pass both force=true and drain=true. A routed pool left without a sendable IP holds its mail.

Pool routing

A dedicated IP carries mail only through a pool. For each message, Telnyx selects one of the sending account’s pools:
  1. The pool scoped to the message’s sending domain (domain_id).
  2. Otherwise, the account’s default pool (is_default: true).
  3. Otherwise, no dedicated pool: the account sends on the shared Telnyx pool.
A pool that is neither the default nor scoped to a domain carries no mail, and an IP outside every pool carries no mail. Scope at most one pool to each domain; when several pools share a domain_id, which one is used is not defined. Deleting a pool changes routing for subsequently resolved messages. It does not reroute messages already assigned to the deleted pool. To send from dedicated IPs:
  1. Call start_warmup for each IP.
  2. Create a pool with is_default: true (all sending domains) or with domain_id (one domain), or set either field on an existing pool.
  3. Add the IPs to that pool.
Start warm-up before adding an IP to a routed pool: while every member of the selected pool is still provisioning, that pool’s mail is held.

Releasing an IP

DELETE /email/dedicated_ips/{id} releases the IP:
  • The IP stops sending immediately and leaves its pool.
  • status becomes released; released_at is set, and quarantine_until is set to 30 days later. The address is not reassigned before then.
  • 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, including suspended. Releasing a released IP returns 422. A released IP cannot be restarted.
Pass these options as query parameters or in a JSON body: Releasing a pool’s last IP without both force=true and drain=true returns 409 (code 40901).

Next steps