Arb Capital API

REST API for Arb Capital tokens (wstGBP) and the legacy multi-vault rewards products.

Auth: If API_KEY is configured, include Authorization: Bearer <key> on all requests.
Rate limits: 60 req/min for D1 reads, 30 req/min for on-chain routes. Per-IP, per-route.
BigInt: Large numbers (TVL, balances, amounts) are serialized as strings to preserve precision.
Addresses: All on-chain addresses are stored and returned lowercase.
vault_id: Accepts a vault slug (e.g. arbcap-usdt-core) or contract address (case-insensitive). Untracked addresses return empty results (200).
token: Token routes take a path segment that accepts a token slug (e.g. wstgbp) or the home-chain contract address (case-insensitive). Unknown tokens return 404.

Tokens

GET/api/tokens60/min

All tokens with cached metrics (APR, NAV price, TVL, holders).

Cache: 120s

Response

{
  "tokens": [{
    "slug": "wstgbp",
    "name": "Wren Staked tGBP",
    "symbol": "wstGBP",
    "decimals": 18,
    "chainId": 1,
    "address": "0x57C3...B7aE",
    "underlying": { "symbol": "tGBP", "address": "0x27f6...5287", "decimals": 18 },
    "deploymentCount": 11,
    "poolCount": 3,
    "apr30d": 3.82,
    "apr7d": null,
    "aprTrend": "stable",
    "navprice": "1023456789012345678",
    "navpriceFloat": 1.023456,
    "tvl": "5250000000000000000000000",
    "tvlFloat": 5250000,
    "holderCount": 128,
    "updatedAt": "2026-07-11 12:00:00"
  }]
}
GET/api/tokens/{token}30/min

Token detail with live on-chain wrapper state (NAV price, mint/redeem costs, supply, TVL, gates).

Cache: 60s

Wei values are strings; *Float fields are display-precision floats.

ParamTypeRequiredDescription
tokenstringYesToken slug (e.g. wstgbp) or home-chain contract address (path segment)

Response

{
  "slug": "wstgbp",
  "live": {
    "navprice": "1023456789012345678",
    "mintcost": "1023456789012345678",
    "burncost": "1020898147039814313",
    "totalSupply": "5130000000000000000000000",
    "tvl": "5250000000000000000000000",
    "mintable": true,
    "burnable": true,
    "capacity": "10000000000000000000000000",
    "cooldown": "0",
    "redemptionCount": "4",
    "feeBps": { "in": 0, "out": 25 }
  }
}
GET/api/tokens/{token}/snapshots60/min

Hourly NAV price / supply / TVL snapshots.

Cache: 300s

ParamTypeRequiredDescription
daysnumberNoLookback period (default 30, 1–365)

Response

{
  "snapshots": [{
    "timestamp": "2026-07-10 00:00:03",
    "navprice": "1023456789012345678",
    "total_supply": "5130000000000000000000000",
    "tvl": "5250000000000000000000000"
  }]
}
GET/api/tokens/{token}/daily60/min

Daily rollup (last snapshot per day).

Cache: 300s

ParamTypeRequiredDescription
daysnumberNoLookback period (default 30, 1–365)

Response

{
  "daily": [{
    "date": "2026-07-10",
    "timestamp": "2026-07-10 23:00:02",
    "navprice": "1023456789012345678",
    "total_supply": "5130000000000000000000000",
    "tvl": "5250000000000000000000000"
  }]
}
GET/api/tokens/{token}/apr60/min

Trailing 30-day NAV growth annualized over actual elapsed seconds (simple APR, no compounding).

Cache: 300s

apr7d is often null — oracle pokes are weekly, so a 7-day window may hold fewer than two points.

Response

{
  "apr30d": 3.82,
  "apr7d": null,
  "aprWad": "38200000000000000",
  "aprTrend": "stable",
  "windowDays": 30,
  "sampleCount": 4,
  "fromTimestamp": 1780000000,
  "asOf": 1782000000,
  "updatedAt": "2026-07-11 12:00:00"
}
GET/api/tokens/{token}/price-history60/min

Oracle poke history (NAV price updates, pauses included).

Cache: 300s

ParamTypeRequiredDescription
daysnumberNoLookback period (default 90, 1–730)

Response

{
  "updates": [{
    "price": "1023456789012345678",
    "is_pause": 0,
    "block_timestamp": 1782000000,
    "timestamp": "2026-07-08 09:00:11"
  }]
}
GET/api/tokens/{token}/supply60/min

Per-chain supply: primary figures are the token balances escrowed in each bridge's L1 contract (refreshed 6-hourly via one mainnet multicall), cross-checked weekly against actual L2 totalSupply.

Cache: 300s

