Take the docs into your AI

Every product guide, integration instructions and the complete API specification in one document.

All documentation

Every product guide and the generated API reference, in reading order. The Markdown export contains the same guides and the complete API specification.

Last verified against production: . See current limits and availability.

Open What Fletch is

What Fletch is

A hosted control panel for Robinhood Chain: build an app, watch a token, or look up the chain.

Three things you can do

Build turns a description into an app with source code, toolchain results and a hosted front end; apps that need their own contract can deploy it to Robinhood Chain testnet. Watch follows a token or registry condition on the server and sends matching events to Telegram or a webhook. Registry & Markets shows listed assets, discovered pools and token provenance alongside the facts Fletch has read.

Fletch is for people trading and building on Robinhood Chain. Look up the contract behind a ticker, keep an alert running after the tab closes, and turn an idea into an app without setting up a server or supplying an RPC key.

Start with your task

Read the receipt

A build's compiler and test reports describe what ran. A publication link points to the recorded hosted app. Registry observations carry their reading times and coverage. A missing measurement appears as a dash in the interface and usually null in JSON.

The registry follows mainnet, chain 4663. The hosted builder currently deploys contracts to testnet, chain 46630. Check the limits page for the current credit grant, deployment availability and work still planned.

Open Why it is different

Why it is different

Addresses, observations, server checkpoints and toolchain results give you evidence to inspect.

Identity starts with an address

Several contracts can use the same ticker. Search CASHCAT in Markets and compare the separate addresses, pools, observed depth and available activity. A familiar name alone cannot establish which contract people trade.

Fletch checks Robinhood's published listings against bytecode, symbol and decimals. Other discovered tokens receive a community, lookalike or unknown verdict according to their recorded evidence. A lookalike warning includes the verified address it matches. Provenance describes identity; investment decisions and contract-risk assessment need further evidence.

Numbers have a source and an age

A DEX price comes from recorded pool state. A feed price comes from the specific feed Fletch reads. Compiler results come from Foundry. These sources answer different questions, and the interface labels them.

Unread means Fletch has no usable reading. Stale means a previous observation has passed its current-data window. Partial history means the indexer has not covered the requested interval. A dash keeps those cases visible; zero is reserved for an observed zero.

The watcher lives on a server

The Watch daemon checkpoints its block position in Postgres, reads logs in bounded ranges and places matched events in a delivery outbox. A process restart resumes from stored progress. Delivery failures retry with backoff, and duplicate event keys prevent repeated matching from creating a new alert.

Events are sequencer-confirmed. A chain reorganization can replace them. When a checkpoint hash changes, the poller rewinds up to 64 blocks and retracts pending deliveries above that point. Messages already sent remain in the recipient's chat. Treat an alert as an observation at that block, with the transaction receipt available to inspect.

The same data is available to agents

An agent can read llms.txt, call the scoped-key API or connect the MCP server. Ask for the relevant token and its freshness before using an address or price in generated code. The builder receives short endpoint guidance and fetches chain facts on demand, so unrelated prompts do not carry a market dump.

Open Quickstart: watch a token

Quickstart: watch a token

Connect a wallet, choose a condition, link Telegram and check the first matching event.

Wallet in, alert out

  1. Open Dashboard → Watch and connect your wallet. Sign the sign-in message, then choose New watcher.
  2. Choose Large transfers for a token-wide amount threshold, or Wallet activity to follow a particular sender or recipient. Use Listed asset to select a listing, or Any token address to paste a full contract address. The address lookup shows the recorded trust verdict before you submit.
  3. Enter the amount in the token's own units. Large transfers needs a positive threshold. Wallet activity also needs a wallet address and accepts 0 to match every transfer involving that wallet. Give the watcher a name and choose Create watcher.
  4. Open Dashboard → Settings → Telegram alerts. Under the Fletch bot option, open the link and press Start in Telegram. Return to Settings and confirm it shows linked. For your own bot, paste the BotFather token, save it, press Start in that bot and use the Find my chat control.
  5. Return to Watch and leave the watcher enabled. After a new transfer meets the condition, open Dashboard → Alerts and inspect its status and transaction link. A sent delivery should also appear in your linked Telegram chat. An empty history means no matching event has been recorded yet.

Before you leave the tab

Watch is free during beta, with 5 watchers per account. The first Telegram watcher can be saved before you link a chat; additional Telegram watchers require the link. Match records can be held while delivery has no destination. A saved watcher and a linked chat are separate states.

A failed bytecode or decimals check asks you to confirm Watch anyway. This records your acknowledgement; it cannot make an unreadable contract emit ERC-20 transfer events. For a first alert, choose a token and condition with activity you can independently inspect.

If delivery does not arrive, check the linked chat, watcher status, Alerts and the registry status page. A real matching transaction and a delivered message are the end-to-end check.

Open Quickstart: build an app

Quickstart: build an app

Describe the app, inspect its build results and open the recorded publication link.

Prompt in, app out

  1. Open Dashboard → Build, connect your wallet and choose New app. Describe what users can do, what belongs on chain and what the page should show.
  2. Attach a long specification with the paperclip. Long pasted briefs become text files with a visible attachment chip. The planner receives attached text before it decides whether the app needs contracts or a wallet. Add a short instruction such as 'Use the attached brief.'
  3. Choose Platform model or a saved model connection. Read the cost on the Build button and send. Enter sends; Shift+Enter inserts a newline. While Enhance is running, wait for it to finish before submitting.
  4. If both execution slots are busy, the reply shows that your build is queued and its position. Cancel removes a queued run. Edit restores its prompt, files and model selection to the composer. Once it starts, Build details streams the recorded steps.
  5. Follow Idea → Contract → Web page → Published. Read the toolchain verdict above the workspace. Open the live URL once a publication is recorded, then test the app's own interactions on the stated network.
A raffle where anyone buys tickets with ETH, the owner draws a winner after a block deadline, and the winner claims the pot.

Allow time and check the build results

Build stages can include compilation, tests, security analysis, deployment and hosting. Each stage takes time and produces its own recorded result. Tests can be absent when the app supplies no test files. Open the toolchain reports and publication link, then check the app's required interactions yourself. The compiler verdict stays visible even when the model's reply is shorter.

Closing the browser leaves the server-owned build running. Reopen the project to reconnect to its stored progress. A failed charged build receives its Fletch credit refund; provider charges for own-key usage follow the provider's billing. Read the current execution limits before starting a large specification.

Open Quickstart: use the API

Quickstart: use the API

One request returns a token's recorded trust verdict, metadata and observation time.

Create a scoped key

  1. Sign in, open Dashboard → Settings → API keys and name a key. Choose Read the registry (registry:read) for this example, then Create key.
  2. Copy the key when it is shown. Keep it in your local environment as FLETCH_API_KEY. This is a Fletch API credential; model provider keys belong in the separate model connection form.
  3. Run the request below. Inspect trust, source, address, symbol and readAt. Use impersonates when the verdict is lookalike. Use the complete address as the identity.
curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer $FLETCH_API_KEY" \
  https://fletch.now/api/v1/tokens/0x6bac06600d220ac5ac281ad1f504d2cf0f90f6e6

Read the response

The response is JSON. trust is verified, listed, lookalike, community or unknown. readAt is the observation time, source names the registry or discovered record, and null means a fact is unavailable. market may be null even when the token is known.

Public registry reads also work without the Authorization header. A valid key without registry:read uses the anonymous allowance for these public reads. Account operations require the scope named by their OpenAPI entry: missing or invalid authentication returns 401, and a missing required scope returns 403. A 429 indicates a rate limit. Honor Retry-After before retrying.

curl --fail-with-body --silent --show-error https://fletch.now/api/v1/status
Open Build

Build

Projects, prompts, models, files, previews and the receipts behind a published app.

Projects and conversation

Choose a project from the menu or create a new app. Rename the project with its rename control. Each prompt becomes a build in that project's conversation. Switching projects updates the conversation, steps, files and preview; a server-owned run continues while you view another project.

Preview shows the hosted app. Code shows grouped files, copy controls, changed-file markers and report or ABI artifacts when present. Chat gives the conversation a centered reading column. The selected mode is saved per project. Drag the desktop divider to widen the conversation up to half the workspace.

Each reply has one Build details disclosure with that run's steps and available tool output. It opens during a running build and collapses at completion. The working or reconnecting indicator describes the stream state; elapsed time alone does not prove that the model has produced another step.

Prompt and attachments

The composer accepts 24,000 characters. Text files can be MD, TXT, CSV, JSON or YAML: five files, 64 KiB each and 128 KiB combined. A large paste becomes a recoverable brief file. Open its chip to inspect the complete text. Attached text is included before needs analysis and is also placed in the sandbox workspace.

Paste, pick or drop PNG and JPEG images when the selected model supports image input. Limits are three images, 2 MiB each, 4 MiB combined, 4096 pixels per side and 16 megapixels. Unsupported input is refused with an error; the UI must confirm an attachment before you rely on it.

Enhance revises the prompt before a build. Its pending state blocks Build. Enter sends, Shift+Enter adds a line, Cmd/Ctrl+Enter also sends and Cmd/Ctrl+K focuses the composer. A failed submission preserves the draft for correction.

Models and your own key

Settings accepts OpenAI, Anthropic and Kimi API connections. Save a provider key, then choose that connection from the composer's model menu. An own-key build costs 0 Fletch credits; your provider charges for API usage. A chat subscription is separate from a provider API account.

Hosted keys are encrypted at rest and decrypted by Fletch's server for provider requests. The coding agent receives a temporary scoped proxy credential. Operators with access to the server and its encryption material can access hosted keys. Revoke or replace a connection in Settings when needed.

A build records its selected provider, model and credential version. Changing the menu affects a future submission. A rejected or unavailable provider returns an error that needs to be resolved with that provider or another connection.

Queue, progress and retry

Two execution slots are coordinated through Postgres. Additional accepted runs wait in the queue and show their position. Queued Cancel and Edit handle the race with a worker claiming the run: if it has started, the interface refreshes its actual state.

Stop requests cancellation during a running build, including tests, deployment and publishing. The console shows Stopping while the server shuts down model and tool work. Saved source stays in your project. Transactions already broadcast keep their on-chain outcome, and provider usage already incurred remains subject to provider billing.

Closing a tab does not cancel the server's run. Reopening a project reloads saved steps and reconnects to the stream. Source and session files are retained through supported maintenance. Current runtime and recovery limits are listed on the limits page.

A failed follow-up preserves the project's recorded published app. Run it again starts another attempt using the available project context. A refund is an append-only credit entry tied to the charged run; an own-key run has no Fletch debit to refund.

The sandbox and verdict

Model-authored commands run in the build container with a read-only root, restricted capabilities and a mounted workspace. Compilation, tests and security analysis produce stored reports. Read those reports to see which checks ran and their exact output.

The pipeline links to recorded contract and host receipts. The verdict is produced by the toolchain and remains above the workspace. A model's account of a change is useful context, while the compiler and transaction receipts establish their own results.

Audit for mainnet places a review instruction in the composer. Submit it to run a follow-up build through the same model and toolchain. Review its reports and remaining findings before any deployment decision.

Preview and wallet behavior

The preview toolbar has the live URL, Refresh, Open app and a settings gear. Fit is the default. The gear contains device widths and zoom; a fixed device viewport scales to fit the available pane.

Signing apps use the shared wallet component. It supports compatible injected EVM wallets, including Phantom's EVM provider, and WalletConnect pairing when a Reown project ID is configured. Wallet availability also depends on the browser, extension and chain support. Inspect the generated app's connection and transaction flows after publication.

Contract deployments currently target Robinhood Chain testnet, 46630. Front ends are hosted under apps.fletch.now. Use Code to inspect or copy the source, reports and ABI that the build actually produced.

Open Watch

Watch

Token conditions, chain events, delivery channels and the daemon that keeps checking them.

Choose the event

KindWhat matches
large_transferERC-20 transfers at or above a positive amount in the token's units.
wallet_activityERC-20 transfers sent or received by one wallet; threshold 0 includes every matching transfer.
token_eventRecorded authority events for a listed token, including pauses, halts, multiplier changes and feed or supply observations.
registry_eventRecorded issuer-registry and chain events, including upgrades, blocked addresses and listings.
new_poolNewly discovered pools after their state has been read; optionally only tokens that collide with a verified asset.

Targets and controls

Transfer watchers accept a listed asset or a pasted mainnet token address. An unlisted address is checked for bytecode and readable decimals. If that check fails, an explicit Watch anyway confirmation is recorded on the watcher. Token-event watchers require a registry asset. Registry-event and new-pool watchers have chain-wide targets.

In Watch, use Pause, Resume or Delete. To change the condition, create a replacement watcher and remove the old one when appropriate. The API can change an existing watcher's enabled state or delivery endpoint. A threshold is a token amount, so use its decimals and units rather than interpreting the amount as dollars.

An account can have 5 watchers, including at most 1 new-pool watcher. Platform capacity is 500. A new-pool matcher handles up to 20 pools per watcher per run.

Telegram and your own endpoint

Settings offers the configured Fletch bot and your own Telegram bot. For the Fletch bot, use the account-linking URL and press Start. For your own bot, create it with BotFather, save its token, press Start and find your chat from Settings. The linked destination is shown before you rely on delivery.

The first Telegram watcher may be saved before linking; further Telegram watchers require a chat. Unlinked matches are held. A registered, enabled webhook can be chosen as a watcher's destination instead. Its signed JSON delivery uses the same outbox and retry process.

Trust in the message

Token transfer and new-pool payloads carry a trust stamp when the alert is formed. A lookalike warning includes the verified address it matches. Authority alerts carry the recorded issuer event and its registry link. Historical payloads created before trust stamps existed may have no stamp.

A verified identity says which listed contract was observed. It does not establish an investment recommendation or a security audit. Follow the transaction and provenance links when evaluating an alert.

