> ## 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 Chart

> Fetch OHLC candles for a perpetual market from a supported DEX (Gains Network, Lighter), normalized to a single shape regardless of upstream.

### Query Details

Returns OHLC candles for the requested market and period. Same param/response shape as `GET /2/market/ohlcv-history` and `GET /2/token/ohlcv-history`, so a single client can render both spot and perp charts.

* Market identifier is `dex` + `market` (perp has no pool address).
* Market mappings are cached server-side for 5 minutes.
* Candles are sorted ascending by `t`. Duplicate timestamps and rows with `h < l` or non-finite values are dropped.
* Empty result sets are not errors — `data: []` with HTTP 200 is returned when the upstream has no data for the range.

<Tip>Timestamps accept **seconds, milliseconds, or ISO date strings** — milliseconds are auto-detected for numeric values above `1e12`.</Tip>

> **Note on Lighter:**
> Only USD-quoted perps are supported (e.g., `BTC/USD`, `SOL/USD`, `HYPE/USD`).

> **Note on Gains:**
> Crypto, forex, stocks, and commodities are supported. Quote can be non-USD (e.g., `USD/JPY`, `EUR/CHF`).

### Query Parameters

| Parameter | Type             | Required | Description                                                                                               |
| --------- | ---------------- | -------- | --------------------------------------------------------------------------------------------------------- |
| dex       | string           | Yes      | Upstream DEX to query. One of `gains`, `lighter`.                                                         |
| market    | string           | Yes      | Pair in `BASE/QUOTE` format (e.g., `BTC/USD`, `USD/JPY`). Case-insensitive.                               |
| period    | string           | No       | Candle width. One of `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d`, `1w`. Default `5m`.                      |
| from      | number \| string | No       | Range start (inclusive). UNIX seconds, UNIX milliseconds, or ISO date string.                             |
| to        | number \| string | No       | Range end (inclusive). Same unit handling as `from`. Must be greater than `from`.                         |
| amount    | number           | No       | Max candles to return (capped at `2000`). When range yields more than `amount`, the most recent are kept. |

### Response

Each entry in `data` is a candle:

| Field | Type   | Description                    |
| ----- | ------ | ------------------------------ |
| t     | number | UNIX seconds.                  |
| o     | number | Opening price.                 |
| h     | number | Highest price in the interval. |
| l     | number | Lowest price in the interval.  |
| c     | number | Closing price.                 |

Note: candle shape matches spot OHLCV endpoints (`{t, o, h, l, c}`). Perp has no `v` field — volume is not reported by the upstream DEXes.

### Usage Examples

