Skip to content

Registration API

Look up registration status, verify ownership, claim registrations, and update token page metadata.

Endpoints

MethodPathDescription
GET/api/v2/registration/{id}Get registration by ID (or symbol)
GET/api/v2/registration/{symbol}/{chain}Get registration status for a symbol on a chain
GET/registration/unified/{symbol}Get unified registration data for a symbol (root-level)
GET/registration/v2/symbol/{symbol}/all-chainsGet all registrations for a symbol across chains (root-level)
GET/registration/{id}/rolesGet registration owner, managers, and maintainers (root-level)
GET/api/v2/registry/infoGet registry protocol info and supported chains
GET/api/v2/registration/feeGet the current claim fee
GET/api/v2/heartbeat/{symbol}/{chain}Get heartbeat score and activity status
POST/api/v2/verify/symbolValidate a symbol before claiming
POST/api/v2/claim/messageGet the ownership message to sign
POST/api/v2/claim/verifyVerify token ownership
POST/api/v2/claimBuild the claim (mint) transaction
POST/api/v2/claim/solana/buildBuild a Solana claim transaction
PUT/api/v2/registration/{id}/profileUpdate token page profile (authenticated)
POST/api/v2/metadata/uploadUpload token metadata

Three root-level routes

Most endpoints live under https://api.chaindaddy.io/api/v2/..., but three registration lookups are served at the root of the API host with no /api/v2 prefix:

  • https://api.chaindaddy.io/registration/unified/{symbol}
  • https://api.chaindaddy.io/registration/v2/symbol/{symbol}/all-chains
  • https://api.chaindaddy.io/registration/{id}/roles

Calling these with an /api/v2 prefix returns a different (or missing) resource. The examples below always show the full URL.

Chain path parameters ({chain}) accept a chain key (eth, arbitrum, base, polygon, bnb, avax, gnosis, solana), a common alias (arb, sol, bsc), or a numeric EVM chain ID.

Get Registration by ID

GET /api/v2/registration/{id}

Retrieve registration data by its on-chain ID. The {id} path parameter accepts a numeric registration ID or a symbol string (resolves to the first registration for that symbol).

Path Parameters

ParameterTypeRequiredDescription
idstringYesRegistration's on-chain ID (numeric) or a symbol

Response Format

json
{
  "tokenId": 123,
  "owner": "0x1234567890abcdef1234567890abcdef12345678",
  "chainId": 42161,
  "symbol": "DOGE",
  "identity": { "displayName": "Doge", "avatarUrl": "https://..." },
  "tierCount": 2,
  "verifiedDomains": ["doge.example.com"],
  "metadataCid": "bafy...",
  "attestationCount": 3
}

Response Fields

FieldTypeDescription
tokenIdintegerRegistration's on-chain ID
ownerstringRegistration owner wallet address
chainIdintegerChain ID where the registration exists
symbolstringToken symbol
identityobject | omittedDisplay identity resolved from registration metadata
tierCountintegerNumber of holder access tiers configured
verifiedDomainsstring[] | omittedDNS-verified domains linked to the registration
canonicalPeerobject | omittedCanonical peer reference (chainId, crownId) when set
metadataCidstring | omittedIPFS CID of the registration metadata
attestationCountinteger | omittedCount of operator attestations

Code Examples

bash
curl -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  "https://api.chaindaddy.io/api/v2/registration/123"
javascript
const API_KEY = 'cd_live_YOUR_KEY_HERE';
const BASE_URL = 'https://api.chaindaddy.io';

async function getRegistration(id) {
  const response = await fetch(
    `${BASE_URL}/api/v2/registration/${id}`,
    { headers: { 'X-API-Key': API_KEY } }
  );
  return response.json();
}

const registration = await getRegistration(123);
console.log(registration.symbol, registration.owner);
python
import requests

API_KEY = 'cd_live_YOUR_KEY_HERE'
BASE_URL = 'https://api.chaindaddy.io'

