Skip to main content
A domain on an account has one claim open at a time and as many behind it as you have made. A claim is an episode: it opens pending, it ends proved, expired or canceled, and an ended claim never moves again. The claim answers what — the token, the window, the outcome. Its verification answers how it is going — the runs, the diagnosis, the wait. They are two resources, and a claim carries the verificationId of its own.

The claim’s four states

pending carries records and expiresAt. The other three carry endedAt and no records — there is nothing left to write in a DNS panel.

The verification’s six

propagating and needs_attention are the split that matters. Both are “not verified”; one is your problem and one is not, and telling someone to fix a record that is already correct is the failure mode this product exists to avoid.

What moves a claim

1

POST /api/claims — open one

Issues the token and starts a verification, whose id comes back on the claim. state is pending, expiresAt is seven days out. On a domain whose last claim has ended, this is also how you start again: a new claim, a new token, and the old one stays as history.
2

POST /api/verifications/:id/runs — ask for a run now

Reads DNS instead of waiting for the schedule. Rate limited per verification. Answers verification_not_running once the process is over.
3

POST /api/claims/:id/cancel

Ends the claim and stops its verification. The token stops being accepted from that moment.
4

POST /api/domains/:id/archive

Leaves the list and ends any claim open on the name. Retracts nothing.
5

DELETE /api/domains/:id

The only eraser. Claims, verifications and proof links go with it.

Why a claim expires

The proof reads “on 15 June, this account demonstrated control”, and that sentence is only true if the demonstration was recent. A token accepted forever breaks it: a record written in January and never cleaned up would keep minting fresh proofs long after control had passed to someone else. Everything follows from that:
  • An ended claim’s token stops being accepted. The record left in the zone is inert.
  • There is no check again. A new date needs a new demonstration, which means a new claim, a new token, and one edit in the DNS panel.
  • Seven days is chosen so nobody who did the work correctly loses it. Negative caching rarely exceeds a day; provider publishing is minutes to hours.
  • When the next claim finds the previous claim’s token still on the challenge host, that is not “nothing found” — it is expired_token, and it turns starting over into a one-line edit.
Expiring is not an accusation. Not proving is never evidence against the person: it can be a holiday, a broken provider, or our own failure.

Archiving is not deleting

Archiving ends the open claim and takes the domain off the list. Every proof keeps its date and every proof link still resolves.
Archiving is a fact about the pair — this account, this name — rather than a state a claim is in. That is why it can sit next to a proof without retracting it, and why it survives every claim you make afterwards. It also stops the domain counting towards coexistence, which is the reason it exists as a distinct action: if a team stops using a domain but its claim keeps counting, a second team claiming the same name is told about a claim nobody is maintaining.

Coexistence

Two accounts can each prove the same domain. That is not a bug and not a race — both created the record, both were verified, and neither has more right to the name than the other. When it happens, the domain carries:
The local part is masked and the domain is not, which is enough for someone to recognise a colleague and not enough to harvest an address. Claiming a domain that already has a claim open on your own account is a different thing entirely — that is already_claimed, a 409, and the fix is to use the claim you already have rather than issue a second token.

Dates

The two domain-level dates are what a proof page states: proved on the first date, most recently on the second. Neither is stored and neither is a field on any response — they are read across the domain’s claims, which is why neither can disagree with them. domain.proof() in the SDK is that read.