Mobula indexes perp markets from Gains Network and Lighter. To enumerate them, use the Pulse v2 POST endpoint withDocumentation Index
Fetch the complete documentation index at: https://docs.mobula.io/llms.txt
Use this file to discover all available pages before exploring further.
poolTypes filters inside a named view. Full schema on the Pulse POST reference.
Endpoint shape
| URL | POST https://api.mobula.io/api/2/pulse |
| Auth header | Authorization: <YOUR_API_KEY> (raw key, no Bearer) |
| Body | { "views": [ { name, poolTypes, sortBy, sortOrder, limit, offset } ] } |
| Response | { "<viewName>": { "data": [...pools] } } — keyed by the name you pass |
view). Pagination is offset-based — increment offset by limit until you hit two consecutive empty pages.
Optional: total count via /pulse/pagination
POST https://api.mobula.io/api/2/pulse/pagination accepts the same body and returns { "<viewName>": { "pagination": <number> } }.
For
lighter-perp the pagination total matches reality. For gains-perp it can under-report (Gains exposes one base market across many pool variants — Mobula returns the variants too). Treat pagination as a hint; rely on the empty-page break in your loop.Quick start — curl
gains-perp → lighter-perp. Both pool types in one call — pass ["gains-perp", "lighter-perp"] (the response is still keyed by your view name; rows from both types are mixed in data).
TypeScript — paginate the full catalog
DEX-specific normalization
The shape ofaddress and metadata differs by DEX. Two utilities cover the common cases.
Gains — dedupe pool variants into markets
Gains exposes the same trading pair across multiple pool variants (e.g.,gains-BTC-USD-0, gains-BTC-USD-1, …). To get a clean per-market list, strip the trailing variant suffix and keep one row per market.
Lighter — derive symbol from address when tokenSymbol is null
Some Lighter rows are returned without tokenSymbol. Fall back to parsing the address (e.g., lighter-BTC-USD → BTC/USD).
Real-time updates — Pulse v2 stream
For live updates instead of (or alongside) the REST snapshot, subscribe to the Pulse v2 WebSocket with the samepoolTypes filter:
Common pitfalls
- Forgetting
nameon the view. The response is keyed by thenameyou provide — if you passname: 'foo', readres.data.foo.data, notres.data.view.data. - Stopping at one page. Pulse caps each
viewpage at 100 rows. Loop withoffset += 100until two consecutive empty pages. - Trusting the Gains pagination total.
pulse/paginationunder-counts forgains-perpbecause of pool variants. Use the empty-page break as ground truth; dedupe afterwards. - Empty
tokenSymbolon Lighter rows. Fall back to parsingaddress(lighter-BTC-USD→BTC/USD). Bearerprefix in the Authorization header. Don’t add it. Pulse expects the raw API key.
Related
Pulse POST reference
Full request/response schema for
/api/2/pulse.Perp Quote
Quote a perp position once you’ve picked a market.
Execute Perp Action
Submit signed payloads via
/2/perp/execute-v2.Perps Data Model
Indexed event shapes for perps.
Need help?
Telegram
Fast support
Discord
Community
Slack
Enterprise
Contact us