totalSupply per chain = L1 escrow balance (backs the bridged supply 1:1; may briefly exceed L2 supply while transfers are in flight). l2Supply is the weekly on-L2 verification — l2Supply above the escrow would indicate an unbacked mint. bridgedSupply mirrors escrowed home-chain tokens and is not additive with home supply.

Response

{
  "home": { "chainId": 1, "totalSupply": "5130000000000000000000000", "stale": false },
  "chains": [{
    "chainId": 8453,
    "name": "Base",
    "address": "0xEa4F...8fff",
    "totalSupply": "12000000000000000000000",
    "timestamp": "2026-07-11 06:00:04",
    "stale": false,
    "source": "escrow",
    "l1Escrow": "0x3154...2C35",
    "l2Supply": "12000000000000000000000",
    "l2Timestamp": "2026-07-06 12:00:02"
  }],
  "aggregate": {
    "bridgedSupply": "45000000000000000000000",
    "chainsReporting": 11,
    "chainsConfigured": 11,
    "l2ReportedSupply": "45000000000000000000000",
    "l2ChainsReporting": 11
  }
}
GET/api/tokens/{token}/total-supply60/min

CoinGecko-compatible: total supply as a plain decimal number in token units (text/plain, no JSON).

Cache: 300s

Always public — exempt from API_KEY auth so supply crawlers can reach it.

Response

19830.263038853336707255
GET/api/tokens/{token}/circulating-supply60/min

CoinGecko-compatible: circulating supply as a plain decimal number in token units (text/plain, no JSON). For wstGBP circulating equals total supply.

Cache: 300s

Always public — exempt from API_KEY auth so supply crawlers can reach it.

Response

19830.263038853336707255
GET/api/tokens/{token}/chains60/min

Static chain/bridge metadata for every deployment (explorer, bridge UI, bridge type, L1 escrow contract).

Cache: 3600s

l1Escrow is the home-chain contract (bridge/gateway/predicate/mediator/vault) that locks the token 1:1 against the bridged supply.

Response

{
  "home": { "chainId": 1, "name": "Ethereum", "address": "0x57C3...B7aE" },
  "chains": [{
    "chainId": 8453,
    "name": "Base",
    "address": "0xEa4F...8fff",
    "bridgeType": "op-stack",
    "l1Escrow": "0x3154...2C35",
    "explorerUrl": "https://basescan.org",
    "bridgeUrl": "https://bridge.base.org",
    "status": "live"
  }]
}
GET/api/tokens/{token}/reserves30/min

Live backing / solvency check: underlying held vs owed at full redemption, net of the redeem-fee buffer.

Cache: 60s

Response

{
  "navprice": "1023456789012345678",
  "totalSupply": "5130000000000000000000000",
  "backing": "5250000000000000000000000",
  "expectedBacking": "5250333128933333333000000",
  "diff": "-333128933333333333000",
  "net": "12792638890000000000000",
  "bpsout": 25,
  "collateralizationPct": 99.99,
  "status": "OVER-COLLATERALIZED",
  "minTopUp": "0"
}
GET/api/tokens/{token}/events60/min

Mint / redeem / claim event feed (newest first).

Cache: 120s

mint amount is the token minted; redeem/claim amounts are the underlying.

ParamTypeRequiredDescription
typemint | redeem | claimNoFilter by event type
useraddressNoFilter by account
daysnumberNoLookback period (default 30, 1–365)
limitnumberNoMax rows (default 100, 1–500)

Response

{
  "events": [{
    "action": "mint",
    "user_address": "0xabc...def",
    "amount": "1000000000000000000000",
    "price": "1023456789012345678",
    "redemption_id": null,
    "tx_hash": "0x123...789",
    "block_number": 24900000,
    "chain_id": 1,
    "timestamp": "2026-07-11 10:15:00"
  }]
}
GET/api/tokens/{token}/pools30/min

Live Uniswap v4 pool state for every configured venue (price, fair value, deviation, dynamic fee).

Cache: 60s

estimatedFeePpm replicates the hook's dynamic-fee math (live feeParams + current deviation) per direction — hooks set fees per swap via beforeSwap override, so slot0 holds no meaningful fee. Backstop pools report the wrapper NAV band (band.mintcost / band.burncost) instead of a fair price and fee.

Response

{
  "pools": [{
    "key": "weth",
    "type": "dynamic-fee",
    "poolId": "0xaa4a...c920",
    "pairToken": { "symbol": "WETH", "decimals": 18 },
    "price": "433000000000000",
    "fairPrice": "432800000000000",
    "deviationPpm": 462,
    "liquidity": "182716...",
    "estimatedFeePpm": { "mintSide": 3000, "redeemSide": 500, "fallback": false },
    "band": null
  }]
}
GET/api/tokens/{token}/pools/history60/min

