# Scopeweb > Domain intelligence and persistent draft hosting for agents. > API: https://api.scopeweb.io · MCP: https://mcp.scopeweb.io/mcp ## How to think with this tool Read this section before the endpoint reference. What this API refuses to claim is the part that matters. ### PARENT LAW — every assertion carries its evidence grade, and absence of evidence never upgrades to a claim The laws below are three instances of one rule. A failed lookup is not a verdict. A non-authoritative source is not an authority. An unregistered name is not a price. In each case something is MISSING — a response, a mandate, a quote — and the missing thing must never be silently promoted into a positive claim. Concretely: every result states what was measured (classification), when (last_verified_at), how it was obtained (source) and on whose authority (rdap_source). When you cannot tell, the answer is 'unknown', and 'unknown' is a real answer here rather than a failure to produce one. This costs a round trip. The alternative costs somebody a domain. ### Unknown is never available A domain is reported 'unregistered' ONLY on an authoritative RDAP 404. If the registry lookup fails, times out or is throttled, the answer is 'unknown' — never 'unregistered'. 'pending' (the per-domain deadline elapsed) and 'unprobed' (generated but never checked) are likewise not registration claims. Re-confirm with check_live immediately before acting on any of it. See also: unregistered is not the same as purchasable. Corollary, learned the hard way: ONLY AN AUTHORITATIVE REGISTRY MAY SAY 'NOT REGISTERED'. Bootstrap aggregators answer 404 both for an unregistered name and for a TLD they cannot route, and the two are indistinguishable in the response — so a 404 from a non-authoritative source is downgraded to 'unknown'. Every result carries rdap_source ('authoritative' or 'aggregator') so you can see which you got. ### Unregistered is not purchasable RDAP 404 proves no registration EXISTS. It proves nothing about whether the name can be bought, or at what price. Registry-reserved names, premium-tier names and registry holds all answer 404 and are reported 'unregistered' — yet cost far more than the TLD's list price, or cannot be bought at all. tld_base_price_usd is the TLD's standard rate, NEVER a quote for a specific name. 'purchasable' stays null until a registrar quote resolves it. Do not tell a user a name is available to buy, or what it costs, on the strength of a scan. ### resolves is three-state, and the states mean different things undefined = never looked (check_live is registration-only) -> classification 'registered', nothing further is claimed. null = the DNS lookup FAILED -> 'unknown'. false = we looked and there is no A record -> 'dormant', a real measurement. The distinction exists so the API never reports a state it did not measure. ### Every verdict carries when it was taken Rows carry last_verified_at and source ('probe' = fetched now, 'cache' = a previous scan still inside its freshness tier, 'generated' = never checked, 'timeout' = deadline elapsed). Availability is cached for 15 minutes; everything else for 6 hours, because a stale 'active' is cosmetic and a stale 'available' sends someone to buy a domain that is gone. ### Versioned identifiers scan_id embeds the expansion algorithm version and liveness scores embed score_v. If the algorithm changes, an old scan_id is REJECTED with HTTP 409 and a re-scan instruction rather than silently returning a differently-generated page. Paginating across a deploy can never yield silent duplicates or gaps. ### Rate-limit headers ride on success x-ratelimit-limit / -remaining / -reset appear on successful responses, not only on 429. A client that learns its budget only at the moment of rejection cannot pace itself. On 429, retry-after is in seconds. ## Idioms ### Sourcing young positives for endpoint admission Admission requires positives spanning registration ages, which is hard on a TLD whose short names all date to launch week — every desirable .me name is 2008-2009, for instance. Certificate Transparency logs solve it: a fresh registration almost always gets a TLS certificate within days, so CT surfaces recent registrations for any TLD. This is how .me's era-cutoff hypothesis was refuted rather than assumed — vibecode.me (2025) and aiagent.me (2024) answered 200 alongside vibe.me (2008), a 17-year span. ### Progressive deepening browse_namespace expands a concept into hundreds of candidates but probes only a budgeted slice per call; the rest come back as 'unprobed'. Re-querying the SAME scan_id spends the next call's budget on candidates not yet checked, and earlier results are served from cache. Coverage converges over roughly 3 calls. Re-query the same scan_id to walk deeper rather than widening limit. ### Registry throttling is detected and routed around Registries rate-limit per source IP, and a throttled RDAP response degrades to 'unknown'. Candidates are grouped by TLD and run in parallel ACROSS registries but gently within one, with a retry on 429/503. Without this, naive parallel scanning silently poisons a large fraction of results with false 'unknown' verdicts. ## Latency Cold and warm are separate contracts. Honesty is preserved at the probe layer; speed comes from the cache layer. - cold p95: 3500 ms (candidates not in cache) - warm p95: 2500 ms (cache hits) - per-domain deadline: 3000 ms A candidate exceeding the per-domain deadline returns 'pending'. Its scan continues server-side and still writes to the scans table, so the next call for that domain is a cache hit — a timed-out probe warms the cache rather than being wasted. ## Rate limits - drafts: 20/day per user - scans: 60/hour per token Counters are KV-backed and eventually consistent: a concurrent burst from one token can overshoot slightly. This is an abuse floor, not a billing meter. ## Preview hosting Draft previews are served from a SEPARATE registrable domain so user content never shares the brand domain's cookie scope or blocklist reputation. Previews are served noindex, with a Content-Security-Policy pinning form-action and connect-src to 'self' — the browser refuses credential exfiltration regardless of what the markup does. Static content screening is a floor on top of that, not the primary control. ## Reference ### create_draft `POST /drafts` — Store a draft website and get a persistent preview URL. Store a draft website in the user's Scopeweb portfolio. Returns a persistent draft_id and a live preview_url. Drafts survive across conversations — use list_drafts in future sessions to resume work. Content is screened on every version; a flagged draft still returns normally here but its preview serves 451. ### update_draft `PUT /drafts/{draft_id}` — Write a new immutable version of a draft (patch semantics). Update files in an existing draft. Acts as a patch: files you send are written as a new version, files you omit are carried forward unchanged. Previous versions are retained immutably. Returns the new version and preview_url. ### list_drafts `GET /drafts` — List the user's drafts. List all drafts in the user's Scopeweb portfolio with status, preview URLs and timestamps. Call this at the start of a session to see existing work. ### get_draft `GET /drafts/{draft_id}` — Read a draft's metadata, file list, or one file's contents. Get a draft's metadata and file list, or a single file's content by passing path. Use to resume work on a draft from a previous conversation. ### verify_ownership `POST /domains/verify-{action}` — Prove domain ownership via a DNS TXT challenge. Prove the user owns a domain via a DNS TXT challenge. action 'start' returns the TXT record to publish; action 'check' verifies it. Verification is required before a domain appears in list_domains. A failed DNS lookup returns an error, never 'not owned'. ### list_domains `GET /domains` — The user's verified domain inventory with cached scan data. List the user's domain inventory: every domain with a verification challenge issued or completed, plus cached liveness, classification, title and expiry. Includes scan_age_ms so a stale verdict is never mistaken for a fresh one. Use before suggesting the user buy anything. ### browse_namespace `POST /browse` — Browse the namespace around a CONCEPT, ranked and classified. Browse the domain namespace around a CONCEPT — pass a word or idea, not a candidate list. Expands it server-side (plurals, prefixes, suffixes, TLDs), then returns results ranked: active sites first, then parked/dormant, then claimable. Every row carries classification, last_verified_at and source ('cache' | 'probe' | 'generated' | 'timeout'). Rows marked 'unprobed' were generated but never checked; re-query the SAME scan_id to spend the next budget on them — coverage converges over about 3 calls. Never treat 'unknown', 'pending' or 'unprobed' as a registration claim, and never treat 'unregistered' as purchasable: reserved and premium names answer RDAP 404 too, tld_base_price_usd is the TLD rate rather than a quote, and purchasable stays null until a registrar quote resolves it. ### score_name `POST /name/score` — Grade candidate names on measurable, audited components. Grade candidate names on measurable properties of the string: length, syllables, pronounceability (the radio test), presence in a published English word list, edit distance to major brands, hyphens/digits, and TLD perception. Every component returns its score, weight and basis so the number can be audited rather than trusted. Severe properties CAP the total instead of being averaged away — a name one edit from a major brand cannot score well however short it is. EXPLICITLY NOT a search-ranking prediction: exact-match-domain SEO value has been largely dead since Google's 2012 EMD update and nothing here forecasts how a name will rank. NOT a trademark search: brand_collision is string similarity to a published list, not legal clearance. Components that cannot be measured (zone rarity, trademark) are returned as unavailable with reasons and never estimated. ### scan_namespace `POST /scan` — Classify an explicit list of domains. Classify an explicit list of candidate domains (max 25). Use browse_namespace instead when you have a concept rather than a list. Returns registered, resolves, serves, parked, classification and liveness for each. ### check_live `POST /scan/live` — Authoritative registration check. The purchase gate. Real-time authoritative registration check for up to 10 domains via RDAP. This is the final gate before recommending a purchase — never rely on cached or older scan results for buying decisions. It answers whether a registration EXISTS, not whether the name can be bought or at what price: reserved and premium names return 404 here too. Registration-only: it does not fetch the site, so it returns 'registered' rather than 'active' or 'dormant'. ### audit_domain `POST /scan/audit` — Fetch one domain's live, observable surface. Fetch a live domain's observable surface: HTTP status, redirect target, title, meta description, h1 headings and tech hints. Use to compare what is actually deployed against a spec, or to check whether a domain serves anything at all. ## Versions - expansion_version: 1 (embedded in every scan_id) - score_version: 1 (embedded in every liveness score) Authentication: `Authorization: Bearer ` on every endpoint except /spec.json, /llms.txt and /openapi.json.