Heartbeat, lag and delivery

The transfer poll loop runs every 6 seconds and the delivery loop every 1.5 seconds. These are scheduling intervals; RPC work, backlogs and retries affect delivery time. The daily RPC ceiling is 200,000.

Active means the watcher is near its last observed head. Catching up means its checkpoint is behind. Degraded means a read or delivery dependency needs attention. A beating daemon proves the process is reporting; inspect individual jobs and checkpoints to judge coverage.

Delivery records can be held, pending, sent, failed or retracted. Transient failures retry with backoff for up to 8 attempts. Events are sequencer-confirmed and can be affected by a reorganization. The recorded block hash and transaction identify the observation.

Open Registry & Markets

Registry & Markets

Find the right contract, compare recorded pool facts and understand freshness and coverage.

Listings and discovery

The Registry follows Robinhood's published asset list and preserves when each listing was first seen. Bytecode and metadata checks establish whether the contract matches the listing. Discovered tokens are stored separately; a factory event or user-submitted address does not create an issuer listing.

DEX discovery reads events from recorded Uniswap deployments. Metadata comes from token contract calls. Pool state, swaps, holders and transfer history are separate indexing jobs with separate coverage. Discovery of a pool can precede a usable price or complete activity window.

Search and compare

Search Markets by ticker, name, token address, pool address or full v4 pool ID. An unresolved token can still have an address page. Similar-ticker notices group collisions so you can compare contract addresses and the pools associated with each one.

Volume sorting uses measured current volume where available, with depth and swap activity as the documented fallback. Missing or stale volume remains empty. Read the ranking note before treating an order based on depth as a volume leaderboard.

A stale or unread search result and a token-page view can queue a bounded refresh. This work is rate limited and shares a small worker budget. A page request can therefore return its existing recorded state while the refresh waits.

Tiers and coverage

The status panel reports newest counted block, lag, pool enrollment and complete windows per tier. Today's newest counted block alone does not prove every pool has 24 hours of history. Separate tail and backfill jobs keep those claims distinct.

Tier or readingHow to use it
ActivePools selected by recorded depth or activity receive priority sampling and live swap work. Check each pool's actual reading time.
QuietLower-activity pools receive a slower background cycle and lower-priority historical work.
DormantIndividual state and metadata reads are demand-driven. A stored pool can remain unread until needed.
Live tailCounts recent canonical swap logs. Its newest block and lag describe how close the indexer is to the observed head.
Historical coverageRecords which block ranges were counted for a pool. A complete rolling window requires the entire interval, not just a recent swap.

Read the numbers

DEX price is derived from pool state. Feed price is a separate reading from a recorded feed. Depth semantics depend on the pool: v3 uses observed quote-side holdings, while v4 uses a bounded estimate where per-pool reserves are unavailable. Read the field's label and API description.

Pool state older than ten minutes is stale for current price and depth. Invalid or future observation times also fail the freshness check. Historical observations retain their real timestamps. Exact rolling swap and transaction counts require complete canonical coverage and a current metrics reading.

A missing USD volume, market value, change percentage or feed premium stays a dash. A readable token name does not supply those measurements. Inspect the API's null values, stateCurrent, stateCheckedAt and coverage fields before using a result.

For a community token with readable supply, decimals, burn balances and a usable pool price, market capitalization uses total supply minus balances at the zero and dead addresses, multiplied by that price. This is an upper bound on circulating value: other locked or inactive balances may still be included. FDV uses the full supply. The API exposes burnedRaw and marketCapUsd; missing inputs or a nonpositive remaining supply leave marketCapUsd null.

The token page

Listed token pages show the contract, issuer listing, available on-chain state, feed readings, pools and historical sections. Stock Tokens retain the issuer's multiplier semantics; apply conversions according to the field description. Bridged-asset pages may show origin and escrow reconciliation when those reads exist.

Holders and transfer history have their own ledger checkpoints. A partial holder table describes the indexed portion. First seen is the first recorded observation, while checked-at timestamps describe later reads. Discovered tokens use address routes so a ticker collision cannot claim a listed token's symbol URL.

Open Trust levels

Trust levels

A provenance verdict identifies the evidence behind a token's identity. It is not an endorsement or a security audit.

The current vocabulary

VerdictEvidenceHow to interpret it
verifiedRobinhood lists the address; bytecode was found and the contract's symbol and decimals match the listing.The recorded contract matches that issuer listing. Read the asset type to distinguish Stock Tokens, stablecoins and bridged assets.
listedThe address is on Robinhood's list, with confirmation incomplete or a contract metadata mismatch.The listing is known; inspect the contract observations before treating it as confirmed.
lookalikeA non-listed token's normalized symbol or name collides with a verified asset, or the recorded lookalike scan supplies matching evidence.Compare the included verified address. The collision describes identity evidence, not the deployer's intent.
communityA discovered contract has bytecode plus readable name, symbol and decimals, with no recorded verified-asset collision.The metadata is the contract's own claim. It remains unverified by the issuer registry.
unknownThe address is unresolved, or bytecode and complete metadata could not be confirmed.Missing fields remain empty. Retry after a successful refresh or inspect the contract directly.

How normalization works

The shared trust rules case-fold names and symbols, remove whitespace, invisible marks and accents, and map common Cyrillic and Greek lookalikes. They fold l/L/I/1 together and O/0 together. For example, Cyrillic Т and Greek Τ compare with Latin T. Normalization tests cover these collisions.

The lookalike scan also reads the issuer beacon. Its unlisted-stock classification is excluded from the scan's impersonation evidence. Read a token's actual verdict and provenance instead of inferring a badge from its name.

Resolve a contract

The response carries trust, label, detail, source, metadata and readAt. A lookalike also carries impersonates with the verified symbol and address. Address reads may queue a bounded metadata or pool refresh and return the current stored result immediately.

Bridge reconciliation is recorded separately on relevant asset pages. Current public trust responses use the five values above. Consult the limits page for planned additions to this vocabulary.

curl --fail-with-body https://fletch.now/api/v1/tokens/0x6bac06600d220ac5ac281ad1f504d2cf0f90f6e6
Open For agents

For agents

Fetch relevant chain facts on demand and preserve their provenance, timestamp and coverage.

Connect the interface you use

A small retrieval loop

  1. Read /api/v1/status when freshness matters. HTTP 200 means the status request succeeded; inspect its verdict, jobs, timestamps and checkpoints.
  2. Resolve a known address through /api/v1/tokens/{address}, or narrow a listed-asset lookup by symbol. Search pools only when the task needs market data. Keep only the fields relevant to the user's task.
  3. Carry the chain ID, address, trust verdict and observation times alongside a number. Preserve nulls and partial-coverage markers. Fetch a specific historical endpoint for a historical question.
  4. Honor ETag and If-None-Match. A 304 has no JSON body; reuse the previous representation. Respect Retry-After on 429 and apply bounded backoff. Subscribe to the registry event stream or signed webhooks when they fit the task.

Authentication and precision

Public registry GETs support cross-origin reads. Account operations use a scoped Fletch bearer key and the x-required-scope in OpenAPI. Keep credentials on your server or local process. A registry:read key does not grant watcher writes or build creation.

Raw token quantities and large block values may be decimal strings. Preserve integer precision and use the token's decimals. A price snapshot is valid only within its own observation window. Ask for provenance before turning a matching ticker into an address in generated code.

Open API reference

API reference

34 operations generated at build time from the same OpenAPI document served by this API. Expand an endpoint for its parameters, body and response definitions.

Base URL and authentication

Base URL: https://fletch.now/api/v1. Public operations have an empty security array. Keyed operations name their required scope. Create a Fletch key in Dashboard Settings and send it as a bearer token.

curl --fail-with-body --silent --show-error \
  -H "Authorization: Bearer $FLETCH_API_KEY" \
  https://fletch.now/api/v1/watchers

Schema references use the named definitions at the bottom of this page. The complete JSON and interactive explorer are also available.

OpenAPI JSON · Interactive API explorer

Status

Whether the registry is live and how old each figure is. Read this first when freshness matters.

GET /chains/{chainId}/statusWhether the registry is live: the daemon's heartbeat, every job against its cadence, the scanners still reading history, and the age of every published figure

Public. Always 200; the verdict is in the body ('live', 'degraded', 'stale', 'never'), so a stale registry is a fact to read rather than an error to retry. Each job carries its cadence, last successful run, age and verdict ('fresh', 'late', 'failing', 'filling', 'stalled', 'never'); metadataBacklog reports the measured due, visible, never-read and failed token counts after the last successful metadata batch; filling does not mean complete coverage; each figure names the job that writes it and the newest timestamp behind it. Also served at /api/v1/status.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  }
]

Responses

{
  "200": {
    "description": "Freshness",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "verdict": {
              "type": "string",
              "enum": [
                "live",
                "degraded",
                "stale",
                "never"
              ]
            },
            "summary": {
              "type": "string"
            },
            "daemon": {
              "type": "object"
            },
            "head": {
              "type": [
                "object",
                "null"
              ]
            },
            "swapIndexer": {
              "type": "object",
              "description": "Live swap tail and separate backwards backfill. Coverage is measured independently of daemon health. Historical USD valuations remain unavailable.",
              "properties": {
                "mode": {
                  "const": "live_and_backwards"
                },
                "checkedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "newestCountedBlock": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "newestCountedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "headBlock": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "headReadAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "lagBlocks": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "lagSeconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0,
                  "description": "Wall-clock age of the newest indexed block, independent of assumed block cadence."
                },
                "windowStartAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "windowEndAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "current": {
                  "type": "boolean",
                  "description": "The indexed boundary is at most 120 seconds old; individual pools also require complete coverage."
                },
                "historicalUsdAvailable": {
                  "const": false
                },
                "tiers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "tier": {
                        "type": "string",
                        "enum": [
                          "active",
                          "quiet",
                          "dormant"
                        ]
                      },
                      "totalPools": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "enrolledPools": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "complete24hPools": {
                        "type": "integer",
                        "minimum": 0
                      }
                    },
                    "required": [
                      "tier",
                      "totalPools",
                      "enrolledPools",
                      "complete24hPools"
                    ]
                  }
                }
              },
              "required": [
                "mode",
                "checkedAt",
                "newestCountedBlock",
                "newestCountedAt",
                "headBlock",
                "headReadAt",
                "lagBlocks",
                "lagSeconds",
                "windowStartAt",
                "windowEndAt",
                "current",
                "historicalUsdAvailable",
                "tiers"
              ]
            },
            "jobs": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "job": {
                    "type": "string"
                  },
                  "cadenceSeconds": {
                    "type": "number"
                  },
                  "verdict": {
                    "type": "string",
                    "enum": [
                      "fresh",
                      "late",
                      "failing",
                      "filling",
                      "stalled",
                      "never"
                    ]
                  },
                  "metadataBacklog": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "Metadata queue measured after this job's last successful batch. Null means no batch has reported coverage yet; a fresh batch does not imply complete token coverage.",
                    "properties": {
                      "total": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "due": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "visibleDue": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "neverRead": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "errors": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "oldestCheckedAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "measuredAt": {
                        "type": "string",
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "total",
                      "due",
                      "visibleDue",
                      "neverRead",
                      "errors",
                      "oldestCheckedAt",
                      "measuredAt"
                    ]
                  }
                },
                "required": [
                  "job",
                  "cadenceSeconds",
                  "verdict",
                  "metadataBacklog"
                ]
              }
            },
            "figures": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /statusAlias of /chains/4663/status: whether the registry is live

Public

Responses

{
  "200": {
    "description": "Freshness",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "verdict": {
              "type": "string",
              "enum": [
                "live",
                "degraded",
                "stale",
                "never"
              ]
            },
            "summary": {
              "type": "string"
            },
            "daemon": {
              "type": "object"
            },
            "head": {
              "type": [
                "object",
                "null"
              ]
            },
            "swapIndexer": {
              "type": "object",
              "description": "Live swap tail and separate backwards backfill. Coverage is measured independently of daemon health. Historical USD valuations remain unavailable.",
              "properties": {
                "mode": {
                  "const": "live_and_backwards"
                },
                "checkedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "newestCountedBlock": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "newestCountedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "headBlock": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "headReadAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "lagBlocks": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "lagSeconds": {
                  "type": [
                    "integer",
                    "null"
                  ],
                  "minimum": 0,
                  "description": "Wall-clock age of the newest indexed block, independent of assumed block cadence."
                },
                "windowStartAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "windowEndAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "current": {
                  "type": "boolean",
                  "description": "The indexed boundary is at most 120 seconds old; individual pools also require complete coverage."
                },
                "historicalUsdAvailable": {
                  "const": false
                },
                "tiers": {
                  "type": "array",
                  "items": {
                    "type": "object",
                    "properties": {
                      "tier": {
                        "type": "string",
                        "enum": [
                          "active",
                          "quiet",
                          "dormant"
                        ]
                      },
                      "totalPools": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "enrolledPools": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "complete24hPools": {
                        "type": "integer",
                        "minimum": 0
                      }
                    },
                    "required": [
                      "tier",
                      "totalPools",
                      "enrolledPools",
                      "complete24hPools"
                    ]
                  }
                }
              },
              "required": [
                "mode",
                "checkedAt",
                "newestCountedBlock",
                "newestCountedAt",
                "headBlock",
                "headReadAt",
                "lagBlocks",
                "lagSeconds",
                "windowStartAt",
                "windowEndAt",
                "current",
                "historicalUsdAvailable",
                "tiers"
              ]
            },
            "jobs": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "job": {
                    "type": "string"
                  },
                  "cadenceSeconds": {
                    "type": "number"
                  },
                  "verdict": {
                    "type": "string",
                    "enum": [
                      "fresh",
                      "late",
                      "failing",
                      "filling",
                      "stalled",
                      "never"
                    ]
                  },
                  "metadataBacklog": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "Metadata queue measured after this job's last successful batch. Null means no batch has reported coverage yet; a fresh batch does not imply complete token coverage.",
                    "properties": {
                      "total": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "due": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "visibleDue": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "neverRead": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "errors": {
                        "type": "integer",
                        "minimum": 0
                      },
                      "oldestCheckedAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "measuredAt": {
                        "type": "string",
                        "format": "date-time"
                      }
                    },
                    "required": [
                      "total",
                      "due",
                      "visibleDue",
                      "neverRead",
                      "errors",
                      "oldestCheckedAt",
                      "measuredAt"
                    ]
                  }
                },
                "required": [
                  "job",
                  "cadenceSeconds",
                  "verdict",
                  "metadataBacklog"
                ]
              }
            },
            "figures": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}

