> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ownsi.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# The claim lifecycle

> A claim runs forwards, ends once, and becomes history. What that buys, and what archiving does and does not destroy.

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

| `state`    | What it means                                         | What you should show                                          |
| ---------- | ----------------------------------------------------- | ------------------------------------------------------------- |
| `pending`  | Open. The window is running and so is a verification. | The record to create, and the verification's own status.      |
| `proved`   | Verified, and dated by the run that verified it.      | The proof and its date.                                       |
| `expired`  | The seven-day window closed without a proof.          | The record it was waiting for, and one button to claim again. |
| `canceled` | Stopped on purpose, or by archiving the domain.       | History.                                                      |

`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

| `status`          | What it means                                                             | What you should show         |
| ----------------- | ------------------------------------------------------------------------- | ---------------------------- |
| `checking`        | Running, and nothing has been read yet — or the last read reached nobody. | The record to create.        |
| `propagating`     | Your own nameservers have the record; resolvers do not yet.               | A wait, with `waitEstimate`. |
| `needs_attention` | A run found something wrong that only you can fix.                        | `diagnosis.fix`.             |
| `proved`          | The record was there. The claim ends with it.                             | The proof and its date.      |
| `exhausted`       | The deadline passed. The claim expires with it.                           | One button to claim again.   |
| `stopped`         | The claim was canceled or its domain archived.                            | Nothing.                     |

`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

<Steps>
  <Step title="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.
  </Step>

  <Step title="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`](/errors#verification_not_running) once the process is over.
  </Step>

  <Step title="POST /api/claims/:id/cancel">
    Ends the claim and stops its verification. The token stops being accepted from that moment.
  </Step>

  <Step title="POST /api/domains/:id/archive">
    Leaves the list and ends any claim open on the name. **Retracts nothing.**
  </Step>

  <Step title="DELETE /api/domains/:id">
    The only eraser. Claims, verifications and proof links go with it.
  </Step>
</Steps>

## 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`](/diagnostics/catalogue#expired_token), and it turns
  starting over into a one-line edit.

<Note>
  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.
</Note>

## Archiving is not deleting

<Check>
  Archiving ends the open claim and takes the domain off the list. Every proof keeps its date and
  every proof link still resolves.
</Check>

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:

```json theme={null}
{
  "coexistence": {
    "maskedEmail": "m•••@acme.com",
    "provedAt": "2026-08-01T09:14:00.000Z"
  }
}
```

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`](/errors#already_claimed), a 409, and the fix is to use the
claim you already have rather than issue a second token.

## Dates

| Field             | Where       | Meaning                                                            |
| ----------------- | ----------- | ------------------------------------------------------------------ |
| `createdAt`       | domain      | When you first added the name.                                     |
| `claim.createdAt` | claim       | When this claim opened.                                            |
| `claim.expiresAt` | open claim  | When the window closes.                                            |
| `claim.endedAt`   | ended claim | When it ended. On a `proved` claim, this is the date of the proof. |
| `firstVerifiedAt` | derived     | The earliest proof across a domain's claims.                       |
| `lastConfirmedAt` | derived     | The most recent one.                                               |

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](/sdk/typescript#the-two-dates-a-proof-states) is that read.
