URL: /docs/concepts

---
title: Concepts
description: Tiers, masks, bands, reveals, holds and watermarks — the vocabulary the rest of these docs assumes you know.
---

This page defines the words. It does not tell you how to do anything — the [guides](/docs/guides/finding-domains) do that.

## Listing

A **listing** is one expired domain in the directory, plus everything Revised knows about it. As of 22 September 2026 the directory holds **17,713 listings**, of which **5,314** are on the open shelf.

Every listing has an **id**: eight characters, case-sensitive, mixed case in practice (`00aLaXEG`, `X00w46xl`). Store it verbatim. Lower-casing one will not match on the way back.

A listing is not an offer. Revised does not sell domains. A listing says: this name is not currently registered, here is its link history, go and register it wherever you like if you want it.

## Tier — the three shelves

`tier` is the single most important field on a listing, because it is the **only** field that tells you whether the name is public.

| `tier` | On the Revised site | May you republish the name? |
| --- | --- | --- |
| `open` | Published — in the listing page's title and in the sitemap | **Yes** |
| `regular` | Masked | No |
| `featured` | Masked; the curated shelf | No |

`regular` and `featured` names are disclosed to API callers under the [API terms](https://getrevised.com/terms) only. [Republishing rules](/docs/guides/republishing-rules) covers this in full, including the defensive check to put in front of any export.

There is also a `featured` **boolean** on each listing. It reads the shelf rank and can disagree with `tier == "featured"`. Branch on `tier`, never on the boolean.

## Masked names

`domain` holds the registrable name — or `null`, where the name is withheld. It can be `null` for **two independent reasons, and the field alone cannot tell you which**:

1. **Another account holds the listing** (`hold_state: "other"`). A hold masks the name for every reader, and an unlimited reveal allowance is not an exemption. `hold_expires_at` says when it comes back.
2. **Your plan has a monthly reveal ceiling and you have not revealed this listing.** You receive names on the open tier and on anything you have already revealed, and a mask on the rest.

On a plan with no reveal ceiling, only reason 1 applies.

`mask_hint` is populated either way and is what to render: the public partial mask, for example `g▓▓▓▓▓▓farms` — true length, first letter, last word, hyphens preserved.

`name_disclosed` is the discriminator for whether you got a real name. `mask_hint` is **not** — it is populated on every row whether or not anything is masked.

## Reveal

A **reveal** buys one name and records the listing against your account. It is the only call on the API that can spend: reading a page never charges for the rows it matched.

It is free in two cases, both of which still write a ledger entry: the listing is on the `open` tier (whose name is published anyway), or your plan has no reveal ceiling. It is **idempotent** — a repeat returns the original `revealed_at` and costs nothing.

A reveal is also a prerequisite: a hold is refused with `REVEAL_REQUIRED` until reveal has run for the same listing and the same account.

## Hold

A **hold** reserves a listing **inside Revised** and nothing else. It takes the listing off the shelf for other accounts for a plan-dependent window, and it does not reserve the name on the open internet — registrability out there is not guaranteed, and someone who never used Revised can register it while you hold it.

Holds are **account-scoped, not key-scoped**. Every key on the account sees, extends and can end the same holds. Who holds a listing is never disclosed to anyone else.

Each hold may be extended exactly once, and the extension runs from where the window was going to end, not from now. A hold ends with an `outcome` of `expired`, `released` or `registered`.

## Banded metrics

The link metrics are published as **bands**, not numbers:

| Field | Example value |
| --- | --- |
| `referring_domains` | `"100-250"` |
| `backlinks` | `"1K-5K"` |
| `domain_authority` | `"50-59"` |
| `snapshots` | `"40+"` |
| `revised_score` | `{ "low": 85, "high": 95 }` |

The shapes you have to parse are `"10-50"`, `"<100"`, `"250+"` and `"1K-5K"`.

This is deliberate. A point estimate implies a precision the underlying link data does not have: a domain measured at 137 referring domains today might measure 119 next week with nothing about the domain having changed. Sorting a shortlist on a fake third significant figure produces a fake ranking.

Flatten bands to a midpoint when you need to sort, keep the band string for display, and never show a midpoint to a reader as if it were a measurement. [Evaluating a domain](/docs/guides/evaluating-a-domain) has the parser.

## Missing is not zero

`null` in a metric means Revised has no figure, not a figure of zero. An unscored domain is not a DA-0 domain, and `agent_citability: null` means the domain has no row in the current index — not a score of zero.

The distinction is invisible in JSON, so every listing carries **`metrics_missing`**: an array naming exactly which of its optional metrics are absent, by the key they are published under. The candidates are `age_years`, `agent_citability`, `backlinks`, `category` and `domain_authority`. An empty array means the row is complete.

Two consequences worth holding on to:

- Filling a missing metric with `0` silently pushes those rows to the bottom of your ranking. That is a judgement you did not intend to make.
- The minimum-value filters (`ageMin`, `citabilityMin`, `rsMin`) **exclude** null rows rather than ranking them low, so a mild-looking floor can drop most of a page. `ageMin=1` means "at least a year old **and** we know how old it is", which is not the same question.

## Revised Score

`revised_score` is a published range — `{low, high}` — summarising the link profile. The exact score is not part of the API. `rsMin` filters on the lower bound of that range.

## Agent Citability

`agent_citability` scores how often a domain is cited by the sources AI answer engines draw on. That is a different question from classic link authority, and a domain can rate well on one and poorly on the other. It carries a `score` and the cited `sources`, and it is `null` where the domain has no row in the current index.

The methodology is published in full at [getrevised.com/agent-citability](https://getrevised.com/agent-citability).

## Spam band

`spam` is `low` or `moderate`. It filters the obvious cases, not all of them — read a domain's archive history before you act on it either way.

## Availability stamp

`availability_checked_at` records **when Revised last checked** that the name is unregistered. It is a stamp, not a live check.

Revealing a name in the web directory re-checks it on the spot. Exports and this API carry the last-checked timestamp instead. Read the age of the stamp before acting on a row, and confirm at a registrar before you register anything. `checkedDays` filters on stamp freshness.

## Estimated value

`estimated_value_cents` is the valuation model's low bound, falling back to a reference figure on rows the model has not valued. It is the same number the `priceRange` filter buckets, so a band and the values it returns agree. Nothing here is for sale, so read it as a signal, not a price.

## Categories

A listing's `category` is one of Revised's own codes — `saas`, `education`, `real-estate` and so on. There are 20 of them as of 22 September 2026, and there is no categories endpoint on the REST API; the codes are listed in [Finding domains](/docs/guides/finding-domains#category-codes).

An unknown code is **refused**, not answered with an empty result, which is the behaviour you want: a typo fails loudly. Many listings carry no category at all, and no category filter reaches those.

## Cursors, watermarks and tombstones

Paging is by **opaque cursor**, not offset. A page carries `next_cursor` and `has_more`; you pass the cursor straight back. A cursor belongs to the ordering it came from, so keep `sort` the same across a run, and never construct one — a cursor the endpoint did not issue is a `400`, not an empty page.

`synced_at` on every page is a **watermark**: the value to pass as `since` on your next run. It is taken before the page is read and is held 120 seconds behind server time, deliberately, so consecutive polls overlap rather than dropping a row that was mid-commit.

A **tombstone** is what the `since` feed returns for a listing that has left the directory: `{ id, status: "delisted", updated_at }` and nothing else. Every row in a feed carries `status`, so read that before treating a row as a listing. See [Incremental sync](/docs/guides/incremental-sync).

## Plans and keys

A key is a bearer token (`rvd_...`) created at [getrevised.com/account](https://getrevised.com/account). Keys are free on every plan. The key carries no entitlement of its own — the **owner's current plan** is resolved on every request.

| | Free | Pro | Business |
| --- | --- | --- | --- |
| Requests per minute, per key | 20 | 60 | 120 |
| Reveal ceiling | Monthly | Monthly | None |
| `since` change feed | No | No | Yes |

Every endpoint answers on every plan. The only thing a plan can be refused outright is the `since` parameter, which returns `402 upgrade_required` on Free and Pro. Read your own numbers from `GET /api/v1/me`.
