Skip to content
OcraMarketsOcraMarkets

Documentation

Build on the same data the interface uses.

Every page in OcraMarkets is rendered from public JSON routes under /api. They return normalised data with signals attached, never raw provider payloads.

Asset keys

Assets are addressed as chain:address. Contract-addressed tokens use their chain slug and contract or mint address; natives and other CoinGecko-listed coins use the coingecko pseudo-chain with the CoinGecko id.

ethereum:0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48   → /asset/ethereum/0xa0b8…
solana:So11111111111111111111111111111111111111112 → /asset/solana/So111…
coingecko:bitcoin                                  → /asset/coingecko/bitcoin

Chains: ethereum · base · arbitrum · solana · robinhood · bsc · polygon · optimism · avalanche · coingecko

Response envelope

200  { "ok": true,  "data": { … }, "meta": { "generatedAt": ISO, "cacheSeconds": n } }
4xx  { "ok": false, "error": { "code": "VALIDATION" | "NOT_FOUND" | "RATE_LIMITED" | "PROVIDER_NOT_CONFIGURED" | "PROVIDER_ERROR", "message": "…" } }

Routes

RouteQueryReturns
GET /api/marketsview (all · trending · new · liquidity · volume · watch · risk), chain, category, q, sort, dir, page, perPage, minVolume, minLiquidity, changePaged MarketRow rows (market data + volatility, OcraScore, Pulse, Signal) + universe description + provider notes
GET /api/tickerTop assets for the live strip + aggregate stats (volume, market cap, pooled liquidity, active markets)
GET /api/searchq (≥ 2 chars)TOKEN / PAIR / POOL results from CoinGecko, DexScreener, Jupiter
GET /api/assetchain + address, or ids=key,key (≤ 12)Full AssetView (pools, on-chain, verification, holders, risk, OcraScore, Pulse reading, sources) or snapshots
GET /api/historychain, address, tf = 1H | 4H | 1D | 7D | 30DCandles (GeckoTerminal) or line (CoinGecko / DefiLlama), or ok:false with the providers tried
GET /api/scanaddress, chain (optional)Chain candidates, AssetView, or on-chain-only reads
GET /api/pulselimit, chain, minLiquidity, statePulse entries ranked by activity, counts per state, weights
GET /api/trendinglimitTrending, gainers, losers, volume surge, liquidity leaders
GET /api/signalsBTC / ETH / SOL live modules with full OcraScore (hero Signal Map)
GET /api/portfolioaddressWallet holdings, prices, allocation, per-chain status
GET /api/statusProvider configuration flags (booleans only)
GET /api/token$OCRA plate: SOON until OCRA_TOKEN_ADDRESS is set, then identity read live from the chain

MarketRow

{
  id: "chain:address", name, symbol, chain, address,
  priceUsd, change1h, change24h, change7d, change5m?, change6h?, buys24h?, sells24h?,
  marketCap, fdv, volume24h, liquidityUsd, high24h, low24h,
  txns24h, poolCount, createdAt, logoUrl, rank, category, sparkline7d,
  source, sources: [{ id, label, url, fields[] }], updatedAt: ISO,
  volatilityPct,                                   // observed 24h range, % of price
  ocra: { score, status, coverage },               // HEALTHY | STABLE | WATCH | HIGH RISK | INSUFFICIENT DATA
  signal: { label, tone },                         // one label per row
  pulse: { state, lines[], reason }                // CALM | ACTIVE | WATCH | RISK
}
// null always means "the provider did not return it", never zero.

Caching and rate limits

Server routes use a process-local TTL cache with stale-while-revalidate (see src/lib/utils/cache.ts) and emit s-maxage headers so Vercel’s edge absorbs repeat hits. Expensive routes are token-bucket limited per client IP; a limited call returns RATE_LIMITED with a retry hint that the interface shows.

RouteBurstRefill
/api/search301 / s
/api/asset402 / s
/api/history402 / s
/api/scan121 per ~3 s
/api/portfolio101 per 5 s

Environment

NEXT_PUBLIC_SITE_URL=            # canonical URL (OpenGraph, sitemap)
COINGECKO_API_KEY=               # optional Demo key
ALCHEMY_API_KEY=                 # optional — EVM wallet token discovery
SOLANA_RPC_URL= EVM_RPC_URL= BASE_RPC_URL= ARBITRUM_RPC_URL= ROBINHOOD_RPC_URL=   # optional overrides
NEXT_PUBLIC_WALLETCONNECT_PROJECT_ID=   # optional — enables WalletConnect
RESOLVE_OVERRIDE=                # local dev only — DNS pin for hijacked hosts
OCRA_TOKEN_ADDRESS= OCRA_TOKEN_CHAIN= OCRA_TOKEN_ACQUIRE_URL=   # $OCRA plate — set with: npm run token:ca -- ADDRESS
The app is fully functional with an empty environment: every core provider is key-free. Keys only add optional accelerators. No sample or simulated market data ships with the project — when a provider is unreachable, the interface says so.

Deployment

Vercel

npm install
npm run build          # next build
vercel --prod          # framework preset: Next.js (pinned in vercel.json)

Set NEXT_PUBLIC_SITE_URL to the production domain. No database, cron or edge config is required.

Local

cp .env.example .env.local
npm run dev            # http://localhost:10000