Registry

Every verified asset on Robinhood Chain with its live state: addresses, multipliers, pauses, feeds, quotes, supply, holders, pools, history.

GET /chains/{chainId}/assetsList (and optionally search) registry assets on a chain, each with its live on-chain state

Public. Anonymous callers get 120 requests a minute per address; a key or a session uses its own budget. Each asset carries `state`: multiplier, pending multiplier, pause flags, supply, canonical proof, the Chainlink feed and Robinhood's quote.

Public

Parameters

[
  {
    "name": "trust",
    "in": "query",
    "schema": {
      "type": "string",
      "enum": [
        "verified",
        "listed",
        "lookalike",
        "community",
        "unknown"
      ]
    },
    "description": "Filter the Robinhood listing collection by its shared trust verdict. Community tokens are resolved by /tokens/{address} and listed under /dex/pools; they are not added to Robinhood's registry."
  },
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "q",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "description": "Symbol or name substring"
  },
  {
    "name": "symbols",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "example": "TSLA,AAPL",
    "description": "Comma-separated exact tickers, up to 200; any past that are ignored"
  },
  {
    "name": "fields",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "example": "lookalikes,feedRounds,concentration",
    "description": "Extra per-asset blocks: lookalikes, corporateActions, multiplierHistory, feedRounds, concentration (up to 50 assets)"
  }
]

Responses

{
  "200": {
    "description": "Assets, each with trust and state, plus any extra blocks fields= asked for",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "assets": {
              "type": "array",
              "items": {
                "allOf": [
                  {
                    "type": "object",
                    "properties": {
                      "id": {
                        "type": "string",
                        "description": "`${chainId}:${address}`"
                      },
                      "chainId": {
                        "type": "integer"
                      },
                      "address": {
                        "type": "string"
                      },
                      "symbol": {
                        "type": "string"
                      },
                      "name": {
                        "type": "string"
                      },
                      "assetType": {
                        "type": "string",
                        "enum": [
                          "stock_token",
                          "stablecoin",
                          "wrapped_native",
                          "bridged"
                        ]
                      },
                      "decimals": {
                        "type": "integer"
                      },
                      "status": {
                        "type": "string"
                      },
                      "source": {
                        "type": "string"
                      },
                      "sourceUri": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "observedAt": {
                        "type": "string",
                        "format": "date-time"
                      },
                      "firstSeenAt": {
                        "type": "string",
                        "format": "date-time",
                        "description": "When Fletch first saw the token; Robinhood publishes no listing date"
                      },
                      "verifiedAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "onchainName": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "onchainSymbol": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "onchainDecimals": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "metadataCheckedAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "isin": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "logoUrl": {
                        "type": [
                          "string",
                          "null"
                        ]
                      }
                    },
                    "required": [
                      "id",
                      "chainId",
                      "address",
                      "symbol",
                      "name",
                      "assetType",
                      "decimals",
                      "status",
                      "source"
                    ]
                  },
                  {
                    "type": "object",
                    "properties": {
                      "trust": {
                        "type": "object",
                        "description": "Derived from the row: whether bytecode was found and the contract agrees with the listing.",
                        "properties": {
                          "level": {
                            "type": "string",
                            "enum": [
                              "verified",
                              "listed",
                              "lookalike",
                              "community",
                              "unknown"
                            ]
                          },
                          "label": {
                            "type": "string"
                          },
                          "detail": {
                            "type": "string"
                          }
                        }
                      },
                      "state": {
                        "type": [
                          "object",
                          "null"
                        ],
                        "description": "The asset's live state as the registry daemon last read it; every sub-block carries the time it was read.",
                        "properties": {
                          "multiplier": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "pendingMultiplier": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "multiplierEffectiveAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          },
                          "tokenPaused": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "oraclePaused": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "totalSupplyRaw": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "totalSupplyUi": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "canonical": {
                            "type": [
                              "boolean",
                              "null"
                            ]
                          },
                          "beacon": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "implementation": {
                            "type": [
                              "string",
                              "null"
                            ]
                          },
                          "feed": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "properties": {
                              "address": {
                                "type": "string"
                              },
                              "price": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "updatedAt": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              },
                              "stale": {
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              }
                            }
                          },
                          "quote": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "properties": {
                              "bid": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "ask": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "tradingHalt": {
                                "type": [
                                  "boolean",
                                  "null"
                                ]
                              },
                              "dailyVolume": {
                                "type": [
                                  "number",
                                  "null"
                                ]
                              },
                              "at": {
                                "type": [
                                  "string",
                                  "null"
                                ]
                              }
                            }
                          },
                          "priceDivergencePct": {
                            "type": [
                              "number",
                              "null"
                            ]
                          },
                          "dex": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "description": "The deepest dollar-priced pool and its premium to the feed."
                          },
                          "secondSource": {
                            "type": [
                              "object",
                              "null"
                            ],
                            "description": "Blockscout's holders, transfers and supply, with supplyAgreement agree|close|differ|unknown."
                          },
                          "checkedAt": {
                            "type": [
                              "string",
                              "null"
                            ],
                            "format": "date-time"
                          }
                        }
                      },
                      "lookalikes": {
                        "type": "array",
                        "items": {
                          "type": "object"
                        }
                      },
                      "corporateActions": {
                        "type": "array",
                        "items": {
                          "type": "object"
                        }
                      },
                      "multiplierHistory": {
                        "type": "array",
                        "items": {
                          "type": "object"
                        }
                      },
                      "feedRounds": {
                        "type": "array",
                        "items": {
                          "type": "object"
                        }
                      }
                    }
                  }
                ]
              }
            },
            "fields": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "The extra blocks a caller may request"
            }
          }
        }
      }
    }
  },
  "400": {
    "description": "fields= was set on more than 50 assets; narrow with symbols=",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/assets/{symbol}Get one registry asset by symbol, with its state, multiplier history, mints and burns, supply snapshots, corporate actions and control-plane events

Public, rate-limited per address when anonymous. Raw amounts are strings (exact on chain); prices and multipliers are numbers.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    }
  },
  {
    "name": "symbol",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    },
    "example": "AAPL"
  }
]

Responses

{
  "200": {
    "description": "The asset with everything the registry knows about it",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "asset": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string",
                  "description": "`${chainId}:${address}`"
                },
                "chainId": {
                  "type": "integer"
                },
                "address": {
                  "type": "string"
                },
                "symbol": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "assetType": {
                  "type": "string",
                  "enum": [
                    "stock_token",
                    "stablecoin",
                    "wrapped_native",
                    "bridged"
                  ]
                },
                "decimals": {
                  "type": "integer"
                },
                "status": {
                  "type": "string"
                },
                "source": {
                  "type": "string"
                },
                "sourceUri": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "observedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "firstSeenAt": {
                  "type": "string",
                  "format": "date-time",
                  "description": "When Fletch first saw the token; Robinhood publishes no listing date"
                },
                "verifiedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "onchainName": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "onchainSymbol": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "onchainDecimals": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "metadataCheckedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "isin": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "logoUrl": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              },
              "required": [
                "id",
                "chainId",
                "address",
                "symbol",
                "name",
                "assetType",
                "decimals",
                "status",
                "source"
              ]
            },
            "trust": {
              "type": "object",
              "description": "Derived from the row: whether bytecode was found and the contract agrees with the listing.",
              "properties": {
                "level": {
                  "type": "string",
                  "enum": [
                    "verified",
                    "listed",
                    "lookalike",
                    "community",
                    "unknown"
                  ]
                },
                "label": {
                  "type": "string"
                },
                "detail": {
                  "type": "string"
                }
              }
            },
            "state": {
              "type": [
                "object",
                "null"
              ],
              "description": "The asset's live state as the registry daemon last read it; every sub-block carries the time it was read.",
              "properties": {
                "multiplier": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "pendingMultiplier": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "multiplierEffectiveAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "tokenPaused": {
                  "type": [
                    "boolean",
                    "null"
                  ]
                },
                "oraclePaused": {
                  "type": [
                    "boolean",
                    "null"
                  ]
                },
                "totalSupplyRaw": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "totalSupplyUi": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "canonical": {
                  "type": [
                    "boolean",
                    "null"
                  ]
                },
                "beacon": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "implementation": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "feed": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "properties": {
                    "address": {
                      "type": "string"
                    },
                    "price": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "updatedAt": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "stale": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    }
                  }
                },
                "quote": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "properties": {
                    "bid": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "ask": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "tradingHalt": {
                      "type": [
                        "boolean",
                        "null"
                      ]
                    },
                    "dailyVolume": {
                      "type": [
                        "number",
                        "null"
                      ]
                    },
                    "at": {
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  }
                },
                "priceDivergencePct": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "dex": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "description": "The deepest dollar-priced pool and its premium to the feed."
                },
                "secondSource": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "description": "Blockscout's holders, transfers and supply, with supplyAgreement agree|close|differ|unknown."
                },
                "checkedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                }
              }
            },
            "multiplierHistory": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "supplyEvents": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "supplySnapshots": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "corporateActions": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "controlEvents": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "lookalikes": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "feedRounds": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "No such asset on this chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/assets/{symbol}/holdersHolders largest first with share of supply and what each address is, holder count, the latest concentration reading with the shares that say where the supply sits, and whether the ledger has reached the chain head

Public. `sits` is always one of `float`, `pools`, `issuer`, `bridge`, `contracts`, `unknown`, and names the concentration share this address's balance counts towards; `unknown` means the code probe has not checked this address yet. `label` and `labelKind` (`pool_manager`, `dex_pool`, `issuer`, `bridge_gateway`, `locker`, `contract`, `exchange`, `eoa`) are null for an address the registry has nothing to say about. `rawBalance` is in the token's base units; divide by 10^`decimals`. `sharePct` is that balance over `totalSupplyRaw`, read live, while the concentration shares are over the sum of every positive balance the ledger held at `concentration.asOfBlock`, so the two can differ slightly while the ledger trails the chain. `concentration` carries `top1Pct`, `top10Pct` and `gini` over every positive balance, and the six shares `floatPct`, `poolsPct`, `issuerPct`, `bridgePct`, `contractsPct` and `unknownPct`, which add to 100: float is the supply in ordinary wallets. `unknownPct` is the share held by addresses the code probe has not checked — it checks every holder above a ten-thousandth of a token's supply, so a tail of small holdings stays here permanently and `floatPct` is always a floor rather than a final answer. `issuerPct` is the share of every wallet labelled `issuer`, which is written only for Stock Tokens, whose mints are the issuer creating inventory; `issuerAddress` is this asset's largest mint recipient whatever the asset type. `concentration.day` is the UTC day of the reading, `takenAt` the ISO instant the job wrote it, and `asOfBlock` the ledger block it was computed at; the job runs every 24 h, so a share can be up to a day old. `concentration.holders` is the address count at that moment, while the top-level `holderCount` is read live and can differ. The shares come from the daily concentration job, which does not run while the transfer ledger is still reading history, so `concentration` is null until the ledger reaches head.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "symbol",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    },
    "example": "TSLA"
  },
  {
    "name": "limit",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500,
      "default": 50
    },
    "description": "How many holders, largest first"
  }
]

Responses

{
  "200": {
    "description": "Holders",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "symbol": {
              "type": "string"
            },
            "decimals": {
              "type": "integer"
            },
            "totalSupplyRaw": {
              "type": [
                "string",
                "null"
              ],
              "description": "Live total supply in base units, the denominator of sharePct"
            },
            "holders": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "holder": {
                    "type": "string"
                  },
                  "rawBalance": {
                    "type": "string",
                    "description": "Base units; divide by 10^decimals"
                  },
                  "sharePct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "asOfBlock": {
                    "type": "string"
                  },
                  "label": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "labelKind": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "enum": [
                      "pool_manager",
                      "dex_pool",
                      "issuer",
                      "bridge_gateway",
                      "locker",
                      "contract",
                      "exchange",
                      "eoa",
                      null
                    ]
                  },
                  "sits": {
                    "type": "string",
                    "enum": [
                      "float",
                      "pools",
                      "issuer",
                      "bridge",
                      "contracts",
                      "unknown"
                    ]
                  }
                }
              }
            },
            "holderCount": {
              "type": "integer"
            },
            "concentration": {
              "type": [
                "object",
                "null"
              ]
            },
            "progress": {
              "type": "object"
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Asset not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/assets/{symbol}/activityTransfers as economics, one row per UTC day: transfers, volume, mints, burns, DvP against USDG, off-hours transfers

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "symbol",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    },
    "example": "TSLA"
  },
  {
    "name": "days",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 400,
      "default": 30
    },
    "description": "How many UTC days back; a malformed value reads as the default"
  }
]

Responses

