Revised

Evaluate a domain

Read a listing properly — banded metrics, missing data, marquee linkers, and the availability stamp that is not a check.

A page of listings gives you rows. Turning rows into a judgement means handling three things the API is deliberate about: the metrics are bands, a missing metric is not a zero, and the availability timestamp is not a live check.

Read the whole row

bash
curl -s https://getrevised.com/api/v1/domains/LxRrd32h \
  -H "Authorization: Bearer $REVISED_KEY"
Example
json
{
  "id": "LxRrd32h",
  "status": "active",
  "domain": "septictankcleaningsydney.com.au",
  "tier": "open",
  "name_disclosed": true,
  "tld": "com.au",
  "category": "other",
  "referring_domains": "100-250",
  "backlinks": "100-500",
  "domain_authority": "10-19",
  "revised_score": { "low": 85, "high": 95 },
  "agent_citability": null,
  "spam": "low",
  "age_years": 4,
  "snapshots": "<10",
  "linked_by": ["FCC"],
  "metrics_missing": ["agent_citability"],
  "hold_state": "none",
  "estimated_value_cents": 100,
  "availability_checked_at": "2026-09-19T21:04:06.589Z",
  "updated_at": "2026-09-19T21:04:06.589Z"
}
FieldWhat it tells you
referring_domainsHow many distinct sites link here. The most durable signal on the row — far harder to manufacture than raw backlink count.
backlinksTotal links. A large number over a small referring-domain count usually means one site linking many times.
domain_authorityAn aggregate of the link graph, 0–100. Correlates with referring domains, but not perfectly.
revised_scoreRevised’s own published range. rsMin filters its lower bound.
agent_citabilityHow often the domain is cited by the sources AI answer engines draw on. A different question from link authority. Methodology.
spamlow or moderate. Filters the obvious cases, not all of them.
snapshotsHow much of the site the public archive holds — a proxy for whether it was a real site rather than a parked shell.
linked_byNamed, recognisable domains that link here. Read this column.
age_yearsAge in whole years, where known.
metrics_missingWhich of the optional metrics on this row are null.

The metrics are bands

referring_domains is "100-250", not 137. domain_authority is "10-19". revised_score is a {low, high} range.

That 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, and sorting on a fake third significant figure produces a fake ranking.

So flatten bands to a midpoint for sorting, keep the band string for display, and never show a midpoint to a reader as if it were a measurement. Four shapes to handle: "10-50", "<100", "250+" and "1K-5K".

python
_SUFFIX = {"K": 1_000, "M": 1_000_000}


def _num(token):
    """'1K' -> 1000.0, '250' -> 250.0"""
    token = token.strip().upper()
    if token and token[-1] in _SUFFIX:
        return float(token[:-1]) * _SUFFIX[token[-1]]
    return float(token)


def band_midpoint(band):
    """Flatten a published band to a single sortable number.

    '10-50' -> 30.0      midpoint
    '<100'  -> 50.0      half the ceiling
    '250+'  -> 375.0     the floor plus 50%, arbitrary but consistent
    None    -> None      genuinely unknown; not zero
    """
    if band is None or band == "":
        return None
    band = str(band).strip()
    if band.startswith("<"):
        return _num(band[1:]) / 2
    if band.endswith("+"):
        return _num(band[:-1]) * 1.5
    if "-" in band:
        low, high = band.split("-", 1)
        return (_num(low) + _num(high)) / 2
    return _num(band)


for probe in ["10-50", "<100", "250+", "1K-5K", "0-9", None]:
    print(f"{str(probe):>8} -> {band_midpoint(probe)}")
Output
text
   10-50 -> 30.0
    <100 -> 50.0
    250+ -> 375.0
   1K-5K -> 3000.0
     0-9 -> 4.5
    None -> None

Missing is not zero

agent_citability: null means the domain has no row in the current index — not a score of zero. The same goes for domain_authority, backlinks, age_years and category. Every row carries metrics_missing naming exactly which of its optional metrics are absent, so you never have to guess whether a blank means “we looked and found nothing” or “we have not looked”.

Filling a missing metric with 0 silently pushes those rows to the bottom of your ranking. That is a judgement, and not one you meant to make.

The honest alternative: drop the missing component and re-normalise the remaining weights.

python
import math

WEIGHTS = {"rd_mid": 0.35, "da_mid": 0.25, "citability": 0.25, "snap_mid": 0.15}

# Ceilings past which more stops meaning better, for the log-scaled components.
CEILINGS = {"rd_mid": 500.0, "snap_mid": 200.0}


def _component(column, value):
    if value is None:
        return None
    if column in CEILINGS:
        # log1p so 0 maps to 0, then clamp at the ceiling.
        return min(math.log1p(value) / math.log1p(CEILINGS[column]), 1.0)
    return min(max(value / 100.0, 0.0), 1.0)  # DA and citability are already 0-100


def rank_score(row):
    """Weighted 0-100 score. Missing components are dropped, not zeroed."""
    total, used = 0.0, 0.0
    for column, weight in WEIGHTS.items():
        value = _component(column, row.get(column))
        if value is not None:
            total += value * weight
            used += weight
    if used == 0:
        return None
    return round(100 * total / used, 1)


def components_used(row):
    """How many of the four components this score is actually built on."""
    return sum(_component(c, row.get(c)) is not None for c in WEIGHTS)


candidate = {"rd_mid": 175.0, "da_mid": 15.0, "citability": None, "snap_mid": 5.0}
print(rank_score(candidate), "from", components_used(candidate), "of", len(WEIGHTS), "components")
Output
text
50.6 from 3 of 4 components

Two rules the weights do not express, and both matter:

  • Log-scaling on the count-like components. The gap between 10 and 100 referring domains matters much more than the gap between 1,000 and 1,090.
  • Report how many components were used. A row scored on two of four is a weaker claim than one scored on all four, even when the number is higher. Re-normalising keeps the arithmetic honest; it cannot invent the missing evidence.

Weights are a judgement call, not a fact. Keep them where whoever reads the ranking can argue with them.

Scan linked_by before you trust the score

linked_by names recognisable domains that link to this one. A listing with a small referring-domain count and a university, a government body or Wikipedia in linked_by is often more interesting than one with hundreds of forgettable links — and no single aggregate captures that. It is the column most worth reading with your own eyes.

Availability is a stamp, not a check

Measure the age of the stamp and act on it:

python
from datetime import datetime, timezone

checked = datetime.fromisoformat(row["availability_checked_at"].replace("Z", "+00:00"))
age_hours = (datetime.now(timezone.utc) - checked).total_seconds() / 3600

if age_hours > 48:
    print(f"{row['id']}: availability last checked {age_hours:.0f}h ago — re-check before acting")
Output
text
LxRrd32h: availability last checked 62h ago — re-check before acting

checkedDays filters the directory on stamp freshness, so you can ask for only recently-checked rows at the source.

Before you register anything

  1. Read the archive

    Pull up what the site actually was. A high referring-domain count on a domain whose archived pages are pharmacy spam is a liability, not an asset — spam: "low" filters the obvious cases, not all of them.

  2. Confirm the links still exist

    A link recorded in a crawl is not necessarily a link on the live page today.

  3. Confirm availability at a registrar

    The stamp is not a check, and a Revised hold reserves the listing here and nothing else.

  4. Have a plan for the content

    Inheriting links to a site about Queensland fishing and pointing them at something unrelated wastes most of what you just picked up.

Next

Type to search…

↑↓ navigate openesc close