{"templateId":"markdown","sharedDataIds":{"sidebar":"sidebar-web3/sidebars.yaml"},"props":{"metadata":{"markdoc":{"tagList":["admonition"]},"type":"markdown"},"seo":{"title":"Reverse Resolve Domains","description":"The developer documentation portal and API reference for Unstoppable Domains.","siteUrl":"https://docs.unstoppabledomains.com","keywords":"unstoppable domains developer portal, api reference docs","lang":"en-US","llmstxt":{"hide":false,"sections":[{"title":"Table of contents","includeFiles":["**/*"],"excludeFiles":[]}],"excludeFiles":[]}},"dynamicMarkdocComponents":[],"compilationErrors":[],"ast":{"$$mdtype":"Tag","name":"article","attributes":{},"children":[{"$$mdtype":"Tag","name":"Heading","attributes":{"level":1,"id":"reverse-resolve-domains","__idx":0},"children":["Reverse Resolve Domains"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["This page details basic configuration and usage of the ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"/web3/apis/resolution/openapi"},"children":["Resolution Service API"]}," to retrieve the reverse record(s) of UD domains."]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"project-setup","__idx":1},"children":["Project Setup"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You'll need the following to get started:"]},{"$$mdtype":"Tag","name":"ul","attributes":{},"children":[{"$$mdtype":"Tag","name":"li","attributes":{},"children":["An ",{"$$mdtype":"Tag","name":"a","attributes":{"href":"https://docs.unstoppabledomains.com/resolution/quickstart/retrieve-an-api-key/"},"children":["API key"]}]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"backend-proxy","__idx":2},"children":["Backend Proxy"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Express.js will serve as the API proxy throughout this quickstart and will handle all interactions with the Resolution Service API."]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["The Resolution Service API is not meant to be directly accessed from a frontend client and will throw ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["CORS"]}," errors if it is."]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"info"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["There is a 20 call/second/key limit on the Resolution Service API. If you need a higher rate limit, please contact partnerengineering@unstoppabledomains.com"]}]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":2,"id":"examples","__idx":3},"children":["Examples"]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"reverse-resolution-for-a-wallet-address","__idx":4},"children":["Reverse Resolution for a Wallet Address"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Resolve the reverse record of a wallet address. The code snippet below shows how to do this in Typescript and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Express.js"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"/**\n * Express route to reverse resolve a wallet address via proxy.\n * \n * Accepts query parameters:\n * - address: The address to reverse resolve\n * \n * @route GET /resolve/reverse\n * @returns {JSON} Resolved domain name or error message\n */\napp.get('/resolve/reverse', async (req: Request, res: Response) => {\n  const { address } = req.query;\n\n  if (!address || !UNSTOPPABLE_API_KEY) {\n    res.status(400).json({ error: 'Missing required parameters' });\n    return;\n  }\n\n  try {\n    const domain = await reverseResolve(\n      address as string, \n    );\n\n    domain \n      ? res.json({ address, domain })\n      : res.status(404).json({ error: 'No domain found' });\n\n  } catch (error) {\n    res.status(500).json({ error: 'Internal server error' });\n  }\n});\n\n/**\n * Resolves a domain name for a given address.\n * \n * @param {string} address - The address to reverse resolve\n * @returns {Promise<string | null>} The resolved domain or null if not found\n * \n * @throws {Error} When no domain can be resolved for the address\n */\nasync function reverseResolve(\n  address: string, \n): Promise<string | null> {\n\n  try {\n    const response = await axios.get(\n      UNSTOPPABLE_API_BASE_URL + 'reverse/' + encodeURIComponent(address), \n      {\n      headers: { 'Authorization': 'Bearer ' + UNSTOPPABLE_API_KEY }\n      }\n    );\n\n    const meta = response.data.meta;\n      \n    const domain = meta['domain'];\n\n    if (domain) return domain;\n\n    throw new Error('No domain found for ' + address);\n  } catch (error) {\n    console.error('Reverse resolution error:', error);\n    return null;\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Heading","attributes":{"level":3,"id":"reverse-resolution-for-multiple-wallet-addresses","__idx":5},"children":["Reverse Resolution for Multiple Wallet Addresses"]},{"$$mdtype":"Tag","name":"p","attributes":{},"children":["Resolve the reverse record of up to 1000 unique wallet address. The code snippet below shows how to do this in Typescript and ",{"$$mdtype":"Tag","name":"code","attributes":{},"children":["Express.js"]},"."]},{"$$mdtype":"Tag","name":"CodeBlock","attributes":{"data-language":"typescript","header":{"controls":{"copy":{}}},"source":"/**\n * Express route to reverse resolve multiple wallet addresses via proxy.\n * \n * Accepts JSON body:\n * {\n *   \"addresses\": string[] - Array of addresses to reverse resolve (up to 1000)\n * }\n * \n * @route POST /resolve/reverse/batch\n * @returns {JSON} Array of resolved domain names or error message\n */\napp.post('/resolve/reverse/query', async (req: Request, res: Response) => {\n  const { addresses } = req.body;\n\n  if (!addresses || !Array.isArray(addresses) || !UNSTOPPABLE_API_KEY) {\n    res.status(400).json({ error: 'Missing required parameters or invalid format' });\n    return;\n  }\n\n  if (addresses.length > 1000) {\n    res.status(400).json({ error: 'Maximum of 1000 addresses allowed per request' });\n    return;\n  }\n\n  try {\n    const domains = await reverseResolveBatch(\n      addresses as Array<string>, \n    );\n\n    domains \n      ? res.json({\n        total: addresses.length,\n        unique: Object.values(domains).length,\n        resolved: Object.values(domains).filter(Boolean).length,\n        addresses: domains\n      })\n      : res.status(404).json({ error: 'No domains found' });\n\n  } catch (error) {\n    res.status(500).json({ error: 'Internal server error' });\n  }\n});\n\ninterface UnstoppableMeta {\n  domain: string;\n  owner: string;\n  reverse: boolean;\n}\n\ninterface UnstoppableResponse {\n  meta: UnstoppableMeta;\n}\n\ninterface AddressMapping {\n  [address: string]: string | null;\n}\n\n/**\n * Resolves a domain name for a given address.\n * \n * @param {string} address - The address to reverse resolve\n * @returns {Promise<string | null>} The resolved domain or null if not found\n * \n * @throws {Error} When no domain can be resolved for the address\n */\nasync function reverseResolveBatch(\n  addresses: Array<string>, \n): Promise<Object | null> {\n\n  try {\n    const uniqAddresses = [...new Set(addresses.map(a => a.toLowerCase()))];\n\n    const response = await axios.post(\n      UNSTOPPABLE_API_BASE_URL + 'reverse/query', \n      { addresses: uniqAddresses },\n      {\n      headers: { 'Authorization': 'Bearer ' + UNSTOPPABLE_API_KEY }\n      }\n    );\n\n    // Create mapping of address to domain\n    const addressToDomain = uniqAddresses.reduce<AddressMapping>((acc, address) => {\n      // Find the corresponding result in the response\n      const result = response.data.data.find((item: UnstoppableResponse) => \n        item.meta.owner.toLowerCase() === address.toLowerCase()\n      );\n      \n      // Add to mapping, using null if no domain was found\n      acc[address] = result ? result.meta.domain : null;\n      return acc;\n    }, {});\n\n\n    if (addressToDomain) return addressToDomain;\n\n    throw new Error('No data found for provided wallet addresses');\n  } catch (error) {\n    console.error('Bulk Reverse resolution error:', error);\n    return null;\n  }\n}\n","lang":"typescript"},"children":[]},{"$$mdtype":"Tag","name":"Admonition","attributes":{"type":"success","name":"Congratulations"},"children":[{"$$mdtype":"Tag","name":"p","attributes":{},"children":["You have successfully integrated Reverse Resolution using Unstoppable Domains Resolution Service API. Happy Hacking!"]}]}]},"headings":[{"value":"Reverse Resolve Domains","id":"reverse-resolve-domains","depth":1},{"value":"Project Setup","id":"project-setup","depth":2},{"value":"Backend Proxy","id":"backend-proxy","depth":2},{"value":"Examples","id":"examples","depth":2},{"value":"Reverse Resolution for a Wallet Address","id":"reverse-resolution-for-a-wallet-address","depth":3},{"value":"Reverse Resolution for Multiple Wallet Addresses","id":"reverse-resolution-for-multiple-wallet-addresses","depth":3}],"frontmatter":{"title":"Resolution Service API Integration Guide | Unstoppable Domains Developer Portal","description":"This guide covers how to retrieve the reverse record of UD domains using the Resolution Service API.","seo":{"title":"Reverse Resolve Domains"}},"editPage":{"to":"https://github.com/unstoppabledomains/dev-docs/blob/main/web3/resolution/quickstart/reverse-resolution.md"},"lastModified":"2026-04-10T16:45:57.000Z","pagePropGetterError":{"message":"","name":""}},"slug":"/web3/resolution/quickstart/reverse-resolution","userData":{"isAuthenticated":false,"teams":["anonymous"]},"isPublic":true}