API reference

Namecheck API

Post a name, get the domains, the handles and a trademark collision signal — each backed by something you can open. One synchronous call, JSON in and out. Three rails share one meter: 5 Ounie credits per check on REST and MCP, $0.060 USDC per check keyless over x402.

Quickstart

curl -X POST https://namecheck.ounie.com/api/checks \
  -H "Authorization: Bearer nmc_live_…" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "orbitkiln",
    "tlds": ["com", "io", "dev"],
    "trademark": true
  }'

The whole board comes back on the same request — typically in 4–10 seconds, since it runs a dozen live probes and a web search. There is no job to poll.

Authentication

Three credentials are accepted, in this order:

  • Your app keyAuthorization: Bearer nmc_live_…, minted at /dashboard/api-keys. Up to 5 active. Only the sha256 hash is stored; the raw token is shown once.
  • The fleet master key — your ounie.com developer key (ounie_live_…) works here too, once you enable “Use across Ounie apps” in your ounie.com settings.
  • The shared session cookie — the dashboard uses it. Any signed-in .ounie.com browser session works.

Hosts that can't set a header (the Ounie AI Team's manual MCP entries, for one) may pass the key as ?api_key=nmc_live_… on any endpoint.

A key can only ever spend its owner's credits, and the reserve happens before any upstream work. An agent that runs out gets a 402 with the exact shortfall — it cannot overdraw and cannot run up a balance.

POST /api/checks

FieldTypeMeaning
namestring, requiredThe brand or product name, up to 63 characters. A URL or a domain is accepted and reduced to its label, so https://acme.com/pricing and Acme check the same thing. The normalised label is echoed back.
tldsstring[], optionalTop-level domains without the dot. Defaults to com, io, ai, net, app, dev. Up to 12 per check. A malformed TLD is a 400, not a silent drop.
handlesstring[], optionalPlatforms to probe. Defaults to all of them. Only github, x, youtube, npm, pypi, crates are accepted — an unsupported platform is a 400 naming the supported set, never a missing row.
trademarkboolean, optionalDefaults to true. Set false to skip the web evidence scan.
Asking for a platform we do not support is refused rather than ignored. A dropped row reads as “available” to anything parsing the response, and a wrong “available” is the most expensive thing this API could hand you.

The response

{
  "ok": true,
  "check": {
    "id": "…",
    "name": "orbitkiln",
    "headline": "orbitkiln: 5 of 6 domains open, 5 of 6 handles open · 3 conflicts found.",
    "domains": [
      { "tld": "com", "domain": "orbitkiln.com", "status": "available",
        "source": "https://rdap.verisign.com/com/v1/", "checkedAt": "…" },
      { "tld": "co",  "domain": "orbitkiln.co",  "status": "unknown",
        "source": "no authoritative RDAP service",
        "reason": "The .co registry publishes no RDAP service to IANA…",
        "checkedAt": "…" }
    ],
    "handles": [
      { "platform": "github", "label": "GitHub", "handle": "orbitkiln",
        "status": "available", "url": "https://github.com/orbitkiln", "checkedAt": "…" }
    ],
    "trademark": {
      "riskBand": "watch",
      "collisions": [
        { "name": "Orbit Kiln Ceramics", "owner": null,
          "url": "https://…", "similarity": "close", "note": "…" }
      ],
      "checked": ["web evidence"],
      "notChecked": ["USPTO register", "EUIPO register"],
      "sourcesSearched": 8,
      "disclaimer": "…"
    },
    "summary": {
      "bestDomains": ["orbitkiln.com", "orbitkiln.io"],
      "conflicts": 3, "domainsAvailable": 5,
      "handlesAvailable": 5, "unresolved": 1
    },
    "thin": false,
    "credits_spent": 5
  }
}

Every status is one of available, taken or unknown. There is no fourth, softer state — if we could not find out, the row says so and carries the reason.

Domains & RDAP

Domain answers come from the registries themselves over RDAP, the successor to WHOIS. The TLD's endpoint is resolved through the IANA bootstrap at data.iana.org/rdap/dns.json, then queried directly. A registry record means taken; no record means available; anything else is unknown.

A 200 is only trusted when the body is an actual RDAP domain object. That guard exists because a wrong base URL will happily 404 everything, or 200 everything, and either one produces a confident wrong answer for an entire TLD.

TLDWhy it cannot be answered
.coThe .co registry publishes no RDAP service to IANA, and the endpoints that answer are not authoritative — one 404s for registered names, the other returns a help page for every label. We will not guess.

Handles

Six platforms are supported, and the list is exactly the set that was verified to return a different status for a taken handle and a free one. The handle we probe is your name run through that platform's own rules; both the handle and a public URL come back so you can check it yourself.

PlatformWhat a hit meansHandle rule
githubuser or organisationGitHub handles are up to 39 characters of letters, digits and hyphens.
xhandleX handles are at most 15 characters and allow only letters, digits and underscores.
youtubechannel handleYouTube handles are 3–30 characters of letters, digits, dots, dashes and underscores.
npmpackagenpm package names are lowercase letters, digits and hyphens.
pypipackagePyPI project names are letters, digits, hyphens, dots and underscores.
cratescrateCrate names are letters, digits, hyphens and underscores.

