Preferred public API is GraphQL v2.
REST v1 (PostgREST-compatible) documentation is available in
docs/rest-v1.md. GraphQL v2 remains the preferred API for new deployments.
Self-hosted: run your own indexer instance with 8004-solana-indexer. Set
INDEX_COLLECTION_METADATA=trueto ingest collection metadata from CID JSON.
The 8004 Agent Registry is indexed as a set of Metaplex Core assets under the same Solana program.
| Environment | GraphQL Endpoint | Health | Ready | Status |
|---|---|---|---|---|
| Mainnet (production) | https://8004-indexer-main.qnt.sh/v2/graphql |
https://8004-indexer-main.qnt.sh/health |
https://8004-indexer-main.qnt.sh/ready |
Live |
| Devnet (reference deployment) | https://8004-indexer-dev.qnt.sh/v2/graphql |
https://8004-indexer-dev.qnt.sh/health |
https://8004-indexer-dev.qnt.sh/ready |
Live |
| Self-hosted | https://your-indexer.example.com/v2/graphql |
https://your-indexer.example.com/health |
https://your-indexer.example.com/ready |
Custom |
SDK/public fallback slots:
- Mainnet secondary:
https://8004-indexer-main2.qnt.sh/v2/graphql - Devnet secondary:
https://8004-indexer-dev2.qnt.sh/v2/graphql - Mainnet REST secondary:
https://8004-indexer-main2.qnt.sh/rest/v1 - Devnet REST secondary:
https://8004-indexer-dev2.qnt.sh/rest/v1
Legacy public endpoints (not used by current SDK defaults and may lag behind the primary deployments):
- Mainnet legacy endpoint:
https://8004-api.qnt.sh/v2/graphql - Devnet legacy endpoint:
https://8004-indexer-production.up.railway.app/v2/graphql
The reference GraphQL deployment is public read-only.
For self-hosted production, add your own API gateway/auth if needed.
Indexer defaults (self-hosted):
- Global API limiter:
100 requests/minuteper IP - GraphQL limiter:
100 requests/minuteper IP on/v2/graphql - Replay verification limiter (
/rest/v1/verify/replay/:asset):1 request/30 secondsper IP
These defaults are configurable by environment variables for self-hosted deployments
(RATE_LIMIT_MAX_REQUESTS, GRAPHQL_RATE_LIMIT_MAX_REQUESTS, REPLAY_RATE_LIMIT_MAX_REQUESTS, REPLAY_RATE_LIMIT_WINDOW_MS).
Available Query operations:
agent(id: ID!)agents(first, skip, after, where, orderBy, orderDirection)feedback(id: ID!)feedbacks(first, skip, after, where, orderBy, orderDirection)feedbackResponse(id: ID!)feedbackResponses(first, skip, after, where, orderBy, orderDirection)revocation(id: ID!)revocations(first, skip, after, where, orderBy, orderDirection)agentMetadatas(first, skip, where)agentStats(id: ID!)protocol(id: ID!)(deprecated; useglobalStats)protocols(first, skip)(deprecated; useglobalStats)globalStatsagentReputation(asset: ID!)leaderboard(first, collection, includeOrphaned)verificationStatsagentSearch(query, first)agentRegistrationFiles(first, skip, where)hashChainHeads(agent: ID!)hashChainLatestCheckpoints(agent: ID!)hashChainReplayData(agent, chainType, fromCount, toCount, first)collections(first, skip, collectionId, collection, creator)collectionAssetCount(collection, creator)collectionAssets(collection, creator, first, skip, orderBy, orderDirection)agentChildren(parent, first, skip)agentTree(root, maxDepth, includeRoot, first, skip)agentLineage(asset, includeSelf, first, skip)
Compatibility note:
- Validation indexing is archived on-chain (
agent-registry-8004v0.5.0+). - Public API surfaces no longer expose
validation/validations; REST/rest/v1/validationsreturns410 Gone.
Collection registry lookup note:
- GraphQL supports
collections(collectionId: "<sequential_id>"). - REST supports
GET /rest/v1/collections?collection_id=eq.<sequential_id>.
GraphQL IDs use:
- Agent:
<asset_pubkey> - Feedback entity id (
Feedback.id):<asset>:<client>:<feedback_index>(canonical) - Response entity id (
FeedbackResponse.id):<asset>:<client>:<feedback_index>:<responder>:<signature_or_count>(canonical) - Revocation entity id (
Revocation.id):<asset>:<client>:<feedback_index>(canonical)
Lookup note:
feedback(id:)accepts canonical<asset>:<client>:<feedback_index>and also the legacy sequential<feedback_id>.- Sequential
feedback_idis scoped per agent/asset, not globally. Prefer canonicalFeedback.id, or pair sequential lookups with the agent scope that issued them. feedbackResponse(id:)expects canonical<asset>:<client>:<feedback_index>:<responder>:<signature_or_count>.- Legacy
sol:<...>inputs are still accepted for backward compatibility.
ProofPass note:
Feedback.solana.proofPassAuthis a GraphQL-only enrichment flag.- On self-hosted indexers it becomes meaningful when
ENABLE_PROOFPASS=trueonDB_MODE=supabaseandsupabase/migrations/20260309192500_add_extra_proofpass_feedbacks.sqlhas been applied; otherwise the field still exists and resolvesfalse.
curl "https://8004-indexer-main.qnt.sh/health"Response (example):
{ "status": "ok" }curl "https://8004-indexer-main.qnt.sh/ready"Response (example):
{
"status": "ready",
"phase": "catching_up",
"state": {
"mainSlot": 448669631,
"mainTxIndex": 29,
"counts": {
"agents": 2064,
"feedbacks": 2384,
"responses": 1196,
"revocations": 955,
"collections": 54
},
"pending": {
"agents": 0,
"feedbacks": 0,
"responses": 0,
"revocations": 0,
"metadata": 0,
"registries": 0,
"validations": 0
},
"orphans": {
"agents": 0,
"feedbacks": 0,
"responses": 9,
"revocations": 3,
"metadata": 0,
"registries": 0,
"validations": 0
}
}
}curl -X POST "https://8004-indexer-main.qnt.sh/v2/graphql" \
-H "content-type: application/json" \
--data '{"query":"{ __typename }"}'Response (example):
{ "data": { "__typename": "Query" } }curl -X POST "https://8004-indexer-main.qnt.sh/v2/graphql" \
-H "content-type: application/json" \
--data '{
"query":"query { agents(first: 5, orderBy: createdAt, orderDirection: desc) { id owner totalFeedback solana { assetPubkey } } }"
}'Response (example):
{
"data": {
"agents": [
{ "id": "ASSET_PUBKEY", "owner": "OWNER_WALLET", "totalFeedback": "12", "solana": { "assetPubkey": "ASSET_PUBKEY" } }
]
}
}curl -X POST "https://8004-indexer-main.qnt.sh/v2/graphql" \
-H "content-type: application/json" \
--data '{
"query":"query($from: BigInt!, $to: BigInt!) { agents(first: 100, where: { updatedAt_gt: $from, updatedAt_lt: $to }, orderBy: updatedAt, orderDirection: asc) { id owner totalFeedback updatedAt } }",
"variables":{"from":"1770421000","to":"1770422000"}
}'curl -X POST "https://8004-indexer-main.qnt.sh/v2/graphql" \
-H "content-type: application/json" \
--data '{
"query":"query($agent: ID!) { feedbacks(first: 10, where: { agent: $agent }) { id clientAddress isRevoked } }",
"variables":{"agent":"FmWeWQYzyt6zoANeqXT8DcNiYAom9ioNh9hXxWr6oxjX"}
}'Response (example):
{
"data": {
"feedbacks": [
{ "id": "ASSET_PUBKEY:CLIENT_WALLET:0", "clientAddress": "CLIENT_WALLET", "isRevoked": false }
]
}
}curl -X POST "https://8004-indexer-main.qnt.sh/v2/graphql" \
-H "content-type: application/json" \
--data '{
"query":"query($q: String!) { agentSearch(query: $q, first: 10) { id owner createdAt solana { trustTier qualityScore } } }",
"variables":{"q":"agent"}
}'Response (example):
{
"data": {
"agentSearch": [
{ "id": "ASSET_PUBKEY", "owner": "OWNER_WALLET", "createdAt": "1700000000", "solana": { "trustTier": 2, "qualityScore": 8400 } }
]
}
}curl -X POST "https://8004-indexer-main.qnt.sh/v2/graphql" \
-H "content-type: application/json" \
--data '{
"query":"query($id: ID!) { agent(id: $id) { id owner registrationFile { name description image active mcpEndpoint mcpTools a2aEndpoint a2aSkills oasfSkills oasfDomains hasOASF } } }",
"variables":{"id":"FmWeWQYzyt6zoANeqXT8DcNiYAom9ioNh9hXxWr6oxjX"}
}'Response (example):
{
"data": {
"agent": {
"id": "ASSET_PUBKEY",
"owner": "OWNER_WALLET",
"registrationFile": {
"name": "My Agent",
"description": "Short description",
"image": "ipfs://bafy...",
"active": true,
"mcpEndpoint": "https://example.com/mcp",
"mcpTools": ["tool_a", "tool_b"],
"a2aEndpoint": "https://example.com/a2a",
"a2aSkills": ["skill_a", "skill_b"],
"oasfSkills": ["skill_a", "skill_b"],
"oasfDomains": ["domain_a", "domain_b"],
"hasOASF": true
}
}
}
}curl -X POST "https://8004-indexer-main.qnt.sh/v2/graphql" \
-H "content-type: application/json" \
--data '{
"query":"query { globalStats { id totalAgents totalFeedback totalCollections platinumAgents goldAgents avgQuality tags } }"
}'Response (example):
{
"data": {
"globalStats": {
"id": "global-mainnet",
"totalAgents": "136",
"totalFeedback": "420",
"totalCollections": "89",
"platinumAgents": "3",
"goldAgents": "12",
"avgQuality": 78,
"tags": ["tag_a", "tag_b"]
}
}
}totalCollections counts canonical collection scopes (creator + collectionPointer), not raw registries or raw Metaplex collection pubkeys.
- Agents
- Feedbacks
- Responses
- Metadata
- Leaderboard
- Collections
- Collection + Parent-Child Examples
- Collection + Parent-Child REST Examples
- Stats
- Integrity / Hash-Chain
aftercursor is supported onagents,feedbacks,feedbackResponses,revocations- Cursor pagination is only valid with
orderBy: createdAt - Do not combine
afterandskipin the same query - Request the
cursorfield in list queries, and pass it back asafterto fetch the next page
If you need PostgREST-compatible endpoints, use: