Skip to main content

Resolve API & SDK

Look up who owns a handle. Resolution is read-only and public — no wallet, no signature, and no API key. The REST base URL is https://api.x1id.io; there is no /v1 prefix. The REST endpoint returns the handle’s owner; for per-chain addresses (X1 / SOL / ETH / BTC), records, and on-chain writes, use the @x1id/resolve SDK below.
Handles, not domains. X1ID handles (@jack) and X1NS domains (jack.x1) are complementary — this API resolves handles. See how they fit together.
The @handle registry is deployed on X1 testnet today. Resolutions reflect testnet state until the mainnet cutover, which is a separate, deliberate step — see Trust & transparency.

Resolve a handle

Look up the owner of a handle.
string
required
The handle to resolve, with or without the leading @. Case-insensitive — x1 and @X1 resolve the same record. Given as a path segment: /resolve/x1.

Response

Returns the resolution object for the handle. It reports the current owner and whether the handle is tokenized — it does not carry an addresses map or an expiry (names are permanent, so there is nothing to expire). An unregistered handle returns 404 { "error": "handle not registered" }.
string
The raw value you passed.
string
The normalized handle (no @).
string
Always handle for this endpoint.
string
The wallet that owns the handle. For a tokenized handle this is informational — authority follows the NFT holder.
boolean
Whether the handle has been turned into an NFT.
string
owner when the owner controls the registry account.
Ownership you can audit. Every handle is a record on the X1 registry program (8JgnNWi24bq9uzfnT9XmkWxvaWMVgoEs9bu8QsHhLe1P), so a resolution can be verified independently on-chain. See Trust & transparency.

Reverse lookup

Go the other way — an address back to its @handle. Only the address the owner has explicitly marked as their primary reverse-resolves, which is what prevents impersonation. An address with no primary returns 404 { "error": "no primary set" }.
string
required
A base58 wallet address to reverse-resolve to its primary handle.
When the address has a primary handle, the response carries that handle instead. A primary is only returned when it is still trustworthy — the pointer and the handle it names both exist, the pointer was set after the handle’s current registration, and the address still holds authority over the name.

Health

A liveness check for the service.

SDK: multi-chain, records, and writes

The REST endpoint answers “who owns this handle.” For per-chain addresses, records, and on-chain writes, use the @x1id/resolve SDK (0.3.0). It reads chain state directly over RPC — it never depends on this API’s uptime — and its writes are unsigned instruction builders you sign and relay yourself; the SDK never holds keys. The @handle registry is on X1 testnet today (https://rpc.testnet.x1.xyz).
Address derivation runs in a small Rust→WASM module, so createResolver needs the WASM bytes. The package ships them at @x1id/resolve/wasm/x1_resolve_wasm.wasm — load them once and reuse the resolver. Full loading recipes (Node and browser) are in the SDK README.

Read: resolve across chains

resolve(input, { chain }) returns a Resolved object. X1/SOL come from the handle’s authority; ETH/BTC from its on-chain records. A handle with no record for the requested chain is explicit (no-record-for-chain), never a wrong address on the wrong chain.
Show the namespace before you send. @jack and jack.x1 can resolve to different owners, so every result carries its namespace. Render it — @jack or jack.x1 — in the recipient field before a transfer is committed. @jack.x1 (both shapes at once) throws ResolveError { code: 'ambiguous' } rather than guessing.

Read: reverse and records

Records are judged against a universal staleness rule: a record whose updatedAt predates the handle’s current registration was left behind by a previous owner of the same name, so it is flagged stale and its stored verified is forced to false. Use the exported liveRecords(recs) to keep only the ones that belong to the current owner.

Write: sign and relay yourself

Registration and set_primary run from app.x1id.io today. The SDK ships builders for the rest of the registry — each returns an unsigned { programId, keys, data } you assemble, sign, and send:
Also shipped, same build → sign → relay shape:
Which RPC? Point the resolver at the chain that holds the names you want. @handle resolution is on X1 testnet today; on an RPC where the registry is not deployed a handle is an honest not-found, never a fabricated address. The full builder list, PDA seeds, and error codes are in the SDK README.