Test the endpoint
Start with a known name. The API normalizes case, validates the namespace, and returns the resolved address plus ownership and expiry context when available.
curl --request GET \
--url https://arcname.services/api/v1/resolve/name/alice.arc \
--header 'Accept: application/json'Expected success
{
"status": "ok",
"name": "alice.arc",
"address": "0x...",
"owner": "0x...",
"expiry": 1800000000,
"source": "subgraph"
}Add a typed client
Keep the adapter behind one function so your application has a single place for normalization, error handling, caching, and future version changes.
type ArcNSResolution =
| { status: "ok"; name: string; address: `0x${string}`; owner: string | null; expiry: number | null; source: "subgraph" | "rpc" }
| { status: "not_found"; hint: string }
| { status: "error"; code: string; hint: string };
export async function resolveArcNSName(name: string) {
const normalized = name.trim().toLowerCase();
const response = await fetch(
`https://arcname.services/api/v1/resolve/name/${encodeURIComponent(normalized)}`,
{ headers: { Accept: "application/json" } },
);
const result = (await response.json()) as ArcNSResolution;
if (!response.ok || result.status !== "ok") {
throw new Error("hint" in result ? result.hint : "ArcNS resolution failed");
}
return result;
}200 / okResolved address returned
200 / not_foundValid input, no record
400 / errorMalformed name or TLD
503 / errorUpstream temporarily unavailable
Build safe recipient UX
Resolve after the user pauses or leaves the input, then show the complete destination address before any signature request. Never replace the address with the name in the final review screen.
import { useEffect, useState } from "react";
import { resolveArcNSName } from "./arcns";
export function RecipientPreview({ name }: { name: string }) {
const [address, setAddress] = useState<string | null>(null);
const [error, setError] = useState<string | null>(null);
useEffect(() => {
let active = true;
setAddress(null);
setError(null);
resolveArcNSName(name)
.then(result => active && setAddress(result.address))
.catch(err => active && setError(err.message));
return () => { active = false; };
}, [name]);
if (error) return <p role="alert">{error}</p>;
if (!address) return <p>Resolving...</p>;
return <p>{name} → {address}</p>;
}Add reverse names
Use reverse resolution to decorate wallet addresses in activity feeds and account menus. ArcNS only returns a primary name after forward confirmation, preventing a name from claiming an unrelated address.
const address = "0x1234...";
const response = await fetch(
`https://arcname.services/api/v1/resolve/address/${address}`,
);
const result = await response.json();
// A reverse name is returned only after forward confirmation.
if (response.ok && result.status === "ok") {
console.log(result.name);
}Harden production
For backend-heavy applications, proxy and cache the public adapter so you control retries, observability, and your user-facing availability policy.
// app/api/recipient/[name]/route.ts
import { NextResponse } from "next/server";
export async function GET(_: Request, { params }: { params: { name: string } }) {
const upstream = await fetch(
`https://arcname.services/api/v1/resolve/name/${encodeURIComponent(params.name)}`,
{ next: { revalidate: 30 } },
);
const body = await upstream.json();
return NextResponse.json(body, { status: upstream.status });
}