Every wallet we can associate with a Giraffe
A live, public, no-auth feed for anyone running an airdrop, an allowlist, or a holder check against Gary Club. Wallets are grouped per holder, so you can treat a cluster as one person instead of guessing at it.
GET them from a browser, a script, an n8n flow, or an agent. CORS is *.Who is in the feed#
A wallet appears for either of two independent reasons, and the type field tells you which:
memberhas a Gary Club accountnon_memberholds a Giraffe, no accountplatformGary Club itselfWhat it tells you — and what it doesn’t#
This feed is deliberately narrow. It answers “which addresses belong to the same holder, and is that holder a member?” and nothing more.
giraffe: true · roles, badges, traits, rarity, or token balances · names, emails, phone numbers, avatars, bios, socials, and internal ids.The collapse of owned / rented / delegated into a single boolean is the point of the design, not a gap in it. If you need to distinguish them, this feed is not the right source and we will not add a field that splits them.
Two things that would otherwise be holes, and are not: listed Giraffes still count — a Giraffe listed for sale sits in a marketplace escrow program, and we resolve it back to the seller, so putting yours on the market does not drop you from the feed. And a Giraffe that has been delegated or rented counts for both sides: the owner never stopped owning it, and the member using it reads as having one too.
Our other collections — MAGA Giraffe, Dark MAGA Giraffe, Vibin Giraffe, Giraffe Glimpses, Giraffish Moments, Gary Club Stacker, Golden Ticket — are separate collections, not Giraffes, and holding one does not put a wallet in this feed.
Endpoints#
The snapshot, grouped per holder
https://gary.club/snapshot.jsonwallet so consecutive snapshots diff cleanly. This is the canonical format.curl https://gary.club/snapshot.jsonResponse:
{
"schema": "gary-club-wallet-snapshot/2",
"generated_at": "2026-08-09T19:20:11.482Z",
"key": "wallet — for a member, their Gary Club custodial SOL wallet; ...",
"disclosure": {
"discloses": ["wallet addresses", "membership status", "..."],
"withholds": ["how many Giraffes anyone has", "..."]
},
"collection": {
"giraffe_tower": "H5P4frZiXzTKucCPHyFwQoSSY5bVPG5BPdeeKAnX7CnA",
"supply": 7291
},
"freshness": {
"membership": "live — read from the database on each build",
"giraffe_index_updated_at": "2026-08-09T19:11:44.776Z"
},
"counts": {
"entries": 931,
"wallets": 1218,
"members": 489,
"non_members": 441,
"platform": 1,
"with_giraffe": 581,
"without_giraffe": 350,
"giraffes_in_marketplace_escrow": 90,
"excluded_without_wallet": 5
},
"entries": [
{
"wallet": "Ga1ExampLeCustodia1Wa11etAddress1111111111",
"wallets": [
"Ga1ExampLeCustodia1Wa11etAddress1111111111",
"Ga1ExampLeConnectedWa11etAddress2222222222"
],
"type": "member",
"giraffe": true,
"member_since": "2026-03-17"
},
{
"wallet": "Ga1ExampLeNonMemberWa11etAddress3333333333",
"wallets": ["Ga1ExampLeNonMemberWa11etAddress3333333333"],
"type": "non_member",
"giraffe": true
}
]
}Entry fields#
walletstring · the unique keywalletsstring[]wallet — a member may hold assets in any of them. No address appears in more than one entry.type'member' | 'non_member' | 'platform'giraffebooleanmember_sincestring · YYYY-MM-DD · members onlyThe same snapshot, one row per wallet
https://gary.club/snapshot.csvcluster value are the same holder; kind is custodial, connected, or holder. The holder-level fields repeat on every row, so a naive dedupe by cluster loses nothing.curl -o gary-club-wallets.csv https://gary.club/snapshot.csvwallet,cluster,kind,type,giraffe,member_since
Ga1ExampLeCustodia1Wa11etAddress1111111111,Ga1ExampLeCustodia1Wa11etAddress1111111111,custodial,member,true,2026-03-17
Ga1ExampLeConnectedWa11etAddress2222222222,Ga1ExampLeCustodia1Wa11etAddress1111111111,connected,member,true,2026-03-17
Ga1ExampLeNonMemberWa11etAddress3333333333,Ga1ExampLeNonMemberWa11etAddress3333333333,holder,non_member,true,Freshness#
The feed is rebuilt from the database on request behind a 30-second cache, so generated_at moves continuously. Membership, wallet connections, rentals, and delegations are live at write time.
On-chain Giraffe holding is the one input that is not read per request: it comes from a full-collection index refreshed hourly, and the feed publishes its exact timestamp as freshness.giraffe_index_updated_at rather than asking you to take freshness on trust. A wallet that bought a Giraffe minutes ago may not appear until the next index run.
X-Snapshot-Stale: true and X-Snapshot-Age-Seconds. Treat true as “retry later”, never as “this holder no longer qualifies”.Rate limits and caching#
60 requests per minute per source IP, on each format. Responses are Cache-Control: public, max-age=30 — please cache your side rather than polling in a loop. The whole snapshot is a single request; there is no pagination and no partial fetch.
Reconciling against the collection#
Every Giraffe Tower in the collection is accounted for. collection.supply equals the Giraffes held by members, plus those held by non-members, plus platform-held, plus counts.giraffes_in_marketplace_escrow.
That last bucket is why the numbers add up: a Giraffe listed for sale sits in a marketplace escrow program address, not a wallet anyone holds. Those are counted but never published as entries, because listing a program address as a holder invites an airdrop straight into it.
counts.excluded_without_wallet reports members who have signed up but have no custodial wallet yet. They have no key to publish, so they are counted rather than listed.