{
  "200": {
    "description": "Days",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "days": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Asset not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/assets/{symbol}/poolsPools trading the asset on every DEX the registry reads, deepest first, with venue, price, liquidity, fee, hooks, last-day swaps and volume, and the pool behind the asset's premium to the feed

Public. `venue` is `uniswap_v4` or `uniswap_v3`; a v4 pool is an id inside the one PoolManager and has a null `poolAddress`, a v3 pool is a contract and carries its address. A pool is recorded when one side is this asset and the other is a listed quote (USDG, WETH or another Stock Token). Pools are deepest first by `depthUsd`. V3 depth uses observed quote-side holdings. V4 depth uses a bounded quote estimate for a 1% price move, where per-pool token reserves are unavailable; `liquidity` is the pool's in-range Uniswap liquidity L in raw units, not a dollar figure, and is comparable only between pools of the same pair (its scale follows the two tokens' decimals). `best` is the deepest pool in dollars of any venue, which is the one the asset's premium to the Chainlink feed is measured from, and names its venue. `swaps24h` counts swap logs and `transactions24h` counts distinct transactions in (metricsAsOf - 24 hours, metricsAsOf], using each event block timestamp. Values are null until the entire window is indexed and when its end is more than 120 seconds old. `volumeUsd24h` requires historical per-swap USD valuations; a current pool price is never substituted. Zero means a completely scanned window with no matching activity. `discovery` says how far each venue's pool scan has read: while `readingHistory` is true, a pool created in blocks the scan has not reached yet is not listed, and a venue whose `scanned` is false has not been read at all.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "symbol",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    },
    "example": "TSLA"
  }
]

Responses

{
  "200": {
    "description": "Pools",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "pools": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "best": {
              "type": [
                "object",
                "null"
              ]
            },
            "discovery": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "venue": {
                    "type": "string"
                  },
                  "scanned": {
                    "type": "boolean",
                    "description": "Discovery has read this venue at least once; false means no pool from it is listed yet because nothing has looked."
                  },
                  "scannedToBlock": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "headBlock": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "headAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the chain head above was read."
                  },
                  "blocksBehind": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "readingHistory": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "venue",
                  "scanned",
                  "readingHistory"
                ]
              }
            },
            "note": {
              "type": "string"
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Asset not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/assets/{symbol}/historyOne row per UTC day of everything the registry publishes about an asset: multiplier, pause and halt flags, feed price and staleness, bid and ask, divergence, DEX price, premium and liquidity, supply, holders and lookalike count

Public. Written by the state-daily job, which runs hourly and rewrites the current UTC day's row, so a past day can be read back; the live tables carry only the current answer. Each row is a single reading taken at `takenAt`, not a daily open, close, mean or end-of-day value: it is the last reading the job took on that day, and the row for the current day is rewritten on the job's next run, so today's row is a partial day. Compare `takenAt` across rows before treating the series as evenly spaced. `from`/`to` are UTC days and default to the last 90; `days` sets the window length instead of `from`; `at=YYYY-MM-DD` returns that one day (an empty `days` array when no snapshot was taken); `fields` narrows each row to the keys named, `day` always included. `coverage` says how many days are actually on record and the first of them: there is nothing before the day the job first ran. A null is a figure that was not read that day, never a zero: a figure is copied only when the job that writes it read it that day, and `stateCheckedAt`, `feedCheckedAt`, `apiCheckedAt`, `dexCheckedAt` and `blockscoutCheckedAt` say when each group of figures was last read. `ledgerHolders` is written only for assets whose transfer history the ledger had finished reading, and `lookalikes` only once the lookalike scan has completed a pass. Rows are flat versions of the live `state` block: `feedPrice`/`feedStale` are `state.feed.price`/`.stale`, `bid`/`ask`/`tradingHalt` are `state.quote.bid`/`.ask`/`.tradingHalt`, `dexPriceUsd`/`dexPremiumPct`/`dexLiquidity` are `state.dex.priceUsd`/`.premiumPct`/`.liquidity`, `blockscoutHolders` is `state.secondSource.holders`, `multiplier` is `state.multiplier`.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "symbol",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    },
    "example": "TSLA"
  },
  {
    "name": "from",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "format": "date"
    },
    "description": "First UTC day, YYYY-MM-DD; must not be after `to`"
  },
  {
    "name": "to",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "format": "date"
    },
    "description": "Last UTC day, YYYY-MM-DD; defaults to today"
  },
  {
    "name": "days",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 3650,
      "default": 90
    },
    "description": "Window length in days ending at `to`; ignored when `from` is given"
  },
  {
    "name": "at",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "format": "date"
    },
    "example": "2026-08-12"
  },
  {
    "name": "fields",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "example": "feedPrice,dexPremiumPct",
    "description": "Comma-separated keys to keep from each row: multiplier, tokenPaused, oraclePaused, tradingHalt, feedPrice, feedStale, bid, ask, priceDivergencePct, dexPriceUsd, dexPremiumPct, dexLiquidity, totalSupplyRaw, blockscoutHolders, ledgerHolders, lookalikes, stateCheckedAt, feedCheckedAt, apiCheckedAt, dexCheckedAt, blockscoutCheckedAt, takenAt. `day` is always included; an unknown key is a 400."
  }
]

Responses

{
  "200": {
    "description": "History",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "chainId": {
              "type": "integer"
            },
            "symbol": {
              "type": "string"
            },
            "decimals": {
              "type": "integer",
              "description": "Token decimals, for converting totalSupplyRaw"
            },
            "from": {
              "type": "string"
            },
            "to": {
              "type": "string"
            },
            "coverage": {
              "type": "object",
              "properties": {
                "daysOnRecord": {
                  "type": "integer"
                },
                "firstDay": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "latestDay": {
                  "type": [
                    "string",
                    "null"
                  ]
                }
              }
            },
            "days": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "400": {
    "description": "at, from, to, days or fields is malformed, or from is after to",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Asset not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/assets/{symbol}/feed/roundsThe Chainlink feed's round history for one asset, newest first: roundId, answer (price × multiplier, USD), startedAt, updatedAt

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "symbol",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    },
    "example": "TSLA"
  },
  {
    "name": "since",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "format": "date-time"
    }
  },
  {
    "name": "limit",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 2000,
      "default": 200
    },
    "description": "Rounds, newest first; a malformed value reads as the default, a larger one as the maximum"
  }
]

Responses

{
  "200": {
    "description": "Rounds",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "symbol": {
              "type": "string"
            },
            "feed": {
              "type": [
                "string",
                "null"
              ]
            },
            "rounds": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Asset not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}

Changelog

Every change the daemon noticed, as JSON with a cursor and as a live stream.

GET /chains/{chainId}/eventsThe registry changelog: every pause, block, upgrade, multiplier change, stale feed, supply residual, listing, corporate action and chain status change the daemon recorded

Public. Without `since`/`cursor`: newest first, with `kinds` (every kind the daemon can emit) and `nextCursor`. With `since` or `cursor` (an ISO instant, use the previous `nextCursor`): only newer rows, oldest first, so a consumer catches up without gaps; a `since` or `cursor` that does not parse is a 400, never a silent restart from now. `kind` matches exactly or by prefix (`registry.`, `multiplier.`) and `symbol` narrows to one token, on the newest-first read only: the cursor read returns every kind, and a consumer following a cursor filters on `kind` itself. `limit` up to 500. When the changelog is empty, `nextCursor` is the epoch, which passed back yields every event from the first.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "kind",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "example": "multiplier."
  },
  {
    "name": "symbol",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "example": "TSLA"
  },
  {
    "name": "since",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "format": "date-time"
    }
  },
  {
    "name": "cursor",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "description": "An opaque position, `${observedAt}|${id}`, as returned in `nextCursor`. Pass it back verbatim; a bare ISO instant is also accepted.",
    "example": "2026-09-05T11:50:43.476Z|ev_9f3256ce83b6dd98fedbe4ec"
  },
  {
    "name": "limit",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500,
      "default": 100
    },
    "description": "A malformed value reads as the default, a larger one as the maximum"
  }
]

Responses

{
  "200": {
    "description": "Events",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "events": {
              "type": "array",
              "items": {
                "type": "object",
                "description": "One entry in the registry changelog. `id` is stable across re-runs; the cursor for the row is `${observedAt}|${id}`.",
                "properties": {
                  "id": {
                    "type": "string",
                    "description": "`ev_` followed by 24 hex characters; the same change is never written twice"
                  },
                  "kind": {
                    "type": "string",
                    "description": "A dotted kind such as `registry.paused` or `multiplier.applied`; every kind the daemon can emit is in the response's `kinds`",
                    "example": "multiplier.applied"
                  },
                  "title": {
                    "type": "string",
                    "description": "The change as one changelog line"
                  },
                  "symbol": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The token concerned; null for a chain-wide event"
                  },
                  "address": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The contract or account concerned; null for a chain-wide event"
                  },
                  "detail": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "additionalProperties": true,
                    "description": "The numbers behind the title; fields depend on the kind"
                  },
                  "block": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Block number as a decimal string; null for events not tied to a block"
                  },
                  "txHash": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "occurredAt": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the change happened on chain or at the source"
                  },
                  "observedAt": {
                    "type": "string",
                    "format": "date-time",
                    "description": "When the daemon recorded it; the cursor orders by this"
                  }
                },
                "required": [
                  "id",
                  "kind",
                  "title",
                  "symbol",
                  "address",
                  "detail",
                  "block",
                  "txHash",
                  "occurredAt",
                  "observedAt"
                ]
              }
            },
            "kinds": {
              "type": "array",
              "items": {
                "type": "string"
              },
              "description": "Every kind the daemon can emit; present only on the newest-first read (no `since`/`cursor`)"
            },
            "nextCursor": {
              "type": "string",
              "description": "`${observedAt}|${id}` of the last row seen; pass it back as `cursor` to receive only what follows. The epoch when the changelog is empty."
            }
          },
          "required": [
            "events",
            "nextCursor"
          ]
        }
      }
    }
  },
  "400": {
    "description": "since or cursor is malformed",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/events/streamThe same changelog as Server-Sent Events; each frame's id is the event's cursor (`${observedAt}|${id}`), so Last-Event-ID (or ?since=) resumes without gaps

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "since",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "description": "An ISO instant or a cursor `${observedAt}|${id}`; the Last-Event-ID header takes precedence. Without either the stream starts at now."
  }
]

Responses

{
  "200": {
    "description": "text/event-stream; `event` is the kind, `data` an AuthorityEvent as JSON, `id` the event's cursor. The first frame carries `retry` and an `id` with no event, so a reconnect always has a position."
  },
  "400": {
    "description": "since or Last-Event-ID is malformed",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests, or too many open streams from this address",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}

Chain

The issuer's control plane, the token bridge, the issuer's paperwork, lookalike tokens, DEX venues and chain health.

GET /chains/{chainId}/control-planeThe issuer's AccessControlsRegistry: paused, implementation, blocked-address count, and its latest events

Public. One contract governs every Stock Token: this is the surface no other index publishes. `limit` caps events (default 50, max 200), newest first. `offset` skips that many events, so `offset=200&limit=200` is the second page; an event that lands between two page reads repeats one row on the next page, so a consumer copying the log dedupes by `txHash` and `logIndex`. A page shorter than `limit` is the last one. `state` is the same on every page.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "limit",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 200
    },
    "description": "Events per page (default 50)"
  },
  {
    "name": "offset",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 0
    },
    "description": "Events to skip before the page (default 0)"
  }
]

Responses

{
  "200": {
    "description": "Registry state and events",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "state": {
              "type": "object"
            },
            "events": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/healthThe chain's latest vital signs: head, block time, base fee, L1 block, batch count, delayed messages, batch-poster balance, status page

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  }
]

Responses

{
  "200": {
    "description": "Latest reading",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "health": {
              "type": "object"
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/corporate-actionsCorporate actions in progress, as Robinhood publishes them, tied to the token each affects

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  }
]

Responses

{
  "200": {
    "description": "Actions in progress",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "actions": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/dexThe DEX venues the registry reads and what each contributes: pools trading a listed asset, how many carry a dollar price, the last day's swaps and volume, and how many assets take their premium from a pool there

Public. One row per venue read (`uniswap_v4`, `uniswap_v3`), whether or not it has a pool on record yet, so `venues` and `discovery` name the same set. `assetsPricedHere` counts the assets whose deepest pool in dollars sits on that venue, so the venues' figures add up to the assets with a DEX price. `depthUsd` sums depth over the venue's priced pools: observed quote-side holdings for v3, and a bounded quote estimate for a 1% price move for v4 where per-pool token reserves are unavailable; Uniswap's raw liquidity L compares two pools only when they hold the same pair. `swaps24h` counts swap logs and `transactions24h` counts distinct transactions in (metricsAsOf - 24 hours, metricsAsOf], using each event block timestamp. Values are null until the entire window is indexed and when its end is more than 120 seconds old. `volumeUsd24h` requires historical per-swap USD valuations; a current pool price is never substituted. Zero means a completely scanned window with no matching activity. `checkedAt` is when the state read last priced a pool on that venue; `headAt` inside `discovery` is when the chain head there was read. `discovery` carries each venue's pool scan position against that head; while `readingHistory` is true the counts are a floor, not a total, and while `scanned` is false the venue has not been read at all. The Pons launchpad creates its pools on the Uniswap v3 factory, so they are counted as `uniswap_v3` rather than as a venue of their own.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  }
]

Responses

{
  "200": {
    "description": "DEX venues",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "venues": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "venue": {
                    "type": "string",
                    "enum": [
                      "uniswap_v4",
                      "uniswap_v3"
                    ]
                  },
                  "pools": {
                    "type": "integer",
                    "description": "Pools that trade a listed asset against a listed quote."
                  },
                  "pricedPools": {
                    "type": "integer",
                    "description": "Of those, how many the state read has put a dollar price on."
                  },
                  "depthUsd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "Depth in USD uses observed quote-side holdings for v3. For v4 it uses a bounded quote estimate for a 1% price move; per-pool token reserves are unavailable. Check the pool's observation time and stateCurrent flag. Venue depth is the sum over its priced pools."
                  },
                  "swaps24h": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Swap logs in the exact indexed 24-hour window, null for incomplete or stale coverage."
                  },
                  "volumeUsd24h": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "USD over the same exact window using historical per-swap valuations; null when valuations are incomplete."
                  },
                  "assetsPricedHere": {
                    "type": "integer"
                  },
                  "checkedAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the state read last priced a pool on this venue."
                  }
                },
                "required": [
                  "venue",
                  "pools",
                  "pricedPools",
                  "swaps24h",
                  "assetsPricedHere"
                ]
              }
            },
            "discovery": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "venue": {
                    "type": "string"
                  },
                  "scanned": {
                    "type": "boolean",
                    "description": "Discovery has read this venue at least once; false means no pool from it is listed yet because nothing has looked."
                  },
                  "scannedToBlock": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "headBlock": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "headAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the chain head above was read."
                  },
                  "blocksBehind": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "readingHistory": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "venue",
                  "scanned",
                  "readingHistory"
                ]
              }
            },
            "note": {
              "type": "string"
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/bridgeThe token bridge: each bridged asset's L1 escrow against its L2 supply, recent deposits and withdrawals seen on L2, and withdrawals past their seven-day window

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "symbol",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "example": "WBTC"
  },
  {
    "name": "limit",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500,
      "default": 100
    },
    "description": "Flows, newest first; a malformed value reads as the default, a larger one as the maximum"
  }
]