Hourly pool snapshots for one venue.

Cache: 300s

ParamTypeRequiredDescription
poolstringYesPool key (backstop | weth | usdc) or 0x poolId
daysnumberNoLookback period (default 30, 1–365)

Response

{
  "snapshots": [{
    "pool_key": "weth",
    "price": "433000000000000",
    "fair_price": "432800000000000",
    "deviation_ppm": 462,
    "liquidity": "182716...",
    "fee_mint_ppm": 3000,
    "fee_redeem_ppm": 500,
    "timestamp": "2026-07-11 10:00:05"
  }]
}
GET/api/tokens/{token}/quote30/min

Preview a mint or redeem at current on-chain prices, cross-checked against the backstop quoter.

Uncached — quotes are amount-dependent and must be fresh.

ParamTypeRequiredDescription
sidemint | redeemYesmint pays underlying, redeem pays token
amountstringYesExact input amount in wei (BigInt as string)

Response

{
  "side": "mint",
  "amountIn": "1000000000000000000000",
  "amountOut": "977080000000000000000",
  "price": "1023456789012345678",
  "feeBps": 0,
  "executable": true,
  "reason": null,
  "cooldown": "0",
  "quoter": { "amountIn": "1000000000000000000000", "amountOut": "977080000000000000000" }
}

Vaults

GET/api/vaults30/min

On-chain data for all vaults on a given chain.

ParamTypeRequiredDescription
chainId1 | 8453YesEthereum (1) or Base (8453)

Response

{
  "0x5c1E...64bc": {
    "vaultId": "arbcap-usdt-core",
    "totalAssets": "1234567890",
    "totalSupply": "1234567890",
    "assetAddress": "0x...",
    "vaultDecimals": 6
  }
}
GET/api/vaults/metadata60/min

APY, utilization, and trend data for vaults.

Cache: 60s

ParamTypeRequiredDescription
vault_idstringNoVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)

Response

[{
  "vault_id": "arbcap-usdt-core",
  "apy": 4.52,
  "apy_7d": 4.81,
  "apy_trend": "up",
  "utilization": 0.85,
  "updated_at": "2026-02-25T12:00:00"
}]
GET/api/vaults/allocations30/min

Per-strategy/market allocations for a vault with APYs.

MetaMorpho: APYs from Morpho GraphQL with on-chain IRM fallback. Euler: APYs from D1.

ParamTypeRequiredDescription
vault_idstringYesVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)

Response

{
  "allocations": [{
    "strategy": "0xabc...def",
    "name": "WBTC / USDT",
    "allocated": "500000000",
    "percentage": 45.23,
    "cap": "1000000000",
    "apy": 4.54
  }]
}
GET/api/vaults/snapshots60/min

Historical TVL snapshots for a vault.

Cache: 300s

ParamTypeRequiredDescription
vault_idstringYesVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)
daysnumberNoLookback period (default 30, 1–365)

Response

{
  "snapshots": [{
    "timestamp": "2026-02-20T00:00:00",
    "total_assets": "1234567890",
    "total_supply": "1234567890"
  }]
}
GET/api/vaults/apy-history60/min

Historical APY snapshots for a vault.

Cache: 300s

ParamTypeRequiredDescription
vault_idstringYesVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)
daysnumberNoLookback period (default 7, 1–90)

Response

{
  "snapshots": [{
    "timestamp": "2026-02-20T00:00:00",
    "apy": 4.52
  }]
}
GET/api/vaults/performance60/min

Aggregated performance stats over a time window.

Cache: 300s

ParamTypeRequiredDescription
vault_idstringYesVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)
daysnumberNoLookback period (default 30, 1–365)

Response

{
  "avg_apy": 7.83,
  "min_apy": 5.12,
  "max_apy": 11.04,
  "tvl_start": "1000000000",
  "tvl_end": "1125000000",
  "tvl_change_pct": 12.5
}
GET/api/vaults/strategy-history60/min

Historical TVL snapshots for a strategy.

Cache: 300s

ParamTypeRequiredDescription
strategystringYesStrategy contract address
daysnumberNoLookback period (default 30, 1–365)

Response

{
  "snapshots": [{
    "timestamp": "2026-02-20T00:00:00",
    "strategy_address": "0xabc...def",
    "total_assets": "1234567890",
    "total_supply": "1234567890"
  }]
}
GET/api/vaults/daily60/min

Daily snapshot for a vault (1 point per day, closest to 00:00 UTC). Includes TVL, computed share price, and APY. Untracked addresses return 200 with empty array.

Cache: 300s

ParamTypeRequiredDescription
vault_idstringYesVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)
daysnumberNoLookback period (default 30, 1–1000)

Response