def get_registration(registration_id):
    response = requests.get(
        f'{BASE_URL}/api/v2/registration/{registration_id}',
        headers={'X-API-Key': API_KEY}
    )
    response.raise_for_status()
    return response.json()

registration = get_registration(123)
print(registration['symbol'], registration['owner'])

Get Registration Status

GET /api/v2/registration/{symbol}/{chain}

Resolve the registration status for a symbol on a specific chain — the primary "is this claimed, and by whom?" lookup.

Parameters

ParameterLocationTypeRequiredDescription
symbolpathstringYesToken symbol
chainpathstringYesChain key (e.g. arbitrum) or numeric chain ID
tokenAddressquerystringNoToken contract address to scope the lookup

Response

Returns the resolved registration status object, including status (available, unclaimed, grace_period, claimed, owned, inactive), tokenId, owner, heartbeat data, metadata, and verifiedDomains when present. The same status values are documented in the Search API.

bash
curl -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  "https://api.chaindaddy.io/api/v2/registration/DOGE/arbitrum"

Get Unified Registration

GET /registration/unified/{symbol}

(Root-level route — no /api/v2 prefix.) Get registration data for a symbol, abstracting whether the registration is confirmed on-chain or still pending from token creation.

Path Parameters

ParameterTypeRequiredDescription
symbolstringYesToken symbol

Response Format

json
{
  "symbol": "DOGE",
  "owner": "0x1234567890abcdef1234567890abcdef12345678",
  "tokenId": 123,
  "chainId": 42161,
  "status": "confirmed",
  "primaryType": "evm",
  "primaryClaimedAt": null,
  "isPending": false
}

Response Fields

FieldTypeDescription
symbolstringToken symbol
ownerstringRegistration owner wallet address
tokenIdintegerRegistration's on-chain ID
chainIdintegerChain ID of the registration
statusstringRegistration status: confirmed or pending
primaryTypestringPrimary chain type: evm or solana
primaryClaimedAtstring | nullTimestamp of initial claim
isPendingbooleanWhether the registration is awaiting on-chain confirmation

Code Examples

bash
# Root-level route: no /api/v2 prefix
curl -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  "https://api.chaindaddy.io/registration/unified/DOGE"
javascript
async function getUnifiedRegistration(symbol) {
  // Root-level route: no /api/v2 prefix
  const response = await fetch(
    `${BASE_URL}/registration/unified/${symbol}`,
    { headers: { 'X-API-Key': API_KEY } }
  );
  return response.json();
}

const registration = await getUnifiedRegistration('DOGE');
console.log(registration.status, registration.isPending);
python
def get_unified_registration(symbol):
    # Root-level route: no /api/v2 prefix
    response = requests.get(
        f'{BASE_URL}/registration/unified/{symbol}',
        headers={'X-API-Key': API_KEY}
    )
    response.raise_for_status()
    return response.json()

registration = get_unified_registration('DOGE')
print(registration['status'], registration['isPending'])

Get All Registrations Across Chains

GET /registration/v2/symbol/{symbol}/all-chains

(Root-level route — no /api/v2 prefix.) Retrieve all registrations for a symbol across all supported chains, including pending ones.

Parameters

ParameterLocationTypeRequiredDescription
symbolpathstringYesToken symbol
excludeEvmquerystringNoExclude registrations owned by this EVM address

Response Format

json
{
  "symbol": "DOGE",
  "crowns": [
    {
      "tokenId": 123,
      "owner": "0x1234567890abcdef1234567890abcdef12345678",
      "ownerType": "evm",
      "chainType": "evm",
      "isLinked": true,
      "isActive": true,
      "deploymentCount": 1,
      "primaryChainId": 42161,
      "isPending": false
    },
    {
      "tokenId": 456,
      "owner": "7nYB...3kPZ",
      "ownerType": "solana",
      "chainType": "solana",
      "isLinked": false,
      "isActive": true,
      "deploymentCount": 1,
      "primaryChainId": null,
      "isPending": false
    }
  ]
}