Responses

{
  "200": {
    "description": "Bridge",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "escrow": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "flows": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "claimable": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain or asset",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/issuerThe issuer's paperwork: every PDF the legal hub lists with ETag, Last-Modified and the token it maps to, plus watched pages and when their text changed

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "kind",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "enum": [
        "base_prospectus",
        "supplement",
        "notice",
        "final_terms",
        "other"
      ]
    }
  }
]

Responses

{
  "200": {
    "description": "Documents and pages",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "documents": {
              "type": "array",
              "items": {
                "type": "object"
              }
            },
            "pages": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/lookalikesEvery ERC-20 that borrows a listed ticker or exact name at another address, with holders and the beacon check that separates an impostor from an issuer-deployed token

Public. Most held first. `limit` caps rows (default 300, max 1000); `offset` skips that many rows, so `offset=1000&limit=1000` is the second page, and a page shorter than `limit` is the last one. Holder counts are refreshed by the lookalike scan, so the order can shift between pages read across a scan: a consumer copying the whole table dedupes by `address`.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "symbol",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "example": "TSLA"
  },
  {
    "name": "limit",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 1000
    },
    "description": "Rows per page (default 300)"
  },
  {
    "name": "offset",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 0
    },
    "description": "Rows to skip before the page (default 0)"
  }
]

Responses

{
  "200": {
    "description": "Lookalikes, most held first",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "lookalikes": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}

Watch

Watchers that alert on transfers and authority events, delivered to Telegram or a signed webhook. Needs a key.

GET /watchersList this account's watchers

Authentication required: watchers:read

Responses

{
  "200": {
    "description": "Watchers",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "watchers": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "projectId": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "name": {
                    "type": "string"
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "large_transfer",
                      "wallet_activity",
                      "registry_event",
                      "token_event",
                      "new_pool"
                    ]
                  },
                  "chainId": {
                    "type": "integer"
                  },
                  "address": {
                    "type": "string"
                  },
                  "assetId": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "threshold": {
                    "type": "string"
                  },
                  "wallet": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "wallet_activity only — the watched address."
                  },
                  "delivery": {
                    "type": "string",
                    "enum": [
                      "telegram",
                      "webhook"
                    ],
                    "description": "Where this watcher's alerts are sent."
                  },
                  "webhookId": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The endpoint alerts are posted to when delivery is \"webhook\"."
                  },
                  "webhookName": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The endpoint's name. Null when delivery is \"telegram\". Also null when the endpoint was deleted: delivery stays \"webhook\", webhookId is null, and the watcher is paused with the reason in lastError. Such a watcher cannot be resumed until it is re-pointed with PATCH /watchers/{id} { webhookId }."
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "active",
                      "catching_up",
                      "degraded",
                      "paused"
                    ]
                  },
                  "lastCheckedBlock": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "lastTriggeredAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "lastError": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "updatedAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "lastDelivery": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "The most recent delivery of any status, or null before the first.",
                    "properties": {
                      "sentAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      },
                      "amount": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "txHash": {
                        "type": "string"
                      }
                    },
                    "required": [
                      "sentAt",
                      "amount",
                      "txHash"
                    ]
                  }
                },
                "required": [
                  "id",
                  "name",
                  "kind",
                  "chainId",
                  "address",
                  "threshold",
                  "enabled",
                  "status",
                  "createdAt",
                  "updatedAt",
                  "lastDelivery"
                ]
              }
            }
          }
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
POST /watchersCreate a watcher

Authentication required: watchers:write

Parameters

[
  {
    "name": "Idempotency-Key",
    "in": "header",
    "required": false,
    "schema": {
      "type": "string"
    },
    "description": "Repeat a POST with the same key to get the same watcher back instead of creating another."
  }
]

Request body

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "assetId": {
            "type": "string",
            "description": "Required for large_transfer, wallet_activity and token_event; omitted for registry_event."
          },
          "threshold": {
            "type": "string",
            "example": "1000",
            "description": "Required for large_transfer (positive) and wallet_activity (\"0\" means every transfer); ignored by registry_event, token_event and new_pool."
          },
          "kind": {
            "type": "string",
            "enum": [
              "large_transfer",
              "wallet_activity",
              "registry_event",
              "token_event",
              "new_pool"
            ],
            "default": "large_transfer"
          },
          "lookalikesOnly": {
            "type": "boolean",
            "description": "new_pool only: alert only on a pool whose token borrows a listed ticker or name. Off by default."
          },
          "wallet": {
            "type": "string",
            "description": "Required when kind is wallet_activity — a 0x-prefixed 40-character hex address.",
            "example": "0x1234567890123456789012345678901234567890"
          },
          "name": {
            "type": "string"
          },
          "projectId": {
            "type": "string"
          },
          "webhookId": {
            "type": "string",
            "description": "Deliver this watcher to a registered webhook endpoint instead of Telegram."
          }
        },
        "required": []
      }
    }
  }
}

Responses

{
  "200": {
    "description": "Idempotency-Key replay: the existing watcher",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "watcher": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "projectId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "name": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "large_transfer",
                    "wallet_activity",
                    "registry_event",
                    "token_event",
                    "new_pool"
                  ]
                },
                "chainId": {
                  "type": "integer"
                },
                "address": {
                  "type": "string"
                },
                "assetId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "threshold": {
                  "type": "string"
                },
                "wallet": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "wallet_activity only — the watched address."
                },
                "delivery": {
                  "type": "string",
                  "enum": [
                    "telegram",
                    "webhook"
                  ],
                  "description": "Where this watcher's alerts are sent."
                },
                "webhookId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The endpoint alerts are posted to when delivery is \"webhook\"."
                },
                "webhookName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The endpoint's name. Null when delivery is \"telegram\". Also null when the endpoint was deleted: delivery stays \"webhook\", webhookId is null, and the watcher is paused with the reason in lastError. Such a watcher cannot be resumed until it is re-pointed with PATCH /watchers/{id} { webhookId }."
                },
                "enabled": {
                  "type": "boolean"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "catching_up",
                    "degraded",
                    "paused"
                  ]
                },
                "lastCheckedBlock": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "lastTriggeredAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "lastError": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "updatedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "lastDelivery": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "description": "The most recent delivery of any status, or null before the first.",
                  "properties": {
                    "sentAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "amount": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "txHash": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "sentAt",
                    "amount",
                    "txHash"
                  ]
                }
              },
              "required": [
                "id",
                "name",
                "kind",
                "chainId",
                "address",
                "threshold",
                "enabled",
                "status",
                "createdAt",
                "updatedAt",
                "lastDelivery"
              ]
            }
          }
        }
      }
    }
  },
  "201": {
    "description": "Created",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "watcher": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "projectId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "name": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "large_transfer",
                    "wallet_activity",
                    "registry_event",
                    "token_event",
                    "new_pool"
                  ]
                },
                "chainId": {
                  "type": "integer"
                },
                "address": {
                  "type": "string"
                },
                "assetId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "threshold": {
                  "type": "string"
                },
                "wallet": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "wallet_activity only — the watched address."
                },
                "delivery": {
                  "type": "string",
                  "enum": [
                    "telegram",
                    "webhook"
                  ],
                  "description": "Where this watcher's alerts are sent."
                },
                "webhookId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The endpoint alerts are posted to when delivery is \"webhook\"."
                },
                "webhookName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The endpoint's name. Null when delivery is \"telegram\". Also null when the endpoint was deleted: delivery stays \"webhook\", webhookId is null, and the watcher is paused with the reason in lastError. Such a watcher cannot be resumed until it is re-pointed with PATCH /watchers/{id} { webhookId }."
                },
                "enabled": {
                  "type": "boolean"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "catching_up",
                    "degraded",
                    "paused"
                  ]
                },
                "lastCheckedBlock": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "lastTriggeredAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "lastError": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "updatedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "lastDelivery": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "description": "The most recent delivery of any status, or null before the first.",
                  "properties": {
                    "sentAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "amount": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "txHash": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "sentAt",
                    "amount",
                    "txHash"
                  ]
                }
              },
              "required": [
                "id",
                "name",
                "kind",
                "chainId",
                "address",
                "threshold",
                "enabled",
                "status",
                "createdAt",
                "updatedAt",
                "lastDelivery"
              ]
            }
          }
        }
      }
    }
  },
  "400": {
    "description": "Invalid asset id, threshold, wallet, project, or a disabled webhook endpoint",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Asset, project or webhook endpoint not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Per-account or platform watcher limit reached",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /watchers/{id}Get one watcher

Authentication required: watchers:read

Parameters

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  }
]

Responses

{
  "200": {
    "description": "The watcher",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "watcher": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "projectId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "name": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "large_transfer",
                    "wallet_activity",
                    "registry_event",
                    "token_event",
                    "new_pool"
                  ]
                },
                "chainId": {
                  "type": "integer"
                },
                "address": {
                  "type": "string"
                },
                "assetId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "threshold": {
                  "type": "string"
                },
                "wallet": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "wallet_activity only — the watched address."
                },
                "delivery": {
                  "type": "string",
                  "enum": [
                    "telegram",
                    "webhook"
                  ],
                  "description": "Where this watcher's alerts are sent."
                },
                "webhookId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The endpoint alerts are posted to when delivery is \"webhook\"."
                },
                "webhookName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The endpoint's name. Null when delivery is \"telegram\". Also null when the endpoint was deleted: delivery stays \"webhook\", webhookId is null, and the watcher is paused with the reason in lastError. Such a watcher cannot be resumed until it is re-pointed with PATCH /watchers/{id} { webhookId }."
                },
                "enabled": {
                  "type": "boolean"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "catching_up",
                    "degraded",
                    "paused"
                  ]
                },
                "lastCheckedBlock": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "lastTriggeredAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "lastError": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "updatedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "lastDelivery": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "description": "The most recent delivery of any status, or null before the first.",
                  "properties": {
                    "sentAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "amount": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "txHash": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "sentAt",
                    "amount",
                    "txHash"
                  ]
                }
              },
              "required": [
                "id",
                "name",
                "kind",
                "chainId",
                "address",
                "threshold",
                "enabled",
                "status",
                "createdAt",
                "updatedAt",
                "lastDelivery"
              ]
            }
          }
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
PATCH /watchers/{id}Pause, resume, or re-point a watcher

Authentication required: watchers:write

Parameters

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  }
]

Request body

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "description": "Send enabled, webhookId, or both.",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "webhookId": {
            "type": [
              "string",
              "null"
            ],
            "description": "Re-point this watcher: an endpoint id delivers there, null goes back to Telegram. The endpoint must be yours and enabled."
          }
        }
      }
    }
  }
}

Responses

{
  "200": {
    "description": "Updated",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "watcher": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "projectId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "name": {
                  "type": "string"
                },
                "kind": {
                  "type": "string",
                  "enum": [
                    "large_transfer",
                    "wallet_activity",
                    "registry_event",
                    "token_event",
                    "new_pool"
                  ]
                },
                "chainId": {
                  "type": "integer"
                },
                "address": {
                  "type": "string"
                },
                "assetId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "threshold": {
                  "type": "string"
                },
                "wallet": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "wallet_activity only — the watched address."
                },
                "delivery": {
                  "type": "string",
                  "enum": [
                    "telegram",
                    "webhook"
                  ],
                  "description": "Where this watcher's alerts are sent."
                },
                "webhookId": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The endpoint alerts are posted to when delivery is \"webhook\"."
                },
                "webhookName": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "description": "The endpoint's name. Null when delivery is \"telegram\". Also null when the endpoint was deleted: delivery stays \"webhook\", webhookId is null, and the watcher is paused with the reason in lastError. Such a watcher cannot be resumed until it is re-pointed with PATCH /watchers/{id} { webhookId }."
                },
                "enabled": {
                  "type": "boolean"
                },
                "status": {
                  "type": "string",
                  "enum": [
                    "active",
                    "catching_up",
                    "degraded",
                    "paused"
                  ]
                },
                "lastCheckedBlock": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "lastTriggeredAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "lastError": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "updatedAt": {
                  "type": "string",
                  "format": "date-time"
                },
                "lastDelivery": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "description": "The most recent delivery of any status, or null before the first.",
                  "properties": {
                    "sentAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time"
                    },
                    "amount": {
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "txHash": {
                      "type": "string"
                    }
                  },
                  "required": [
                    "sentAt",
                    "amount",
                    "txHash"
                  ]
                }
              },
              "required": [
                "id",
                "name",
                "kind",
                "chainId",
                "address",
                "threshold",
                "enabled",
                "status",
                "createdAt",
                "updatedAt",
                "lastDelivery"
              ]
            }
          }
        }
      }
    }
  },
  "400": {
    "description": "Neither enabled nor webhookId was sent, or the endpoint is not yours, is disabled, or was deleted",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
DELETE /watchers/{id}Delete a watcher

Authentication required: watchers:write

Parameters

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  }
]

