REST, GraphQL, and WebSocket reference for the Agent City 8004 Scan API.
https://agentcity.dev/8004scan/api/v1Pass your API key via the Authorization header using the Bearer scheme. Never include keys in URLs — they are visible in server logs, browser history, and referrer headers.
Authorization: Bearer ac8004_live_<your32hexchars>Limits are enforced per API key (or per IP for unauthenticated requests) in 60-second sliding windows via atomic Durable Object counters.
| Tier | Requests / min | Identified by |
|---|---|---|
| free | 100 | IP address |
| pro | 1,000 | API key |
| enterprise | 10,000 | API key |
Every response includes: X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset. On 429 responses a Retry-After header is also included.
HTTP/1.1 200 OK
Content-Type: application/json
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 997
X-RateLimit-Reset: 1743854460
{
"agents": [...],
"cursor": "eyJpZCI6NDJ9",
"hasMore": true,
"total": 2847
}HTTP/1.1 400 Bad Request
Content-Type: application/json
{
"error": {
"code": "INVALID_SORT",
"message": "sort must be one of: 'reputation', 'lastActivity', 'createdAt'"
}
}| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /8004scan/api/v1/agents | List indexed agents with filtering and cursor-based pagination | — |
| GET | /8004scan/api/v1/agents/{id} | Fetch a single agent by canonical ID | — |
| GET | /8004scan/api/v1/agents/{id}/reputation | Aggregated reputation and feedback breakdown for an agent | — |
| GET | /8004scan/api/v1/agents/{id}/validations | Validation request and response history for an agent | — |
| GET | /8004scan/api/v1/search | Full-text search over agent names and descriptions with relevance ranking | — |
| GET | /8004scan/api/v1/events | On-chain events with filtering by chain, type, and agent | — |
| GET | /8004scan/api/v1/stats | Global indexer statistics (cached for 60 seconds) | — |
| Method | URL | Purpose |
|---|---|---|
| POST | /8004scan/api/v1/graphql | Execute GraphQL queries |
| GET | /8004scan/api/v1/graphql | GraphiQL playground — dev only, requires ENABLE_GRAPHQL_INTROSPECTION=true |
depthMax query nesting depth5complexityMax query complexity score1,000batchMax batched operations per request5query TopAgents {
agents(sort: reputation, limit: 5) {
nodes {
canonicalId
name
feedbackAvg
feedbackCount
chains
isKnownRegistry
}
pageInfo {
hasNextPage
endCursor
total
}
}
}query GetAgent($id: String!) {
agent(id: $id) {
canonicalId
name
description
feedbackAvg
feedbackCount
reputation {
count
average
byTag { tag average }
trend { last30dAvg previous30dAvg delta }
}
validations {
count
passRate
byValidator { validator count avgScore }
}
services { name endpoint chainId }
chainRegistrations { chainId contractAddress agentId }
}
}query SearchAgents($q: String!) {
search(query: $q, limit: 10) {
nodes {
canonicalId
name
highlightedName
rank
feedbackAvg
chains
}
pageInfo { total page limit }
}
}query ChainEvents {
events(chain: "ethereum", type: "Registered", limit: 10) {
nodes {
eventType
chainId
agentId
txHash
blockNumber
createdAt
}
pageInfo { hasNextPage endCursor total }
}
}wss://agentcity.dev/8004scan/api/v1/ws?chain=1The chain query parameter accepts a chain ID (1, 8453, 42161, 137, 56, 587) or chain name (ethereum, base, arbitrum, polygon, bsc, netx). Defaults to ethereum.
Send a subscribe message to filter events. Empty arrays mean "all". Omitting a field also means "all".
// Subscribe to events on Ethereum and Base
{
"type": "subscribe",
"chains": ["ethereum", "base"],
"events": ["Registered", "NewFeedback"],
"agents": []
}// Server acknowledges your subscription
{
"type": "subscribed",
"filters": {
"chains": ["ethereum", "base"],
"events": ["Registered", "NewFeedback"],
"agents": []
}
}// Server pushes a live event
{
"type": "event",
"chain": "ethereum",
"event": "Registered",
"data": {
"agentId": "eip155:1:0xRegistry:42",
"contractAddress": "0xRegistry...",
"blockNumber": 19874512,
"txHash": "0xabc123..."
},
"timestamp": "2026-04-05T12:00:00Z"
}The server emits a heartbeat every 30 seconds. Connections with no client response within 90 seconds are closed with WebSocket code 1001. Send a ping at any time to reset the timer.
// Client -> Server (keep-alive)
{ "type": "ping" }
// Server -> Client (response)
{ "type": "pong" }ac8004_live_<32 hex characters>ac8004_live_# Always use the Authorization header — never pass keys in the URL
curl -H "Authorization: Bearer ac8004_live_<your-key>" \
"https://agentcity.dev/8004scan/api/v1/agents?sort=reputation"Key management requires the ADMIN_SECRET environment variable passed as a Bearer token. These endpoints are not rate-limited by API tier.
POST/8004scan/api/v1/keys— Create a new API key
curl -X POST "https://agentcity.dev/8004scan/api/v1/keys" \
-H "Authorization: Bearer <your-admin-secret>" \
-H "Content-Type: application/json" \
-d '{"owner": "your-app-name", "tier": "pro"}'
# Response (201 Created) — save rawKey immediately, it is never shown again
{
"data": {
"keyId": "key_a1b2c3d4e5f60718",
"rawKey": "ac8004_live_a1b2c3d4e5f60718293a4b5c6d7e8f90",
"tier": "pro",
"owner": "your-app-name",
"createdAt": "2026-04-05T12:00:00Z"
}
}GET/8004scan/api/v1/keys/{id}— Retrieve key info
curl "https://agentcity.dev/8004scan/api/v1/keys/key_a1b2c3d4e5f60718" \
-H "Authorization: Bearer <your-admin-secret>"DELETE/8004scan/api/v1/keys/{id}— Revoke a key
curl -X DELETE "https://agentcity.dev/8004scan/api/v1/keys/key_a1b2c3d4e5f60718" \
-H "Authorization: Bearer <your-admin-secret>"