Response Fields

Registration Object

FieldTypeDescription
tokenIdintegerRegistration's on-chain ID
ownerstringRegistration owner wallet address
ownerTypestringOwner wallet type: evm or solana
chainTypestringChain type: evm or solana
isLinkedbooleanWhether this registration is linked to other same-symbol registrations
isActivebooleanWhether the registration is currently active
deploymentCountintegerNumber of chain deployments linked
primaryChainIdinteger | nullPrimary chain ID (null for Solana)
isPendingbooleanWhether the registration is awaiting confirmation

Code Examples

bash
# Root-level route: no /api/v2 prefix
curl -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  "https://api.chaindaddy.io/registration/v2/symbol/DOGE/all-chains"

# Exclude a specific owner
curl -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  "https://api.chaindaddy.io/registration/v2/symbol/DOGE/all-chains?excludeEvm=0x1234..."
javascript
async function getAllRegistrations(symbol, options = {}) {
  const params = new URLSearchParams(options);
  // Root-level route: no /api/v2 prefix
  const url = `${BASE_URL}/registration/v2/symbol/${symbol}/all-chains?${params}`;
  const response = await fetch(url, {
    headers: { 'X-API-Key': API_KEY }
  });
  return response.json();
}

const data = await getAllRegistrations('DOGE');
console.log(`Found ${data.crowns.length} registrations across chains`);

// Find linked registrations (same wallet, shared metadata)
const linked = data.crowns.filter(r => r.isLinked);
python
def get_all_registrations(symbol, **kwargs):
    # Root-level route: no /api/v2 prefix
    response = requests.get(
        f'{BASE_URL}/registration/v2/symbol/{symbol}/all-chains',
        params=kwargs,
        headers={'X-API-Key': API_KEY}
    )
    response.raise_for_status()
    return response.json()

data = get_all_registrations('DOGE')
print(f"Found {len(data['crowns'])} registrations across chains")

# Find linked registrations (same wallet, shared metadata)
linked = [r for r in data['crowns'] if r['isLinked']]

Get Registration Roles

GET /registration/{id}/roles

(Root-level route — no /api/v2 prefix.) Get owner, managers, and maintainers for a registration. The id parameter accepts either a numeric registration ID or a symbol string.

Path Parameters

ParameterTypeRequiredDescription
idstringYesRegistration ID (numeric) or symbol (string)

Response Format

json
{
  "tokenId": 123,
  "owner": "0x1234567890abcdef1234567890abcdef12345678",
  "manager": "0xabcdef1234567890abcdef1234567890abcdef12",
  "managers": [
    "0xabcdef1234567890abcdef1234567890abcdef12"
  ],
  "maintainers": [],
  "isPending": false
}

Response Fields

FieldTypeDescription
tokenIdintegerRegistration ID
ownerstringRegistration owner address
managerstring | nullPrimary manager address
managersstring[]All manager addresses
maintainersstring[]All maintainer addresses
isPendingbooleanWhether the registration is awaiting confirmation

Code Examples

bash
# Root-level route: no /api/v2 prefix
curl -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  "https://api.chaindaddy.io/registration/123/roles"

# By symbol
curl -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  "https://api.chaindaddy.io/registration/DOGE/roles"
javascript
async function getRegistrationRoles(id) {
  // Root-level route: no /api/v2 prefix
  const response = await fetch(
    `${BASE_URL}/registration/${id}/roles`,
    { headers: { 'X-API-Key': API_KEY } }
  );
  return response.json();
}

const roles = await getRegistrationRoles('DOGE');
console.log('Owner:', roles.owner);
console.log('Manager:', roles.manager);
python
def get_registration_roles(registration_id):
    # Root-level route: no /api/v2 prefix
    response = requests.get(
        f'{BASE_URL}/registration/{registration_id}/roles',
        headers={'X-API-Key': API_KEY}
    )
    response.raise_for_status()
    return response.json()

