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 key —
Authorization: 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.combrowser 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.
402 with the exact shortfall — it cannot overdraw and cannot run up a balance.POST /api/checks
| Field | Type | Meaning |
|---|---|---|
| name | string, required | The 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. |
| tlds | string[], optional | Top-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. |
| handles | string[], optional | Platforms 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. |
| trademark | boolean, optional | Defaults to true. Set false to skip the web evidence scan. |
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.
| TLD | Why it cannot be answered |
|---|---|
| .co | The .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.
| Platform | What a hit means | Handle rule |
|---|---|---|
| github | user or organisation | GitHub handles are up to 39 characters of letters, digits and hyphens. |
| x | handle | X handles are at most 15 characters and allow only letters, digits and underscores. |
| youtube | channel handle | YouTube handles are 3–30 characters of letters, digits, dots, dashes and underscores. |
| npm | package | npm package names are lowercase letters, digits and hyphens. |
| pypi | package | PyPI project names are letters, digits, hyphens, dots and underscores. |
| crates | crate | Crate names are letters, digits, hyphens and underscores. |
These are not supported, and asking for one is a 400:
| Platform | Measured behaviour |
|---|---|
| Returns 200 for handles that are free, so a hit means nothing. | |
| TikTok | Returns 200 for handles that are free, so a hit means nothing. |
| Twitch | Returns 200 for handles that are free, so a hit means nothing. |
| Returns 403 to server-side callers regardless of the handle. | |
| Product Hunt | Returns 403 to server-side callers regardless of the handle. |
| Blocks server-side requests, so availability cannot be observed. |
Trademark signal
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.
| Band | Meaning |
|---|---|
| Clear | No brand collisions surfaced in the public web evidence we read. That is a signal, not a clearance — the registers were not searched. |
| Watch | At least one existing brand uses this name or something very near it. Read the evidence before you commit. |
| Crowded | Several brands already use this name or a close variant. Expect a fight over it, in the register and in search results. |
| Unknown | Not 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.
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_…| Tool | Cost | What it does |
|---|---|---|
| check_name | 5 cr | Run one name across domains, handles and the trademark signal. |
| get_name_check | free | Re-read a check by id, with every row and collision. |
| list_name_checks | free | The caller's history, newest first, filterable by risk band. |
| get_supported_targets | free · public | Exactly what can and cannot be resolved, with the measured reason for each refusal. Read this before interpreting a result. |
| get_credit_balance | free | The account's spendable Ounie credits. |
| get_pricing | free · public | Credit price and the x402 endpoint. |
| whoami | free | The 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
4xxwith 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_resultand 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
| Status | Body | Meaning |
|---|---|---|
| 400 | name_required · name_invalid · tld_invalid · platform_unsupported · too_many_tlds | Something about the request is always fatal. Fix it and retry. |
| 401 | unauthorized | No usable credential. Bearer routes never redirect. |
| 402 | insufficient_credits | Carries required_credits, balance_credits and buy_credits_url. |
| 402 | thin_result (x402 only) | Nothing resolved. Your payment was not settled. |
| 429 | too_many_running | More than 5 checks in flight for one owner. |
| 502 | check_failed | An upstream broke. You were not charged. |
| 503 | service_unavailable | Checking is not configured on this deployment. |
Limits
| Limit | Value |
|---|---|
| Name length | 63 characters |
| TLDs per check | 12 |
| Concurrent checks per owner | 5 |
| Active API keys per owner | 5 |
| Price | 5 credits · $0.060 on x402 |
Credits are shared across every Ounie app and bought at ounie.com/dashboard/settings.