Skip to main content

Migrating from Other APIs

Switching from Alchemy, Infura, or Moralis? Here's your migration guide.

Why Migrate?โ€‹

FeatureOthersWeb3 Identity API
SignupRequiredNone
API KeysManage keysNo keys needed
ENS + SocialBasic966 endpoints
PricingMonthly plansPay-per-use
Free TierVaries100 calls/day

Quick Comparisonโ€‹

ENS Resolutionโ€‹

Alchemy:

const alchemy = new Alchemy({ apiKey: 'YOUR_KEY' });
const address = await alchemy.core.resolveName('vitalik.eth');

Web3 Identity API:

const response = await fetch('https://api.web3identity.com/api/ens/resolve/vitalik.eth');
const { address } = await response.json();
// No API key, no SDK required!

Token Pricesโ€‹

Moralis:

const Moralis = require('moralis').default;
await Moralis.start({ apiKey: 'YOUR_KEY' });
const price = await Moralis.EvmApi.token.getTokenPrice({ address: '0x...' });

Web3 Identity API:

const response = await fetch('https://api.web3identity.com/api/price/ETH');
const { price } = await response.json();

Wallet Balancesโ€‹

Infura:

const provider = new ethers.InfuraProvider('mainnet', 'YOUR_KEY');
const balance = await provider.getBalance(address);

Web3 Identity API:

const response = await fetch(`https://api.web3identity.com/api/wallet/${address}/balance`);
const data = await response.json();
// Returns ETH + tokens in one call

Migration Pathsโ€‹

From Alchemyโ€‹

Alchemy EndpointWeb3 Identity API
resolveName()GET /api/ens/resolve/{name}
lookupAddress()GET /api/ens/reverse/{address}
getTokenBalances()GET /api/wallet/{address}/balance
getAssetTransfers()GET /api/wallet/{address}/transactions

Migration Steps:

  1. Remove Alchemy SDK dependency
  2. Replace calls with fetch to api.web3identity.com
  3. Update response parsing (similar structure)
  4. Optional: Add SDK for automatic payments
// Before: Alchemy
import { Alchemy, Network } from 'alchemy-sdk';
const alchemy = new Alchemy({ apiKey: 'KEY', network: Network.ETH_MAINNET });
const name = await alchemy.core.lookupAddress(address);

// After: Web3 Identity API
const res = await fetch(`https://api.web3identity.com/api/ens/reverse/${address}`);
const { name } = await res.json();

From Infuraโ€‹

Infura UsageWeb3 Identity API
ENS resolutionGET /api/ens/resolve/{name}
Gas pricesGET /api/gas
Token metadataGET /api/token/{address}

Migration Steps:

  1. Remove ethers.js Infura provider (if only used for ENS/metadata)
  2. Replace with REST calls
  3. Keep Infura for raw RPC if needed (we complement, not replace)
// Before: Infura
import { ethers } from 'ethers';
const provider = new ethers.InfuraProvider('mainnet', 'KEY');
const address = await provider.resolveName('vitalik.eth');

// After: Web3 Identity API
const res = await fetch('https://api.web3identity.com/api/ens/resolve/vitalik.eth');
const { address } = await res.json();

From Moralisโ€‹

Moralis FeatureWeb3 Identity API
Token pricesGET /api/price/{symbol}
Wallet tokensGET /api/wallet/{address}/balance
NFT metadataGET /api/nft/{contract}/{tokenId}
DeFi positionsGET /api/defi/positions/{address}

Migration Steps:

  1. Remove Moralis SDK
  2. No initialization needed
  3. Update response parsing
// Before: Moralis
await Moralis.start({ apiKey: 'KEY' });
const price = await Moralis.EvmApi.token.getTokenPrice({
address: '0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48'
});

// After: Web3 Identity API
const res = await fetch('https://api.web3identity.com/api/price/USDC');
const { price } = await res.json();

Response Format Differencesโ€‹

ENS Response Comparisonโ€‹

Alchemy returns:

"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045"  // Just the address

We return:

{
"name": "vitalik.eth",
"address": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045",
"avatar": "https://...",
"records": {
"twitter": "VitalikButerin",
"github": "vbuterin"
}
}

Benefit: More data in fewer calls.


Handling the Transitionโ€‹

Keep Both During Migrationโ€‹

const ENS_PROVIDER = process.env.USE_NEW_API 
? 'web3identity'
: 'alchemy';

async function resolveENS(name) {
if (ENS_PROVIDER === 'web3identity') {
const res = await fetch(`https://api.web3identity.com/api/ens/resolve/${name}`);
return res.json();
} else {
return alchemy.core.resolveName(name);
}
}

Feature Flag Rolloutโ€‹

  1. Deploy with feature flag defaulting to old provider
  2. Enable for internal testing
  3. Monitor errors and performance
  4. Gradually increase rollout
  5. Remove old provider code

Payment Handlingโ€‹

Unlike key-based APIs, we use x402 payments after the free tier.

Without SDK (Manual)โ€‹