* Lighter `BTC/USD`, 1-minute candles for the last hour:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/perp/ohlcv-history?dex=lighter&market=BTC/USD&period=1m&from=1777035900&to=1777039500"
```

* Gains `USD/JPY`, 5-minute candles, last 200 candles only:

```bash theme={null}
curl -X GET "https://api.mobula.io/api/2/perp/ohlcv-history?dex=gains&market=USD/JPY&period=5m&from=1777000000&to=1777039500&amount=200"
```

Response:

```json theme={null}
{
  "data": [
    { "t": 1777035900, "o": 78328.9, "h": 78370.8, "l": 78328.9, "c": 78367.1 },
    { "t": 1777035960, "o": 78367.1, "h": 78388.6, "l": 78340.2, "c": 78380.0 }
  ]
}
```

### Errors

| Status | When                                                                             | `message`                                   |
| ------ | -------------------------------------------------------------------------------- | ------------------------------------------- |
| 400    | Zod validation failed (invalid `dex`, malformed `market`)                        | `zod validation failed`                     |
| 400    | `from >= to`                                                                     | `from must be < to`                         |
| 400    | `period` not in supported set                                                    | `unsupported period "<period>"`             |
| 404    | Market not found for the selected DEX (`errors[0]` lists example pairs)          | `unknown market "<market>" for dex "<dex>"` |
| 502    | Upstream DEX returned an error (timeout, non-200, or `code !== 200` for Lighter) | `upstream <dex> error`                      |
| 500    | Unexpected internal error                                                        | `internal server error`                     |

### Notes

* Market mappings (Gains pairs, Lighter `orderBookDetails`) are fetched lazily on first request per process and cached for 5 minutes.
* Upstream requests have a 10s timeout.
* Each request is traced server-side with a short `traceId` included in every log line for that request.


## OpenAPI

````yaml GET /2/perp/ohlcv-history
openapi: 3.0.0
info:
  version: 1.0.0
  title: Mobula API
  description: >-
    Documentation of the Mobula API


    **Demo API**: The default server (demo-api.mobula.io) is a demo API with
    rate limits.

    For production use, please use api.mobula.io with an API key from
    https://admin.mobula.io
servers:
  - url: https://demo-api.mobula.io/api/
    description: Demo API (rate limited, for testing only)
  - url: https://api.mobula.io/api/
    description: Production API (requires API key)
security: []
tags:
  - name: V2 - Token
    description: Token details, price, security, ATH, and holder data
  - name: V2 - Market Data
    description: Market details, OHLCV history, and lighthouse metrics
  - name: V2 - Trades
    description: Token trades, enriched trades, and trade filters
  - name: V2 - Wallet
    description: Wallet positions, activity, trades, analysis, and labels
  - name: V2 - Assets
    description: Cross-chain asset details and price history
  - name: V2 - Swap
    description: Swap quoting and execution
  - name: V2 - Perps
    description: Perpetual futures quoting, execution, and positions
  - name: V2 - Bridge
    description: Cross-chain bridge quoting and intent status (Alpha Preview)
  - name: V2 - DeFi
    description: Bonding pools and pulse data
  - name: V2 - Search
    description: Universal fast search
  - name: V2 - Blockchains
    description: System metadata and chain listings
  - name: V1 - Market Data
    description: Market prices, history, sparklines, pairs, and multi-data
  - name: V1 - Wallet
    description: Wallet portfolio, transactions, history, and NFTs
  - name: V1 - Token
    description: First buyers
  - name: V1 - Trades
    description: Market trades by pair
  - name: V1 - Metadata
    description: Token metadata, categories, trendings, and news
  - name: V1 - Assets
    description: List all assets
  - name: V1 - Search
    description: Search for assets, tokens, and pairs
  - name: V1 - DeFi
    description: Bonding pool pulse data
  - name: V1 - Blockchains
    description: Blockchain listings, pairs, and stats
  - name: V1 - Webhooks
    description: Webhook management
  - name: V1 - Feed
    description: Custom feed creation
paths:
  /2/perp/ohlcv-history:
    get:
      tags:
        - V2 - Perps
      summary: Get perp OHLCV history
      description: >-
        Fetch OHLC candles for a perpetual market from a supported DEX (Gains
        Network, Lighter), normalized to the same shape as spot OHLCV endpoints.
        Market identifier is `dex` + `market` (perp has no pool address). Market
        mappings are cached server-side for 5 minutes. Timestamps accept
        seconds, milliseconds, or ISO date strings — milliseconds are
        auto-detected for numeric values above 1e12.
      parameters:
        - schema:
            type: string
            enum:
              - gains
              - lighter
            description: Upstream DEX to query.
          required: true
          description: Upstream DEX to query.
          name: dex
          in: query
        - schema:
            type: string
            description: >-
              Human-readable pair in `BASE/QUOTE` format (e.g., `BTC/USD`,
              `ETH/USD`, `USD/JPY`). Case-insensitive — internally uppercased.
              Lighter only supports USD-quoted perps; Gains supports crypto,
              forex, stocks and commodities (quote may be non-USD).
          required: true
          description: >-
            Human-readable pair in `BASE/QUOTE` format (e.g., `BTC/USD`,
            `ETH/USD`, `USD/JPY`). Case-insensitive — internally uppercased.
            Lighter only supports USD-quoted perps; Gains supports crypto,
            forex, stocks and commodities (quote may be non-USD).
          name: market
          in: query
        - schema:
            type: string
            enum:
              - 1m
              - 5m
              - 15m
              - 30m
              - 1h
              - 4h
              - 1d
              - 1w
            description: Candle width.
          required: false
          description: Candle width.
          name: period
          in: query
        - schema:
            anyOf:
              - type: number
              - type: string
            description: >-
              Range start (inclusive). UNIX seconds, UNIX milliseconds, or ISO
              date string.
          required: false
          description: >-
            Range start (inclusive). UNIX seconds, UNIX milliseconds, or ISO
            date string.
          name: from
          in: query
        - schema:
            anyOf:
              - type: number
              - type: string
            description: >-
              Range end (inclusive). Same unit handling as `from`. Must be
              greater than `from`.
          required: false
          description: >-
            Range end (inclusive). Same unit handling as `from`. Must be greater
            than `from`.
          name: to
          in: query
        - schema:
            type: number
            description: >-
              Max number of candles to return (capped at 2000). When the range
              yields more candles than `amount`, only the most recent `amount`
              are returned.
          required: false
          description: >-
            Max number of candles to return (capped at 2000). When the range
            yields more candles than `amount`, only the most recent `amount` are
            returned.
          name: amount
          in: query
      responses:
        '200':
          description: >-
            Perp OHLCV history response. Candles sorted ascending by `t`.
            Duplicate timestamps and rows with `h < l` or non-finite values are
            dropped. Empty result sets are not errors — `data: []` with HTTP 200
            is returned when the upstream has no data for the range.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: array
                    items:
                      type: object
                      properties:
                        t:
                          type: number
                          description: UNIX seconds.
                        o:
                          type: number
                          description: Opening price.
                        h:
                          type: number
                          description: Highest price in the interval.
                        l:
                          type: number
                          description: Lowest price in the interval.
                        c:
                          type: number
                          description: Closing price.
                      required:
                        - t
                        - o
                        - h
                        - l
                        - c
                required:
                  - data
        '400':
          description: >-
            Validation failed (invalid `dex`, malformed `market`, `from >= to`,
            or unsupported `period`).
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - message
        '404':
          description: >-
            Market not found for the selected DEX. `errors[0]` lists example
            pairs.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - message
        '500':
          description: Unexpected internal error.
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                required:
                  - message
        '502':
          description: >-
            Upstream DEX returned an error (timeout, non-200, or `code !== 200`
            for Lighter).
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
                  errors:
                    type: array
                    items:
                      type: string
                required:
                  - message

````