Infrastructure as Code has transformed how teams manage servers, databases, and networks. Yet DNS remains a manual bottleneck for many engineering teams. You log into a dashboard, click through forms, and hope you don't fat-finger a record during a deployment. This works until you're managing dozens of domains, spinning up ephemeral environments, or coordinating deployments across multiple services.
The name.com API is a REST API that lets you programmatically search, register, and manage DNS records. Unlike registrars that treat APIs as an afterthought, name.com provides API access as a core feature — standard HTTP methods, JSON responses, and clear documentation.
Authentication and Security
API access starts in your name.com dashboard under API → API Token Management. You get two environments: production (api.name.com) and Development/Test (api.dev.name.com). The test environment uses your username with -test appended, so you can test DNS changes without affecting live domains.
The API uses HTTP Basic Auth. Your username and token combine into a base64-encoded header:
import base64
import os
username = os.getenv('NAMECOM_USERNAME')
token = os.getenv('NAMECOM_TOKEN')
credentials = f"{username}:{token}"
encoded_credentials = base64.b64encode(credentials.encode()).decode()
auth_header = f"Basic {encoded_credentials}"
headers = {
'Authorization': auth_header,
'Content-Type': 'application/json'
}Never hardcode credentials in scripts. Use environment variables or a secrets manager. For team environments, rotate tokens periodically — name.com lets you generate multiple tokens for token-per-service patterns.
Understanding API Constraints
The name.com API implements a rate limit of 3,000 requests per hour. For bulk operations, exponential backoff is the right pattern:
import time
import requests
def make_request_with_backoff(url, headers, method='GET', data=None, max_retries=5):
for attempt in range(max_retries):
if method == 'GET':
response = requests.get(url, headers=headers)
elif method == 'POST':
response = requests.post(url, headers=headers, json=data)
elif method == 'PUT':
response = requests.put(url, headers=headers, json=data)
elif method == 'DELETE':
response = requests.delete(url, headers=headers)
if response.status_code == 429:
wait_time = 2 ** attempt
print(f"Rate limited. Waiting {wait_time}s before retry {attempt+1}/{max_retries}")
time.sleep(wait_time)
continue
return response
return NoneRetrieving Data and Handling Pagination
The API uses page and perPage parameters, with a default of 1,000 records per page — enough to cover most domains in a single call:
def get_all_dns_records(domain, headers):
base_url = "https://api.name.com/core/v1"
all_records = []
page = 1
per_page = 1000
while True:
url = f"{base_url}/domains/{domain}/records?page={page}&perPage={per_page}"
response = requests.get(url, headers=headers)
if response.status_code != 200:
break
data = response.json()
records = data.get('records', [])
if not records:
break
all_records.extend(records)
if len(records) < per_page:
break
page += 1
return all_recordsEach record includes an id field — your handle for updates and deletions. Store these IDs when building automation.
Managing State with CRUD Operations
Creating Records
def create_dns_record(domain, record_type, host, answer, ttl=300, headers=None):
url = f"https://api.name.com/core/v1/domains/{domain}/records"
payload = {
"host": host,
"type": record_type,
"answer": answer,
"ttl": ttl
}
if record_type == "MX":
payload["priority"] = 10
response = requests.post(url, headers=headers, json=payload)
if response.status_code == 200:
return response.json()
else:
print(f"Failed: {response.status_code} — {response.text}")
return None
# Create an A record for staging
create_dns_record(
domain="yourdomain.com",
record_type="A",
host="staging",
answer="192.168.2.50",
ttl=300,
headers=headers
)Updating Records
Updates are atomic at the record level — the API replaces the entire record, not individual fields. Use PUT /core/v1/domains/{domain}/records/{record_id} with the record ID from a previous GET request.
def update_dns_record(domain, record_id, record_type, host, answer, ttl=300, headers=None):
url = f"https://api.name.com/core/v1/domains/{domain}/records/{record_id}"
payload = {"host": host, "type": record_type, "answer": answer, "ttl": ttl}
response = requests.put(url, headers=headers, json=payload)
if response.status_code == 200:
return response.json()
return NoneDeleting Records with Safety Checks
def delete_dns_record(domain, record_id, headers, require_confirmation=True):
url = f"https://api.name.com/core/v1/domains/{domain}/records/{record_id}"
response = requests.get(url, headers=headers)
if response.status_code == 200:
record = response.json()
critical_hosts = ['', 'www', 'mail', 'mx']
if record['host'] in critical_hosts and require_confirmation:
confirm = input("Critical record. Type 'DELETE' to confirm: ")
if confirm != 'DELETE':
return False
response = requests.delete(url, headers=headers)
return response.status_code == 200Building a Self-Healing DNS Strategy
With CRUD operations in place, you can build automation that keeps DNS synchronized with your infrastructure state: health-check scripts that automatically update A records when servers change IP, CI/CD pipelines that create preview environment DNS records on PR creation and delete them on merge, or blue-green deployment scripts that atomically switch DNS between server pools.
The key is treating DNS records as infrastructure state: read before writing, validate before deleting, log every change with timestamps and record IDs. The name.com API provides the foundation. The rest is execution discipline.