roles = get_registration_roles('DOGE')
print('Owner:', roles['owner'])
print('Manager:', roles['manager'])

Get Registry Info

GET /api/v2/registry/info

Get information about the underlying registry protocol. No parameters required. Cached for 1 hour.

Response Format

json
{
  "success": true,
  "protocol": "opencrown",
  "protocolVersion": "v1",
  "isOpenCrown": true,
  "supportedChains": ["eth", "arbitrum", "base", "polygon", "bnb", "avax", "gnosis", "solana"]
}
FieldTypeDescription
protocolstringRegistry protocol identifier (wire value)
protocolVersionstringRegistry protocol version
supportedChainsstring[]Chain keys the registry supports

For fee-cap data see GET /api/v2/registry/fee-caps; for the current claim fee use GET /api/v2/registration/fee below.

Get Claim Fee

GET /api/v2/registration/fee

Get the current claim fee. The fee is a flat USD amount, identical on every chain — payment happens on whichever chain you are claiming on.

Response Format

json
{
  "baseFeeUsd": 15,
  "multiplier": 1,
  "totalFeeUsd": 15,
  "currency": "USD"
}
FieldTypeDescription
baseFeeUsdnumberBase claim fee in USD
multipliernumberFee multiplier (currently always 1)
totalFeeUsdnumberEffective total fee in USD
currencystringAlways "USD"

Get Heartbeat Status

GET /api/v2/heartbeat/{symbol}/{chain}

Get the heartbeat score and activity status for a registration. EVM chains only.

Parameters

ParameterLocationTypeRequiredDescription
symbolpathstringYesToken symbol
chainpathstringYesChain key (e.g. arbitrum)
tokenAddressquerystringNoToken contract address to scope the lookup

Response Format

json
{
  "symbol": "DOGE",
  "chainId": 42161,
  "score": 85,
  "status": "healthy",
  "lastUpdated": "2026-01-15T12:00:00Z",
  "components": {
    "timestamp": 45,
    "volume": 25,
    "holders": 15,
    "confidence": 1
  }
}

Response Fields

FieldTypeDescription
symbolstringToken symbol
chainIdintegerChain ID
scorenumberComposite heartbeat score (0-100)
statusstringhealthy, moderate, at_risk, or inactive
lastUpdatedstringISO 8601 timestamp of the last heartbeat
componentsobjectScore breakdown: timestamp, volume, holders, confidence

Related: GET /api/v2/heartbeat/{symbol}/{chain}/history returns the score history, and GET /api/v2/heartbeat/at-risk lists registrations currently at risk.

Code Examples

bash
curl -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  "https://api.chaindaddy.io/api/v2/heartbeat/DOGE/arbitrum"
javascript
async function getHeartbeat(symbol, chain) {
  const response = await fetch(
    `${BASE_URL}/api/v2/heartbeat/${symbol}/${chain}`,
    { headers: { 'X-API-Key': API_KEY } }
  );
  return response.json();
}

const heartbeat = await getHeartbeat('DOGE', 'arbitrum');
if (heartbeat.score < 60) {
  console.log(`Warning: ${heartbeat.symbol} is at risk (score: ${heartbeat.score})`);
}
python
def get_heartbeat(symbol, chain):
    response = requests.get(
        f'{BASE_URL}/api/v2/heartbeat/{symbol}/{chain}',
        headers={'X-API-Key': API_KEY}
    )
    response.raise_for_status()
    return response.json()

heartbeat = get_heartbeat('DOGE', 'arbitrum')
if heartbeat['score'] < 60:
    print(f"Warning: {heartbeat['symbol']} is at risk (score: {heartbeat['score']})")

Validate a Symbol

POST /api/v2/verify/symbol

Check whether a symbol is valid and claimable before starting a claim — catches format errors, blocked symbols, canonical-asset collisions, and cross-chain compatibility issues.

