Voor ontwikkelaars
API-documentatie
Koppel DNSWatcher aan je eigen systemen. Voeg domeinen toe, start scans en haal DMARC-rapporten en alerts op met de REST API, of laat ons je systemen bellen met webhooks.
Authenticatie
Maak een sleutel aan in de app onder Instellingen → API-sleutels. Een sleutel begint met dnsw_ en is alleen direct na het aanmaken zichtbaar. Stuur hem mee als Bearer-token. Alle data is beperkt tot het account van de sleutel.
Basis-URL: https://dnswatcher.nl/api/v1
curl https://dnswatcher.nl/api/v1/domains \
-H "Authorization: Bearer dnsw_xxxxxxxxxxxxxxxxxxxx" \
-H "Accept: application/json"
Limieten en paginering
- Maximaal 60 requests per minuut per sleutel. Daarboven krijg je 429.
- Lijsten zijn gepagineerd. Gebruik ?page=2 enzovoort; in links en meta staat waar je bent.
- Het aantal sleutels hangt af van je pakket: 3 in Pro, onbeperkt in Business en MSP.
- Datums zijn ISO 8601 met tijdzone.
/api/v1/domains
Domeinen opvragen
Alle domeinen van je account met score en status, gesorteerd op naam. 100 per pagina.
| Queryparameter | Betekenis |
|---|---|
| page | Paginanummer (standaard 1) |
Voorbeeldantwoord
{
"data": [
{
"name": "voorbeeld.nl",
"score": 86,
"verified": true,
"verified_at": "2026-09-14T10:02:11+02:00",
"scanning": false,
"last_checked_at": "2026-10-01T08:15:02+02:00",
"email_auth": {
"spf": "pass",
"dmarc": "warn",
"dkim": "pass",
"dkim_selector": "selector1"
},
"registration": {
"registrar": "TransIP",
"expires_at": "2027-03-14T00:00:00+01:00"
},
"tls": {
"issuer": "Let's Encrypt",
"expires_at": "2026-12-02T10:11:00+01:00"
},
"mails_30d": 4812,
"url": "https://dnswatcher.nl/domeinen/42"
}
],
"links": {
"first": "https://dnswatcher.nl/api/v1/domains?page=1",
"last": "https://dnswatcher.nl/api/v1/domains?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "https://dnswatcher.nl/api/v1/domains",
"per_page": 100,
"to": 1,
"total": 1
}
}
/api/v1/domains
Domein toevoegen
Voegt een domein toe en start meteen de eerste scan. Bestaat het domein al in je account, dan krijg je dat terug. Antwoordt met 201.
Request-body
{
"name": "voorbeeld.nl"
}
Voorbeeldantwoord
{
"data": {
"name": "voorbeeld.nl",
"score": 0,
"verified": false,
"verified_at": null,
"scanning": true,
"last_checked_at": null,
"email_auth": {
"spf": "pass",
"dmarc": "warn",
"dkim": "pass",
"dkim_selector": "selector1"
},
"registration": {
"registrar": "TransIP",
"expires_at": "2027-03-14T00:00:00+01:00"
},
"tls": {
"issuer": "Let's Encrypt",
"expires_at": "2026-12-02T10:11:00+01:00"
},
"mails_30d": 4812,
"url": "https://dnswatcher.nl/domeinen/42"
}
}
/api/v1/domains/{name}
Eén domein
Details van één domein, inclusief de gevonden SPF-, DMARC- en DKIM-records.
Voorbeeldantwoord
{
"data": {
"name": "voorbeeld.nl",
"score": 86,
"verified": true,
"verified_at": "2026-09-14T10:02:11+02:00",
"scanning": false,
"last_checked_at": "2026-10-01T08:15:02+02:00",
"email_auth": {
"spf": "pass",
"dmarc": "warn",
"dkim": "pass",
"dkim_selector": "selector1"
},
"registration": {
"registrar": "TransIP",
"expires_at": "2027-03-14T00:00:00+01:00"
},
"tls": {
"issuer": "Let's Encrypt",
"expires_at": "2026-12-02T10:11:00+01:00"
},
"mails_30d": 4812,
"url": "https://dnswatcher.nl/domeinen/42",
"records": [
{
"type": "SPF",
"status": "pass",
"value": "v=spf1 include:spf.protection.outlook.com -all"
},
{
"type": "DMARC",
"status": "warn",
"value": "v=DMARC1; p=none; rua=mailto:rua@dnswatcher.nl"
}
]
}
}
/api/v1/domains/{name}/rescan
Opnieuw scannen
Start een volledige scan. Antwoordt met 202 als de scan is gestart, of 200 als er al een scan loopt.
Voorbeeldantwoord
{
"message": "Scan gestart.",
"data": {
"name": "voorbeeld.nl",
"score": 86,
"verified": true,
"verified_at": "2026-09-14T10:02:11+02:00",
"scanning": true,
"last_checked_at": "2026-10-01T08:15:02+02:00",
"email_auth": {
"spf": "pass",
"dmarc": "warn",
"dkim": "pass",
"dkim_selector": "selector1"
},
"registration": {
"registrar": "TransIP",
"expires_at": "2027-03-14T00:00:00+01:00"
},
"tls": {
"issuer": "Let's Encrypt",
"expires_at": "2026-12-02T10:11:00+01:00"
},
"mails_30d": 4812,
"url": "https://dnswatcher.nl/domeinen/42"
}
}
/api/v1/domains/{name}
Domein verwijderen
Verwijdert het domein met alle historie uit je account. Antwoordt met 204 zonder inhoud.
/api/v1/dmarc-reports
DMARC-rapporten
Regels uit de DMARC-rapporten van je geverifieerde domeinen, nieuwste eerst. Hoe ver terug hangt af van je pakket. 200 per pagina.
| Queryparameter | Betekenis |
|---|---|
| domain | Alleen dit domein, bijvoorbeeld voorbeeld.nl |
| result | pass, partial of fail |
| page | Paginanummer |
Voorbeeldantwoord
{
"data": [
{
"domain": "voorbeeld.nl",
"date": "2026-09-30",
"reporter": "google.com",
"source_ip": "203.0.113.5",
"messages": 120,
"aligned": 118,
"policy": "none",
"result": "pass"
}
],
"links": {
"first": "https://dnswatcher.nl/api/v1/domains?page=1",
"last": "https://dnswatcher.nl/api/v1/domains?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "https://dnswatcher.nl/api/v1/domains",
"per_page": 100,
"to": 1,
"total": 1
}
}
/api/v1/alerts
Alerts
Ongelezen alerts van je account, nieuwste eerst. 100 per pagina.
| Queryparameter | Betekenis |
|---|---|
| severity | fail, warn of info |
| include_read | Zet op 1 om ook gelezen alerts te tonen |
| page | Paginanummer |
Voorbeeldantwoord
{
"data": [
{
"id": 731,
"domain": "voorbeeld.nl",
"severity": "fail",
"title": "DMARC-record verwijderd",
"description": "Het DMARC-record voor voorbeeld.nl is niet meer gevonden in DNS.",
"read": false,
"triggered_at": "2026-10-01T10:42:00+02:00"
}
],
"links": {
"first": "https://dnswatcher.nl/api/v1/domains?page=1",
"last": "https://dnswatcher.nl/api/v1/domains?page=1",
"prev": null,
"next": null
},
"meta": {
"current_page": 1,
"from": 1,
"last_page": 1,
"path": "https://dnswatcher.nl/api/v1/domains",
"per_page": 100,
"to": 1,
"total": 1
}
}
Foutcodes
Fouten komen altijd als JSON terug met een message-veld; bij 422 staat per veld de fout in errors.
| 401 | Unauthorized | Geen, een ongeldige of een ingetrokken API-sleutel. |
| 402 | Payment Required | Je pakket heeft geen API-toegang (Free), of je domeinlimiet is bereikt bij POST /domains. |
| 404 | Not Found | Het domein bestaat niet in je account. |
| 422 | Unprocessable Content | De invoer klopt niet, bijvoorbeeld een ongeldige domeinnaam. Details staan in errors. |
| 429 | Too Many Requests | Meer dan 60 requests per minuut met dezelfde sleutel. |
{
"message": "Voer een geldig domein in, bijvoorbeeld voorbeeld.nl.",
"errors": {
"name": [
"Voer een geldig domein in, bijvoorbeeld voorbeeld.nl."
]
}
}
Webhooks
Stel in de app onder Instellingen → Notificaties een https-URL in. We sturen dan een POST met JSON bij elke gebeurtenis:
alert.created: een nieuwe alert, zoals een verdwenen record, kapotte DNSSEC of een onbekende afzender.dns.changed: een gewijzigd, toegevoegd of verwijderd DNS-record.test: het testbericht vanuit de instellingen.
Mislukte aflevering (een 5xx-antwoord of time-out) proberen we nog drie keer opnieuw: na 10 seconden, na 1 minuut en na 5 minuten. Webhooks zitten in Pro en hoger.
alert.created
{
"id": "9b1f6c1e-3c2a-4f0e-8d6a-2f6f4b7c9e01",
"event": "alert.created",
"sent_at": "2026-10-01T10:42:03+02:00",
"data": {
"id": 731,
"domain": "voorbeeld.nl",
"severity": "fail",
"title": "DMARC-record verwijderd",
"description": "Het DMARC-record voor voorbeeld.nl is niet meer gevonden in DNS.",
"triggered_at": "2026-10-01T10:42:00+02:00",
"url": "https://dnswatcher.nl/alerts"
}
}
dns.changed · data
{
"domain": "voorbeeld.nl",
"type": "MX",
"action": "Record toegevoegd (@)",
"from": null,
"to": "0 voorbeeld-nl.mail.protection.outlook.com",
"severity": "pass",
"occurred_at": "2026-10-01T09:15:00+02:00",
"url": "https://dnswatcher.nl/dns-historie?domain=42"
}
Handtekening controleren
Elk bericht heeft de header X-DNSWatcher-Signature met de waarde sha256= gevolgd door een HMAC-SHA256 (hex) van de ruwe request-body, berekend met je webhook-sleutel (whsec_…). Vergelijk in constante tijd en verwerk alleen berichten waarvan de handtekening klopt.
// PHP
$expected = 'sha256='.hash_hmac('sha256', $rawBody, $secret);
if (! hash_equals($expected, $request->header('X-DNSWatcher-Signature'))) {
abort(401);
}
// Node.js
const expected = 'sha256=' + crypto.createHmac('sha256', secret).update(rawBody).digest('hex');
const valid = crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(req.get('X-DNSWatcher-Signature')));
Klaar om te koppelen?
Maak een account, kies Pro of hoger en genereer je eerste API-sleutel.
Liever meteen bewaken? Maak een gratis account