URL: /docs/guides/new-listings

---
title: Find newly listed expired domains
sidebarTitle: Newly listed
description: Poll the Revised API for expired domains added since your last run with sort=latest, on any plan — and how the new-listing delay, batch timestamps and availability stamps affect what you see.
icon: sparkles
---

New names enter the directory every time the discovery pipeline runs. This guide polls for them: list the directory newest first, stop at the last listing you already have, and repeat on a schedule. It works on every plan, and it is a different job from [Incremental sync](/docs/guides/incremental-sync), which tracks changes to listings you already hold.

## Newest first

`sort=latest` orders the directory by `discovered_at`, newest first, tie-broken by listing id. `discovered_at` is written once, when the listing entered the directory, and never changes — which is what makes the ordering safe to page with a cursor.

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

`discovered_at` is a fact about the directory, not the domain. It is neither the date the name expired nor its original registration date.

## Your plan decides what "new" means

A new listing is hidden from each plan for a set time after it enters the directory:

| Plan | New listings visible after |
| --- | --- |
| Free | 7 days |
| Pro | 1 day |
| Business | Immediately |

Until then it is not in your results at all, and `GET /api/v1/domains/{id}` for it returns `404`. On Free, the newest listing you can see is at least a week old. See [Plans and limits](/docs/api/plans-and-limits).

## Poll for what you have not seen

Listings arrive in batches, and every listing in a batch can share one `discovered_at`. So do not stop at the first timestamp equal to your last run's — stop at the first one **older** than it, and skip ids you already hold.

```python
import os
import time

import requests

URL = "https://getrevised.com/api/v1/domains"
session = requests.Session()
session.headers["Authorization"] = f"Bearer {os.environ['REVISED_API_KEY']}"


def new_listings(last_seen_at, known_ids, max_pages=20, **filters):
    """Listings discovered at or after `last_seen_at` that are not in `known_ids`."""
    fresh, cursor = [], None
    for _ in range(max_pages):
        params = {"sort": "latest", "limit": 250, **filters}
        if cursor:
            params["cursor"] = cursor
        response = session.get(URL, params=params, timeout=30)
        response.raise_for_status()
        page = response.json()

        for row in page["data"]:
            if last_seen_at and row["discovered_at"] < last_seen_at:
                return fresh              # older than anything new: done
            if row["id"] not in known_ids:
                fresh.append(row)

        if not page["has_more"]:
            return fresh
        cursor = page["next_cursor"]
        time.sleep(0.6)
    return fresh


fresh = new_listings("2026-09-15T00:00:00.000Z", known_ids=set(), tier="open", spam="low")
print(len(fresh), "new listings")
if fresh:
    print("next last_seen_at:", max(row["discovered_at"] for row in fresh))
```

Timestamps are ISO 8601 in UTC with the same format on every row, so comparing the strings compares the instants. Store the newest `discovered_at` you saw and the ids at that timestamp, and pass both on the next run.

Keep `sort=latest` and your filters the same on every page of a run. A cursor belongs to the ordering and the query it came from.

## Narrow what you poll for

Everything in [Filters](/docs/api/filters) combines with `sort=latest`. Useful ones for this job:

- `tier=open` — only names you may republish, which arrive with their names on every plan.
- `category`, `tld` — the niche you are watching.
- `rsMin`, `rd` — a quality floor. New listings are often the sparsest: the five newest open-tier listings on 23 September 2026 all lacked age, category and Agent Citability.
- `checkedDays` — only rows whose availability was checked recently.

## Before you act on a new listing

`availability_checked_at` is when Revised last confirmed the name was unregistered. New listings are not re-checked when you read them, and a newly dropped name is exactly the kind someone else is also watching. Confirm at a registrar before you act. See [Availability is a stamp, not a check](/docs/guides/evaluating-a-domain#availability-is-a-stamp-not-a-check).

## `sort=latest` or `since`?

| | `sort=latest` | `since` |
| --- | --- | --- |
| Answers | What entered the directory? | What changed, including what left? |
| Plans | All | Business only |
| Ordered by | `discovered_at`, newest first | Listing id |
| Returns tombstones | No | Yes |

They cannot be combined. To keep a local copy correct, use `since`. To watch for new names, use `sort=latest`.

## Over MCP

`search_domains` takes `sort: "newest"` for the same ordering, capped at 50 rows with no paging:

> Show me the 20 newest open-tier SaaS listings with a low spam band.
