Questions · Updated 2026-09-27
Why did my domain verification fail?
Domain verification fails when a required record answers with a value other than the one on the sheet, or when nothing required has resolved by the time the check window closes. GET /domains/{id} names the record with reason, observed and fix, and POST /domains/{id}/verify re-checks and reopens the window.
Domain verification fails for one of two reasons: a required record answers with a value other than the one on the sheet, or nothing required has resolved by the time the check window closes. GET /domains/{id} says which. Every record row carries status, reason, observed (what DNS returned) and fix. The catalogue fix for domain_not_verified says that if the domain is failed, GET /domains/{id} names the record to fix, then POST /domains/{id}/verify reopens the window.
Read the row
reason on a record is one of ok, not_found, unreachable, mismatch or not_published.
mismatch— the name answers, and not with our value.observedholds what it answered. For DKIM this is nearly always a key cut short by a DNS editor; the DKIM row'sfixsays "A truncated key is the commonest reason DKIM never resolves." Publish everyvalue_stringsentry.not_found— the name has no record of that type. The usual cause is a panel that appended the zone to a full name, so paste the row'shost, never itsname. Each registrar page has that host's own field names: Cloudflare, Namecheap, GoDaddy, Route 53, Google Domains, Porkbun, Hostinger.unreachable— the lookup did not complete. The row keeps the status of its last real answer and the next check is still scheduled. This says nothing about what you published.not_published— a recommended row that is not there. Root SPF and DMARC never fail the domain; Domains and DNS says they "never move the domain's status in either direction." A second SPF record on one name is the exception worth checking, and Can I have two SPF records on one domain? covers it.
How the domain reaches failed
Inside the window, one thing fails a domain: a required record that answered with the wrong value on a check and still does on a later check. GET /domains/{id}/wait then reports reason mismatch, or dkim_key_mismatch when the row is DKIM. The catalogue entry of that name says "The DKIM selector is publishing a different key than the one issued for this domain." and its fix is to replace that TXT with the value on GET /domains/{id}, then verify.
When the window closes with required records still absent, the domain reads failed and GET /domains/{id}/events records "The 72-hour check window closed." The wait reason is domain_check_window_expired, and the catalogue entry of that name says "The 72-hour check window closed before the required DNS records resolved." A failed domain is not re-checked on its own; the server waits for you.
A domain that was verified and then lost a record is the third route, and How do I get notified when domain verification breaks? covers it.
Fix, then re-check
Correct the record at your DNS provider, then call POST /domains/{id}/verify. From failed it reopens the window, and it restarts the server's own check sequence. The response is the full sheet with each row's new status, plus warnings for an SPF that conflicts with ours. GET /domains/{id}/events shows what each check found: "DNS checked for the first time.", "The DKIM record was found.", "Domain verified." When the status becomes failed, the domain.failed webhook fires with status, reason and every record in data.
curl -sS -X POST https://api.agentisend.com/domains/9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42/verify \
-H "Authorization: Bearer $AGENTISEND_API_KEY" \
-H "Idempotency-Key: $(uuidgen)"201
{
"click_tracking": true,
"created_at": "2026-09-04T09:14:00Z",
"dkim_selector": "string",
"id": "9c8f8f0e-3d1a-4d3f-9a1e-2b7c1a0f5e42",
"name": "yourdomain.com",
"open_tracking": true,
"provider_hints": {},
"recent_events": []
}