Forward Resolution

Resolve an ENS name into its address(es) and records. Given vitalik.eth, returns the address behind it, the avatar, the Twitter handle, and any other record. For the opposite direction (address → name), see Reverse Resolution

Endpoint

GET /ens/v2/resolve

Base 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/resolve?ens=vitalik.eth&rpcUrl=https://eth.drpc.org"
const url = new URL('https://api.justaname.id/ens/v2/resolve');
url.searchParams.append('ens', 'vitalik.eth');
url.searchParams.append('rpcUrl', process.env.RPC_URL!);

const res = await fetch(url);

The caller's RPC pays for the on-chain reads. JustaName performs resolution through the ENS Universal Resolver with CCIP-Read support and returns the decoded records.

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

Parameter
Type
Required
Description

ens

string (repeatable)

Yes

ENS name to resolve. Repeat to batch up to 50 names (?ens=a.eth&ens=b.eth). Append @<chain> to scope to a single chain — see Interop addresses

rpcUrl

string

See below

HTTPS RPC URL used to perform the on-chain resolution.

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, resolution returns every address attached to the name across every chain in records.addresses. To scope the result to a single chain, append a chain suffix to the name:

Format
Effect

vitalik.eth

Returns all addresses on all chains

vitalik.eth@ethereum

Returns only the Ethereum address

vitalik.eth@eip155:1

Returns only the Ethereum address

Both the human-readable chain name and the CAIP-2 form (eip155:<chainId>) are accepted. The suffix is per-name, so a batch can mix scoped and unscoped lookups:

When a suffix is present, records.addresses contains at most one entry — the address for the requested chain, or an empty array if the name has no record for that chain.

RPC URL requirements

  • Must be HTTPS.

  • Private, loopback, and link-local hosts are rejected.

  • Embedded credentials (https://user:pass@host) are rejected.

Response

Returns a single object when one ens is requested, or an array (in input order, null for hard-failed slots) when multiple are requested.

Single name

Batch

Behavior

  • Resolution is performed through the on-chain ENS Universal Resolver with CCIP-Read support.

  • The caller supplies the RPC URL — the service does not pay for the on-chain reads.

  • Batch failures are localized: a hard-failed slot becomes null while the rest succeed.

  • Unregistered names do not return null. Wildcard resolvers return an object with records.addresses: [].

  • Duplicate names in a batch are not deduplicated — each slot is resolved independently.

  • viaUniversalResolver: true confirms the ENSv2-ready resolver path was used.

Reading records

Pull the L1 wallet, avatar, and a social handle from a batch result:

Errors

Status
When

400

rpcUrl not HTTPS, has embedded credentials, or resolves to a private/loopback host.

400

ens array empty or > 50 entries.

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:

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:

Scheme
Request header
Receipt header (on 200)

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 random nonce.

  • validBefore should be ~10 min from now(). 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 402 with 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 carries x-payment-info: { offers: [{ amount, currency, description, intent, method }] } per draft-payment-discovery-00.

Payment-path errors

Status
When

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