.fomo

documentation

The .fomo resolver API

Turn a .fomo domain into the Solana address behind it with a single HTTP request. Every read endpoint is public, CORS-open, cacheable, and requires no authentication.

quickstart

$ curl https://fomosns.wtf/api/resolve/alice.fomo

A 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. Not rate limited; cache headers included. 404 when unregistered.

{
  "name": "alice.fomo",
  "tld": "fomo",
  "owner": "7xKX…gAsU",
  "target": "9WzD…AWWM",
  "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",
  "priceSol": 0.1,
  "priceLamports": 100000000
}

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 base58 address owns, newest first. Lists by owner, not target. Served no-store.

{
  "owner": "7xKX…gAsU",
  "tld": "fomo",
  "count": 2,
  "names": [ { "name": "alice", "fqdn": "alice.fomo", … } ]
}

POST /api/register/reserve

Reserve a name

Body: { name, wallet }. Inserts a pending row with a fresh memo reference and a ten-minute expiry. A unique index decides races: the loser gets 409 NAME_UNAVAILABLE.

{
  "reservationId": "…",
  "memo": "fomo:reg:alice:1a2b3c4d",
  "treasury": "F7R5…yRA2",
  "lamports": 100000000,
  "expiresAt": "…"
}

POST /api/register/confirm

Confirm payment

Body: { reservationId, signature }. The server fetches the transaction itself and verifies: it landed with no error, the treasury's settled balance delta covers the price, a memo instruction exactly equals the reservation reference, and the fee payer is the reserving wallet. 425 TX_NOT_FOUND is retryable.

{
  "ok": true,
  "fqdn": "alice.fomo",
  "owner": "7xKX…gAsU",
  "signature": "4Nd1…",
  "registeredAt": "…"
}

Domain rules

Error codes

Non-2xx responses carry a stable error.code plus a human-readable message. Branch on the code.

INVALID_NAME400The domain failed validation.
INVALID_WALLET400Not a valid base58 public key.
NOT_FOUND404The domain is not registered.
NAME_UNAVAILABLE409Taken, or held by a live reservation.
NO_RESERVATION404The reservation id does not exist.
RESERVATION_EXPIRED409The ten-minute window closed.
TX_NOT_FOUND425Not visible at confirmed commitment yet. Retryable.
TX_FAILED400The transaction landed but failed on-chain.
UNDERPAID400Treasury balance change below the required lamports.
MEMO_MISMATCH400Missing this reservation's memo reference.
PAYER_MISMATCH400A different wallet signed the payment.
SIGNATURE_ALREADY_USED409Transaction already credited to a domain.
NOT_CONFIGURED503Deployment is missing its credentials.
DB_ERROR500The registry database could not be reached.

MVP notes: per-IP rate limits, record updates and transfers are not enforced or exposed yet. Registration is reserve → pay → confirm as documented above.