Reverse Resolution
Resolve an address into its ENS reverse record on a given chain. Given 0xd8dA6BF…, returns vitalik.eth so you can show a name instead of a hex string. For the opposite direction (name → address and records), see Forward Resolution.
Endpoint
GET /ens/v2/reverseBase URL: https://api.justaname.id
Quick start
The endpoint is free when you supply your own RPC URL via the rpcUrl query parameter. No API key required. Rate-limited to 30 requests per 60 seconds per IP.
curl "https://api.justaname.id/ens/v2/reverse?address=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&coinType=60&rpcUrl=https://eth.drpc.org"const url = new URL('https://api.justaname.id/ens/v2/reverse');
url.searchParams.append('address', '0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045');
url.searchParams.set('coinType', '60');
url.searchParams.set('rpcUrl', process.env.RPC_URL!);
const res = await fetch(url);To get the full profile in the same call, add records=true. The response then includes every record set on the resolved name (text records, addresses, contenthash) alongside it:
curl "https://api.justaname.id/ens/v2/reverse?address=0xd8da6bf26964af9d7eed9e03e53415d37aa96045&coinType=60&records=true&rpcUrl=https://eth.drpc.org"The caller's RPC pays for the on-chain reads. JustaName performs the reverse lookup through the ENS Universal Resolver and falls back to its off-chain reverse-record store when no on-chain reverse record is set.
Autonomous clients without an RPC URL (AI agents, MCP servers, scripts) can pay per-request in USDC on Base instead of supplying
rpcUrl. See Programmatic access without an RPC URL.
Parameters
address
string (repeatable)
Yes
Address to reverse-resolve. Repeat to batch up to 50 addresses (?address=0x…&address=0x…). Plain (0x…) or interop-formatted — see Interop addresses.
coinType
number
Conditional
ENSIP-19 coinType — see coinType reference. Required for plain addresses; optional when every address in the batch carries an interop suffix.
rpcUrl
string
See below
HTTPS RPC URL used to perform the on-chain resolution.
records
boolean
No
Default false. When true, fetches all records set on each resolved name (text records, addresses, contenthash) and returns them in the response. Applies to every address in a batch. Skipped for addresses with no reverse record (name: null).
Either rpcUrl must be present or the request must carry a valid payment header. Without either, the endpoint returns 402 with a payment challenge — see Programmatic access without an RPC URL.
Interop addresses
By default, the request-level coinType applies to every address in the batch. To override per-slot — for example, when batching addresses across different chains — append a chain suffix to the address:
0xd8dA…6045 (with coinType=60)
Reverse on Ethereum
0xd8dA…6045@ethereum
Reverse on Ethereum (overrides coinType)
0xd8dA…6045@eip155:1
Reverse on Ethereum (overrides coinType)
0xbbb…@eip155:8453
Reverse on Base
Both the human-readable chain name and the CAIP-2 form (eip155:<chainId>) are accepted. The suffix is per-address, so a batch can mix suffixed and request-level-scoped slots:
When every address in the batch carries a suffix, the request-level coinType becomes optional.
RPC URL requirements
Same as Forward Resolution: HTTPS only, no private/loopback/link-local hosts, no embedded credentials.
coinType reference
ENSIP-19 coinTypes follow the formula 0x80000000 | chainId for EVM L2 primaries. Ethereum mainnet is the exception (60).
Ethereum mainnet
60
0x3c
Optimism
2147483658
0x8000000a
Base
2147492837
0x80002105
Arbitrum One
2147525809
0x8000a4b1
ENSIP-19 default (step-2 fallback)
2147483648
0x80000000
Response
Returns a single object when one address is requested, or an array of slot-level objects (with per-slot error) when multiple are requested.
Single address
Batch
Behavior
For each address, a 3-step fallback chain is walked. The first hit wins:
On-chain reverse lookup with the supplied
coinType(or the coinType derived from the interop suffix).On-chain reverse lookup with the ENSIP-19 default coinType (
0x80000000) — covers L2 names with a chain-agnostic reverse record.JustaName off-chain reverse-record store.
Other notes:
viaUniversalResolver: true→ resolved on-chain (step 1 or 2).viaUniversalResolver: false→ resolved from the JustaName off-chain store (step 3).name: nullis a normal outcome (most addresses do not have a reverse record set), not a failure.In batch mode, slot failures are localized: the slot returns
name: nullwith a populatederror, and the rest of the batch succeeds.For batch slots that fail preflight (malformed interop suffix, unsupported chain label, missing
coinTypefor a plain address),coinTypeisnull.
Labelling a multi-chain list
Errors
400
rpcUrl not HTTPS, has embedded credentials, or resolves to a private/loopback host.
400
address malformed (not 0x[40-hex] optionally followed by @<chain>).
400
address array empty or > 50 entries.
400
Single-address request with a plain address and no coinType.
400
Unknown chain label in the interop suffix.
429
Rate limit (30 req / 60 s per IP) exceeded. Body includes retryAfterSeconds.
502 / 504
RPC provider error or CCIP-Read gateway timeout.
Payment-related statuses (402, 503) are documented in the paid path section.
Programmatic access without an RPC URL
For clients that don't manage their own RPC infrastructure — AI agents, MCP servers, autonomous scripts — the endpoint accepts per-request payment in place of rpcUrl. The service performs the on-chain reads and charges the caller in USDC on Base.
Two protocols are accepted on the same route. Clients pick whichever fits their stack:
x402 v2 — Coinbase's HTTP-payment protocol. See x402.org.
MPP-charge — IETF Internet-Draft
draft-httpauth-payment-00with EVM methoddraft-evm-charge-00. Co-authored by Tempo Labs and Stripe.
Both protocols settle identically — a signed EIP-3009 transferWithAuthorization submitted by a facilitator on Base. They differ only in HTTP envelope.
Chain
Base mainnet (eip155:8453)
Asset
USDC (0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913)
Price
1000 base units per request (0.001 USDC at 6 decimals)
402 challenge
A request without rpcUrl and without a payment header receives both challenges in one response. The headers are disjoint, so they coexist:
Decoded PAYMENT-REQUIRED (x402 v2):
Decoded WWW-Authenticate request= (MPP draft-evm-charge-00):
Paying
Sign an EIP-3009 transferWithAuthorization against the USDC contract on Base (e.g. viem's signTypedData with primaryType: "TransferWithAuthorization" and a fresh 32-byte nonce). Wrap the signed message in either envelope and retry the request:
x402 v2
PAYMENT-SIGNATURE: <base64 JSON>
PAYMENT-RESPONSE: <base64 JSON>
MPP-charge
Authorization: Payment <base64url-nopad JSON>
Payment-Receipt: <base64url-nopad JSON>
The facilitator submits the on-chain tx and pays gas — the payer only needs USDC, not ETH.
Idempotency, replay, validity
Set
Idempotency-Key: <uuid>on every retry. Without it, each retry is a fresh payment.(nonce, recipient)is locked in a 5-minute LRU. Always sign with a fresh randomnonce.validBeforeshould be ~10 min fromnow(). Longer windows risk re-sending stale signatures past expiry.A retriable failure (facilitator transient error) returns
503+Retry-After. Repeat the same request.A non-retriable failure (malformed payload, replay, network/asset mismatch) returns a fresh
402with the reason in the challenge.
Discovery
GET /ens/v2/pricing(free) — JSON list of paid routes:{ path, method, schemes, amount, asset, network, recipient }.GET /.well-known/x402.json(free) — x402 manifest (services[]+accepts[]) for catalog crawlers (Bazaar, x402scan).GET /openapi.json— OpenAPI document. Each paid operation carriesx-payment-info: { offers: [{ amount, currency, description, intent, method }] }perdraft-payment-discovery-00.
Payment-path errors
402
Request lacks rpcUrl and no payment header was supplied. PAYMENT-REQUIRED and WWW-Authenticate carry the challenge.
402
Payment proof was malformed, replayed, expired, or targeted the wrong network/asset.
503
Facilitator transient error during verify/settle. Retry-After set; repeat the same request.
Last updated