documentation
The .fomo resolver API
Turn a .fomo domain into the Robinhood Chain address behind it with a single HTTP request. Every read endpoint is public, CORS-open, cacheable, and requires no authentication.
quickstart
$ curl https://fomodomains.com/api/resolve/alice.fomoA registered domain returns 200 with the resolution payload. An unregistered one returns 404. That is the whole integration surface for most applications.
Endpoints
GET /api/resolve/{domain}
Resolve a domain
Returns the address a domain points at, plus its owner. With or without the TLD: alice and alice.fomo are equivalent. Addresses are lowercase 0x hex. Cache headers included. 404 when unregistered.
{
"name": "alice.fomo",
"tld": "fomo",
"owner": "0x8f2a…c41d",
"target": "0x93b7…7e02",
"records": {},
"registeredAt": "2026-08-16T11:02:44.180Z"
}GET /api/check?name={name}
Check availability
Validates the name and reports availability. Always 200; read the available flag. A free result is a snapshot, not a hold — the database decides the winner at reservation time.
{
"available": true,
"normalized": "alice",
"tld": "fomo",
"priceEth": "0.01",
"priceWei": "10000000000000000"
}GET /api/domains?limit=50&offset=0&q=
List the registry
Every confirmed domain, newest first. limit caps at 100; q is a case-insensitive substring filter.
{
"tld": "fomo",
"total": 128,
"limit": 50,
"offset": 0,
"domains": [ { "name": "alice", "fqdn": "alice.fomo", … } ]
}GET /api/wallet/{address}
Domains by wallet
Reverse lookup: everything a 0x address owns, newest first. Case-insensitive. Lists by owner, not target. Served no-store.
{
"owner": "0x8f2a…c41d",
"tld": "fomo",
"count": 2,
"names": [ { "name": "alice", "fqdn": "alice.fomo", … } ]
}POST /api/register/reserve
Reserve a name
Body: { name, wallet }. Requires a wallet session (Sign in with Ethereum via the site) matching wallet. Inserts a pending row with a fresh reservation reference and a ten-minute expiry. A unique index decides races: the loser gets 409 NAME_UNAVAILABLE. Send memo as the transaction's calldata (UTF-8 hex) and wei as its value.
{
"reservationId": "…",
"memo": "fomo:reg:alice:1a2b3c4d",
"treasury": "0xf09e…5ae8",
"wei": "10000000000000000",
"expiresAt": "…"
}POST /api/register/confirm
Confirm payment
Body: { reservationId, txHash }. The server fetches the transaction itself and verifies: the receipt succeeded, the recipient is the treasury, the value covers the price, the calldata is exactly the reservation reference, and the sender is the reserving wallet. 425 TX_NOT_FOUND is retryable while the transaction is still pending.
{
"ok": true,
"fqdn": "alice.fomo",
"owner": "0x8f2a…c41d",
"txHash": "0x7d3e…",
"registeredAt": "…"
}Domain rules
- Character set — a-z, 0-9 and hyphens. The ASCII check runs on the raw input before lowercasing, so Unicode lookalikes are refused outright.
- Length — 3 to 63 characters, excluding the TLD.
- Hyphens — no leading, trailing, or consecutive hyphens.
- Reserved — admin, www, api, support, help, mail, root, system, official, and fomo itself.
Error codes
Non-2xx responses carry a stable error.code plus a human-readable message. Branch on the code.
| INVALID_NAME | 400 | The domain failed validation. |
| INVALID_WALLET | 400 | Not a valid 0x address. |
| INVALID_BODY | 400 | The request body is not the expected JSON object. |
| UNAUTHORIZED | 401 | No wallet session, or it does not match the wallet in the body. |
| NOT_FOUND | 404 | The domain is not registered. |
| NAME_UNAVAILABLE | 409 | Taken, or held by a live reservation. |
| NO_RESERVATION | 404 | The reservation id does not exist. |
| RESERVATION_EXPIRED | 409 | The reservation window closed. |
| TX_NOT_FOUND | 425 | Not mined yet. Retryable. |
| TX_FAILED | 400 | The transaction landed but reverted. |
| WRONG_RECIPIENT | 400 | The payment did not go to the treasury. |
| UNDERPAID | 400 | The value sent was below the registration price. |
| MEMO_MISMATCH | 400 | Calldata is not this reservation's reference. |
| PAYER_MISMATCH | 400 | A different wallet sent the payment. |
| TX_ALREADY_USED | 409 | Transaction already credited to a domain. |
| RATE_LIMITED | 429 | Too many requests from this client. Retry after the delay in the message. |
| NOT_CONFIGURED | 503 | Deployment is missing its credentials. |
| RPC_ERROR | 502 | The chain RPC could not be reached. Retryable. |
| DB_ERROR | 500 | The registry database could not be reached. |
Notes: write endpoints are rate limited per IP and per wallet. Record updates and transfers are not exposed yet. Registration is reserve → pay → confirm as documented above.