Find newly listed expired domains
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.
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, 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.
curl -s -G https://getrevised.com/api/v1/domains \
-H "Authorization: Bearer $REVISED_API_KEY" \
-d sort=latest \
-d tier=open \
-d limit=20discovered_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.
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.
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 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.
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.