{
  "daily": [{
    "date": "2026-03-22",
    "timestamp": "2026-03-22T00:00:00Z",
    "total_assets": "1234567890",
    "total_supply": "1234567890",
    "share_price": "1.000423891274651283",
    "apy": 4.52
  }]
}

User Positions

GET/api/vaults/position30/min

On-chain position data for a user in a vault.

ParamTypeRequiredDescription
chainId1 | 8453YesChain ID
vaultaddressYesVault contract address
assetaddressYesUnderlying asset address
useraddressYesUser wallet address

Response

{
  "assetBalance": "1000000",
  "allowance": "500000",
  "shareBalance": "980000",
  "maxWithdraw": "990000"
}
GET/api/vaults/preview-withdraw30/min

Preview shares required to withdraw a given asset amount.

ParamTypeRequiredDescription
chainId1 | 8453YesChain ID
vaultaddressYesVault contract address
amountstringYesAsset amount (BigInt as string)

Response

{
  "sharesRequired": "980000"
}
GET/api/vaults/position-snapshots60/min

Historical position value snapshots for a user.

ParamTypeRequiredDescription
userstringYesUser wallet address
vault_idstringYesVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)
daysnumberNoLookback period (default 30, 1–365)

Response

{
  "snapshots": [{
    "timestamp": "2026-02-20T00:00:00",
    "asset_value": "1050000"
  }]
}

Portfolio

GET/api/portfolio60/min

User portfolio summary across all vaults.

ParamTypeRequiredDescription
userstringYesUser wallet address
chainId1 | 8453NoFilter to a specific chain (omit for all chains)

Response

{
  "total_value": "125000000",
  "vaults": [{
    "vault_id": "arbcap-usdt-core",
    "asset_value": "100000000",
    "share_balance": "98000000",
    "timestamp": "2026-02-25T12:00:00",
    "deposit_count": 3,
    "withdraw_count": 1
  }]
}

Transactions

GET/api/transactions60/min

Recent transactions for a user (max 100, newest first).

ParamTypeRequiredDescription
userstringYesUser wallet address
vault_idstringNoVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)

Response

[{
  "id": 1,
  "user_address": "0xabc...def",
  "vault_id": "arbcap-usdt-core",
  "chain_id": 1,
  "tx_hash": "0x123...789",
  "action": "deposit",
  "amount": "1000000",
  "shares": "980000",
  "timestamp": "2026-02-25T10:30:00"
}]
GET/api/transactions/summary60/min

Aggregated transaction volume stats.

Cache: 120s

ParamTypeRequiredDescription
vault_idstringNoVault slug or contract address (case-insensitive)
chainId1 | 8453NoChain filter for address lookups (default 1)
daysnumberNoLookback period (default 30, 1–365)

Response

{
  "deposit_count": 47,
  "withdraw_count": 12,
  "total_deposited": "1250000000",
  "total_withdrawn": "320000000",
  "unique_users": 18
}

Strategies

GET/api/strategies60/min

All strategy APYs, ordered by APY descending.

Cache: 120s

Response

[{
  "strategy_address": "0xabc...def",
  "chain_id": 1,
  "name": "WBTC / USDT",
  "apy": 4.54,
  "updated_at": "2026-02-25T12:00:00"
}]

Overview

GET/api/overview60/min

Protocol-wide aggregate stats.

Cache: 120s

Response

{
  "total_tvl": "5250000000",
  "vault_count": 3,
  "avg_apy": 7.2,
  "total_users": 42
}

RPC Proxy

POST/api/rpc30/min

Proxies JSON-RPC requests to Alchemy. Only whitelisted methods allowed.

Auth: Required — Bearer <WORKER_SECRET | API_KEY>

Allowed methods: eth_chainId, eth_call, eth_estimateGas, eth_getTransactionReceipt. Max body: 8KB. No batch requests.

ParamTypeRequiredDescription
chainId"1" | "8453"NoChain ID (default "1")

Response

Upstream Alchemy JSON-RPC response

MCP

POST/api/mcp/mcp30/min

MCP (Model Context Protocol) server — exposes token data as tools for AI clients over Streamable HTTP.

Tools: get_token_stats, get_token_daily, get_token_snapshots, get_price_history, get_token_events, get_quote, get_bridge_status, get_pools, get_pool_history, get_ops_status, get_docs (integrator docs from docs.wstgbp.com, fetched live). Tool results include restRoutes (the equivalent REST calls; get_ops_status and get_docs have none) and, for quote/pool/bridge tools, a docs field linking the relevant guide. The full API reference is exposed as the api-reference MCP resource, and the integrator docs as integration-docs. Always public (no API key). Connect from Claude Code: claude mcp add --transport http arb-api https://<host>/api/mcp/mcp

Response

JSON-RPC 2.0 over Streamable HTTP