Request Body

FieldTypeRequiredDescription
symbolstringYesSymbol to validate (1-12 alphanumeric characters)

Response Format

json
{
  "success": true,
  "symbol": "DOGE",
  "status": "warning",
  "warningMessage": "DOGE matches a well-known asset",
  "requiresAcknowledgment": true,
  "crossChainCompatibility": {
    "solana": { "compatible": true },
    "evm": { "compatible": true }
  }
}
FieldTypeDescription
statusstringallowed, warning, og_required, or blocked
blockedReasonstring | omittedWhy the symbol is blocked (invalid length/characters, reserved)
canonicalAssetobject | omittedKnown canonical asset that matches this symbol
warningMessagestring | omittedHuman-readable warning to surface to the user
requiresAcknowledgmentbooleanWhether the user must acknowledge the warning to proceed
requiresOgVerificationbooleanWhether claiming requires original-project verification
crossChainCompatibilityobject | omittedPer-ecosystem compatibility (solana, evm)

Claim a Registration

Claiming is a four-step flow: get a message to sign, sign it with the wallet, verify ownership, then build and submit the mint transaction.

Sequence diagram of the four-step claim flow: your app requests the ownership message, has the wallet sign it, and verifies ownership to receive a proof hash; it then builds the unsigned claim transaction with the proof hash, signs and submits it on-chain, and polls the claim status endpoint with the transaction hash until the mint confirmsSequence diagram of the four-step claim flow: your app requests the ownership message, has the wallet sign it, and verifies ownership to receive a proof hash; it then builds the unsigned claim transaction with the proof hash, signs and submits it on-chain, and polls the claim status endpoint with the transaction hash until the mint confirms

Step 1: Get the message to sign

POST /api/v2/claim/message
FieldTypeRequiredDescription
symbolstringYesToken symbol
chainIdintegerYesTarget chain ID
tokenAddressstringYesToken contract address
claimerAddressstringYesWallet address claiming the registration

Returns { message, timestamp, params, feeEstimate }. Sign message with the claimer wallet, and keep timestamp — you must send the same value to /claim/verify.

Step 2: Verify ownership

POST /api/v2/claim/verify
FieldTypeRequiredDescription
symbolstringYesToken symbol
chainIdintegerYesTarget chain ID
tokenAddressstringYesToken contract address
walletAddressstringYesWallet address claiming the registration
signaturestringYesSignature over the message from step 1
timestampintegerYesThe timestamp returned in step 1

Response:

json
{
  "verified": true,
  "verificationMethod": "deployer",
  "methodsAttempted": ["deployer"],
  "message": "Wallet deployed the token contract",
  "proofHash": "0xabc...",
  "expiresAt": 1767312000
}
FieldTypeDescription
verifiedbooleanWhether ownership was verified
verificationMethodstringMethod that succeeded: deployer, owner, majorityHolder, etc.
methodsAttemptedstring[]All methods tried
proofHashstringProof reference to pass to /api/v2/claim
expiresAtintegerUnix timestamp when the verification expires (24h)

Step 3: Build the claim transaction

POST /api/v2/claim
FieldTypeRequiredDescription
symbolstringYesToken symbol
chainIdintegerYesTarget chain ID (must be an enabled minting chain)
tokenAddressstringYesToken contract address
walletAddressstringYesWallet address claiming the registration
proofHashstringYesProof hash returned by /api/v2/claim/verify

Response:

json
{
  "success": true,
  "transaction": {
    "to": "0x1234...",
    "data": "0xabcdef...",
    "value": "10000000000000000",
    "chainId": 42161
  },
  "feeEstimate": { "gasLimit": "250000", "maxFeePerGas": "..." },
  "message": "Sign and submit the transaction to claim your crown"
}

Unsigned transaction

The response contains unsigned transaction data. Your application must sign and submit it with the claiming wallet to complete the mint. Returns 409 if the symbol is already claimed on that chain.

