URL: /docs/guides/republishing-rules

---
title: Republishing rules
description: Only open-tier names may be republished. How to tell, and the assertion to put in front of every export.
---

<Warning>
  **Only `tier: "open"` names may be republished.** `regular` and `featured` names are masked everywhere on the Revised site and are disclosed to API callers under the [API terms](https://getrevised.com/terms) only. Do not put them on a public page, in a shared spreadsheet, in a newsletter, in a public dataset, or anywhere else another person can read them.
</Warning>

This is the one rule in these docs with consequences outside your own codebase, so it gets its own page. It comes down to a single field.

## `tier` is the only field that says a name is public

| `tier` | Where the name appears on getrevised.com | May you republish it? |
| --- | --- | --- |
| `open` | In the listing page's title, and in the sitemap | **Yes** |
| `regular` | Nowhere — masked | **No** |
| `featured` | Nowhere — masked. This is the curated shelf | **No** |

As of 22 September 2026, 5,314 of the directory's 17,713 listings are on the open shelf. If you are building anything public, `tier=open` is a server-side filter and you should be using it:

```bash
curl -s -G https://getrevised.com/api/v1/domains \
  -H "Authorization: Bearer $REVISED_KEY" \
  -d tier=open \
  -d limit=250
```

`open` is the only value that filter accepts. There is no way to ask the API for `regular` or `featured` rows specifically — but there is also nothing stopping them arriving in an unfiltered page, which is the whole reason for the rest of this page.

## Three fields that look like the answer and are not

### `featured` (the boolean) is not `tier == "featured"`

Each listing carries a `featured` boolean **and** a `tier`. The boolean reads the shelf rank and **can disagree with the tier**. It is not a permission field and it never was.

```python
# WRONG — the boolean is a rank signal, not a shelf
if not row["featured"]:
    publish(row["domain"])

# RIGHT
if row["tier"] == "open":
    publish(row["domain"])
```

### A non-null `domain` is not permission

Receiving the name means you are entitled to *see* it. It says nothing about republishing it. On a plan with no reveal ceiling every name arrives disclosed, on every tier — that plan buys you access, not publication rights.

```python
# WRONG — "I can see it, so I can publish it"
if row["domain"]:
    publish(row["domain"])
```

### `mask_hint` is not a discriminator

`mask_hint` is populated on **every** row, whether or not anything is masked. It is what to render when a name is withheld; it is not how you tell whether one was.

If you need to know whether you got a real name, read `name_disclosed`. If you need to know whether you may publish it, read `tier`. They answer different questions.

## Why `domain` can be `null`

Two independent reasons, indistinguishable from the field itself:

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.** `POST /api/v1/domains/{id}/reveal` buys one.

Render `mask_hint` either way. Neither reason has anything to do with whether the name may be republished — a masked `regular` listing and a revealed `regular` listing are equally off-limits.

## The pattern: filter at the source, assert at the boundary

Filtering is not enough on its own. A filter lives at the top of a pipeline where a later edit can quietly widen it; the assertion lives immediately before the write, where nothing can get past it.

```python
import json


def export_open_shortlist(rows, path):
    """Write a public CSV. Refuses outright if a non-open row got this far."""
    open_rows = [r for r in rows if r.get("status") == "active" and r["tier"] == "open"]

    # The guard. Immediately before the write, so no future edit to the filters
    # above can bypass it.
    assert all(r["tier"] == "open" for r in open_rows), (
        "refusing to export: non-open rows are disclosed under the API terms, "
        "not for republication"
    )

    with open(path, "w", encoding="utf-8") as handle:
        for row in open_rows:
            handle.write(json.dumps({"domain": row["domain"], "tier": row["tier"]}) + "\n")

    return len(open_rows)
```

With pandas, the same guard in one line before `to_csv`:

```python
assert (df["tier"] == "open").all(), \
    "refusing to export: non-open rows are disclosed under the API terms, not for republication"

df.to_csv(filename, index=False)
```

And in a shell pipeline, where it is easiest to forget:

```bash
curl -s -G https://getrevised.com/api/v1/domains \
  -H "Authorization: Bearer $REVISED_KEY" \
  -d tier=open -d limit=250 \
  | jq -e '[.data[] | select(.status == "active")] | all(.tier == "open")' > /dev/null \
  || { echo "refusing to publish: non-open rows in the page" >&2; exit 1; }
```

```text Output when a non-open row slips through
refusing to publish: non-open rows in the page
```

`jq -e` exits non-zero when the last output is `false` or `null`, so the guard fails the pipeline rather than printing a warning nobody reads.

<Note>
  Put the assertion in front of **every** public boundary, not just the CSV writer: the template that renders a page, the endpoint that returns JSON to a browser, the job that posts to a channel, the prompt that hands rows to a model whose output you publish. Each of those is a place a name escapes.
</Note>

## What counts as republishing

Treat anything another person can read as publication: a web page, a public API of your own, a downloadable file, a newsletter, a social post, a dataset, a dashboard shared outside your organisation, or model output you publish.

What you may do with any tier, on any plan:

- Read it, store it, rank it, and make decisions with it inside your own systems.
- Register the domain yourself, at any registrar. The restriction is on republishing Revised's data, not on acting on it. Nothing in the directory is sold by Revised, and every listing is a name available to register.
- Tell your own users about a name **you have registered**. Once it is yours, it is yours.

## Checklist before anything goes public

<Steps>
  <Step title="Filter server-side">
    `tier=open` on the request. Cheapest possible place to drop a row you cannot use.
  </Step>
  <Step title="Drop tombstones">
    Branch on `status`. A `delisted` row has no `tier` at all and will throw or, worse, compare falsely.
  </Step>
  <Step title="Assert immediately before the write">
    `assert all(r["tier"] == "open" ...)`. Not at the top of the function — at the boundary.
  </Step>
  <Step title="Re-check the stamp">
    `availability_checked_at` is a last-checked timestamp, not a live check. A public list of "available" names that were registered last week is its own kind of problem. See [Evaluating a domain](/docs/guides/evaluating-a-domain#availability-is-a-stamp-not-a-check).
  </Step>
  <Step title="Date the output">
    Stamp the export with the `synced_at` watermark it came from, so a reader knows how old it is.
  </Step>
</Steps>

The full terms are at [getrevised.com/terms](https://getrevised.com/terms).
