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

# Export SQL results as Parquet or CSV

> POST /v1/query/export runs read-only SQL over Ironflow's Hyperliquid tables and returns a Parquet or CSV file, on Explorer and Builder plans.

For whole-market history you may not need this: the [free datasets](https://docs.ironflow.sh/guides/datasets.md) are one download. Use export for what they do not hold, such as every fill with fees and PnL, per-wallet tables, sub-hourly marks and custom filters.

```bash theme={null}
curl -sS https://api.ironflow.sh/v1/query/export \
  -H "Authorization: Bearer $IRONFLOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"sql":"SELECT ts, tid, side, price, size, notional FROM hl.trades WHERE market = \'BTC-PERP\' AND ts >= toDate(\'2026-10-15\') AND ts < toDate(\'2026-10-16\')","format":"parquet"}' \
  -o btc-2026-10-15.parquet
```


## OpenAPI

````yaml POST /v1/query/export
openapi: 3.1.0
info:
  title: Ironflow API
  version: 1.0.0
  description: >
    Hyperliquid market data from Ironflow's own nodes: tick-level fills and

    trades, candles, funding rates, liquidations, mark prices, open interest,

    markets and wallet analytics over REST, live Server-Sent Events streams and

    read-only SQL. One schema across native HL perps, HIP-3 builder markets,

    HIP-4 outcome contracts and HL spot.


    The same data is a hosted MCP server for AI agents at

    `https://mcp.ironflow.sh/mcp`, and agents with a USDC wallet on Base can pay

    per call with x402, no key: the data GET endpoints are also served at

    `/x402/v1/...` (discovery: `https://api.ironflow.sh/openapi.json` and

    `https://api.ironflow.sh/.well-known/x402`).


    **Base URL:** `https://api.ironflow.sh`


    **Authentication:** Read endpoints work without a key (keyless access) or

    with a Bearer token in the `Authorization` header. Writes always need a key.

    ```

    Authorization: Bearer if_your_api_key

    ```

    Get a free key at https://ironflow.sh/key.


    **Access levels:**


    | Access | Requests per minute | History | Max range per request |

    |---|---|---|---|

    | No key | 30 per IP (300 a day) | 24 hours | 1 hour |

    | Free key | 60 | 14 days | 6 hours |

    | Explorer | 100 | 90 days | 24 hours |

    | Builder | 1,000 | 1 year | 7 days |

    | Enterprise | 10,000 | full | unlimited |


    Without a market filter, high-volume endpoints allow at most 4 hours per
    request.

    `/v1/trades` filtered to one perp or spot market allows 24 hours per request

    without a key and on a free key.

    Each caller can also read a set number of rows per hour: 2 billion without a
    key,

    10 billion on a free key, 100 billion on Explorer, 500 billion on Builder,
    none set

    on Enterprise. REST and SQL count separately. Over it, REST answers 429

    `READ_BUDGET_EXCEEDED` until the next hour.

    A header that is present but malformed returns 401; keyless access applies
    only

    when no `Authorization` header is sent. The keyless 300 a day is a rolling
    24

    hours per IP: past it, `KEYLESS_DAILY_LIMIT` (429, or 402 with x402 payment

    terms) carries a `Retry-After` of the seconds until the next call is
    allowed.


    **Data availability:** fills and trades start on 25 May 2025; other

    datasets start later (funding 2025-09-27, open interest and mark prices

    2026-04-29). Bulk history is free to download from

    https://huggingface.co/ironflow.


    **Timestamps:** All timestamps are Unix milliseconds (int64).


    **Pagination:** Paginated endpoints return a `cursor` in
    `pagination.next_cursor`.

    Pass it as the `cursor` query parameter to fetch the next page.

    When `pagination.has_more` is `false`, you have reached the last page.


    **Notices:** a successful JSON object may start with `notice`, the

    `X-Ironflow-Notice` header in the body: what was served when it differs from

    what was asked (a keyless sample, a shortened history, a guessed path) and

    how to get the rest.


    **Guessed paths:** a few paths callers guess are answered by the endpoint

    they mean, with a `notice` and the `X-Ironflow-Canonical` header naming it:

    `/v1/liquidations/aggregate`, `/v1/summary/liquidations` and similar by

    `/v1/liquidations/summary`, `/v1/liquidations/buckets` and `heatmap` by

    `/v1/analytics/liquidation-levels`, and `/v1/liquidations/map/BTC-PERP` by

    `/v1/liquidations/map?market=BTC-PERP`. A path with trailing `.`, `,`, `;`
    or

    `)` (`/v1/query.`, copied from a sentence) is answered by the endpoint
    without

    them, with the same method, query and body. OpenAI-style paths
    (`/v1/models`,

    `/v1/chat/completions`) answer 404: this is not an LLM API, and agents use
    the

    MCP server above.
  contact:
    name: Ironflow Support
    url: https://ironflow.sh
servers:
  - url: https://api.ironflow.sh
    description: Production
security:
  - bearerAuth: []
  - {}
tags:
  - name: Hyperliquid RPC
    description: Your API key as a Hyperliquid /info URL, on your plan's limits.
  - name: Market Data
    description: Historical tick-level market data stored in ClickHouse.
  - name: Analytics
    description: >-
      Aggregated analytics. Net flows, funding stats and the liquidation map
      markets work without a key; liquidation levels, the liquidation map and
      the vault leaderboard return a sample without one; order flow needs a key
      (a free key works).
  - name: Cohorts
    description: Predefined and custom address groups for filtering market data.
  - name: Alerts
    description: >-
      Liquidation alerts that Ironflow posts to your webhook, Discord channel,
      Slack channel or Telegram chat.
  - name: Ironbox
    description: >-
      Secure, sandboxed environments in Tokyo, next to Hyperliquid, where a
      trading agent runs with Ironflow's data, analytics, alerts and execution.
      Any API key, free included.
  - name: Query
    description: >-
      Read-only ClickHouse SQL over curated Hyperliquid tables (hl.*), limited
      by tier.
  - name: Billing
    description: >-
      Paid plans, paid in USDC on Hyperliquid or with x402 on Base. No card, no
      account page.
  - name: System
    description: Health checks and metadata endpoints.
  - name: TradingApp
    description: >-
      The trading terminal's own endpoints (terminal.ironflow.sh),
      wallet-session auth. Not part of the public data API; left out of the docs
      copy.
paths:
  /v1/query/export:
    post:
      tags:
        - Query
      summary: Export a SQL query as a Parquet or CSV file
      description: >
        Runs one read-only ClickHouse SELECT over the `hl.*` views and returns
        the result as a

        file, Parquet by default. It is for pulling a window of data you would
        otherwise page

        through `/v1/query`, including what the free datasets do not hold: every
        fill with fees

        and PnL (`hl.fills`), per-wallet tables, sub-hourly marks and any
        filter.


        | Plan | History | Time per export | Rows per file |

        |---|---|---|---|

        | Explorer | 90 days | 60 s | 1,000,000 |

        | Builder | 365 days | 85 s | 5,000,000 |

        | Enterprise | everything stored | 85 s | 10,000,000 |


        One export runs per key at a time, and a few across the service (`429
        EXPORT_BUSY`).

        Time counts toward the plan's hourly SQL budget. Over the row cap the
        export fails with

        `EXPORT_TOO_LARGE` rather than returning a cut file: split it by `ts`.
        Nothing is sent

        until the file is complete, so a response that starts is whole. Finish
        the download

        within 15 minutes. In Parquet, `DateTime` columns are written as Unix
        seconds; cast with

        `toDateTime64(col, 3)` for a timestamp. `DateTime64` columns (`ts` on
        most tables) keep

        their timestamp type. No pay-per-call: needs a key on a paid plan.
      operationId: exportQuery
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
              required:
                - sql
              properties:
                sql:
                  type: string
                  maxLength: 20000
                  description: One read-only ClickHouse statement, without a FORMAT clause.
                format:
                  type: string
                  enum:
                    - parquet
                    - csv
                  default: parquet
                  description: File format.
            example:
              sql: >-
                SELECT ts, tid, side, price, size, notional FROM hl.trades WHERE
                market = 'BTC-PERP' AND ts >= toDate('2026-10-15') AND ts <
                toDate('2026-10-16')
              format: parquet
      responses:
        '200':
          description: >-
            The file. `Content-Disposition` names it; `X-Ironflow-Export-Rows`
            and `X-Ironflow-Export-Max-Rows` give its size against the cap.
          headers:
            X-Ironflow-Export-Rows:
              description: Rows in the file.
              schema:
                type: integer
            X-Ironflow-Export-Max-Rows:
              description: The plan's row cap per file.
              schema:
                type: integer
          content:
            application/vnd.apache.parquet:
              schema:
                type: string
                format: binary
            text/csv:
              schema:
                type: string
        '400':
          description: >-
            `EXPORT_TOO_LARGE` over the row cap, or the statement was rejected:
            `INVALID_REQUEST`, `INVALID_PARAMETER`, `INVALID_QUERY`,
            `QUERY_ERROR`, `QUERY_NOT_ALLOWED`, `QUERY_TOO_EXPENSIVE`.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '402':
          description: >-
            `TIER_LIMIT`: free keys and keyless callers get the standard
            `upgrade` object naming Explorer.
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
              example:
                error:
                  code: TIER_LIMIT
                  message: >-
                    SQL file export (Parquet or CSV) needs a paid plan: Explorer
                    or Builder, see the upgrade object. The free datasets cover
                    whole-market history: https://ironflow.sh/datasets
                  upgrade:
                    plan: explorer
                    price_usdc: 49
                    days: 30
                    unlocks: >-
                      SQL export to Parquet or CSV (1,000,000 rows a file), 100
                      requests a minute, 90 days of history
                    limit: tier
                    lifts: unlocked by Explorer
                    url: >-
                      https://ironflow.sh/upgrade?utm_source=api&plan=explorer&limit=tier
                    how: >-
                      POST https://api.ironflow.sh/v1/billing/upgrade with your
                      email, wallet, plan and network, then send the USDC
        '429':
          description: '`EXPORT_BUSY`, `RATE_LIMIT_EXCEEDED`, or `QUERY_BUDGET_EXCEEDED`.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '503':
          description: '`EXPORT_UNAVAILABLE`: exports are not switched on.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
        '504':
          description: '`EXPORT_TIMEOUT`: the export ran past the plan''s time limit.'
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Error'
      security:
        - bearerAuth: []
components:
  schemas:
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Machine-readable error code.
              example: RATE_LIMIT_EXCEEDED
            message:
              type: string
              description: Human-readable error description.
              example: Rate limit exceeded. Retry after 60 seconds.
            upgrade:
              type: object
              description: >-
                On a limit a higher plan lifts, the next plan, its price, what
                it lifts and the call that gets it.
              properties:
                plan:
                  type: string
                  example: explorer
                price_usdc:
                  type: number
                  example: 49
                days:
                  type: integer
                  example: 30
                unlocks:
                  type: string
                  description: >-
                    What the plan adds, starting with SQL export to Parquet or
                    CSV
                limit:
                  type: string
                  description: >-
                    The limit this error hit: rate, history, window, sql_budget,
                    read_budget, streams, alerts, keyless_day or tier
                  example: rate
                lifts:
                  type: string
                  description: What the plan changes about that limit
                  example: 60 requests a minute now, 100 on Explorer
                url:
                  type: string
                  format: uri
                  description: Where to upgrade; the link carries the plan and the limit
                how:
                  type: string
                  description: The API call that opens the upgrade request
                buy_url:
                  type: string
                  format: uri
                  description: Buy this plan in one x402 call (USDC on Base)
                  when x402 is on: null
                pay_per_call:
                  type: object
                  description: On limits one paid call lifts
                  how to pay for this call with x402: null
                offer:
                  type: string
                  description: Founding-member offer
                  while seats remain: null
            get_key:
              type: object
              description: >-
                On every keyless 429 (daily cap, per-minute rate, SQL and read
                budgets, stream cap) and keyless history refusal, the one call
                that gets a free key. `page` is the key page tagged with the
                refusal (utm_campaign).
              properties:
                method:
                  type: string
                  example: POST
                url:
                  type: string
                  format: uri
                  example: https://api.ironflow.sh/v1/keys
                body:
                  type: object
                  additionalProperties:
                    type: string
                  example:
                    email: you@example.com
                page:
                  type: string
                  format: uri
            dataset:
              type: object
              description: >-
                On `HISTORY_OUT_OF_RANGE`, and on a rate limit for a closed past
                range, the free download that holds the requested rows, when one
                does. The message repeats it with its dates.
              properties:
                name:
                  type: string
                  example: Hyperliquid Liquidations
                url:
                  type: string
                  format: uri
                  example: >-
                    https://huggingface.co/datasets/ironflow/hyperliquid-liquidations?utm_source=api
                holds:
                  type: string
                  example: every liquidation
                from:
                  type: string
                  format: date
                  example: '2025-05-25'
                through:
                  type: string
                  format: date
                  example: '2026-10-31'
            ironbox:
              type: object
              description: >-
                On a rate limit, the keyless daily cap, the stream limit, the
                SQL budget and the read budget, how to run the agent in an
                Ironbox instead.
              properties:
                why:
                  type: string
                  example: >-
                    No rate limits inside an Ironbox: your agent runs next to
                    Hyperliquid with the data on the box.
                create:
                  type: string
                  example: POST https://api.ironflow.sh/v1/ironbox
                url:
                  type: string
                  format: uri
                  example: https://ironflow.sh/ironbox?utm_source=api
            stream:
              type: string
              description: >-
                On the keyless daily limit, a per-minute rate limit, the read
                budget and a keyless history refusal of `/v1/liquidations` and
                `/v1/trades`, the live stream that replaces polling.
              example: >-
                GET https://api.ironflow.sh/v1/liquidations/stream (no daily
                limit for keyless streams)
            allowed_from:
              type: integer
              format: int64
              description: >-
                On `HISTORY_OUT_OF_RANGE`, the earliest `from` (Unix ms; `at` on
                `/v1/positions`) the caller's history reaches; a request from
                there is served.
              example: 1794394800000
            did_you_mean:
              type: array
              items:
                type: string
              description: >-
                On an unknown market (the liquidation map, the order book), the
                markets the name most likely meant. The message repeats them.
              example:
                - xyz:GOLD-PERP
                - PAXG-PERP
  securitySchemes:
    bearerAuth:
      type: http
      scheme: bearer
      description: >-
        Ironflow API key, format `if_xxxx`. Free keys at
        https://ironflow.sh/key. Optional on read endpoints.

````

This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.