Look up a wallet
curl --request GET \
--url https://walletlink.social/api/v1/wallet/{address}import requests
url = "https://walletlink.social/api/v1/wallet/{address}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://walletlink.social/api/v1/wallet/{address}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://walletlink.social/api/v1/wallet/{address}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://walletlink.social/api/v1/wallet/{address}"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://walletlink.social/api/v1/wallet/{address}")
.asString();require 'uri'
require 'net/http'
url = URI("https://walletlink.social/api/v1/wallet/{address}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"data": {
"wallet": "<string>",
"ens_name": "<string>",
"twitter": {},
"farcaster": {},
"lens": "<string>",
"github": "<string>",
"sources": [
"<string>"
],
"agent": {},
"quality": {}
},
"meta": {
"wallet": "<string>",
"found": true,
"last_updated": "<string>",
"stale": true,
"checked_at": {}
}
}Lookups
Look up a wallet
GET /v1/wallet/
GET
/
api
/
v1
/
wallet
/
{address}
Look up a wallet
curl --request GET \
--url https://walletlink.social/api/v1/wallet/{address}import requests
url = "https://walletlink.social/api/v1/wallet/{address}"
response = requests.get(url)
print(response.text)const options = {method: 'GET'};
fetch('https://walletlink.social/api/v1/wallet/{address}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://walletlink.social/api/v1/wallet/{address}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "GET",
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"net/http"
"io"
)
func main() {
url := "https://walletlink.social/api/v1/wallet/{address}"
req, _ := http.NewRequest("GET", url, nil)
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.get("https://walletlink.social/api/v1/wallet/{address}")
.asString();require 'uri'
require 'net/http'
url = URI("https://walletlink.social/api/v1/wallet/{address}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Get.new(url)
response = http.request(request)
puts response.read_body{
"data": {
"wallet": "<string>",
"ens_name": "<string>",
"twitter": {},
"farcaster": {},
"lens": "<string>",
"github": "<string>",
"sources": [
"<string>"
],
"agent": {},
"quality": {}
},
"meta": {
"wallet": "<string>",
"found": true,
"last_updated": "<string>",
"stale": true,
"checked_at": {}
}
}Returns every identity attached to a single address. Costs 1 match credit if the address resolves to an X handle or a Farcaster account, and nothing if it does not.
For more than a handful of addresses use batch instead.
Both are absent on fresh records, so test for presence rather than comparing values.
Path parameters
string
required
An address as
0x followed by 40 hex characters. Case-insensitive; returned
lowercased.Request
curl https://walletlink.social/api/v1/wallet/0x00000000000000000000000000000000000000a1 \
-H "Authorization: Bearer wts_live_YOUR_KEY"
Response
object | null
The record, or
null when nothing is attached to the address.Show properties
Show properties
string
Lowercased address. Always present.
string
Primary ENS name.
object
handle, url, verified, and, once we have checked, reachable, reachability and reachability_checked_at. See the verified flags, which are narrower than they look, and when a handle stops being true.also, an object with handle, url and source, is present only where a second X account is attested for the same wallet and both accounts are live. See a second X account.object
username, url, followers, fid, and verified.string
Lens handle.
string
GitHub username.
string[]
Evidence classes backing the record:
onchain, farcaster, attested-social, manual, aggregated. See evidence classes.object
Present only when the address is a known onchain agent. Carries
is_agent, name, framework, type, token_symbol and verified.Absent where the address owner attested an identity that is not the agent’s own. A catalog entry is a third party’s claim about an address; an attestation is the owner’s, and the address a launch protocol files against an agent is frequently its creator’s rather than the agent’s. Absent means we decline to say, not that we checked and it is not an agent.object
score from 0 to 100, and last_verified.object
Show properties
Show properties
string
The normalized address you asked for.
boolean
Whether any identities were attached.
string
When the record last changed. Present only when
found is true.boolean
Whether the record is past its freshness window. Present only when
found
is true.string | null
Present only when
found is false. A timestamp means we checked and found
nothing; null means we have never seen this address.{
"data": {
"wallet": "0x00000000000000000000000000000000000000a1",
"ens_name": "example.eth",
"twitter": {
"handle": "example_user",
"url": "https://x.com/example_user",
"verified": true,
"reachable": true,
"reachability": "live",
"reachability_checked_at": "2026-08-17T09:41:02.000Z"
},
"farcaster": {
"username": "example",
"url": "https://warpcast.com/example",
"followers": 123456,
"fid": 900001,
"verified": true
},
"sources": ["onchain", "farcaster"],
"quality": {
"score": 90,
"last_verified": "2026-08-10T09:12:00.000Z"
}
},
"meta": {
"wallet": "0x00000000000000000000000000000000000000a1",
"found": true,
"last_updated": "2026-08-10T09:12:00.000Z",
"stale": false
}
}
{
"data": null,
"meta": {
"wallet": "0x0000000000000000000000000000000000000001",
"found": false,
"checked_at": "2026-07-02T11:30:00.000Z"
}
}
{
"data": null,
"meta": {
"wallet": "0x0000000000000000000000000000000000000002",
"found": false,
"checked_at": null
}
}
All three of these are HTTP 200. A wallet with nothing attached is a
successful lookup with a negative answer, not an error.
A second X account
A wallet can have two X accounts attested for it: one through a Farcaster verification, say, and a different one through a signed attestation made later. When we have checked both and both still reach someone, there is no evidence for preferring either, so the record keeps itshandle and carries the other
as twitter.also.
"twitter": {
"handle": "someone",
"url": "https://x.com/someone",
"verified": true,
"reachable": true,
"reachability": "live",
"reachability_checked_at": "2026-08-17T09:41:02.000Z",
"also": {
"handle": "someone_eth",
"url": "https://x.com/someone_eth",
"source": "attested-social"
}
}
source is the evidence class of
the attestation behind the second handle. The field is absent, not null, on
every other record. It never appears where the stored handle has stopped
reaching anyone: that record is corrected instead, and handle becomes the
account that still works.
Staleness headers
When a record is past its freshness window the response adds:X-Data-Staleness: stale
X-Last-Updated: 2026-05-01T00:00:00.000Z
Errors
INVALID_ADDRESS, plus the standard errors.