Responses

{
  "200": {
    "description": "Deleted",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "ok": {
              "type": "boolean"
            }
          }
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /watchers/{id}/runsA watcher's delivery history

Authentication required: watchers:read

Parameters

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  },
  {
    "name": "limit",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "default": 50,
      "maximum": 200
    }
  }
]

Responses

{
  "200": {
    "description": "Deliveries, newest first",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "runs": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "watcherId": {
                    "type": "string"
                  },
                  "status": {
                    "type": "string",
                    "enum": [
                      "pending",
                      "sent",
                      "failed",
                      "retracted"
                    ]
                  },
                  "lastError": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "sentAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "payload": {
                    "type": "object",
                    "description": "DeliveryPayload — kind, chainId, address, symbol, from, to, value, amount, threshold, txHash, logIndex, blockNumber, blockHash, explorerUrl; wallet_activity adds wallet and direction (\"in\" | \"out\"); an authority payload (kind \"authority\", from a registry_event or token_event watcher) instead carries eventId, eventKind, title, symbol, address, detail, txHash, blockNumber, occurredAt (ISO 8601 UTC), explorerUrl and registryUrl."
                  }
                },
                "required": [
                  "id",
                  "watcherId",
                  "status",
                  "createdAt",
                  "payload"
                ]
              }
            }
          }
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Watcher not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /webhooksList this account's webhook endpoints

Authentication required: watchers:read

Responses

{
  "200": {
    "description": "Endpoints, oldest first",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "webhooks": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "url": {
                    "type": "string"
                  },
                  "secretPrefix": {
                    "type": "string",
                    "description": "The first characters of the signing secret; the secret itself is returned only once, at creation or rotation."
                  },
                  "enabled": {
                    "type": "boolean"
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "lastDeliveredAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When this endpoint last answered 2xx, including test pings — not necessarily an alert."
                  },
                  "lastError": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The most recent failure whenever it happened, cleared by the next success. Compare lastErrorAt with lastDeliveredAt before reading it as a fault now."
                  },
                  "lastErrorAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When lastError was written. Null on an endpoint whose last failure predates this field."
                  },
                  "secret": {
                    "type": "string",
                    "description": "Present only in the response that created or rotated this endpoint. Stored encrypted and never returned again."
                  }
                },
                "required": [
                  "id",
                  "name",
                  "url",
                  "secretPrefix",
                  "enabled",
                  "createdAt"
                ]
              }
            }
          }
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
POST /webhooksRegister a webhook endpoint

Returns the signing secret once. Every delivery carries X-Fletch-Signature: t=<unix>,v1=<hex hmac-sha256 over "<t>.<body>"> and X-Fletch-Event.

Authentication required: watchers:write

Request body

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "url": {
            "type": "string",
            "description": "An https:// URL on a public host.",
            "example": "https://example.com/fletch"
          },
          "name": {
            "type": "string",
            "description": "Defaults to the URL's host."
          }
        },
        "required": [
          "url"
        ]
      }
    }
  }
}

Responses

{
  "201": {
    "description": "Created, with the secret shown once",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "webhook": {
              "allOf": [
                {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "secretPrefix": {
                      "type": "string",
                      "description": "The first characters of the signing secret; the secret itself is returned only once, at creation or rotation."
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "lastDeliveredAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "When this endpoint last answered 2xx, including test pings — not necessarily an alert."
                    },
                    "lastError": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The most recent failure whenever it happened, cleared by the next success. Compare lastErrorAt with lastDeliveredAt before reading it as a fault now."
                    },
                    "lastErrorAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "When lastError was written. Null on an endpoint whose last failure predates this field."
                    },
                    "secret": {
                      "type": "string",
                      "description": "Present only in the response that created or rotated this endpoint. Stored encrypted and never returned again."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "url",
                    "secretPrefix",
                    "enabled",
                    "createdAt"
                  ]
                },
                {
                  "type": "object",
                  "required": [
                    "secret"
                  ]
                }
              ]
            }
          }
        }
      }
    }
  },
  "400": {
    "description": "The URL is not an https:// URL on a public host",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Per-account endpoint limit reached",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
PATCH /webhooks/{id}Enable, disable, or rotate the secret of an endpoint

Authentication required: watchers:write

Parameters

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  }
]

Request body

{
  "required": true,
  "content": {
    "application/json": {
      "schema": {
        "type": "object",
        "properties": {
          "enabled": {
            "type": "boolean"
          },
          "rotateSecret": {
            "type": "boolean"
          }
        }
      }
    }
  }
}

Responses

{
  "200": {
    "description": "The endpoint; a rotation includes the new secret once",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "webhook": {
              "oneOf": [
                {
                  "type": "object",
                  "properties": {
                    "id": {
                      "type": "string"
                    },
                    "name": {
                      "type": "string"
                    },
                    "url": {
                      "type": "string"
                    },
                    "secretPrefix": {
                      "type": "string",
                      "description": "The first characters of the signing secret; the secret itself is returned only once, at creation or rotation."
                    },
                    "enabled": {
                      "type": "boolean"
                    },
                    "createdAt": {
                      "type": "string",
                      "format": "date-time"
                    },
                    "lastDeliveredAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "When this endpoint last answered 2xx, including test pings — not necessarily an alert."
                    },
                    "lastError": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "description": "The most recent failure whenever it happened, cleared by the next success. Compare lastErrorAt with lastDeliveredAt before reading it as a fault now."
                    },
                    "lastErrorAt": {
                      "type": [
                        "string",
                        "null"
                      ],
                      "format": "date-time",
                      "description": "When lastError was written. Null on an endpoint whose last failure predates this field."
                    },
                    "secret": {
                      "type": "string",
                      "description": "Present only in the response that created or rotated this endpoint. Stored encrypted and never returned again."
                    }
                  },
                  "required": [
                    "id",
                    "name",
                    "url",
                    "secretPrefix",
                    "enabled",
                    "createdAt"
                  ]
                },
                {
                  "allOf": [
                    {
                      "type": "object",
                      "properties": {
                        "id": {
                          "type": "string"
                        },
                        "name": {
                          "type": "string"
                        },
                        "url": {
                          "type": "string"
                        },
                        "secretPrefix": {
                          "type": "string",
                          "description": "The first characters of the signing secret; the secret itself is returned only once, at creation or rotation."
                        },
                        "enabled": {
                          "type": "boolean"
                        },
                        "createdAt": {
                          "type": "string",
                          "format": "date-time"
                        },
                        "lastDeliveredAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "When this endpoint last answered 2xx, including test pings — not necessarily an alert."
                        },
                        "lastError": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "description": "The most recent failure whenever it happened, cleared by the next success. Compare lastErrorAt with lastDeliveredAt before reading it as a fault now."
                        },
                        "lastErrorAt": {
                          "type": [
                            "string",
                            "null"
                          ],
                          "format": "date-time",
                          "description": "When lastError was written. Null on an endpoint whose last failure predates this field."
                        },
                        "secret": {
                          "type": "string",
                          "description": "Present only in the response that created or rotated this endpoint. Stored encrypted and never returned again."
                        }
                      },
                      "required": [
                        "id",
                        "name",
                        "url",
                        "secretPrefix",
                        "enabled",
                        "createdAt"
                      ]
                    },
                    {
                      "type": "object",
                      "required": [
                        "secret"
                      ]
                    }
                  ]
                }
              ]
            }
          }
        }
      }
    }
  },
  "400": {
    "description": "Neither enabled nor rotateSecret was sent",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
DELETE /webhooks/{id}Delete an endpoint

Watchers delivering to it are paused; the response says how many.

Authentication required: watchers:write

Parameters

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  }
]

Responses

{
  "200": {
    "description": "Deleted",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "ok": {
              "type": "boolean"
            },
            "pausedWatchers": {
              "type": "integer"
            }
          }
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
POST /webhooks/{id}/testSend a signed ping to an endpoint now

Always HTTP 200: the endpoint's own answer is in the body as ok, status and error. Sent directly rather than through the delivery outbox, so a failure is not retried.

Authentication required: watchers:write

Parameters

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  }
]

Responses

{
  "200": {
    "description": "What the endpoint answered",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "ok": {
              "type": "boolean"
            },
            "status": {
              "type": [
                "integer",
                "null"
              ]
            },
            "error": {
              "type": [
                "string",
                "null"
              ]
            }
          }
        }
      }
    }
  },
  "400": {
    "description": "The endpoint is disabled; enable it first",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many test deliveries; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}

Build

Builds and projects. Needs a key.

GET /projectsList this account's projects

Authentication required: projects:read

Responses

{
  "200": {
    "description": "Projects",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "projects": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "id": {
                    "type": "string"
                  },
                  "name": {
                    "type": "string"
                  },
                  "slug": {
                    "type": "string"
                  },
                  "createdAt": {
                    "type": "string",
                    "format": "date-time"
                  },
                  "buildCount": {
                    "type": "integer"
                  }
                },
                "required": [
                  "id",
                  "name",
                  "slug",
                  "createdAt",
                  "buildCount"
                ]
              }
            }
          }
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /builds/{id}Get one build's status, contracts, and toolchain report

Authentication required: builds:read

Parameters

[
  {
    "name": "id",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string"
    }
  }
]

Responses

{
  "200": {
    "description": "The build",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "build": {
              "type": "object",
              "properties": {
                "id": {
                  "type": "string"
                },
                "projectId": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "prompt": {
                  "type": "string"
                },
                "status": {
                  "type": "string"
                },
                "billingMode": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    "platform",
                    "own_key",
                    null
                  ],
                  "description": "Immutable queued billing choice. Null means the older record did not capture this choice."
                },
                "custodyMode": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "enum": [
                    "platform",
                    "hosted",
                    "gateway",
                    null
                  ]
                },
                "provider": {
                  "type": "string"
                },
                "model": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "capabilities": {
                  "type": [
                    "object",
                    "null"
                  ],
                  "properties": {
                    "text": {
                      "type": "boolean"
                    },
                    "tools": {
                      "type": "boolean"
                    },
                    "images": {
                      "type": "boolean"
                    }
                  }
                },
                "error": {
                  "type": [
                    "string",
                    "null"
                  ]
                },
                "startedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "finishedAt": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "createdAt": {
                  "type": "string",
                  "format": "date-time"
                }
              }
            },
            "previewUrl": {
              "type": [
                "string",
                "null"
              ]
            },
            "contracts": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "chainId": {
                    "type": "integer"
                  },
                  "address": {
                    "type": "string"
                  },
                  "verified": {
                    "type": [
                      "boolean",
                      "null"
                    ]
                  },
                  "deployer": {
                    "type": "string"
                  }
                }
              }
            },
            "templateVersion": {
              "type": [
                "string",
                "null"
              ],
              "description": "Sandbox frontend template version recorded for this build. Null when unknown, including legacy builds."
            },
            "compile": {
              "type": [
                "object",
                "null"
              ],
              "description": "forge build --json result, or null if not yet compiled."
            },
            "tests": {
              "type": [
                "object",
                "null"
              ],
              "description": "forge test --json result, or null if not yet run."
            },
            "analysis": {
              "type": [
                "object",
                "null"
              ],
              "description": "Recorded Slither result, including whether the tool ran."
            },
            "artifacts": {
              "type": "array",
              "items": {
                "type": "object"
              }
            }
          }
        }
      }
    }
  },
  "401": {
    "description": "Missing or invalid credentials; carries WWW-Authenticate",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "403": {
    "description": "Credentials valid but missing the required scope",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Not found",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "The key's hourly budget is spent; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}

Chains

The networks Fletch knows.

GET /chainsList Robinhood Chain networks

Public. The public RPC URL, the explorer and whether Fletch has a provider key for the chain; a configured provider URL is never returned.

Public

Responses

{
  "200": {
    "description": "The two Robinhood chains",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "chains": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "chainId": {
                    "type": "integer"
                  },
                  "name": {
                    "type": "string"
                  },
                  "network": {
                    "type": "string",
                    "enum": [
                      "mainnet",
                      "testnet"
                    ]
                  },
                  "rpcUrl": {
                    "type": "string"
                  },
                  "explorerUrl": {
                    "type": "string"
                  },
                  "providerConfigured": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "chainId",
                  "name",
                  "network",
                  "rpcUrl",
                  "explorerUrl",
                  "providerConfigured"
                ]
              }
            }
          }
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /tokens/{address}What a token at an address is: listed and confirmed, listed and unconfirmed, impersonating a listed asset, a community token nobody has vouched for, or unreadable

