Skip to Content
ReferenceREST API

REST API

Obscura’s indexer (apps/api, Node + Express + MongoDB) listens to registry and wrapper events and serves fast cached reads. It exists so lists, feeds, and charts don’t hammer an RPC. Every write still happens on-chain from the user’s wallet, and the API is stateless with respect to user identity.

Public data only. The indexer stores addresses, transaction hashes, and the amounts that are public by nature (wrap and finalized-unwrap amounts). It never sees, stores, or serves anything encrypted.

All routes are mounted under /api. Base URL is deployment-specific; the web app reads it from NEXT_PUBLIC_API_URL.

Endpoints

Method & pathReturns
GET /api/statsGlobal totals: pair count, valid vs revoked, aggregate TVS
GET /api/pairsAll pairs; filter with ?isValid=true|false and search with ?q=
GET /api/pairs/:addressSingle pair by wrapper or token address; 404 if unknown
GET /api/activityPaginated activity feed
GET /api/tvs/:addressTVS history for one pair; optional ?from= / ?to= (ISO dates)
GET /api/healthLiveness plus indexer progress

Activity feed

GET /api/activity accepts:

Query paramMeaning
page1-based page number (default 1)
pageSizeItems per page, max 100 (default 20)
typeOne of wrap, unwrap_requested, unwrap_finalized, pair_registered, pair_revoked
pairFilter by wrapper address
actorFilter by account address
GET /api/activity?type=wrap&pageSize=2 (abridged)
{ "events": [ { "type": "wrap", "pairAddress": "0x7c5B…3639", "actor": "0x1234…abcd", "txHash": "0x…", "blockNumber": 8412345, "timestamp": "2026-07-04T18:21:09.000Z", "publicAmount": "25500000000000000000" } ], "page": 1, "pageSize": 2, "total": 137 }

publicAmount is only present where the amount is public by nature: wraps and finalized unwraps. Confidential transfers appear as events without an amount.

Health

GET /api/health reports the last block each indexer processed, so you can judge how fresh the data is:

GET /api/health
{ "ok": true, "latestBlock": "8412391", "indexer": { "registry": 8412390, "wrappers": 8412388 } }

Consuming it

const API = process.env.NEXT_PUBLIC_API_URL; // e.g. https://api.your-deploy.app const stats = await fetch(`${API}/api/stats`).then((r) => r.json());

The web app treats the API as an accelerator, not a dependency. Pair data always has the on-chain read path (Read the Registry) as its source of truth, and the indexer itself periodically reconciles against direct registry state so missed events can’t corrupt coverage.

Deployment and environment knobs (MONGODB_URI, INDEXER_CHUNK_SIZE, look-back windows, poll intervals) are documented in the repo’s .env.example.

Last updated on