These are not supported, and asking for one is a 400:

PlatformMeasured behaviour
InstagramReturns 200 for handles that are free, so a hit means nothing.
TikTokReturns 200 for handles that are free, so a hit means nothing.
TwitchReturns 200 for handles that are free, so a hit means nothing.
RedditReturns 403 to server-side callers regardless of the handle.
Product HuntReturns 403 to server-side callers regardless of the handle.
LinkedInBlocks server-side requests, so availability cannot be observed.

Trademark signal

This is a collision signal, not a trademark clearance. It reads public web evidence and never queries the USPTO register or EUIPO register. A low risk band does not mean the name is free to use.

Two brand-shaped searches pull public pages. A model extracts the brands visible in them, and every citation is checked against the pages actually fetched — a URL that was not in that set is dropped, never repaired. The band is then a pure function of what survived, so you can re-derive it from the collisions in the response.

BandMeaning
ClearNo brand collisions surfaced in the public web evidence we read. That is a signal, not a clearance — the registers were not searched.
WatchAt least one existing brand uses this name or something very near it. Read the evidence before you commit.
CrowdedSeveral brands already use this name or a close variant. Expect a fight over it, in the register and in search results.
UnknownNot enough public evidence surfaced to say anything useful. Treat this as unanswered, not as a green light.

Thin results & refunds

A check is thin only when every single probe returned unknown — no registry answered, no platform answered, and the trademark scan read nothing. That taught you nothing, so it refunds in full and credits_spent is 0.

A name that is simply taken everywhere is not thin. It is the most valuable answer this API gives — it stops you building three months on a name you can never own — and it bills normally.

Reading past checks

Free forever, on any rail.

GET /api/checks?limit=20&risk_band=watch
GET /api/checks/<id>

MCP

Endpoint  https://namecheck.ounie.com/api/mcp   (legacy SSE: /api/sse)
Auth      Authorization: Bearer nmc_live_…
          …or https://namecheck.ounie.com/api/mcp?api_key=nmc_live_…
ToolCostWhat it does
check_name5 crRun one name across domains, handles and the trademark signal.
get_name_checkfreeRe-read a check by id, with every row and collision.
list_name_checksfreeThe caller's history, newest first, filterable by risk band.
get_supported_targetsfree · publicExactly what can and cannot be resolved, with the measured reason for each refusal. Read this before interpreting a result.
get_credit_balancefreeThe account's spendable Ounie credits.
get_pricingfree · publicCredit price and the x402 endpoint.
whoamifreeThe authenticated key's owner metadata.

get_supported_targets is public and exists for a reason: an agent that does not know a platform is unsupported will read the absent row as available.

x402 — keyless, pay per call

Agents with no Ounie account pay in USDC on Base. Two gates protect the payer, and the order is deliberate.

  • Before quoting. Anything wrong with the request itself — a malformed name, a junk TLD, an unsupported platform — returns a 4xx with no price in the body. You are never asked to sign a payment for work that cannot succeed.
  • Before settling. The signature is verified off-chain, the check runs, and only then does the money move. A check where nothing resolved returns 402 thin_result and is never settled — an on-chain settlement is final, so the refusal has to come first.
curl -X POST https://namecheck.ounie.com/api/x402/namecheck \
  -H "Content-Type: application/json" \
  -d '{"name":"orbitkiln"}'
# → 402 { "x402Version": 1, "accepts": [{
#     "scheme": "exact", "network": "base",
#     "maxAmountRequired": "60000",
#     "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
#     "payTo": "0x…",
#     "extra": { "name": "USD Coin", "version": "2" } }] }

curl -X POST https://namecheck.ounie.com/api/x402/namecheck \
  -H "X-Payment: <base64 signed payload>" \
  -H "Content-Type: application/json" \
  -d '{"name":"orbitkiln"}'

$0.060 per check. The exact scheme is an offline EIP-3009 authorization — the facilitator pays the gas, so a wallet holding only USDC can pay.

Errors

StatusBodyMeaning
400name_required · name_invalid · tld_invalid · platform_unsupported · too_many_tldsSomething about the request is always fatal. Fix it and retry.
401unauthorizedNo usable credential. Bearer routes never redirect.
402insufficient_creditsCarries required_credits, balance_credits and buy_credits_url.
402thin_result (x402 only)Nothing resolved. Your payment was not settled.
429too_many_runningMore than 5 checks in flight for one owner.
502check_failedAn upstream broke. You were not charged.
503service_unavailableChecking is not configured on this deployment.

Limits

LimitValue
Name length63 characters
TLDs per check12
Concurrent checks per owner5
Active API keys per owner5
Price5 credits · $0.060 on x402

Credits are shared across every Ounie app and bought at ounie.com/dashboard/settings.