Bulk Operations
Efficiently manage large numbers of DNS records with bulk operations including zone import/export and batch record creation.
Batch Record Creation
Create multiple records in a single API call.
Endpoint
POST /v1/dns/zones/{zone_id}/records/batch
Request
curl -X POST https://api.wayscloud.services/v1/dns/zones/zone_abc123/records/batch \
-H "Authorization: Bearer wayscloud_dns_prod_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"records": [
{"type": "A", "name": "www", "value": "192.0.2.1", "ttl": 3600},
{"type": "A", "name": "blog", "value": "192.0.2.2", "ttl": 3600},
{"type": "AAAA", "name": "www", "value": "2001:db8::1", "ttl": 3600},
{"type": "MX", "name": "@", "value": "mail.example.com", "priority": 10, "ttl": 3600},
{"type": "TXT", "name": "@", "value": "v=spf1 include:_spf.google.com ~all", "ttl": 3600}
]
}'
Limits:
- Maximum 1000 records per request
- All records must be for the same zone
- Invalid records will cause entire batch to fail
Response
{
"success": true,
"zone_id": "zone_abc123",
"created_count": 5,
"records": [
{
"record_id": "rec_001",
"type": "A",
"name": "www",
"value": "192.0.2.1",
"ttl": 3600
},
{
"record_id": "rec_002",
"type": "A",
"name": "blog",
"value": "192.0.2.2",
"ttl": 3600
}
// ... additional records
]
}
Zone Import
Import existing DNS zones from BIND zone file format.
Endpoint
POST /v1/dns/zones/{zone_id}/import
Zone File Format
Standard BIND zone file format:
$TTL 3600
$ORIGIN example.com.
@ IN SOA grieg.wayscloud.no. hostmaster.example.com. (
2025110401 ; Serial
7200 ; Refresh
3600 ; Retry
1209600 ; Expire
3600 ) ; Minimum TTL
@ IN NS grieg.wayscloud.no.
@ IN NS lindgren.wayscloud.se.
@ IN A 192.0.2.1
www IN A 192.0.2.1
mail IN A 192.0.2.10
@ IN MX 10 mail.example.com.
@ IN TXT "v=spf1 include:_spf.google.com ~all"
Request
curl -X POST https://api.wayscloud.services/v1/dns/zones/zone_abc123/import \
-H "Authorization: Bearer wayscloud_dns_prod_YOUR_API_KEY" \
-H "Content-Type: text/plain" \
--data-binary @zone-file.txt
Options:
# Replace all existing records
curl -X POST "https://api.wayscloud.services/v1/dns/zones/zone_abc123/import?replace=true" \
-H "Authorization: Bearer wayscloud_dns_prod_YOUR_API_KEY" \
-H "Content-Type: text/plain" \
--data-binary @zone-file.txt
# Merge with existing records (default)
curl -X POST "https://api.wayscloud.services/v1/dns/zones/zone_abc123/import?replace=false" \
-H "Authorization: Bearer wayscloud_dns_prod_YOUR_API_KEY" \
-H "Content-Type: text/plain" \
--data-binary @zone-file.txt
Response
{
"success": true,
"zone_id": "zone_abc123",
"imported_records": 15,
"skipped_records": 2,
"errors": [
{
"line": 12,
"record": "invalid IN A 999.999.999.999",
"error": "Invalid IPv4 address"
}
]
}
Zone Export
Export DNS zone to BIND zone file format.
Endpoint
GET /v1/dns/zones/{zone_id}/export
Request
curl -X GET https://api.wayscloud.services/v1/dns/zones/zone_abc123/export \
-H "Authorization: Bearer wayscloud_dns_prod_YOUR_API_KEY" \
> zone-backup.txt
Response
;; Zone: example.com
;; Exported: 2025-11-04T12:00:00Z
;; Records: 15
$TTL 3600
$ORIGIN example.com.
@ IN SOA grieg.wayscloud.no. hostmaster.example.com. (
2025110401 ; Serial
7200 ; Refresh
3600 ; Retry
1209600 ; Expire
3600 ) ; Minimum TTL
@ IN NS grieg.wayscloud.no.
@ IN NS lindgren.wayscloud.se.
@ IN NS aalto.wayscloud.fi.
@ IN NS bohr.wayscloud.dk.
@ IN A 192.0.2.1
www IN A 192.0.2.1
blog IN A 192.0.2.2
www IN AAAA 2001:db8::1
mail IN A 192.0.2.10
@ IN MX 10 mail.example.com.
@ IN TXT "v=spf1 include:_spf.google.com ~all"
_dmarc IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com"
Batch Record Updates
Update multiple records at once.
Endpoint
PUT /v1/dns/zones/{zone_id}/records/batch
Request
curl -X PUT https://api.wayscloud.services/v1/dns/zones/zone_abc123/records/batch \
-H "Authorization: Bearer wayscloud_dns_prod_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"updates": [
{"record_id": "rec_001", "value": "192.0.2.100", "ttl": 300},
{"record_id": "rec_002", "value": "192.0.2.200", "ttl": 300},
{"record_id": "rec_003", "ttl": 300}
]
}'
Response
{
"success": true,
"updated_count": 3,
"records": [
{
"record_id": "rec_001",
"type": "A",
"name": "www",
"value": "192.0.2.100",
"ttl": 300,
"updated_at": "2025-11-04T12:00:00Z"
}
// ... additional records
]
}
Batch Record Deletion
Delete multiple records at once.
Endpoint
DELETE /v1/dns/zones/{zone_id}/records/batch
Request
curl -X DELETE https://api.wayscloud.services/v1/dns/zones/zone_abc123/records/batch \
-H "Authorization: Bearer wayscloud_dns_prod_YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"record_ids": ["rec_001", "rec_002", "rec_003"]
}'
Response
{
"success": true,
"deleted_count": 3,
"record_ids": ["rec_001", "rec_002", "rec_003"]
}
Python Examples
Batch Create Records
import requests
def batch_create_records(api_key, zone_id, records):
"""Create multiple DNS records at once"""
url = f'https://api.wayscloud.services/v1/dns/zones/{zone_id}/records/batch'
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
response = requests.post(url, json={'records': records}, headers=headers)
response.raise_for_status()
return response.json()
# Usage
api_key = 'wayscloud_dns_prod_YOUR_API_KEY'
zone_id = 'zone_abc123'
records = [
{'type': 'A', 'name': 'www', 'value': '192.0.2.1', 'ttl': 3600},
{'type': 'A', 'name': 'blog', 'value': '192.0.2.2', 'ttl': 3600},
{'type': 'AAAA', 'name': 'www', 'value': '2001:db8::1', 'ttl': 3600},
{'type': 'MX', 'name': '@', 'value': 'mail.example.com', 'priority': 10}
]
result = batch_create_records(api_key, zone_id, records)
print(f"Created {result['created_count']} records")
Import Zone File
def import_zone_file(api_key, zone_id, zone_file_path, replace=False):
"""Import DNS zone from BIND zone file"""
url = f'https://api.wayscloud.services/v1/dns/zones/{zone_id}/import'
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'text/plain'
}
params = {'replace': replace}
with open(zone_file_path, 'r') as f:
zone_data = f.read()
response = requests.post(url, data=zone_data, headers=headers, params=params)
response.raise_for_status()
return response.json()
# Usage
result = import_zone_file(api_key, zone_id, 'zone-file.txt', replace=False)
print(f"Imported {result['imported_records']} records")
if result['errors']:
print(f"Errors: {result['errors']}")
Export Zone
def export_zone(api_key, zone_id, output_file):
"""Export DNS zone to BIND zone file"""
url = f'https://api.wayscloud.services/v1/dns/zones/{zone_id}/export'
headers = {'Authorization': f'Bearer {api_key}'}
response = requests.get(url, headers=headers)
response.raise_for_status()
with open(output_file, 'w') as f:
f.write(response.text)
print(f"Zone exported to {output_file}")
# Usage
export_zone(api_key, zone_id, 'backup-2025-11-04.txt')
Migrate Zone Between Providers
def migrate_zone(api_key, from_zone_id, to_zone_id):
"""Migrate all records from one zone to another"""
# Export from source zone
source_url = f'https://api.wayscloud.services/v1/dns/zones/{from_zone_id}/export'
headers = {'Authorization': f'Bearer {api_key}'}
response = requests.get(source_url, headers=headers)
response.raise_for_status()
zone_data = response.text
# Import to destination zone
dest_url = f'https://api.wayscloud.services/v1/dns/zones/{to_zone_id}/import'
response = requests.post(dest_url, data=zone_data, headers=headers)
response.raise_for_status()
result = response.json()
print(f"Migrated {result['imported_records']} records")
return result
# Usage
migrate_zone(api_key, 'zone_old123', 'zone_new456')
Best Practices
1. Validate Before Import
def validate_zone_file(zone_file_path):
"""Validate zone file before importing"""
with open(zone_file_path, 'r') as f:
lines = f.readlines()
errors = []
for i, line in enumerate(lines, 1):
line = line.strip()
if not line or line.startswith(';'):
continue
# Basic validation
if 'IN' not in line:
errors.append(f"Line {i}: Missing 'IN' class")
return len(errors) == 0, errors
# Usage
valid, errors = validate_zone_file('zone-file.txt')
if valid:
import_zone_file(api_key, zone_id, 'zone-file.txt')
else:
print(f"Validation errors: {errors}")
2. Backup Before Replace
def safe_zone_import(api_key, zone_id, zone_file_path, replace=False):
"""Import zone with automatic backup"""
# Backup existing zone
backup_file = f'backup-{zone_id}-{datetime.now().isoformat()}.txt'
export_zone(api_key, zone_id, backup_file)
print(f"Backup created: {backup_file}")
# Import new zone
try:
result = import_zone_file(api_key, zone_id, zone_file_path, replace)
print(f"Import successful: {result['imported_records']} records")
return result
except Exception as e:
print(f"Import failed: {e}")
print(f"Restore from backup: {backup_file}")
raise
3. Chunk Large Batches
def batch_create_records_chunked(api_key, zone_id, records, chunk_size=100):
"""Create records in chunks to avoid limits"""
created = 0
for i in range(0, len(records), chunk_size):
chunk = records[i:i + chunk_size]
result = batch_create_records(api_key, zone_id, chunk)
created += result['created_count']
print(f"Created {created}/{len(records)} records")
time.sleep(1) # Rate limiting
return created
# Usage
created = batch_create_records_chunked(api_key, zone_id, large_record_list)
4. Regular Backups
#!/bin/bash
# daily-dns-backup.sh
API_KEY="wayscloud_dns_prod_YOUR_API_KEY"
BACKUP_DIR="/backups/dns"
DATE=$(date +%Y-%m-%d)
# Get all zones
ZONES=$(curl -s https://api.wayscloud.services/v1/dns/zones \
-H "Authorization: Bearer $API_KEY" | jq -r '.zones[].zone_id')
# Export each zone
for ZONE_ID in $ZONES; do
curl -s https://api.wayscloud.services/v1/dns/zones/$ZONE_ID/export \
-H "Authorization: Bearer $API_KEY" \
> "$BACKUP_DIR/zone-$ZONE_ID-$DATE.txt"
echo "Backed up $ZONE_ID"
done
# Keep only last 30 days
find $BACKUP_DIR -name "*.txt" -mtime +30 -delete
Error Handling
| Error Code | Description | Resolution |
|---|---|---|
BATCH_TOO_LARGE | Too many records in batch | Split into smaller batches (max 1000) |
INVALID_ZONE_FILE | Zone file format error | Check BIND format syntax |
DUPLICATE_RECORDS | Records already exist | Use replace=true or update instead |
QUOTA_EXCEEDED | Too many records for plan | Upgrade plan or delete unused records |
Next Steps
- Record Management - Individual record operations
- Advanced Use Cases - Production migration strategies
- Code Examples - Complete SDK implementations