📘 DNS API User Guide
Overview
The DNS API allows you to manage DNS records programmatically via HTTP calls. You can use it from scripts, automation tools, or your own applications.
Getting Started
Obtain API Key
Contact your administrator to get an API key. The key is personal and should be kept secret.
Basic Usage
All API calls:
Use HTTPS (encrypted)
Require authentication
Return JSON
Follow REST principles
Base URL: <https://tools.tornevall.net/api>
Authentication
Bearer Token (recommended)
curl https://tools.tornevall.net/api/dns/zones \
-H "Authorization: Bearer YOUR_API_KEY"X-API-Key Header
curl https://tools.tornevall.net/api/dns/zones \
-H "X-API-Key: YOUR_API_KEY"Query Parameter (not recommended)
curl https://tools.tornevall.net/api/dns/zones?api_key=YOUR_API_KEYFetch Zones
List all your zones
GET /api/dns/zonesExample:
curl https://tools.tornevall.net/api/dns/zones \
-H "Authorization: Bearer YOUR_API_KEY"Response:
{
"ok": true,
"count": 5,
"zones": [
{
"zone": "example.com",
"file": "example.com/example.com",
"key": "example.com"
},
{
"zone": "test.se",
"file": "test.se/test.se",
"key": "test.se"
}
],
"is_admin": false,
"access_type": "authenticated"
}Fetch specific zone
GET /api/dns/zones/{zone}Example:
curl https://tools.tornevall.net/api/dns/zones/example.com \
-H "Authorization: Bearer YOUR_API_KEY"Response:
{
"ok": true,
"zone": "example.com",
"method": "AXFR",
"record_count": 12,
"zoneData": [
{
"name": "example.com",
"type": "A",
"rdata": "192.0.2.1",
"ttl": 3600,
"class": "IN"
},
{
"name": "www.example.com",
"type": "A",
"rdata": "192.0.2.1",
"ttl": 3600,
"class": "IN"
}
]
}Manage DNS Records
Add Record
POST /api/dns/records/add
Content-Type: application/json
{
"domain": "test.example.com",
"type": "A",
"target": "192.0.2.1",
"ttl": 3600
}Example:
curl -X POST https://tools.tornevall.net/api/dns/records/add \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "test.example.com",
"type": "A",
"target": "192.0.2.1",
"ttl": 3600
}'Response (success):
{
"ok": true,
"message": "✓ Update successful (via DnsDirect)",
"domain": "test.example.com",
"type": "A",
"target": "192.0.2.1",
"ttl": 3600
}Response (error):
{
"ok": false,
"reason": "validation_failed",
"errors": {
"target": ["The target field is required."]
}
}Delete Record
POST /api/dns/records/delete
Content-Type: application/json
{
"domain": "test.example.com",
"type": "A"
}Example:
curl -X POST https://tools.tornevall.net/api/dns/records/delete \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "test.example.com",
"type": "A"
}'Response:
{
"ok": true,
"message": "✓ Update successful (via DnsDirect)",
"domain": "test.example.com",
"type": "A"
}Update Record
POST /api/dns/records/update
Content-Type: application/json
{
"domain": "test.example.com",
"type": "A",
"old_target": "192.0.2.1",
"new_target": "192.0.2.100",
"ttl": 3600
}Example:
curl -X POST https://tools.tornevall.net/api/dns/records/update \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"domain": "test.example.com",
"type": "A",
"old_target": "192.0.2.1",
"new_target": "192.0.2.100",
"ttl": 3600
}'Bulk Operations
Add or delete multiple records at once:
POST /api/dns/records/bulk
Content-Type: application/json
{
"operations": [
{
"action": "ADD",
"domain": "test1.example.com",
"type": "A",
"target": "192.0.2.1",
"ttl": 300
},
{
"action": "DELETE",
"domain": "test2.example.com",
"type": "A"
}
]
}Example:
curl -X POST https://tools.tornevall.net/api/dns/records/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"operations": [
{"action":"ADD","domain":"test1.example.com","type":"A","target":"192.0.2.1","ttl":300},
{"action":"ADD","domain":"test2.example.com","type":"A","target":"192.0.2.2","ttl":300}
]
}'Record Types
A Record (IPv4)
{
"domain": "www.example.com",
"type": "A",
"target": "192.0.2.1",
"ttl": 3600
}AAAA Record (IPv6)
{
"domain": "www.example.com",
"type": "AAAA",
"target": "2001:db8::1",
"ttl": 3600
}CNAME Record
{
"domain": "blog.example.com",
"type": "CNAME",
"target": "example.com.",
"ttl": 3600
}NOTE: Target must end with a period!
MX Record
{
"domain": "example.com",
"type": "MX",
"target": "10 mail.example.com.",
"ttl": 3600
}TXT Record
{
"domain": "example.com",
"type": "TXT",
"target": "v=spf1 include:_spf.google.com ~all",
"ttl": 3600
}NS Record
{
"domain": "subdomain.example.com",
"type": "NS",
"target": "ns1.provider.com.",
"ttl": 3600
}Usage Examples
Bash Script: Update IP on Dynamic IP
#!/bin/bash
API_KEY="your-api-key"
DOMAIN="home.example.com"
CURRENT_IP=$(curl -s ifconfig.me)
# Update A record
curl -X POST https://tools.tornevall.net/api/dns/records/add \
-H "Authorization: Bearer $API_KEY" \
-H "Content-Type: application/json" \
-d "{
\"domain\": \"$DOMAIN\",
\"type\": \"A\",
\"target\": \"$CURRENT_IP\",
\"ttl\": 300
}"
echo "Updated $DOMAIN to $CURRENT_IP"Python: Automated DNS Management
import requests
API_KEY = "your-api-key"
BASE_URL = "https://tools.tornevall.net/api"
headers = {
"Authorization": f"Bearer {API_KEY}",
"Content-Type": "application/json"
}
# Add record
def add_record(domain, record_type, target, ttl=3600):
data = {
"domain": domain,
"type": record_type,
"target": target,
"ttl": ttl
}
response = requests.post(
f"{BASE_URL}/dns/records/add",
headers=headers,
json=data
)
return response.json()
# Delete record
def delete_record(domain, record_type):
data = {
"domain": domain,
"type": record_type
}
response = requests.post(
f"{BASE_URL}/dns/records/delete",
headers=headers,
json=data
)
return response.json()
# Usage
result = add_record("test.example.com", "A", "192.0.2.1")
print(result)Node.js/JavaScript
const API_KEY = 'your-api-key';
const BASE_URL = 'https://tools.tornevall.net/api';
async function addDnsRecord(domain, type, target, ttl = 3600) {
const response = await fetch(`${BASE_URL}/dns/records/add`, {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ domain, type, target, ttl })
});
return await response.json();
}
// Usage
addDnsRecord('test.example.com', 'A', '192.0.2.1')
.then(result => console.log(result))
.catch(error => console.error(error));PHP
<?php
$apiKey = 'your-api-key';
$baseUrl = 'https://tools.tornevall.net/api';
function addDnsRecord($domain, $type, $target, $ttl = 3600) {
global $apiKey, $baseUrl;
$data = [
'domain' => $domain,
'type' => $type,
'target' => $target,
'ttl' => $ttl
];
$ch = curl_init("$baseUrl/dns/records/add");
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Authorization: Bearer $apiKey",
'Content-Type: application/json'
]);
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
// Usage
$result = addDnsRecord('test.example.com', 'A', '192.0.2.1');
var_dump($result);Error Handling
HTTP Status Codes
200 OK: Success
400 Bad Request: Invalid parameters
401 Unauthorized: Invalid API key
403 Forbidden: No permission for zone
404 Not Found: Zone not found
429 Too Many Requests: Rate limit reached
500 Internal Server Error: Server error
Error Messages
{
"ok": false,
"reason": "permission_denied",
"message": "No permission for zone: example.com"
}Common errors:
unauthenticated: Invalid or missing API keypermission_denied: No access to zonevalidation_failed: Invalid parameterszone_not_found: Zone doesn't exist
Rate Limiting
300 requests per minute per API key
Header
X-RateLimit-Remainingshows remaining callsOn exceeded: HTTP 429 +
Retry-Afterheader
Security
Best Practices
✅ Do:
Store API key in environment variables
Use HTTPS (always)
Implement retry logic with exponential backoff
Log API calls in your application
❌ Don't:
Commit API key to Git
Share API key with others
Hardcode API key in source code
Expose API key in frontend JavaScript
Revoke Key
If API key has leaked:
Contact administrator immediately
Get key revoked
Get new key
Update all systems using the old key
Support
Documentation: https://tools.tornevall.net/docs
API Status: Contact administrator
Rate Limits: 300/min (contact administrator for higher limit)
Version: 1.0
Last updated: 2026-02-16