NEW Bare Metal Servers with 20G Dedicated Unmetered Bandwidth 20G Dedicated Unmetered Servers Read more STATUS

Automate reverse DNS for a delegated block

Sep 22, 2026 4 min read

When a whole block is delegated to your server, every address in it is yours to name, and naming them one by one in the portal gets old fast. A short script does the lot: read the block's usable range, then set a PTR on each address you care about. It is the right tool for a mail pool, a set of load-balancer addresses, or an IPv6 range that is never listed at all. If reverse DNS is new to you, start with Set reverse DNS for your IPs; this page is the automated version.

One scope, one call shape

You need a key with ips.write (which includes reading). The whole job uses two endpoints: GET /v1/ips to discover your blocks, and PUT /v1/ips/rdns to name an address. The write takes the address itself, not a row id, so it works for an address whether or not it has ever been listed.

Find the block

GET /v1/ips groups your addresses by the resource that holds them, and each server carries its delegated blocks under prefixes with the usable range:

curl -s https://api.amoni.app/v1/ips \
  -H "Authorization: Bearer nr_live_..."
"prefixes": [
  {
    "cidr": "203.0.113.8/29",
    "version": 4,
    "usable_from": "203.0.113.10",
    "usable_to": "203.0.113.14",
    "usable": 5,
    "ips": [ { "address": "203.0.113.10", "dns_name": "ip4-203-0-113-10.rdns.netrouting.net" } ]
  }
]

Everything between usable_from and usable_to is yours to name; the listed ips are only the ones already named. For IPv6, usable is null because a /64 is too large to count, so you name the specific addresses you use rather than looping the range.

Name the addresses

Each write is PUT /v1/ips/rdns with an address and a dns_name. It is idempotent: setting the same value twice is harmless, and created is true only the first time an unlisted address is named. This bash loop names a mail pool across the block:

#!/usr/bin/env bash
set -euo pipefail
KEY="nr_live_..."
API="https://api.amoni.app/v1"
DOMAIN="mail.example.com"

for n in 10 11 12 13 14; do
  addr="203.0.113.$n"
  host="mx${n}.${DOMAIN}"
  curl -sf -X PUT "$API/ips/rdns" \
    -H "Authorization: Bearer $KEY" -H "Content-Type: application/json" \
    -d "{\"address\": \"$addr\", \"dns_name\": \"$host\"}" \
    | jq -r '.data | "\(.address) -> \(.dns_name) (created: \(.created))"'
done

Each call answers with the address, the name now on it, and whether the row was created:

{ "success": true, "data": {
    "id": 11687, "address": "203.0.113.12",
    "dns_name": "mx12.mail.example.com", "created": false,
    "message": "Reverse DNS updated."
} }

To clear a PTR, send an empty dns_name: {"address": "203.0.113.12", "dns_name": ""}. To keep a block in sync with a source of truth, run the same script from a config file; because the write is idempotent, re-running it only changes what actually differs.

Handle the two refusals

Two errors are worth catching by their code rather than treating every non-200 the same.

  • An address that is the block's network, gateway or broadcast answers 422 with code address_reserved. Skip those; a loop over usable_from to usable_to already avoids them.
  • An address outside any block delegated to you answers 404, never a 403, so a typo in the range is caught rather than silently accepted.

A key without ips.write answers 403 with code insufficient_scope. Everything else follows the usual envelope, so branch on success and read code when it is false.

The forward record still matters

Reverse DNS is only half of a forward-confirmed pair. For mail especially, the hostname you set as the PTR must also resolve forward to that same address in your own DNS. This API sets the reverse side on our nameservers; the matching A or AAAA record lives with whoever runs the domain. Set both, or receiving mail servers will still distrust the address.

Questions we get

  • Do I need the row id? No. The by-address write needs only the address. Ids are for addresses already listed, and the response hands you one if you want it.
  • Does this work for IPv6? Yes, and it is the only way. A /64 is never enumerated, so you name each IPv6 address you use through this same call.
  • Will re-running my script cause churn? No. Writing an unchanged value is a no-op on our side, so a scheduled sync is safe.
  • How fast can I go? A key is limited to 120 requests a minute. For a block larger than that, pace the loop or spread it over a couple of minutes.

Still stuck?

Open a support ticket with the block and a failing address. We can confirm the delegation and why a specific write was refused.

Built for production

Why teams stay with Netrouting

We connect you to the Internet using network engineers (and not order takers) and hardware and infrastructure that is built to last, so we can pick up where you left off when you need us.

  • Expert-Level Support Our staff is available 24 hours a day, 7 days a week to handle network administration and systems management issues as they occur.
  • Scalable Solutions Build whatever depth or breadth your infrastructure needs and then scale as required.
  • Enhanced Security Enable 2-factor authentication and also limit by IP address from the control panel to secure your account.
  • Cost-Efficient Infrastructure You will always receive the best value from your investment as you will be optimized for budget without any compromise on Quality.