Sandbox: verify without a real domain
The full magic-domain table, what journey each one scripts, and why .test is safe to use.
Any domain ending in .test is a sandbox domain. Claiming one never touches real DNS — it's routed to an in-memory fixture that scripts a specific verification journey on demand, so you can experience every state (verified, pending, wrong record, unreachable, expired) without owning a domain or waiting on real propagation.
.test is reserved by RFC 6761 for documentation and testing — it can never be delegated in real DNS, so a sandbox domain can never collide with a real owner's domain. It's a safe, permanent namespace, not a convention that happens to work today.
Sandbox domains only work with a test-mode API key (dp_test_...). Claiming one with a live-mode key returns 400 sandbox_requires_test_mode.
The journeys
The first label of a sandbox domain (before any .test suffix) selects which journey it scripts. Every journey is deterministic and timed from when the domain was claimed — nothing here depends on wall-clock time beyond that.
| Domain | What happens |
|---|---|
verified.test | The correct record is present from the very first check. Verifies immediately — models an owner who published the record before starting verification. |
pending-then-verified.test | Reports not_found (nxdomain) until 12 seconds after the claim, then the correct record appears. Models real DNS propagation delay: long enough to feel real on a polling UI, short enough to still fit inside a live demo. |
wrong-value.test | Always returns a syntactically valid but incorrect record. Every check reports wrong_value with a detected value that never matches the expected one — useful for exercising the expected-vs-detected diff. |
nxdomain.test | Never resolves. Every check reports not_found, forever — models an owner who never added the record. |
flaky.test | Alternates every 30 seconds between unreachable (a simulated timeout) and the correct record. Drives the temporarily_failed grace-window story and its recovery UX. |
conflict.test | Resolves the correct record immediately, exactly like verified.test. DNS has no notion of "this domain is already claimed by someone else" — that's enforced by the claim endpoint itself (409 domain_already_claimed), not simulated in DNS. Claim conflict.test twice under the same mode to see it. |
Parallel runs
Append +<anything> to a journey's label to get an independent domain that scripts the same journey without colliding with another claim — for example verified+run1.test and verified+run2.test behave identically but are separate claims. This is what lets a test suite (or two people demoing at once) each get their own sandbox domain per journey.
Only .test is sandboxed
The magic only applies to the .test TLD, letter for letter. pending-then-verified.txt (or .tst, or any other suffix) isn't a sandbox domain — it's routed straight to the real DNS resolver like any other hostname, which reports not_found and keeps reporting it forever, since nobody has published anything at a hostname like that in real DNS. If a claim seems stuck in pending and its domain doesn't end in exactly .test, check for a typo in the TLD before anything else — that one-character mistake is the most common way a demo or test suite quietly hangs.
Trying it
Claim any of these the same way you'd claim a real domain — see the Quickstart for the full request/response shapes, and Claim and verify a domain for the complete integration guide.
curl https://api.domainproof.dev/v1/domains \
-H "Authorization: Bearer dp_test_k7h2m5p3qrtx_a3b4c5d6e7f2g3h4i5j6k7l2m3" \
-H "Content-Type: application/json" \
-d '{"domain": "flaky.test"}'Then call POST /v1/domains/:id/verify a few times, roughly 30 seconds apart, and watch the outcome alternate between unreachable and found.
Why a sandbox verify can still feel slow
A journey's own timing — 12 seconds for pending-then-verified, 30-second windows for flaky — is how fast the underlying DNS answer changes, not how often anything actually checks it. If you never call /verify yourself, the only thing checking is the same background recheck scheduler that watches real domains, on the same backoff ladder: the first automatic check lands 1 minute after the claim, then 5 minutes, then 15, then hourly (see How verification works). So a pending-then-verified.test domain whose record "appears" at 12 seconds can still show pending for a minute or more longer than that if you're just watching passively, until the next scheduled check happens to land after the 12-second mark. Poll /verify yourself, like the Quickstart does — or use the dashboard's onboarding walkthrough, which polls actively while its tab is open — any time you want the journey's own timing to be the only clock that matters.