Public. The check to run before an address is pasted anywhere. `trust` is `verified` (Robinhood lists this address and the contract answers with the listed symbol and decimals), `listed` (on the list, not yet confirmed against the chain), `lookalike` (not on the list, and its symbol or name folds to a verified asset's — `impersonates` names the real one and its address), `community` (found on chain, read from its own contract, vouched for by nobody) or `unknown` (nothing answered at this address). Symbols are compared with homoglyphs folded and invisible characters stripped, so a Cyrillic ТSLA is caught as a lookalike of TSLA. `source` says where the facts came from: `registry` is Robinhood's list, `discovered` is the token's own contract as the registry daemon read it, `none` is an address nobody has read. `market` is the deepest pool Fletch has priced from its own reserves, in dollars, and is null when no pool has been priced. A null is a figure not read, never a zero.

Public

Parameters

[
  {
    "name": "address",
    "in": "path",
    "required": true,
    "schema": {
      "type": "string",
      "pattern": "^0x[0-9a-fA-F]{40}$"
    },
    "example": "0x0000000000000000000000000000000000000000"
  }
]

Responses

{
  "200": {
    "description": "What this token is",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "chainId": {
              "type": "integer"
            },
            "address": {
              "type": "string"
            },
            "trust": {
              "type": "string",
              "enum": [
                "verified",
                "listed",
                "lookalike",
                "community",
                "unknown"
              ]
            },
            "label": {
              "type": "string"
            },
            "detail": {
              "type": "string"
            },
            "impersonates": {
              "type": [
                "object",
                "null"
              ],
              "properties": {
                "symbol": {
                  "type": "string"
                },
                "name": {
                  "type": "string"
                },
                "address": {
                  "type": "string"
                },
                "registryUrl": {
                  "type": "string"
                }
              }
            },
            "symbol": {
              "type": [
                "string",
                "null"
              ]
            },
            "name": {
              "type": [
                "string",
                "null"
              ]
            },
            "decimals": {
              "type": [
                "integer",
                "null"
              ]
            },
            "source": {
              "type": "string",
              "enum": [
                "registry",
                "discovered",
                "none"
              ]
            },
            "firstSeenAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "readAt": {
              "type": [
                "string",
                "null"
              ],
              "format": "date-time"
            },
            "registryUrl": {
              "type": [
                "string",
                "null"
              ]
            },
            "explorerUrl": {
              "type": "string"
            },
            "market": {
              "type": [
                "object",
                "null"
              ],
              "properties": {
                "poolId": {
                  "type": "string"
                },
                "venue": {
                  "type": "string"
                },
                "priceUsd": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "depthUsd": {
                  "type": [
                    "number",
                    "null"
                  ]
                },
                "swaps24h": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "transactions24h": {
                  "type": [
                    "integer",
                    "null"
                  ]
                },
                "metricsAsOf": {
                  "type": [
                    "string",
                    "null"
                  ],
                  "format": "date-time"
                },
                "priceSource": {
                  "const": "dex"
                },
                "volumeUsd24h": {
                  "type": [
                    "number",
                    "null"
                  ]
                }
              }
            },
            "note": {
              "type": "string"
            }
          },
          "required": [
            "chainId",
            "address",
            "trust",
            "label",
            "detail",
            "source",
            "explorerUrl"
          ]
        }
      }
    }
  },
  "400": {
    "description": "Not an address",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}
GET /chains/{chainId}/dex/poolsEvery pool on every DEX the registry reads, listed and community alike, one page at a time: the pair, the priced side, price, depth, the last day's swaps and volume, and FDV for an unlisted token

Public. The market table behind a DexScreener-style page. `kind=listed` keeps pools with one side on Robinhood's list; `kind=community` keeps pools whose priced side is a token the list does not carry, described by `token` from its own contract and verified by nobody; `kind=lookalike` keeps the community pools whose token borrows a listed ticker or name at another address. `trust` is accepted as a synonym for `kind`. `sort` defaults to `volume`: fresh measured 24h volume, then measured quote-side depth and swap count. Missing values sort last; `traction` uses the same relevance ordering. `depth`, `swaps` and `newest` are explicit alternatives. `q` takes a listed ticker, a token symbol or name by prefix, a token contract address, a Uniswap v3 pool address, or a Uniswap v4 pool id. `total` counts every pool that matches before paging. A pool the state read has not reached carries nulls; a community pool whose token has not answered decimals() stays unpriced. `swaps24h` counts swap logs and `transactions24h` counts distinct transactions in (metricsAsOf - 24 hours, metricsAsOf], using each event block timestamp. Values are null until the entire window is indexed and when its end is more than 120 seconds old. `volumeUsd24h` requires historical per-swap USD valuations; a current pool price is never substituted. Zero means a completely scanned window with no matching activity.

Public

Parameters

[
  {
    "name": "chainId",
    "in": "path",
    "required": true,
    "schema": {
      "type": "integer"
    },
    "example": 4663
  },
  {
    "name": "kind",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "enum": [
        "all",
        "listed",
        "community",
        "lookalike"
      ],
      "default": "all"
    },
    "description": "Also accepted as `trust`."
  },
  {
    "name": "tier",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "enum": [
        "active",
        "quiet",
        "dormant",
        "all"
      ],
      "default": "active"
    },
    "description": "Which tiers to list; the default is the pools worth watching."
  },
  {
    "name": "sort",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "enum": [
        "traction",
        "depth",
        "volume",
        "swaps",
        "newest"
      ],
      "default": "volume"
    }
  },
  {
    "name": "venue",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string",
      "enum": [
        "uniswap_v4",
        "uniswap_v3"
      ]
    }
  },
  {
    "name": "q",
    "in": "query",
    "required": false,
    "schema": {
      "type": "string"
    },
    "description": "Token or pool name, symbol, or a complete 0x address. Addresses are matched in full.",
    "example": "PIPE"
  },
  {
    "name": "limit",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 1,
      "maximum": 500,
      "default": 100
    }
  },
  {
    "name": "offset",
    "in": "query",
    "required": false,
    "schema": {
      "type": "integer",
      "minimum": 0,
      "default": 0
    }
  }
]

Responses

{
  "200": {
    "description": "A page of pools",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "pools": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "poolId": {
                    "type": "string"
                  },
                  "venue": {
                    "type": "string",
                    "enum": [
                      "uniswap_v4",
                      "uniswap_v3"
                    ]
                  },
                  "kind": {
                    "type": "string",
                    "enum": [
                      "listed",
                      "community"
                    ]
                  },
                  "tier": {
                    "type": "string",
                    "enum": [
                      "active",
                      "quiet",
                      "dormant"
                    ],
                    "description": "Active pools are prioritized for background sampling; quiet pools receive a daily cycle; dormant pools receive demand-driven reads. Scheduling does not establish freshness: inspect stateCheckedAt and stateCurrent."
                  },
                  "lastSwapAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "poolAddress": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "currency0": {
                    "type": "string"
                  },
                  "currency1": {
                    "type": "string"
                  },
                  "fee": {
                    "type": "integer"
                  },
                  "feeDynamic": {
                    "type": "boolean"
                  },
                  "feePct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "tickSpacing": {
                    "type": "integer"
                  },
                  "hooks": {
                    "type": "string"
                  },
                  "asset": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "The listed asset's ticker; null for a community pool."
                  },
                  "token": {
                    "type": [
                      "object",
                      "null"
                    ],
                    "description": "The unlisted side of a community pool, as its own contract describes it. Nothing here is verified.",
                    "properties": {
                      "address": {
                        "type": "string"
                      },
                      "symbol": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "name": {
                        "type": [
                          "string",
                          "null"
                        ]
                      },
                      "decimals": {
                        "type": [
                          "integer",
                          "null"
                        ]
                      },
                      "totalSupplyRaw": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "description": "Base units; divide by 10^decimals."
                      },
                      "fdvUsd": {
                        "type": [
                          "number",
                          "null"
                        ],
                        "description": "Total supply times the pool's dollar price."
                      },
                      "burnedRaw": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "description": "Sum of readable balances at the zero and dead addresses, in base units."
                      },
                      "marketCapUsd": {
                        "type": [
                          "number",
                          "null"
                        ],
                        "description": "Total supply minus zero/dead-address balances, times the pool price. An upper bound on circulating value. Null without supply, burn balances, decimals or usable price, and when remaining supply is nonpositive."
                      },
                      "readAt": {
                        "type": [
                          "string",
                          "null"
                        ],
                        "format": "date-time"
                      }
                    }
                  },
                  "quote": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "createdBlock": {
                    "type": "string"
                  },
                  "sqrtPriceX96": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "tick": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "liquidity": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "depthUsd": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "Depth in USD uses observed quote-side holdings for v3. For v4 it uses a bounded quote estimate for a 1% price move; per-pool token reserves are unavailable. Check the pool's observation time and stateCurrent flag."
                  },
                  "priceInQuote": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "priceUsd": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "swaps24h": {
                    "type": [
                      "integer",
                      "null"
                    ]
                  },
                  "transactions24h": {
                    "type": [
                      "integer",
                      "null"
                    ],
                    "description": "Distinct transactions in the exact indexed 24-hour window."
                  },
                  "metricsAsOf": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "End of the indexed 24-hour window; metrics expire after 120 seconds."
                  },
                  "metricsWindowStartAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "metricsCoverageComplete": {
                    "type": "boolean"
                  },
                  "metricsCurrent": {
                    "type": "boolean"
                  },
                  "volume0Raw": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Sum of absolute currency0 swap amounts in base units, only for a complete current window."
                  },
                  "volume1Raw": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "description": "Sum of absolute currency1 swap amounts in base units. Separate from currency0; the legs are never added together."
                  },
                  "volumeUsd24h": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "stateCheckedAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time"
                  },
                  "stateCurrent": {
                    "type": "boolean",
                    "description": "The pool state was observed within ten minutes and its timestamp is not in the future. When false, depth, price, FDV and price changes are null; stateCheckedAt retains the actual observation time."
                  },
                  "pricePublished": {
                    "type": "boolean",
                    "description": "Current state has a finite positive price and clears the configured depth floor."
                  },
                  "change5mPct": {
                    "type": [
                      "number",
                      "null"
                    ],
                    "description": "Dollar price against the newest sample at or before five minutes ago; null when no sample is old enough."
                  },
                  "change1hPct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "change6hPct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  },
                  "change24hPct": {
                    "type": [
                      "number",
                      "null"
                    ]
                  }
                },
                "required": [
                  "poolId",
                  "venue",
                  "kind",
                  "currency0",
                  "currency1",
                  "fee",
                  "createdBlock",
                  "stateCurrent",
                  "pricePublished"
                ]
              }
            },
            "total": {
              "type": "integer"
            },
            "limit": {
              "type": "integer"
            },
            "offset": {
              "type": "integer"
            },
            "kind": {
              "type": "string"
            },
            "tier": {
              "type": "string"
            },
            "sort": {
              "type": "string"
            },
            "venue": {
              "type": [
                "string",
                "null"
              ]
            },
            "q": {
              "type": [
                "string",
                "null"
              ]
            },
            "discovery": {
              "type": "array",
              "items": {
                "type": "object",
                "properties": {
                  "venue": {
                    "type": "string"
                  },
                  "scanned": {
                    "type": "boolean",
                    "description": "Discovery has read this venue at least once; false means no pool from it is listed yet because nothing has looked."
                  },
                  "scannedToBlock": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "headBlock": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "headAt": {
                    "type": [
                      "string",
                      "null"
                    ],
                    "format": "date-time",
                    "description": "When the chain head above was read."
                  },
                  "blocksBehind": {
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "readingHistory": {
                    "type": "boolean"
                  }
                },
                "required": [
                  "venue",
                  "scanned",
                  "readingHistory"
                ]
              }
            },
            "note": {
              "type": "string"
            }
          },
          "required": [
            "pools",
            "total",
            "limit",
            "offset",
            "discovery"
          ]
        }
      }
    }
  },
  "404": {
    "description": "Unknown chain",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  },
  "429": {
    "description": "Too many anonymous requests from this address; Retry-After says when the window ends",
    "content": {
      "application/json": {
        "schema": {
          "type": "object",
          "properties": {
            "error": {
              "type": "string"
            }
          },
          "required": [
            "error"
          ]
        }
      }
    }
  }
}

Named schemas