Step 4: Track the mint

GET /api/v2/claim/status/{txHash}

Poll with the submitted transaction hash until the mint confirms.

Solana claims

For Solana tokens, use the Solana pipeline instead of step 3:

POST /api/v2/claim/solana/build

Builds an unsigned Solana claim transaction. Supporting endpoints: POST /api/v2/claim/solana/quote (fee quote), GET /api/v2/claim/solana/status/{symbol} (status), GET /api/v2/claim/methods/{chainType} (available verification methods).

Full Claim Flow Example

javascript
async function claimRegistration(symbol, tokenAddress, chainId, signer) {
  const walletAddress = await signer.getAddress();
  const post = (path, body) => fetch(`${BASE_URL}${path}`, {
    method: 'POST',
    headers: { 'X-API-Key': API_KEY, 'Content-Type': 'application/json' },
    body: JSON.stringify(body),
  }).then(r => r.json());

  // Step 1: Get the message to sign
  const { message, timestamp } = await post('/api/v2/claim/message', {
    symbol, chainId, tokenAddress, claimerAddress: walletAddress,
  });

  // Step 2: Sign it and verify ownership
  const signature = await signer.signMessage(message);
  const verification = await post('/api/v2/claim/verify', {
    symbol, chainId, tokenAddress, walletAddress, signature, timestamp,
  });
  if (!verification.verified) {
    throw new Error(`Not verified: ${verification.message}`);
  }

  // Step 3: Build the claim transaction
  const claim = await post('/api/v2/claim', {
    symbol, chainId, tokenAddress, walletAddress,
    proofHash: verification.proofHash,
  });
  if (!claim.success) throw new Error('Claim build failed');

  // Step 4: Sign and submit on-chain
  const tx = await signer.sendTransaction(claim.transaction);
  const receipt = await tx.wait();
  return { txHash: receipt.hash, success: true };
}
python
import time

def claim_registration(symbol, token_address, chain_id, signer):
    """Complete claim flow: message -> sign -> verify -> claim."""
    wallet = signer.address

    def post(path, body):
        res = requests.post(f'{BASE_URL}{path}', json=body,
                            headers={'X-API-Key': API_KEY})
        res.raise_for_status()
        return res.json()

    # Step 1: Get the message to sign
    msg = post('/api/v2/claim/message', {
        'symbol': symbol, 'chainId': chain_id,
        'tokenAddress': token_address, 'claimerAddress': wallet,
    })

    # Step 2: Sign it and verify ownership
    signature = signer.sign_message(msg['message'])  # your wallet library
    verification = post('/api/v2/claim/verify', {
        'symbol': symbol, 'chainId': chain_id,
        'tokenAddress': token_address, 'walletAddress': wallet,
        'signature': signature, 'timestamp': msg['timestamp'],
    })
    if not verification['verified']:
        raise Exception(f"Not verified: {verification.get('message')}")

    # Step 3: Build the claim transaction
    claim = post('/api/v2/claim', {
        'symbol': symbol, 'chainId': chain_id,
        'tokenAddress': token_address, 'walletAddress': wallet,
        'proofHash': verification['proofHash'],
    })

    # Step 4: Sign and submit on-chain
    tx_hash = signer.send_transaction(claim['transaction'])
    return {'txHash': tx_hash, 'success': True}

Error Responses

StatusErrorDescription
400bad_requestMissing required fields or chain is not an enabled minting chain
401unauthorizedOwnership verification failed
409conflictSymbol already claimed on this chain

Update Token Page Profile

PUT /api/v2/registration/{id}/profile

Update the token page profile for a registration. Requires authentication — a wallet session (Authorization: Bearer <JWT> from signing in at chaindaddy.io) belonging to the registration owner or an authorized manager, in addition to your X-API-Key.

Request Body

All fields are optional — send only what you want to change:

