Create Multiple Monitors at Once
The bulk monitor creation endpoint allows you to create up to 1,000 DNS monitors in a single API request. This is ideal for onboarding new customers, deploying monitoring across multiple domains, or managing large DNS infrastructures.
Bulk Creation Endpoint
Send a POST request to /monitors/bulk with an array of monitor configurations.
curl -X POST https://api.dnsradar.dev/monitors/bulk \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"monitors": [
{
"domain": "piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4",
"5.6.7.8"
]
},
{
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app"
},
{
"domain": "piedpiper.com",
"record_type": "TXT",
"expected_value": "v=spf1 include:_spf.service.com -all"
},
{
"domain": "piedpiper.com",
"subdomain": "_dmarc",
"record_type": "TXT",
"expected_value": "v=DMARC1; p=reject; pct=100; adkim=s; aspf=s"
}
],
"group": "production-dns",
"frequency": 60
}'const response = await fetch('https://api.dnsradar.dev/monitors/bulk', {
method: 'POST',
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
"monitors": [
{
"domain": "piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4",
"5.6.7.8"
]
},
{
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app"
},
{
"domain": "piedpiper.com",
"record_type": "TXT",
"expected_value": "v=spf1 include:_spf.service.com -all"
},
{
"domain": "piedpiper.com",
"subdomain": "_dmarc",
"record_type": "TXT",
"expected_value": "v=DMARC1; p=reject; pct=100; adkim=s; aspf=s"
}
],
"group": "production-dns",
"frequency": 60
})
});
const data = await response.json();import requests
response = requests.post(
'https://api.dnsradar.dev/monitors/bulk',
headers={
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
"monitors": [
{
"domain": "piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4",
"5.6.7.8"
]
},
{
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app"
},
{
"domain": "piedpiper.com",
"record_type": "TXT",
"expected_value": "v=spf1 include:_spf.service.com -all"
},
{
"domain": "piedpiper.com",
"subdomain": "_dmarc",
"record_type": "TXT",
"expected_value": "v=DMARC1; p=reject; pct=100; adkim=s; aspf=s"
}
],
"group": "production-dns",
"frequency": 60
}
)require 'net/http'
require 'json'
uri = URI('https://api.dnsradar.dev/monitors/bulk')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY'
request['Content-Type'] = 'application/json'
request.body = {
"monitors": [
{
"domain": "piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4",
"5.6.7.8"
]
},
{
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app"
},
{
"domain": "piedpiper.com",
"record_type": "TXT",
"expected_value": "v=spf1 include:_spf.service.com -all"
},
{
"domain": "piedpiper.com",
"subdomain": "_dmarc",
"record_type": "TXT",
"expected_value": "v=DMARC1; p=reject; pct=100; adkim=s; aspf=s"
}
],
"group": "production-dns",
"frequency": 60
}.to_json
response = http.request(request)package main
import (
"bytes"
"encoding/json"
"net/http"
)
data := {
"monitors": [
{
"domain": "piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4",
"5.6.7.8"
]
},
{
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app"
},
{
"domain": "piedpiper.com",
"record_type": "TXT",
"expected_value": "v=spf1 include:_spf.service.com -all"
},
{
"domain": "piedpiper.com",
"subdomain": "_dmarc",
"record_type": "TXT",
"expected_value": "v=DMARC1; p=reject; pct=100; adkim=s; aspf=s"
}
],
"group": "production-dns",
"frequency": 60
}
jsonData, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", "https://api.dnsradar.dev/monitors/bulk", bytes.NewBuffer(jsonData))
req.Header.Set("X-API-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
response, _ := client.Do(req)<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.dnsradar.dev/monitors/bulk');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$headers = [
'X-API-Key: YOUR_API_KEY',
'Content-Type: application/json'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$data = json_encode({
"monitors": [
{
"domain": "piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4",
"5.6.7.8"
]
},
{
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app"
},
{
"domain": "piedpiper.com",
"record_type": "TXT",
"expected_value": "v=spf1 include:_spf.service.com -all"
},
{
"domain": "piedpiper.com",
"subdomain": "_dmarc",
"record_type": "TXT",
"expected_value": "v=DMARC1; p=reject; pct=100; adkim=s; aspf=s"
}
],
"group": "production-dns",
"frequency": 60
});
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
curl_close($ch);import java.net.http.*;
import java.net.URI;
HttpClient client = HttpClient.newHttpClient();
String json = """{
"monitors": [
{
"domain": "piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4",
"5.6.7.8"
]
},
{
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app"
},
{
"domain": "piedpiper.com",
"record_type": "TXT",
"expected_value": "v=spf1 include:_spf.service.com -all"
},
{
"domain": "piedpiper.com",
"subdomain": "_dmarc",
"record_type": "TXT",
"expected_value": "v=DMARC1; p=reject; pct=100; adkim=s; aspf=s"
}
],
"group": "production-dns",
"frequency": 60
}""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.dnsradar.dev/monitors/bulk"))
.header("X-API-Key", "YOUR_API_KEY")
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var data = new
{
"monitors": [
{
"domain": "piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4",
"5.6.7.8"
]
},
{
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app"
},
{
"domain": "piedpiper.com",
"record_type": "TXT",
"expected_value": "v=spf1 include:_spf.service.com -all"
},
{
"domain": "piedpiper.com",
"subdomain": "_dmarc",
"record_type": "TXT",
"expected_value": "v=DMARC1; p=reject; pct=100; adkim=s; aspf=s"
}
],
"group": "production-dns",
"frequency": 60
};
var json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://api.dnsradar.dev/monitors/bulk",
content
);Request Structure
Required Fields
monitors(array): Array of monitor objects to create (1-1000 items). Please refer to Create a DNS Monitor for its detailled structure.
Each monitor object requires:
domain: The domain name to monitorrecord_type: DNS record type (A, AAAA, CNAME, MX, TXT, NS, PTR)expected_value: Expected DNS value(s)
Optional Global Parameters
You can specify default values that apply to all monitors in the batch:
group(string): Default group slug for all monitorsfrequency(integer): Default check frequency in minutes (5, 10, 15, 30, 60, 120)
Individual monitors can override these defaults by including their own group or frequency fields.
Auto-Creation: If a specified group provided by its slug doesn't exist, we will create one automatically during the bulk operation.
Per-Monitor Configuration
Each monitor in the array can have its own configuration:
curl -X POST https://api.dnsradar.dev/monitors/bulk \
-H "X-API-Key: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"monitors": [
{
"domain": "api.piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4"
],
"frequency": 5,
"group": "critical-services"
},
{
"domain": "blog.piedpiper.com",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app",
"frequency": 60,
"group": "marketing-sites"
},
{
"domain": "mail.piedpiper.com",
"record_type": "MX",
"expected_value": [
"10 mx1.provider.com",
"20 mx2.provider.com"
],
"is_exact_match": false,
"group": "email-infrastructure"
}
]
}'const response = await fetch('https://api.dnsradar.dev/monitors/bulk', {
method: 'POST',
headers: {
"X-API-Key": "YOUR_API_KEY",
"Content-Type": "application/json"
},
body: JSON.stringify({
"monitors": [
{
"domain": "api.piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4"
],
"frequency": 5,
"group": "critical-services"
},
{
"domain": "blog.piedpiper.com",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app",
"frequency": 60,
"group": "marketing-sites"
},
{
"domain": "mail.piedpiper.com",
"record_type": "MX",
"expected_value": [
"10 mx1.provider.com",
"20 mx2.provider.com"
],
"is_exact_match": false,
"group": "email-infrastructure"
}
]
})
});
const data = await response.json();import requests
response = requests.post(
'https://api.dnsradar.dev/monitors/bulk',
headers={
'X-API-Key': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
json={
"monitors": [
{
"domain": "api.piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4"
],
"frequency": 5,
"group": "critical-services"
},
{
"domain": "blog.piedpiper.com",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app",
"frequency": 60,
"group": "marketing-sites"
},
{
"domain": "mail.piedpiper.com",
"record_type": "MX",
"expected_value": [
"10 mx1.provider.com",
"20 mx2.provider.com"
],
"is_exact_match": false,
"group": "email-infrastructure"
}
]
}
)require 'net/http'
require 'json'
uri = URI('https://api.dnsradar.dev/monitors/bulk')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri)
request['X-API-Key'] = 'YOUR_API_KEY'
request['Content-Type'] = 'application/json'
request.body = {
"monitors": [
{
"domain": "api.piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4"
],
"frequency": 5,
"group": "critical-services"
},
{
"domain": "blog.piedpiper.com",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app",
"frequency": 60,
"group": "marketing-sites"
},
{
"domain": "mail.piedpiper.com",
"record_type": "MX",
"expected_value": [
"10 mx1.provider.com",
"20 mx2.provider.com"
],
"is_exact_match": false,
"group": "email-infrastructure"
}
]
}.to_json
response = http.request(request)package main
import (
"bytes"
"encoding/json"
"net/http"
)
data := {
"monitors": [
{
"domain": "api.piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4"
],
"frequency": 5,
"group": "critical-services"
},
{
"domain": "blog.piedpiper.com",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app",
"frequency": 60,
"group": "marketing-sites"
},
{
"domain": "mail.piedpiper.com",
"record_type": "MX",
"expected_value": [
"10 mx1.provider.com",
"20 mx2.provider.com"
],
"is_exact_match": false,
"group": "email-infrastructure"
}
]
}
jsonData, _ := json.Marshal(data)
req, _ := http.NewRequest("POST", "https://api.dnsradar.dev/monitors/bulk", bytes.NewBuffer(jsonData))
req.Header.Set("X-API-Key", "YOUR_API_KEY")
req.Header.Set("Content-Type", "application/json")
client := &http.Client{}
response, _ := client.Do(req)<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.dnsradar.dev/monitors/bulk');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
$headers = [
'X-API-Key: YOUR_API_KEY',
'Content-Type: application/json'
];
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$data = json_encode({
"monitors": [
{
"domain": "api.piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4"
],
"frequency": 5,
"group": "critical-services"
},
{
"domain": "blog.piedpiper.com",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app",
"frequency": 60,
"group": "marketing-sites"
},
{
"domain": "mail.piedpiper.com",
"record_type": "MX",
"expected_value": [
"10 mx1.provider.com",
"20 mx2.provider.com"
],
"is_exact_match": false,
"group": "email-infrastructure"
}
]
});
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$response = curl_exec($ch);
curl_close($ch);import java.net.http.*;
import java.net.URI;
HttpClient client = HttpClient.newHttpClient();
String json = """{
"monitors": [
{
"domain": "api.piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4"
],
"frequency": 5,
"group": "critical-services"
},
{
"domain": "blog.piedpiper.com",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app",
"frequency": 60,
"group": "marketing-sites"
},
{
"domain": "mail.piedpiper.com",
"record_type": "MX",
"expected_value": [
"10 mx1.provider.com",
"20 mx2.provider.com"
],
"is_exact_match": false,
"group": "email-infrastructure"
}
]
}""";
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.dnsradar.dev/monitors/bulk"))
.header("X-API-Key", "YOUR_API_KEY")
.header("Content-Type", "application/json")
.method("POST", HttpRequest.BodyPublishers.ofString(json))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());using System.Net.Http;
using System.Text;
using System.Text.Json;
var client = new HttpClient();
client.DefaultRequestHeaders.Add("X-API-Key", "YOUR_API_KEY");
var data = new
{
"monitors": [
{
"domain": "api.piedpiper.com",
"record_type": "A",
"expected_value": [
"1.2.3.4"
],
"frequency": 5,
"group": "critical-services"
},
{
"domain": "blog.piedpiper.com",
"record_type": "CNAME",
"expected_value": "piedpiper.netlify.app",
"frequency": 60,
"group": "marketing-sites"
},
{
"domain": "mail.piedpiper.com",
"record_type": "MX",
"expected_value": [
"10 mx1.provider.com",
"20 mx2.provider.com"
],
"is_exact_match": false,
"group": "email-infrastructure"
}
]
};
var json = JsonSerializer.Serialize(data);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(
"https://api.dnsradar.dev/monitors/bulk",
content
);API Response
The API returns an array of created monitor objects, maintaining the same order as your request:
{
"data": [
{
"uuid": "mon_abc123",
"created": "2026-01-06T12:34:56Z",
"domain": "piedpiper.com",
"subdomain": null,
"record_type": "A",
"expected_value": ["1.2.3.4", "5.6.7.8"],
"current_value": null,
"is_exact_match": true,
"state": "UNSET",
"incidence_count": 0,
"last_checked": null,
"is_active": true,
"frequency": 60
},
{
"uuid": "mon_abc456",
"created": "2026-01-06T12:34:56Z",
"domain": "piedpiper.com",
"subdomain": "www",
"record_type": "CNAME",
"expected_value": ["piedpiper.netlify.app"],
"current_value": null,
"is_exact_match": true,
"state": "UNSET",
"incidence_count": 0,
"last_checked": null,
"is_active": true,
"frequency": 60
}
]
}
Scalability and Performance
The bulk creation endpoint is optimized for high-throughput operations:
Rate Limiting
Higher Limits: The /monitors/bulk endpoint, like the /monitors endpoint, has a rate limit of 250 requests per minute.
In the /monitors/bulk endpoint, this allows you to create up to 250,000 monitors per minute (250 requests × 1,000 monitors).
Batch Size Recommendations
- Small batches (1-100 monitors): Fast response times, ideal for real-time operations
- Medium batches (100-500 monitors): Good balance of throughput and response time
- Large batches (500-1000 monitors): Maximum efficiency for bulk imports
Error Handling
If any monitor in the batch fails validation, the entire request is rejected, and no monitors are created. This ensures data consistency.
Transaction Guarantee: Bulk creation is atomic. Either all monitors are created successfully, or none are created. This prevents partial deployments.
Common validation errors include:
- Invalid domain format
- Unsupported record type
- Missing required fields
- Monitor limit exceeded
Plan Limitations
Monitor Limits: Free plan limited to 50 total monitors.
Premium plans support unlimited monitors. The bulk creation endpoint respects these limits.
Best Practices
- Group Related Monitors: Use the
groupparameter to organize monitors logically - Set Appropriate Frequencies: Balance monitoring coverage with API usage
- Use Consistent Naming: Establish naming conventions for your groups
- Implement Error Handling: Always handle API errors gracefully in your application