Error
{
  "type": "object",
  "properties": {
    "error": {
      "type": "string"
    }
  },
  "required": [
    "error"
  ]
}
Chain
{
  "type": "object",
  "properties": {
    "chainId": {
      "type": "integer"
    },
    "name": {
      "type": "string"
    },
    "network": {
      "type": "string",
      "enum": [
        "mainnet",
        "testnet"
      ]
    },
    "rpcUrl": {
      "type": "string"
    },
    "explorerUrl": {
      "type": "string"
    },
    "providerConfigured": {
      "type": "boolean"
    }
  },
  "required": [
    "chainId",
    "name",
    "network",
    "rpcUrl",
    "explorerUrl",
    "providerConfigured"
  ]
}
Asset
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "`${chainId}:${address}`"
    },
    "chainId": {
      "type": "integer"
    },
    "address": {
      "type": "string"
    },
    "symbol": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "assetType": {
      "type": "string",
      "enum": [
        "stock_token",
        "stablecoin",
        "wrapped_native",
        "bridged"
      ]
    },
    "decimals": {
      "type": "integer"
    },
    "status": {
      "type": "string"
    },
    "source": {
      "type": "string"
    },
    "sourceUri": {
      "type": [
        "string",
        "null"
      ]
    },
    "observedAt": {
      "type": "string",
      "format": "date-time"
    },
    "firstSeenAt": {
      "type": "string",
      "format": "date-time",
      "description": "When Fletch first saw the token; Robinhood publishes no listing date"
    },
    "verifiedAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "onchainName": {
      "type": [
        "string",
        "null"
      ]
    },
    "onchainSymbol": {
      "type": [
        "string",
        "null"
      ]
    },
    "onchainDecimals": {
      "type": [
        "integer",
        "null"
      ]
    },
    "metadataCheckedAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "isin": {
      "type": [
        "string",
        "null"
      ]
    },
    "logoUrl": {
      "type": [
        "string",
        "null"
      ]
    }
  },
  "required": [
    "id",
    "chainId",
    "address",
    "symbol",
    "name",
    "assetType",
    "decimals",
    "status",
    "source"
  ]
}
AuthorityEvent
{
  "type": "object",
  "description": "One entry in the registry changelog. `id` is stable across re-runs; the cursor for the row is `${observedAt}|${id}`.",
  "properties": {
    "id": {
      "type": "string",
      "description": "`ev_` followed by 24 hex characters; the same change is never written twice"
    },
    "kind": {
      "type": "string",
      "description": "A dotted kind such as `registry.paused` or `multiplier.applied`; every kind the daemon can emit is in the response's `kinds`",
      "example": "multiplier.applied"
    },
    "title": {
      "type": "string",
      "description": "The change as one changelog line"
    },
    "symbol": {
      "type": [
        "string",
        "null"
      ],
      "description": "The token concerned; null for a chain-wide event"
    },
    "address": {
      "type": [
        "string",
        "null"
      ],
      "description": "The contract or account concerned; null for a chain-wide event"
    },
    "detail": {
      "type": [
        "object",
        "null"
      ],
      "additionalProperties": true,
      "description": "The numbers behind the title; fields depend on the kind"
    },
    "block": {
      "type": [
        "string",
        "null"
      ],
      "description": "Block number as a decimal string; null for events not tied to a block"
    },
    "txHash": {
      "type": [
        "string",
        "null"
      ]
    },
    "occurredAt": {
      "type": "string",
      "format": "date-time",
      "description": "When the change happened on chain or at the source"
    },
    "observedAt": {
      "type": "string",
      "format": "date-time",
      "description": "When the daemon recorded it; the cursor orders by this"
    }
  },
  "required": [
    "id",
    "kind",
    "title",
    "symbol",
    "address",
    "detail",
    "block",
    "txHash",
    "occurredAt",
    "observedAt"
  ]
}
Watcher
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "projectId": {
      "type": [
        "string",
        "null"
      ]
    },
    "name": {
      "type": "string"
    },
    "kind": {
      "type": "string",
      "enum": [
        "large_transfer",
        "wallet_activity",
        "registry_event",
        "token_event",
        "new_pool"
      ]
    },
    "chainId": {
      "type": "integer"
    },
    "address": {
      "type": "string"
    },
    "assetId": {
      "type": [
        "string",
        "null"
      ]
    },
    "threshold": {
      "type": "string"
    },
    "wallet": {
      "type": [
        "string",
        "null"
      ],
      "description": "wallet_activity only — the watched address."
    },
    "delivery": {
      "type": "string",
      "enum": [
        "telegram",
        "webhook"
      ],
      "description": "Where this watcher's alerts are sent."
    },
    "webhookId": {
      "type": [
        "string",
        "null"
      ],
      "description": "The endpoint alerts are posted to when delivery is \"webhook\"."
    },
    "webhookName": {
      "type": [
        "string",
        "null"
      ],
      "description": "The endpoint's name. Null when delivery is \"telegram\". Also null when the endpoint was deleted: delivery stays \"webhook\", webhookId is null, and the watcher is paused with the reason in lastError. Such a watcher cannot be resumed until it is re-pointed with PATCH /watchers/{id} { webhookId }."
    },
    "enabled": {
      "type": "boolean"
    },
    "status": {
      "type": "string",
      "enum": [
        "active",
        "catching_up",
        "degraded",
        "paused"
      ]
    },
    "lastCheckedBlock": {
      "type": [
        "string",
        "null"
      ]
    },
    "lastTriggeredAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "lastError": {
      "type": [
        "string",
        "null"
      ]
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "updatedAt": {
      "type": "string",
      "format": "date-time"
    },
    "lastDelivery": {
      "type": [
        "object",
        "null"
      ],
      "description": "The most recent delivery of any status, or null before the first.",
      "properties": {
        "sentAt": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time"
        },
        "amount": {
          "type": [
            "string",
            "null"
          ]
        },
        "txHash": {
          "type": "string"
        }
      },
      "required": [
        "sentAt",
        "amount",
        "txHash"
      ]
    }
  },
  "required": [
    "id",
    "name",
    "kind",
    "chainId",
    "address",
    "threshold",
    "enabled",
    "status",
    "createdAt",
    "updatedAt",
    "lastDelivery"
  ]
}
Run
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "watcherId": {
      "type": "string"
    },
    "status": {
      "type": "string",
      "enum": [
        "pending",
        "sent",
        "failed",
        "retracted"
      ]
    },
    "lastError": {
      "type": [
        "string",
        "null"
      ]
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "sentAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time"
    },
    "payload": {
      "type": "object",
      "description": "DeliveryPayload — kind, chainId, address, symbol, from, to, value, amount, threshold, txHash, logIndex, blockNumber, blockHash, explorerUrl; wallet_activity adds wallet and direction (\"in\" | \"out\"); an authority payload (kind \"authority\", from a registry_event or token_event watcher) instead carries eventId, eventKind, title, symbol, address, detail, txHash, blockNumber, occurredAt (ISO 8601 UTC), explorerUrl and registryUrl."
    }
  },
  "required": [
    "id",
    "watcherId",
    "status",
    "createdAt",
    "payload"
  ]
}
Webhook
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "url": {
      "type": "string"
    },
    "secretPrefix": {
      "type": "string",
      "description": "The first characters of the signing secret; the secret itself is returned only once, at creation or rotation."
    },
    "enabled": {
      "type": "boolean"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "lastDeliveredAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "When this endpoint last answered 2xx, including test pings — not necessarily an alert."
    },
    "lastError": {
      "type": [
        "string",
        "null"
      ],
      "description": "The most recent failure whenever it happened, cleared by the next success. Compare lastErrorAt with lastDeliveredAt before reading it as a fault now."
    },
    "lastErrorAt": {
      "type": [
        "string",
        "null"
      ],
      "format": "date-time",
      "description": "When lastError was written. Null on an endpoint whose last failure predates this field."
    },
    "secret": {
      "type": "string",
      "description": "Present only in the response that created or rotated this endpoint. Stored encrypted and never returned again."
    }
  },
  "required": [
    "id",
    "name",
    "url",
    "secretPrefix",
    "enabled",
    "createdAt"
  ]
}
WebhookCreated
{
  "allOf": [
    {
      "type": "object",
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "url": {
          "type": "string"
        },
        "secretPrefix": {
          "type": "string",
          "description": "The first characters of the signing secret; the secret itself is returned only once, at creation or rotation."
        },
        "enabled": {
          "type": "boolean"
        },
        "createdAt": {
          "type": "string",
          "format": "date-time"
        },
        "lastDeliveredAt": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time",
          "description": "When this endpoint last answered 2xx, including test pings — not necessarily an alert."
        },
        "lastError": {
          "type": [
            "string",
            "null"
          ],
          "description": "The most recent failure whenever it happened, cleared by the next success. Compare lastErrorAt with lastDeliveredAt before reading it as a fault now."
        },
        "lastErrorAt": {
          "type": [
            "string",
            "null"
          ],
          "format": "date-time",
          "description": "When lastError was written. Null on an endpoint whose last failure predates this field."
        },
        "secret": {
          "type": "string",
          "description": "Present only in the response that created or rotated this endpoint. Stored encrypted and never returned again."
        }
      },
      "required": [
        "id",
        "name",
        "url",
        "secretPrefix",
        "enabled",
        "createdAt"
      ]
    },
    {
      "type": "object",
      "required": [
        "secret"
      ]
    }
  ]
}
WebhookDelivery
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string",
      "description": "Delivery id, `dl_…` (`ping_…` for a test); the idempotency key."
    },
    "kind": {
      "type": "string",
      "enum": [
        "large_transfer",
        "wallet_activity",
        "authority",
        "ping"
      ]
    },
    "payload": {
      "type": "object",
      "description": "DeliveryPayload — kind, chainId, address, symbol, from, to, value, amount, threshold, txHash, logIndex, blockNumber, blockHash, explorerUrl; wallet_activity adds wallet and direction (\"in\" | \"out\"); an authority payload (kind \"authority\", from a registry_event or token_event watcher) instead carries eventId, eventKind, title, symbol, address, detail, txHash, blockNumber, occurredAt (ISO 8601 UTC), explorerUrl and registryUrl."
    },
    "watcher": {
      "type": [
        "object",
        "null"
      ],
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "kind": {
          "type": "string"
        }
      },
      "description": "null for a ping, which belongs to the endpoint rather than to any watcher."
    },
    "queuedAt": {
      "type": "string",
      "format": "date-time",
      "description": "When Fletch matched the event. On a retry this is well before sentAt."
    },
    "attempt": {
      "type": "integer",
      "description": "1 on the first try."
    },
    "sentAt": {
      "type": "string",
      "format": "date-time",
      "description": "When this attempt was posted."
    }
  },
  "required": [
    "id",
    "kind",
    "payload",
    "queuedAt",
    "attempt",
    "sentAt"
  ]
}
Project
{
  "type": "object",
  "properties": {
    "id": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "slug": {
      "type": "string"
    },
    "createdAt": {
      "type": "string",
      "format": "date-time"
    },
    "buildCount": {
      "type": "integer"
    }
  },
  "required": [
    "id",
    "name",
    "slug",
    "createdAt",
    "buildCount"
  ]
}
Open Limits, pricing, and what is not built yet

Limits, pricing, and what is not built yet

The deployed limits and availability, followed by work that remains planned.

Current limits

AreaCurrent production behavior
Initial grant3 build credits once, at the first eligible build attempt. Eligibility checks wallet activity or balance on Robinhood Chain.
Build cost1 Fletch credit per platform build; 0 with your own model key. Provider API charges still apply.
Execution2 simultaneous build slots, additional accepted runs queued. The current agent-turn timeout is 45 minutes.
Prompt24,000 characters; five text files, 64 KiB each and 128 KiB total.
ImagesPNG/JPEG with a vision-capable selected model: three images, 2 MiB each, 4 MiB total, 4096px per side, 16 megapixels.
Watch5 watchers per account, 1 new-pool watcher, 500 platform-wide.
RPC200,000 calls per day under the shared watcher/indexer ceiling; workers have separate sub-budgets.
Public API120 anonymous registry reads per minute per IP. Keyed requests: 600 per hour per key.
Webhooks5 endpoints per account, 10s delivery timeout and up to 8 attempts.

Payment and deployment availability

The production checkout treasury is not configured, so credit checkout is unavailable. The $19 Builder subscription and FLETCH payment and burn terms shown on the landing page describe a planned offer. The backend currently implements the per-build credit rules above. The landing page's 10-credit offer differs from the deployed initial grant of 3; the grant in this table is what the backend applies.

Contract deployment currently targets Robinhood Chain testnet, 46630. Mainnet deployment is disabled. Watch is free during beta. A failed charged build receives its Fletch credit refund as a separate ledger entry. No Fletch refund can reverse a provider's own API charges.

The deployed wallet foundation supports compatible injected EVM wallets. The production Reown project ID is currently absent, so QR WalletConnect pairing is unavailable until it is configured. Hosted model keys use server-side encryption and decryption; server operators can access them.

Current build verification limits

A succeeded build status can still contain deployment or hosting failure notes. Tests may be absent, and a published page can lack a contract or interaction requested in the brief. Check each recorded stage and the app's required flows before relying on the result.

A security repair can leave the summary showing an earlier test report. Inspect the saved reports and rerun the final source's tests when reviewing a release. Complete requirement checks and consistently updated final reports remain in the build verification backlog.

Planned

  • Small, medium and large build pricing, estimated costs, user-approved maximum budgets and admin price controls.
  • Required-contract and complete user-flow checks, consistent final-source test evidence, and separate outcomes for partial builds. A new attached brief can still select the existing-app coding instruction after planning; the planner itself receives the complete brief.
  • Durable multi-hour execution, automatic conversation compaction, restart-resumable workers and off-host workspace restoration. Current browser reconnect and retained source files cover only part of that work.
  • Complete historical swap coverage and exact rolling USD volume for the top active pools. Recent swap coverage and state sampling remain visible per pool while this work continues.
  • Verified quote-token pricing coverage, broader supply and burn-balance sampling, depth-integrity checks and the remaining Markets acceptance cases.
  • Bridged and verified Ondo trust stamps backed by their required issuer and escrow evidence.
  • The Builder subscription, recurring rollover credits, FLETCH checkout and burn, customer domains, expanded watcher caps and repository export as a plan entitlement.
  • Team workspaces, dedicated capacity, Slack and email alerts, x402 payments and an npm-published MCP package.

Check the current reading

A healthy web response does not establish complete data coverage. The status page reports worker freshness and historical checkpoints. Real Telegram delivery, wallet signing and full app behavior require their own end-to-end tests; a documentation page loading successfully proves only that page's availability.

Open FAQ

FAQ

Short answers about identity, builds, prices, wallets and alerts.

Does verified mean a token is safe to buy?

Verified means the recorded contract matches Robinhood's listing checks. Financial risk, contract behavior and the terms of the underlying asset require separate review.

Why does a price or volume show a dash?

The relevant read may be missing, stale or incomplete. Inspect the observation time and coverage note. A resolved name or recently discovered pool does not supply a price or a full day of swaps.

Can I close the browser during a build?

Yes. The running job belongs to the server. Reopen its project to load saved progress and reconnect. Current execution time and restart limitations are listed on the limits page.

Why is my build queued?

The two execution slots are occupied. The queue shows your position. While it is queued, Cancel removes it and Edit restores the draft. If a worker has already claimed it, the console shows that running state.

Can I use Phantom?

Generated signing apps use the shared component's compatible injected EVM wallet discovery, including Phantom's EVM provider. Use a browser with the extension available and check its chain support. Signing acceptance still depends on testing the generated app's transaction flow.

Can Fletch operators see my hosted model key?

Operators with the server's access and encryption material can access it. It is encrypted in storage and the upstream key is kept out of generated user code. Revoke the connection in Settings when needed.

Why has my watcher sent nothing?

Check that it is enabled, its condition has matched a new event, Telegram or the webhook is linked, and the delivery is sent. A held event needs a destination. A pending event may be waiting for a retry. Inspect the daemon and job status for lag.

Do I need a Fletch key to read the registry?

Public registry GETs work without a key under the anonymous rate limit. Scoped keys authenticate account operations. The generated reference marks each endpoint's requirement.

Which chain does each part use?

Registry and Watch follow mainnet 4663. The hosted builder currently deploys contracts to testnet 46630. Confirm the network in each receipt before using the generated app.

Open Webhooks

Webhooks

Register an endpoint and verify signed, retried alert deliveries.

Open MCP server

MCP server

Connect an agent to Fletch's registry tools.