API Reference

Public HTTP routes exposed by agtnames.com. They power the site's search, directory, migration and registration flows, and you can call them directly with any HTTP client. For programmatic resolution of a name, prefer the Resolver SDK or the MCP server: they read the registry directly and need no intermediary.

Lookups

GET /api/search Live

Rate limit: 30 per minute

Check one name: is it available, reserved for an existing holder to migrate, or taken — and what it costs. name is a label, with or without .agt.

requestsh
curl "https://agtnames.com/api/search?name=launchpad"
response — a registered namejson
{
  "success": true, "name": "launchpad", "fullDomain": "launchpad.agt", "registry": "v2",
  "tier": "standard", "registrationOpen": false,
  "status": "unavailable", "available": false, "reserved": false,
  "price": null, "registerUsd": 10, "renewUsd": 10, "priceNote": "per year"
}
response — an available namejson
{
  "success": true, "name": "zzqv-test-9931", "fullDomain": "zzqv-test-9931.agt", "registry": "v2",
  "tier": "standard", "registrationOpen": false,
  "status": "available", "available": true, "reserved": false,
  "price": { "currency": "USD", "amount": 10 }, "registerUsd": 10, "renewUsd": 10, "priceNote": "per year"
}

status is one of available, reserved (held for its existing holder to migrate), unavailable or protected. registrationOpen is false until the sales cutover. price is the year-one price; names are annual, so renewUsd is what each further year costs and priceNote is the wording shown beside the price (per year when the two match, otherwise first year, then $N/yr). Migrated names are perpetual and never renew. Errors: 400 for a missing or invalid label (1–63 characters of a-z 0-9 -), 429 when rate limited.

GET /api/agents Live

Rate limit: 20 per minute

The agent directory: every active name the indexer knows, with the endpoint records it has on chain. Filters: protocol (mcp, a2a, http, ws) and q (text match on name and description).

requestsh
curl "https://agtnames.com/api/agents?protocol=mcp"
response (unfiltered, today)json
{
  "success": true, "count": 1,
  "agents": [{
    "domain": "launchpad.agt", "version": 2,
    "name": null, "description": null, "icon": null, "website": null,
    "protocols": [], "capabilities": [], "endpoints": [], "pricing": null,
    "owner": "0x37007a1c233f00b423bc0d177ac5b50ca9417596", "manifestUri": null, "perpetual": true
  }]
}

GET /api/badge/<label>.svg Live

Rate limit: 60 per minute

The on-chain identity badge for any valid label as SVG — the same art a mint embeds, so it renders for names that are not registered yet. Cached immutably; safe to hot-link.

requestsh
curl -o launchpad.svg "https://agtnames.com/api/badge/launchpad.svg"
# content-type: image/svg+xml; cache-control: public, max-age=31536000, immutable
embedhtml
<img src="https://agtnames.com/api/badge/launchpad.svg" alt="launchpad.agt identity badge" width="256" height="256" />

400 for an invalid label; 503 if the on-chain renderer cannot be read (not cached).

GET /api/health Live

requestsh
curl https://agtnames.com/api/health
responsejson
{ "ok": true, "service": "agt-site", "registryMode": "claims-only", "durableStorage": true, "time": "2026-09-13T00:22:47.994Z" }

registryMode is claims-only while migration is open and new-name sales are closed; it becomes v2 at the sales cutover.

Holders

GET /api/v2/names Live

Rate limit: 60 per minute

Every Registry v2 name a wallet owns, from the index (it trails the chain by up to ten minutes). Backs My agts.

requestsh
curl "https://agtnames.com/api/v2/names?owner=0x37007a1c233f00b423bc0d177ac5b50ca9417596"
responsejson
{
  "owner": "0x37007a1c233f00b423bc0d177ac5b50ca9417596", "count": 1,
  "names": [{
    "label": "launchpad",
    "tokenId": "74213674913414793103689332001647165694612910724881941644579943946836492950816",
    "owner": "0x37007a1c233f00b423bc0d177ac5b50ca9417596",
    "expiry": "perpetual", "perpetual": true, "version": 0,
    "resolver": "0x66ae037d2a6a770b4772b889b6ca1704504399f2", "reserved": false,
    "registeredBlock": 93654053, "updatedBlock": 93654053, "manifest": null
  }]
}

expiry is "perpetual" or unix seconds as a string. 400 for a malformed address; 503 if the index is unavailable. Response is CDN-cached for 60 s.

GET /api/v2/allowlist Live

Rate limit: 30 per minute

The migration allowlist. With address alone: every entry for that wallet (label + Merkle proof). With label and address: the single proof the proof-migration path submits on chain.

requestsh
curl "https://agtnames.com/api/v2/allowlist?address=0x37007a1c233f00b423bc0d177ac5b50ca9417596"
response (truncated)json
{
  "root": "0x023d33575f28762f0b36a479f49df30c3cfe8c71009e5644288bcdd1b062b9d3",
  "claimant": "0x37007a1c233f00b423bc0d177ac5b50ca9417596",
  "entries": [
    { "label": "123456789", "proof": ["0x956c7eaf…2616", "0x714ca5c8…5c5e", "…"] },
    …
  ]
}

404 when the wallet (or pair) is not on the list; 503 until an allowlist is published.

POST /api/v2/zone-claim/challenge Live

Rate limit: 20 per minute

