GET /api/ens/batch-resolve
Resolve multiple Ethereum addresses to ENS names and social metadata in a single request.
Use Cases
- Token deployer identity verification
- Wallet screening for compliance
- Bulk identity lookups for analytics
- Agent-to-agent identity services
Endpoint
GET https://api.web3identity.com/api/ens/batch-resolve
Query Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
addresses | string | Yes | Comma-separated Ethereum addresses (0x format). Max 100. |
include | string | No | Fields to include: name,avatar,twitter,github,discord,email,url,telegram,linkedin. Default: name,avatar,twitter,github,discord |
Performance
| Addresses | Cold Cache | Warm Cache | Cache Hit Rate |
|---|---|---|---|
| 10 | ~400ms | <10ms | 100% |
| 50 | ~760ms | <50ms | 96% |
| 100 | ~814ms | <100ms | 90% |
Cache TTL: 15 minutes
Pricing & Rate Limits
Free Tier
- 100 addresses per day (anonymous users)
- Resets daily at midnight UTC
- No API key required
- Perfect for testing and low-volume usage
Paid Tier
- $0.01 per batch (up to 100 addresses)
- Payment via x402 protocol (USDC on Base)
- No signup required - pay per request
- Automatic payment settlement via Coinbase CDP
Usage Tracking
All responses include usage metadata:
{
"metadata": {
"usage": {
"tier": "free",
"addressesUsed": 10,
"totalToday": 25,
"limit": 100,
"remaining": 75,
"resetsAt": "2026-02-16T00:00:00.000Z"
}
}
}
When you exceed the free tier, you'll receive a 402 Payment Required response with payment instructions.
Example Request
Basic (2 addresses)
curl "https://api.web3identity.com/api/ens/batch-resolve?addresses=0x4D982788c01402C4E0f657E1192d7736084AE5a8,0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045&include=name,twitter,github"
Large batch (50 addresses)
curl "https://api.web3identity.com/api/ens/batch-resolve?addresses=0x...,0x...&include=name"
Response Format
{
"addresses": [
{
"address": "0x4d982788c01402c4e0f657e1192d7736084ae5a8",
"ens": "garypalmerjr.eth",
"avatar": "eip155:1/erc721:0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d/3636",
"social": {
"twitter": "GaryPalmerJr",
"github": "GaryPalmerJr",
"discord": "garypalmerjr"
}
},
{
"address": "0xd8da6bf26964af9d7eed9e03e53415d37aa96045",
"ens": "vitalik.eth",
"avatar": "https://euc.li/vitalik.eth",
"social": {
"twitter": "VitalikButerin",
"github": "vbuterin"
}
},
{
"address": "0x0000000000000000000000000000000000000001",
"ens": null,
"social": {}
}
],
"metadata": {
"total": 3,
"resolved": 2,
"failed": 0,
"noEns": 1,
"cacheHits": 6,
"cacheMisses": 0,
"cacheHitRate": "100.0%",
"processingTimeMs": 5,
"phase": 2
}
}
Response Fields
addresses[] (array)
| Field | Type | Description |
|---|---|---|
address | string | Lowercase Ethereum address |
ens | string|null | ENS name (null if none) |
avatar | string | Avatar URL or NFT reference (CAIP-22) |
social | object | Social profiles (fields depend on include param) |
error | string | Error message if resolution failed |
reason | string | Failure reason |
metadata (object)
| Field | Type | Description |
|---|---|---|
total | integer | Total addresses requested |
resolved | integer | Addresses with ENS names |
failed | integer | Addresses with errors |
noEns | integer | Addresses without ENS |
cacheHits | integer | Queries served from cache |
cacheMisses | integer | Queries that hit blockchain |
cacheHitRate | string | Cache hit percentage |
processingTimeMs | integer | Total server processing time |
phase | integer | API version (2) |
warning | string | Performance warnings (if any) |
recommendation | string | Usage recommendations (if batch >50) |
Error Codes
400 Bad Request
Missing addresses:
{
"error": true,
"code": "MISSING_ADDRESSES",
"message": "Query parameter \"addresses\" is required",
"timestamp": "2026-02-15T20:00:00.000Z"
}
Invalid address format:
{
"error": true,
"code": "INVALID_ADDRESSES",
"message": "Invalid Ethereum addresses: 0xinvalid, 0xbad",
"timestamp": "2026-02-15T20:00:00.000Z"
}
Too many addresses:
{
"error": true,
"code": "TOO_MANY_ADDRESSES",
"message": "Maximum 100 addresses allowed per request. Requested: 150",
"timestamp": "2026-02-15T20:00:00.000Z"
}
500 Internal Server Error
{
"error": true,
"code": "BATCH_RESOLVE_ERROR",
"message": "Internal resolution error",
"timestamp": "2026-02-15T20:00:00.000Z"
}
Best Practices
1. Batch Size
- Recommended: 50 addresses or fewer
- Absolute max: 100 addresses
- Larger batches (>50) will show performance recommendations
2. Caching
- Results cached for 15 minutes
- Repeated queries are 50-100x faster
- No need to implement client-side caching
3. Field Selection
Only request fields you need to reduce payload size:
# Minimal (just names)
?include=name
# Social only
?include=twitter,github,discord
# Full profile
?include=name,avatar,twitter,github,discord,email,url
4. Error Handling
Always check metadata.failed for partial failures:
const data = await fetch(url).then(r => r.json());
if (data.metadata.failed > 0) {
const failed = data.addresses.filter(a => a.error);
console.warn('Some addresses failed:', failed);
}
const resolved = data.addresses.filter(a => a.ens);
// Process successful results
Integration Examples
JavaScript (Node.js)
async function resolveDeployers(addresses) {
const url = new URL('https://api.web3identity.com/api/ens/batch-resolve');
url.searchParams.set('addresses', addresses.join(','));
url.searchParams.set('include', 'name,twitter,github');
const response = await fetch(url);
if (!response.ok) {
throw new Error(`ENS resolution failed: ${response.statusText}`);
}
const data = await response.json();
return {
identities: data.addresses.filter(a => a.ens),
stats: data.metadata
};
}
// Usage
const deployers = ['0x4D982788...', '0xd8dA6BF2...'];
const { identities, stats } = await resolveDeployers(deployers);
console.log(`Resolved ${stats.resolved}/${stats.total} identities`);
console.log(`Cache hit rate: ${stats.cacheHitRate}`);
Python
import requests
from typing import List, Dict
def resolve_deployers(addresses: List[str]) -> Dict:
"""Resolve ENS names and social profiles for addresses."""
url = "https://api.web3identity.com/api/ens/batch-resolve"
params = {
"addresses": ",".join(addresses),
"include": "name,twitter,github"
}
response = requests.get(url, params=params)
response.raise_for_status()
data = response.json()
return {
"identities": [a for a in data["addresses"] if a["ens"]],
"stats": data["metadata"]
}
# Usage
deployers = ["0x4D982788...", "0xd8dA6BF2..."]
result = resolve_deployers(deployers)
print(f"Resolved {result['stats']['resolved']}/{result['stats']['total']}")
print(f"Cache hit rate: {result['stats']['cacheHitRate']}")
Rate Limits
- Free tier: 100 calls/day
- Paid tier: Coming soon (Phase 3)
Related Endpoints
- /api/ens/reverse/:address - Single address reverse lookup
- /api/ens/records/:name - All text records for a name
- /api/profile/:name - Full profile with ENS + socials
Updated February 15, 2026 - Phase 2 complete