Integrations & API
REST and WebSocket endpoints exposed by the indexer, with example payloads.
On this page
The indexer exposes a small read-only API over the contract events. It is not deployed yet, so every endpoint below currently corresponds to a typed mock module in the interface repository with an identical response shape.
Base URL and conventions
| Property | Value |
|---|---|
| Base URL | https://api.bankhood.xyz |
| Auth | None. All endpoints are public and read-only. |
| Rate limit | 60 requests per minute per IP |
| Pagination | limit (max 100) and cursor query parameters |
| Timestamps | ISO 8601 in UTC |
| Amounts | Decimal strings, pre-scaled for display |
| Errors | RFC 7807 problem+json |
Amounts are returned as strings rather than numbers so that share counts with eighteen decimals survive JSON parsing intact.
GET /v1/reserve
Protocol-level totals. This is the endpoint behind the landing page stat strip and the explorer header.
{
"status": "pre-launch",
"totalFeesEth": "0",
"hoodShares": "0",
"hoodCostBasisUsd": "0",
"holders": 0,
"distributions": 0,
"uniqueClaimers": 0,
"lastIndexedBlock": null,
"nextDistributionAt": null
}status is one of pre-launch, live or paused. It flips to live on the first indexed FeeCollected event.
GET /v1/fees
Individual fee payments, newest first.
{
"data": [
{
"id": "18990421-42",
"txHash": "0x…",
"block": 18990421,
"timestamp": "2026-07-25T14:02:11Z",
"payer": "0x…",
"side": "buy",
"notionalEth": "1.000000",
"feeEth": "0.030000",
"status": "confirmed"
}
],
"cursor": null
}GET /v1/distributions
Settled batches: ETH converted, shares acquired, average fill price and the number of holders credited.
{
"data": [
{
"id": "0x8f2c…",
"txHash": "0x…",
"block": 18990455,
"timestamp": "2026-07-25T14:31:04Z",
"ethRouted": "0.262000",
"hoodShares": "8.610000",
"avgFillPrice": "94.88",
"recipients": 1284,
"status": "confirmed"
}
],
"cursor": null
}GET /v1/claims/:address
Claim history for one address. Omit the address segment to get the global claim feed.
curl -s "https://api.bankhood.xyz/v1/claims/0xYourAddress?limit=20" \
-H "accept: application/json"{
"data": [
{
"id": "1753452664000",
"txHash": "0x…",
"block": 18990512,
"timestamp": "2026-07-25T14:51:04Z",
"recipient": "0x…",
"hoodShares": "0.043050",
"valueUsd": "4.09",
"status": "confirmed"
}
],
"cursor": null
}WebSocket stream
A single multiplexed socket pushes the same events the REST endpoints expose, for interfaces that want live updates without polling.
const socket = new WebSocket("wss://api.bankhood.xyz/v1/stream");
socket.addEventListener("open", () => {
socket.send(JSON.stringify({
op: "subscribe",
channels: ["fees", "distributions", "claims"],
// optional: only claims for one address
address: "0xYourAddress",
}));
});
socket.addEventListener("message", (event) => {
const { channel, data } = JSON.parse(event.data);
// channel: "fees" | "distributions" | "claims" | "reserve"
});| Channel | Pushes |
|---|---|
| fees | One message per indexed FeeCollected event |
| distributions | One message per FillReported event |
| claims | One message per Claimed event, filterable by address |
| reserve | Totals snapshot, at most once every 300 seconds |
Local mock modules
Until the indexer exists, the interface reads these modules. Each exports the same shape as its endpoint, so replacing one is a single change at the call site.
| Module | Replaces | Currently returns |
|---|---|---|
| lib/mock/reserve.ts | GET /v1/reserve | Genesis snapshot, all zeros |
| lib/mock/explorer.ts | fees, distributions, claims | Empty arrays |
| lib/mock/position.ts | balanceOf and claimable reads | Deterministic simulated position |
Swapping one out
-export async function getFeePayments(): Promise<FeePayment[]> {
- return feePayments;
-}
+export async function getFeePayments(): Promise<FeePayment[]> {
+ const res = await fetch(`${API_BASE}/v1/fees?limit=50`, {
+ next: { revalidate: 15 },
+ });
+ const { data } = await res.json();
+ return data;
+}