async function callAPI(endpoint) {
let response = await fetch(`https://api.web3identity.com${endpoint}`);

if (response.status === 402) {
// Handle payment - see x402 docs
const payment = await createPayment(await response.json());
response = await fetch(`https://api.web3identity.com${endpoint}`, {
headers: { 'X-PAYMENT': payment }
});
}

return response.json();
}
import { ATVClient } from '@atv-eth/x402-sdk';

const client = new ATVClient({
privateKey: process.env.WALLET_KEY // USDC on Base
});

// SDK handles payments automatically
const profile = await client.getProfile('vitalik.eth');

Cost Comparisonโ€‹

UsageAlchemyInfuraWeb3 Identity
100 calls/dayFreeFreeFree
10K calls/month~$49~$50~$10*
100K calls/month~$199~$225~$100*

*Varies by endpoint mix. ENS: $0.01, Prices: $0.001, Batch: $0.02

Key difference: No monthly commitment. Pay only for what you use.


Python Migration Examplesโ€‹

From Alchemy (Python)โ€‹

# Before: Alchemy SDK
from alchemy import Alchemy, Network

alchemy = Alchemy(api_key="YOUR_KEY", network=Network.ETH_MAINNET)
address = alchemy.core.resolve_name("vitalik.eth")

# After: Web3 Identity API
import requests

response = requests.get("https://api.web3identity.com/api/ens/resolve/vitalik.eth")
data = response.json()
address = data["address"]
# Also get avatar, records, etc. in same call!

From Moralis (Python)โ€‹

# Before: Moralis
from moralis import evm_api

api_key = "YOUR_KEY"
params = {"address": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48", "chain": "eth"}
result = evm_api.token.get_token_price(api_key=api_key, params=params)

# After: Web3 Identity API
import requests

response = requests.get("https://api.web3identity.com/api/price/USDC")
data = response.json()
price = data["price"] # No API key needed!

Batch Operations (Python)โ€‹

import requests

# Get multiple ENS profiles in one call
names = ["vitalik.eth", "nick.eth", "brantly.eth"]
response = requests.post(
"https://api.web3identity.com/api/ens/bulk",
json={"names": names}
)
profiles = response.json()

# Each profile includes address, avatar, records
for profile in profiles["results"]:
print(f"{profile['name']}: {profile['address']}")

Common Migration Issuesโ€‹

Issue: Different Response Structuresโ€‹

Problem: Field names differ between providers.

// Alchemy returns
{ result: "0xd8dA..." }

// We return
{ address: "0xd8dA...", name: "vitalik.eth", ... }

Solution: Update your response parsing:

// Before
const address = alchemyResponse.result;

// After
const { address } = await response.json();

Issue: Handling 402 Payment Requiredโ€‹

Problem: After free tier, you get 402 responses.

// This will fail after 100 calls/day
const response = await fetch('https://api.web3identity.com/api/ens/resolve/vitalik.eth');
if (response.status === 402) {
// Need to handle payment!
}

Solution: Use our SDK or implement x402:

import { Web3IdentityClient } from '@atv-eth/x402-sdk';

const client = new Web3IdentityClient({
privateKey: process.env.WALLET_KEY // For payments
});

// SDK handles 402 automatically
const data = await client.ens.resolve('vitalik.eth');

Issue: Rate Limitingโ€‹

Problem: Getting 429 Too Many Requests.

ProviderRate Limit
Alchemy330 req/sec
Web3 Identity100 req/min

Solution: Add request throttling:

import pThrottle from 'p-throttle';

const throttle = pThrottle({ limit: 90, interval: 60000 });
const throttledFetch = throttle((url) => fetch(url));

// Use throttledFetch instead of fetch
const response = await throttledFetch('https://api.web3identity.com/api/...');

Issue: Missing Endpointsโ€‹

Problem: We don't have an exact equivalent.

NeedOur Alternative
Raw RPC (eth_call)Use Infura/Alchemy for RPC
WebSocket eventsUse our polling + your RPC for events
Archive stateKeep archive node access

Solution: Hybrid approach:

// Use us for identity/market data
const ensData = await fetch('https://api.web3identity.com/api/ens/resolve/vitalik.eth');

// Use your RPC for raw blockchain calls
const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const balance = await provider.getBalance(address);

Migration Checklistโ€‹

โ–ก Audit current API usage (which endpoints?)
โ–ก Map endpoints to Web3 Identity equivalents
โ–ก Update response parsing for new structure
โ–ก Add error handling for 402 responses
โ–ก Test with free tier (100 calls/day)
โ–ก Add x402 SDK for production
โ–ก Deploy with feature flag
โ–ก Monitor errors for 1 week
โ–ก Remove old provider dependency

What We Don't Replaceโ€‹

Keep your existing provider for:

  • Raw RPC calls (eth_call, eth_sendTransaction)
  • WebSocket subscriptions (real-time events)
  • Archive node queries (historical state)
  • Custom contract calls (use ethers.js + RPC)

We're complementary โ€” handling identity, social, and market data so you can use a cheaper RPC for the basics.


Ready to Migrate?โ€‹

๐Ÿ“– Try in Swagger UI โ†’

  1. Test endpoints in Swagger UI
  2. Start small โ€” migrate one feature
  3. Use feature flags for safe rollout
  4. Add SDK when you exceed free tier