FieldTypeDescription
namestringDisplay name
descriptionstringProject description
logoUrl / bannerUrlstringImage URLs
websitestringProject website URL
xdotcomstringX (Twitter) handle or URL
telegram / discordstringCommunity links
tagsstring[]Freeform tags
anthemUrl, anthemLoop, backgroundUrl, backgroundMode, introVideoUrl, backgroundVideoUrlvariousToken page media settings

Social/website fields that carry verification requirements are only persisted when a matching signed verification exists — unverified values are dropped silently.

Upload Token Metadata

POST /api/v2/metadata/upload

Upload token metadata (name, symbol, chain, description, logo/banner URLs, links) for pinning. URL fields are validated against SSRF and social fields are gated by the verification records for the registration.

bash
curl -X POST \
  -H "X-API-Key: cd_live_YOUR_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Doge",
    "symbol": "DOGE",
    "chain": "arbitrum",
    "description": "Updated project description",
    "website": "https://example.com"
  }' \
  "https://api.chaindaddy.io/api/v2/metadata/upload"

Common Recipes

Get Registration Status for a Symbol on a Chain

Determine if a registration is claimed and who owns it:

javascript
async function getRegistrationStatus(symbol, chain) {
  const response = await fetch(
    `${BASE_URL}/api/v2/registration/${symbol}/${chain}`,
    { headers: { 'X-API-Key': API_KEY } }
  );
  const record = await response.json();
  return {
    status: record.status,
    owner: record.owner,
    tokenId: record.tokenId,
  };
}

const status = await getRegistrationStatus('DOGE', 'arbitrum');
console.log(`Status: ${status.status}, Owner: ${status.owner}`);
python
def get_registration_status(symbol, chain):
    """Get registration status for a symbol on a specific chain."""
    record = requests.get(
        f'{BASE_URL}/api/v2/registration/{symbol}/{chain}',
        headers={'X-API-Key': API_KEY}
    ).json()

    return {
        'status': record.get('status'),
        'owner': record.get('owner'),
        'tokenId': record.get('tokenId'),
    }

status = get_registration_status('DOGE', 'arbitrum')
print(f"Status: {status['status']}, Owner: {status['owner']}")

Monitor Registration Health

Check heartbeat scores and surface at-risk registrations:

javascript
async function monitorRegistrations(entries) {
  // entries: [{ symbol: 'DOGE', chain: 'arbitrum' }, ...]
  const alerts = [];

  for (const { symbol, chain } of entries) {
    const heartbeat = await getHeartbeat(symbol, chain);
    if (heartbeat.score < 60) {
      alerts.push({ symbol, chain, score: heartbeat.score, status: heartbeat.status });
    }
  }

  return alerts;
}

const alerts = await monitorRegistrations([
  { symbol: 'DOGE', chain: 'arbitrum' },
  { symbol: 'PEPE', chain: 'base' },
]);
if (alerts.length > 0) {
  console.log('At-risk registrations:', alerts);
}
python
def monitor_registrations(entries):
    """Check heartbeat scores for multiple (symbol, chain) pairs."""
    alerts = []

    for symbol, chain in entries:
        heartbeat = get_heartbeat(symbol, chain)
        if heartbeat['score'] < 60:
            alerts.append({
                'symbol': symbol,
                'chain': chain,
                'score': heartbeat['score'],
                'status': heartbeat['status'],
            })

    return alerts

alerts = monitor_registrations([('DOGE', 'arbitrum'), ('PEPE', 'base')])
if alerts:
    print('At-risk registrations:', alerts)

Error Responses

StatusErrorDescription
400bad_requestInvalid parameters or missing required fields
401unauthorizedMissing/invalid session for authenticated endpoints
403forbiddenInvalid API key, insufficient tier, or unauthorized
404not_foundRegistration or token not found
409conflictSymbol already claimed on this chain
429rate_limit_exceededDaily or per-second rate limit exceeded

See Authentication for rate limiting details and retry strategies.