Skip to content

The directory feed ​

The whole Chain Daddy directory as one file a day: every ticker with a verified page, on every chain, with the coin's contract, signed so you can check it came from Chain Daddy. And any coin's creator record, read for your server when nobody has read it yet. Both come with the Developer plan and every plan above it.

ReadWhat you get
GET /api/v2/directory/exportToday's export: a download link and its signed manifest
GET /api/v2/directory/coins/{chain}/{symbol}/creator-recordA coin's creator record, read for your key when it has none yet

They are at https://api.chaindaddy.io. Send your API key as X-API-Key (or Authorization: Bearer). A request without one is 401 api_key_required, and a key on a plan below Developer is 403 upgrade_required. Each answer is for your key alone and is not cached. Both operations are in the API Explorer under Directory and part of the public API contract, and your key's request limits apply to them as to every call (Authentication).

The export ​

bash
curl -H "X-API-Key: $CD_API_KEY" https://api.chaindaddy.io/api/v2/directory/export
json
{
  "url": "https://…",
  "expiresAt": "2026-11-13T18:10:00Z",
  "manifest": {
    "jws": "eyJhbGciOiJFZERTQSIsImtpZCI6…",
    "claims": {
      "iss": "https://chaindaddy.io",
      "typ": "cd-directory+v1",
      "iat": 1794580318,
      "exp": 1794753118,
      "sha256": "e16d66472c98620ef80ace5eac7d73c7e65d216a86600053f37bfb8a815d1760",
      "bytes": 33343,
      "rows": 162
    }
  }
}

The file is JSON Lines, one ticker on one chain per line, by ticker:

json
{"symbol":"FLUXGP","chain":"base","chainId":"eip155:8453","status":"registered","tokenAddress":"0x931fce21ddea0549db70324f44ee2db1cb9f7f22","crownId":8,"registeredAt":"2026-09-26T18:30:00Z","house":true}
  • tokenAddress is the verified contract for the ticker on that chain: lowercase on EVM chains, as written on Solana. crownId and registeredAt are its registration's.
  • A ticker that is not in the file has no verified page on that chain.
  • house: true marks a Chain Daddy team coin, and is absent on every other coin.
  • Download url before expiresAt, 10 minutes after you asked; ask again for a fresh link. A new file comes out every day (UTC). Use a file until its exp, two days after it was built.

Check the file ​

The manifest is a compact JWS signed by Chain Daddy with the Ed25519 keys at https://api.chaindaddy.io/api/v2/iap/jwks, the same keys as signed answers, also named on chaindaddy.eth (where the keys are). Its typ claim is cd-directory+v1, so it does not verify as a signed answer, and a signed answer does not verify as a manifest. The file carries no signature of its own: the manifest carries its SHA-256. Trust the file once the JWS verifies and the file's bytes hash to sha256. In TypeScript, with jose:

ts
import { createHash } from 'node:crypto';
import { createRemoteJWKSet, jwtVerify } from 'jose';

const API = 'https://api.chaindaddy.io';
const keys = createRemoteJWKSet(new URL('/api/v2/iap/jwks', API));

const { url, manifest } = await fetch(`${API}/api/v2/directory/export`, {
  headers: { 'X-API-Key': process.env.CD_API_KEY! },
}).then((r) => r.json());

// The signature, the issuer and exp. The header's typ is a plain "JWT": the manifest's own is in its claims.
const { payload } = await jwtVerify(manifest.jws, keys, { algorithms: ['EdDSA'], issuer: 'https://chaindaddy.io' });
if (payload.typ !== 'cd-directory+v1') throw new Error('not a directory manifest');

const file = Buffer.from(await fetch(url).then((r) => r.arrayBuffer()));
if (createHash('sha256').update(file).digest('hex') !== payload.sha256) throw new Error('not the file the manifest signs');

const rows = file.toString('utf8').trim().split('\n').map((line) => JSON.parse(line));

In another language: split the JWS at the dots and decode each part from base64url. The header's alg must be EdDSA, and its kid picks the key from the key set. Check the Ed25519 signature over the first two parts as sent, joined by a dot. Then check the claims: typ is cd-directory+v1, iss is https://chaindaddy.io and exp is in the future. Last, hash the downloaded file with SHA-256 and compare it, in lowercase hex, with sha256.

The creator record with your key ​

bash
curl -H "X-API-Key: $CD_API_KEY" https://api.chaindaddy.io/api/v2/directory/coins/base/0x940181a94a35a4569e4529a3cdfb74e38fd98631/creator-record

The answer is the creator record, the same one the keyless read gives, by ticker or by token address. Your key adds what a server needs: a coin nobody has read yet is read for you. Its first answer is pending; ask again, and the record is there within seconds to minutes. Asking again while it is pending counts once.

Each key, each UTC day
New records read for your key100
Records answered5,000
  • Every answer says what is left: X-Record-Lookups-Remaining for new records and X-Records-Remaining for records. A pending answer does not count toward the 5,000.
  • Past 100 new records, a coin with nothing read yet answers 429 lookup_limit_reached, and records already read still answer. Past 5,000 records, every read answers 429 record_limit_reached. Both last until 00:00 UTC, and Retry-After says how long that is.
  • A coin registered with Chain Daddy has its record read for everyone, so it does not count as a new record.