> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mobula.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Get Perp DEX Status

> Health and status snapshot for supported perp DEXes (Lighter, Gains). Probes upstream HTTP and WebSocket endpoints, surfaces scheduled-maintenance windows, and rolls per-check results into an overall status.

### Query Details

Returns one entry per probed DEX with a rolled-up `status`, the individual probe results powering that rollup, and any active or upcoming maintenance windows.

* Probes both **HTTP** and **WebSocket** upstreams. WS probes connect, wait for the first message, and disconnect.
* Results are cached server-side per check to avoid hammering upstreams. Concurrent cold-cache calls are deduped — `N` parallel requests fire a single upstream probe.
* Probes never throw — failures surface as `ok: false` on the corresponding check.
* Auxiliary checks are informational and never affect the rollup; only `critical` checks do.

### Endpoint

```
GET /api/2/perp/dex-status
```

### Query Parameters

| Parameter | Type                   | Required | Description                                                                                  |
| --------- | ---------------------- | -------- | -------------------------------------------------------------------------------------------- |
| dex       | `'lighter' \| 'gains'` | No       | Filter to a single DEX. If omitted, both DEXes are probed in parallel and returned together. |

### Usage Examples

* Both DEXes:

```bash theme={null}
curl 'https://api.mobula.io/api/2/perp/dex-status'
```

* Lighter only:

```bash theme={null}
curl 'https://api.mobula.io/api/2/perp/dex-status?dex=lighter'
```

* Gains only:

```bash theme={null}
curl 'https://api.mobula.io/api/2/perp/dex-status?dex=gains'
```

### Response

Top-level shape:

```ts theme={null}
{
  data: PerpDexHealth[];
  meta?: {
    generatedAt: number; // unix ms — server-side response build time
    totalMs: number;     // controller-measured request duration in ms
  };
}
```

#### `PerpDexHealth`

One entry per probed DEX.

