Skip to main content
Mobula indexes perp markets from Gains Network and Lighter. To enumerate them, call the Perp Pairs endpoint. It returns every tradable market in one request — no pagination, no per-DEX normalization needed.
Only tradable markets are returned. Disabled, closed, or delisted markets are filtered out server-side, so anything absent from the response is not tradable. There is no separate “disabled” flag to check.

Endpoint shape

URLGET https://api.mobula.io/api/2/perp/pairs
Auth headerAuthorization: <YOUR_API_KEY> (raw key, no Bearer)
Querychain (optional) — filter to a single chain/venue
Response{ "data": [ ...pairs ] }

Query parameter

ParameterTypeRequiredDescription
chainenumNoRestrict the result to one chain/venue. Omit it to get every chain and DEX in one list.
Accepted chain values
ValueMeaningDEX
arbitrumGains markets on Arbitrumgains
baseGains markets on Basegains
arbitrum-sepoliaGains markets on Arbitrum Sepolia (test)gains
lighterLighter marketslighter

Quick start — curl

# All markets (every chain + DEX)
curl "https://api.mobula.io/api/2/perp/pairs" \
  -H "Authorization: YOUR_API_KEY"

# Single chain — Arbitrum (Gains)
curl "https://api.mobula.io/api/2/perp/pairs?chain=arbitrum" \
  -H "Authorization: YOUR_API_KEY"

# Lighter only
curl "https://api.mobula.io/api/2/perp/pairs?chain=lighter" \
  -H "Authorization: YOUR_API_KEY"

Response

{
  "data": [
    {
      "name": "BTC/USD",
      "baseToken": "BTC",
      "quoteToken": "USD",
      "minLeverage": 1.1,
      "maxLeverage": 200,
      "dex": "gains",
      "chain": "arbitrum",
      "assetClass": "crypto",
      "dexMarketId": 0,
      "socialUrl": "",
      "pairFullName": "BTC",
      "percentageChange24h": -2.98,
      "price": 71571.74,
      "logo": "https://metadata.mobula.io/assets/logos/100001656.webp"
    }
  ]
}
data is the full list of tradable markets — there is no pagination.

Market model

FieldTypeDescription
namestringHuman-readable base/quote label, e.g. "BTC/USD".
baseTokenstringBase asset symbol, e.g. "BTC".
quoteTokenstringQuote asset symbol, e.g. "USD".
minLeveragenumberMinimum allowed leverage.
maxLeveragenumberMaximum allowed leverage. Always > 0 (disabled markets are excluded).
dexenum"gains" or "lighter".
chainenum"arbitrum", "base", "arbitrum-sepolia", or "lighter".
assetClassenum"crypto", "forex", "stocks", "indices", "commodities", "degen", or "new".
dexMarketIdinteger (≥ 0)The DEX’s internal market id — Gains pairIndex / Lighter market_id. Use it when referencing the market in quote/execution calls.
socialUrlstringReserved for a social/info URL. Currently empty.
pairFullNamestringFull name of the market as reported by the DEX.
percentageChange24hnumber24h price change, in percent.
pricenumberLatest/mark price in USD (0 if no price is currently available).
logostring | nullBase-asset logo URL, or null when unknown.

TypeScript

import axios from 'axios';

const PAIRS_URL = 'https://api.mobula.io/api/2/perp/pairs';
const API_KEY = process.env.MOBULA_API_KEY!;

type PerpPair = {
  name: string;
  baseToken: string;
  quoteToken: string;
  minLeverage: number;
  maxLeverage: number;
  dex: 'gains' | 'lighter';
  chain: 'arbitrum' | 'base' | 'arbitrum-sepolia' | 'lighter';
  assetClass: 'crypto' | 'forex' | 'stocks' | 'indices' | 'commodities' | 'degen' | 'new';
  dexMarketId: number;
  socialUrl: string;
  pairFullName: string;
  percentageChange24h: number;
  price: number;
  logo: string | null;
};

async function fetchPerpPairs(chain?: PerpPair['chain']): Promise<PerpPair[]> {
  const res = await axios.get<{ data: PerpPair[] }>(PAIRS_URL, {
    headers: { Authorization: API_KEY },
    params: chain ? { chain } : undefined,
  });
  return res.data.data;
}

// Every tradable market across all chains and DEXes
const all = await fetchPerpPairs();

// Gains markets on Arbitrum only
const arbitrum = await fetchPerpPairs('arbitrum');

console.log(`Total markets: ${all.length}`);

Common pitfalls

  • Bearer prefix in the Authorization header. Don’t add it — pass the raw API key.
  • Expecting disabled markets. They are filtered out. If a market isn’t in the response, it isn’t tradable.
  • Using dexMarketId across DEXes. It is only unique within a (dex, chain). Pair it with dex/chain when keying markets.

Perp Quote

Quote a perp position once you’ve picked a market.

Execute Perp Action

Submit signed payloads via /2/perp/execute-v2.

DEX Status

Lighter / Gains uptime, probe results and maintenance windows.

Perps Data Model

Indexed event shapes for perps.

Need help?

Telegram

Fast support

Discord

Community

Slack

Enterprise

Email

Contact us