Migration path 3, for names that exist as zones but were never minted: start a zone-owner challenge and get the TXT record to add. Stateless — the code is derived from the label and wallet and is valid for three days.

requestsh
curl -X POST https://agtnames.com/api/v2/zone-claim/challenge \
  -H "content-type: application/json" \
  -d '{"label":"exampleagent","wallet":"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"}'
responsejson
{
  "label": "exampleagent.agt",
  "wallet": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
  "code": "9319cad50d4b6de6",
  "record": { "type": "TXT", "name": "@", "value": "agt-claim=9319cad50d4b6de6" },
  "validForDays": 3,
  "instructions": [ "…add the TXT record…", "…then verify…", "…then migrate on /migrate with this wallet." ]
}

POST /api/v2/zone-claim/verify Live

Rate limit: 10 per minute

Check the TXT record. On success the label and wallet are queued for the next allowlist publication.

requestsh
curl -X POST https://agtnames.com/api/v2/zone-claim/verify \
  -H "content-type: application/json" \
  -d '{"label":"exampleagent","wallet":"0x70997970C51812dc3A010C7d01b50e0d17dc79C8"}'
responsesjson
200 { "verified": true, "method": "zone-txt", "next": "…" }
404 { "error": "zone does not exist" }
409 { "verified": false, "error": "TXT record not found or does not match", "txtSeen": ["…"] }
503 { "error": "resolver unreachable, try again" }

GET /api/v2/zone-claim/mine Live

Rate limit: 30 per minute

requestsh
curl "https://agtnames.com/api/v2/zone-claim/mine?wallet=0x37007a1c233f00b423bc0d177ac5b50ca9417596"
responsejson
{ "wallet": "0x37007a1c233f00b423bc0d177ac5b50ca9417596", "claims": [] }
// each claim: { "label", "method": "zone-txt" | "minted-owner", "verifiedAt", "published": boolean }

POST /api/notify Live

Rate limit: 5 per minute

Register interest in a name while registration is closed. Idempotent per email and label; the email is never returned by any route.

requestsh
curl -X POST https://agtnames.com/api/notify \
  -H "content-type: application/json" \
  -d '{"email":"you@example.com","label":"exampleagent"}'
responsejson
{ "success": true, "created": true }   // "created": false on a repeat

Manifest

POST /api/v2/manifest/pin Live

Rate limit: 10 per minute

Pin a signed v3 manifest whose signer is the name's current on-chain owner. The server never signs; it only refuses documents that would fail verification. The response uri is what the owner then writes to the resolver with setAgentManifest (the /manifest editor does this in one transaction).

requestsh
curl -X POST https://agtnames.com/api/v2/manifest/pin \
  -H "content-type: application/json" \
  -d @signed-manifest.json          # { "manifest": { "agt": "3.0", "name": "you.agt", "owner": "0x…", …, "signature": "0x…" } }
responsesjson
200 { "uri": "ipfs://bafkrei…", "cid": "bafkrei…", "provider": "pinata", "label": "you", "owner": "0x…" }
400 { "error": "Expected a signed Manifest v3 with agt=3.0 and name=<label>.agt" }
409 { "error": "Manifest does not verify against the on-chain owner", "reasons": ["signer 0x… != owner 0x…"] }
413 { "error": "manifest exceeds 65536 bytes" }
502 { "error": "Pinning failed; try again shortly" }

Registration

POST /api/checkout Closed until Stage 4

Rate limit: 5 per minute

Card checkout for a new name (Stripe Checkout with server-side price verification). Body when open: { domain, walletAddress, email?, termsAccepted, years }{ success, url }.

response todayjson
503 { "success": false, "error": "Registration opens soon. Leave your email on the register page and we will tell you when it does.", "registrationOpen": false }

POST /api/v2/quote Closed until Stage 4

Rate limit: 20 per minute

An EIP-712 registration or renewal quote for the on-chain checkout path. Body when open: { label, to, years = 1, payToken: "usdc" | "native", renew? } → the signed quote, signature and the controller method to call (register(Quote,bytes) or renew(Quote,bytes)).

response todayjson
404 { "error": "Registry v2 checkout is not enabled" }

GET /api/checkout/status Live

Poll fulfillment after a card payment. Param: session_id. Returns fulfillment_status, domain, walletAddress, txHash, mint_after.

GET /api/claim/status Legacy name

Mint status for a name on the registry. The route keeps its original name; in current vocabulary this reports a registration or migration mint.

requestsh
curl "https://agtnames.com/api/claim/status?domain=launchpad.agt"
responsejson
{
  "success": true, "status": "COMPLETE", "transactionHash": null,
  "tokenId": "74213674913414793103689332001647165694612910724881941644579943946836492950816",
  "contract": "0x5B9386C47395B0551c814cC03b69cbD20eb0C87A", "registry": "v2",
  "owner": "0x37007A1C233F00b423BC0d177AC5B50CA9417596"
}

status is COMPLETE, PENDING, CANCELLED, FAILED or UNKNOWN.

Not public

/api/admin/* requires Authorization: Bearer <ADMIN_API_KEY>; /api/cron/* is called by the scheduler with a shared secret; /api/webhooks/stripe accepts Stripe-signed events only. None of them are part of the public surface.

See also

  • Quick start — the same lookups from the SDK, CLI, an MCP client or raw JSON-RPC.
  • Records & Resolution — the on-chain data these routes read.
  • Migrating to v2 — how the allowlist and zone-claim routes fit the three migration paths.