| Field       | Type                                                       | Description                                                                                                  |
| ----------- | ---------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| dex         | `'lighter' \| 'gains'`                                     | DEX identifier.                                                                                              |
| status      | `'operational' \| 'degraded' \| 'maintenance' \| 'down'`   | Roll-up status derived from `checks` and any active maintenance window. See [Status rollup](#status-rollup). |
| checkedAt   | `number`                                                   | Unix ms — when the snapshot for this DEX was assembled.                                                      |
| checks      | `PerpDexCheckResult[]`                                     | Individual probe results powering the rollup.                                                                |
| maintenance | `{ active: boolean; windows: PerpDexMaintenanceWindow[] }` | Active flag and parsed maintenance windows. Currently populated for `lighter` only (Gains: empty).           |
| meta        | `Record<string, unknown>` (optional)                       | DEX-specific extras. For Gains: `{ chains: [{ chainId, isTestnet, pairsCount }, ...] }`.                     |

#### `PerpDexCheckResult`

One per upstream probe.

| Field       | Type                                 | Description                                                                                                                    |
| ----------- | ------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------ |
| name        | `string`                             | Check identifier. See [Checks reference](#checks-reference).                                                                   |
| description | `string`                             | Human-readable summary of what this check probes and why it matters.                                                           |
| weight      | `'critical' \| 'auxiliary'`          | Only `critical` checks contribute to the rollup. `auxiliary` is informational.                                                 |
| transport   | `'http' \| 'ws'`                     | Probe transport.                                                                                                               |
| ok          | `boolean`                            | True if the probe succeeded (and, where applicable, body validation passed — e.g. `pairs.length > 0` for `trading-variables`). |
| slow        | `boolean`                            | True only when `ok === true` and latency exceeds the transport's slow threshold (HTTP: 2000 ms, WS: 3000 ms).                  |
| latencyMs   | `number \| null`                     | Round-trip latency for the probe.                                                                                              |
| cached      | `boolean`                            | True if the value was served from the in-memory cache rather than freshly fetched.                                             |
| fetchedAt   | `number`                             | Unix ms — timestamp of the underlying probe (cache-fill time when `cached === true`).                                          |
| error       | `string` (optional)                  | Present when `ok === false`; short error label.                                                                                |
| meta        | `Record<string, unknown>` (optional) | Check-specific extras (e.g. `pairsCount`, `networkId`, `firstMessageBytes`, `chainId`, `isTestnet`).                           |

#### `PerpDexMaintenanceWindow`

| Field          | Type             | Description                                                                                |
| -------------- | ---------------- | ------------------------------------------------------------------------------------------ |
| title          | `string`         | Source announcement title.                                                                 |
| content        | `string`         | Source announcement body.                                                                  |
| createdAt      | `number`         | Source announcement `created_at`, unix seconds.                                            |
| expiredAt      | `number \| null` | Source announcement `expired_at`, unix seconds (null when none).                           |
| isMaintenance  | `boolean`        | True when title/content match maintenance keywords (`upgrade`, `maintenance`, `downtime`). |
| scheduledAt    | `number \| null` | Parsed window start in unix seconds (null when not extractable).                           |
| scheduledEndAt | `number \| null` | Parsed window end in unix seconds (null when not extractable).                             |
| active         | `boolean`        | True when `now` falls inside the parsed window (or inside the `expiredAt` fallback).       |

### Status Rollup

Ranking best → worst:

1. `maintenance` — any maintenance window with `active === true`.
2. `operational` — every critical check is `ok && !slow`.
3. `down` — zero critical checks `ok`.
4. `degraded` — anything else (some critical OK and some not, or one critical is `slow`).

Auxiliary checks never affect the rollup.

### Checks Reference

#### Lighter

| name          | weight    | transport | Probes                                                                                           |
| ------------- | --------- | --------- | ------------------------------------------------------------------------------------------------ |
| http-root     | critical  | http      | `https://mainnet.zklighter.elliot.ai/` — sequencer reachability; returns network id + timestamp. |
| announcements | auxiliary | http      | Public announcements API. Source of `maintenance.windows`.                                       |
| ws-stream     | critical  | ws        | `wss://mainnet.zklighter.elliot.ai/stream` — live order/transaction confirmations.               |

#### Gains

One `trading-variables` and one `ws-trading` per supported chain, plus a single shared `ws-pricing`.

| name              | weight                                                            | transport | Probes                                                                               |
| ----------------- | ----------------------------------------------------------------- | --------- | ------------------------------------------------------------------------------------ |
| trading-variables | critical (Arbitrum, Base) / auxiliary (Polygon, Arbitrum Sepolia) | http      | `<gains-backend>/trading-variables/all` — pair list and per-pair trading parameters. |
| ws-trading        | critical (Arbitrum, Base) / auxiliary (Polygon, Arbitrum Sepolia) | ws        | Gains backend event WS — order, position and chain events.                           |
| ws-pricing        | critical                                                          | ws        | `wss://backend-pricing.eu.gains.trade` — shared price feed for every Gains chain.    |

Per-chain weights:

| chainId    | network          | weight    | isTestnet |
| ---------- | ---------------- | --------- | --------- |
| evm:42161  | Arbitrum         | critical  | false     |
| evm:8453   | Base             | critical  | false     |
| evm:137    | Polygon          | auxiliary | false     |
| evm:421614 | Arbitrum Sepolia | auxiliary | true      |

### Caching & Timeouts

In-memory per-check TTLs:

| Check                       | TTL      |
| --------------------------- | -------- |
| lighter `http-root`         | 10000 ms |
| lighter `announcements`     | 30000 ms |
| lighter `ws-stream`         | 15000 ms |
| gains `trading-variables/*` | 15000 ms |
| gains `ws-trading/*`        | 15000 ms |
| gains `ws-pricing`          | 15000 ms |

Probe budgets:

* HTTP — timeout: 5000 ms · slow threshold: 2000 ms.
* WS — timeout: 4000 ms · slow threshold: 3000 ms.

### Example Response

Truncated for readability.

```json theme={null}
{
  "data": [
    {
      "dex": "lighter",
      "status": "operational",
      "checkedAt": 1714200000000,
      "checks": [
        {
          "name": "http-root",
          "description": "Lighter HTTP root endpoint. Returns the current network id and chain timestamp; failure means the L2 sequencer is unreachable.",
          "weight": "critical",
          "transport": "http",
          "ok": true,
          "slow": false,
          "latencyMs": 142,
          "cached": false,
          "fetchedAt": 1714199999850,
          "meta": { "status": 200, "networkId": 1, "serverTimestamp": 1714199999 }
        },
        {
          "name": "announcements",
          "description": "Lighter public announcements API. Source of scheduled maintenance and network-upgrade notices surfaced under `maintenance.windows`.",
          "weight": "auxiliary",
          "transport": "http",
          "ok": true,
          "slow": false,
          "latencyMs": 198,
          "cached": true,
          "fetchedAt": 1714199985000,
          "meta": { "totalAnnouncements": 42, "maintenanceWindowsTotal": 1, "maintenanceWindowsRelevant": 1 }
        },
        {
          "name": "ws-stream",
          "description": "Lighter WebSocket stream (`/stream`). Used for live order-status and transaction confirmations; failure breaks order tracking.",
          "weight": "critical",
          "transport": "ws",
          "ok": true,
          "slow": false,
          "latencyMs": 612,
          "cached": false,
          "fetchedAt": 1714199999800,
          "meta": { "firstMessageBytes": 184 }
        }
      ],
      "maintenance": {
        "active": false,
        "windows": [
          {
            "title": "Network Upgrade May 1",
            "content": "...",
            "createdAt": 1713000000,
            "expiredAt": null,
            "isMaintenance": true,
            "scheduledAt": 1714572000,
            "scheduledEndAt": 1714575600,
            "active": false
          }
        ]
      }
    },
    {
      "dex": "gains",
      "status": "operational",
      "checkedAt": 1714200000000,
      "checks": [
        {
          "name": "trading-variables",
          "description": "Gains backend `trading-variables/all` HTTP endpoint. Returns the pair list and per-pair trading parameters used to build orders.",
          "weight": "critical",
          "transport": "http",
          "ok": true,
          "slow": false,
          "latencyMs": 311,
          "cached": false,
          "fetchedAt": 1714199999700,
          "meta": { "chainId": "evm:42161", "isTestnet": false, "pairsCount": 168 }
        },
        {
          "name": "ws-trading",
          "description": "Gains backend WebSocket event stream. Pushes order, position and chain events; failure breaks live order tracking.",
          "weight": "critical",
          "transport": "ws",
          "ok": true,
          "slow": false,
          "latencyMs": 510,
          "cached": false,
          "fetchedAt": 1714199999700,
          "meta": { "chainId": "evm:42161", "isTestnet": false, "firstMessageBytes": 12 }
        },
        {
          "name": "ws-pricing",
          "description": "Gains pricing WebSocket (`backend-pricing.eu.gains.trade`). Provides the price feed used across every Gains chain.",
          "weight": "critical",
          "transport": "ws",
          "ok": true,
          "slow": false,
          "latencyMs": 240,
          "cached": false,
          "fetchedAt": 1714199999700,
          "meta": { "firstMessageBytes": 96 }
        }
      ],
      "maintenance": { "active": false, "windows": [] },
      "meta": {
        "chains": [
          { "chainId": "evm:42161", "isTestnet": false, "pairsCount": 168 },
          { "chainId": "evm:8453",  "isTestnet": false, "pairsCount": 168 },
          { "chainId": "evm:137",   "isTestnet": false, "pairsCount": 168 },
          { "chainId": "evm:421614","isTestnet": true,  "pairsCount": 168 }
        ]
      }
    }
  ],
  "meta": { "generatedAt": 1714200000000, "totalMs": 740 }
}
```

### Errors

| Status | When                                                                 | `message`               |
| ------ | -------------------------------------------------------------------- | ----------------------- |
| 400    | Zod validation failed on `dex` (only `lighter` or `gains` accepted). | `zod validation failed` |
| 500    | Unexpected internal error.                                           | `internal server error` |

Probes themselves never throw — upstream failures are reflected as `ok: false` on the per-check result, not as HTTP errors.

### Related

<CardGroup cols={2}>
  <Card title="Perpetuals APIs Overview" icon="chart-mixed" href="/perps-introduction">Supported exchanges and capability map.</Card>
  <Card title="Perp Fees" icon="coins" href="/perps-fees">Fee structure for each integrated DEX.</Card>
  <Card title="Get Perp Quote" icon="calculator" href="/exec/perps/perp-quote">Preview fees, fills and venue routing before executing.</Card>
  <Card title="Perp Execution Flow" icon="bolt" href="/cookbooks/perp-execution-flow">Build → execute flow against Lighter and Gains.</Card>
</CardGroup>
