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

# Key levels (classified nodes) for one or more symbols

> The strikes Skylit classifies as nodes (king, gatekeeper, pika, barney,
significant) for up to 10 symbols, strongest first, with each level's
distance from spot. Same live source, filters and 5-second cache as
`/v1/heatmap`; 1 credit per request.




## OpenAPI

````yaml /openapi.yaml get /v1/gex/levels
openapi: 3.1.0
info:
  title: Skylit Public API
  version: 1.0.0
  summary: Options-Greeks heatmaps as a public HTTP API.
  description: |
    Skylit exposes its real-time options-Greeks (gamma / vanna) heatmaps as a
    versioned public HTTP API, per strike, with the live velocity metric and
    Skylit's node classification (King / Gatekeeper / etc.).

    **Authentication.** Send your Skylit API key as a bearer token:

        Authorization: Bearer <key>

    A request without an `Authorization` header gets `401`; an invalid,
    revoked or expired key gets `403`.

    **Credit metering.** Every chargeable request debits a fixed cost from
    your credit balance:

    | Endpoint        | Cost |
    |-----------------|-----:|
    | `/v1/heatmap`    | 1   |
    | `/v1/historical` | 5   |
    | `/v1/stream`     | 1 per minute open |
    | `/v1/openapi.json` | 0 |

    New customers are seeded with 5,000 credits. Every chargeable response
    carries `X-Credits-Remaining: <balance>`. Out of credits → `402`
    `insufficient_credits`; an admin-suspended account → `403`
    `account_suspended`. Top up via your account console.

    **Rate limits.** A safety ceiling of 600 requests / minute is enforced
    by the Skylit gateway and surfaced via `X-RateLimit-Limit`,
    `X-RateLimit-Remaining`, and `X-RateLimit-Reset`. `429` includes
    `Retry-After`. This is a runaway-protection ceiling, not a quota —
    credit metering does the per-customer accounting.

    Live streams (`/v1/stream`) cost 1 credit to open plus 1 per minute
    connected, and close after one hour.

    **Resolution.** The heatmap is a 1-second time series. Endpoints return the
    single snapshot nearest the requested instant — poll `/v1/heatmap` every
    60-90s for live, or query `/v1/historical` at any minute boundary for a
    1-minute replay grid (no server-side downsampling needed).

    **Velocity is live-only.** The `velocityPct` field is present on
    `/v1/heatmap` (live) and absent on `/v1/historical` (replay).

    **Response shape.** Success → `{ "data": ..., "meta": { ... } }`; errors →
    `{ "error": { "code": "...", "message": "..." } }`. camelCase throughout.
    `data.symbols` is always an array (one element per requested symbol), so a
    single-symbol call and a multi-symbol "Trinity" call share one shape.
servers:
  - url: https://api.skylit.ai
    description: Production
security:
  - bearerApiKey: []
tags:
  - name: Heatmap
  - name: Meta
paths:
  /v1/gex/levels:
    get:
      tags:
        - Heatmap
      summary: Key levels (classified nodes) for one or more symbols
      description: |
        The strikes Skylit classifies as nodes (king, gatekeeper, pika, barney,
        significant) for up to 10 symbols, strongest first, with each level's
        distance from spot. Same live source, filters and 5-second cache as
        `/v1/heatmap`; 1 credit per request.
      operationId: getLevels
      parameters:
        - $ref: '#/components/parameters/Symbols'
        - $ref: '#/components/parameters/Metric'
        - $ref: '#/components/parameters/MaxStrikes'
        - $ref: '#/components/parameters/MaxExpirations'
        - $ref: '#/components/parameters/Expirations'
      responses:
        '200':
          description: Levels per symbol.
          content:
            application/json:
              schema:
                type: object
                properties:
                  data:
                    type: object
                    properties:
                      symbols:
                        type: array
                        items:
                          type: object
                          properties:
                            symbol:
                              type: string
                            asOf:
                              type: string
                              format: date-time
                            spot:
                              type: number
                            previousClose:
                              type: number
                            kingNode:
                              description: >-
                                The strongest king node, or null when none is
                                classified.
                              nullable: true
                              allOf:
                                - $ref: '#/components/schemas/Level'
                            levels:
                              type: array
                              items:
                                $ref: '#/components/schemas/Level'
                  meta:
                    $ref: '#/components/schemas/Meta'
        '400':
          $ref: '#/components/responses/BadRequest'
        '401':
          $ref: '#/components/responses/Unauthorized'
        '402':
          $ref: '#/components/responses/PaymentRequired'
        '404':
          $ref: '#/components/responses/NotFound'
components:
  parameters:
    Symbols:
      name: symbols
      in: query
      required: true
      description: |
        One ticker, or a comma-separated list for a single cross-asset call
        (e.g. `SPY` or `SPY,SPX,QQQ`). Each is returned as an element of
        `data.symbols`.
      schema:
        type: string
        example: SPY,SPX,QQQ
    Metric:
      name: metric
      in: query
      required: false
      description: Which Greek exposure to return per strike.
      schema:
        type: string
        enum:
          - gamma
          - vanna
        default: gamma
    MaxStrikes:
      name: maxStrikes
      in: query
      required: false
      description: Maximum number of strikes around spot to return.
      schema:
        type: integer
        default: 92
        minimum: 1
        maximum: 400
    MaxExpirations:
      name: maxExpirations
      in: query
      required: false
      description: |
        How many of the nearest expirations to net into each strike's `value`.
        Ignored when `expirations` is set.
      schema:
        type: integer
        default: 5
        minimum: 1
        maximum: 60
    Expirations:
      name: expirations
      in: query
      required: false
      description: |
        Net each strike over exactly these expirations (`YYYY-MM-DD`,
        comma-separated) — one for a single-expiration heatmap (`2026-05-22`)
        or several for a custom set (`2026-05-22,2026-06-19`). Supersedes
        `maxExpirations`, and reaches any expiration the snapshot has, not just
        the nearest ones. Requested dates the symbol does not have are ignored;
        the `expirations` array in the response lists what was actually used.
        If none of them match, the response is `404` with
        `code: expiration_not_found` and the available dates in the message.
        On `/v1/heatmap`, expirations that have already expired are not
        available (they are trimmed from the live snapshot) — replay them with
        `/v1/historical` instead.
      schema:
        type: string
        example: '2026-05-22'
  schemas:
    Level:
      type: object
      required:
        - strike
        - value
        - nodeType
        - distancePct
      properties:
        strike:
          type: number
        value:
          type: number
          description: Net exposure at this strike for the selected metric.
        nodeType:
          type: string
          enum:
            - king
            - gatekeeper
            - pika
            - barney
            - significant
        distancePct:
          type: number
          description: Percent distance from spot (negative = below).
    Meta:
      type: object
      required:
        - metric
        - resolution
        - mode
        - cached
      properties:
        metric:
          type: string
          enum:
            - gamma
            - vanna
        resolution:
          type: string
          example: 1m
        mode:
          type: string
          enum:
            - live
            - historical
        cached:
          type: boolean
          description: True if served from the in-process cache.
    Error:
      type: object
      required:
        - error
      properties:
        error:
          type: object
          required:
            - code
            - message
          properties:
            code:
              type: string
              description: Stable, machine-readable error code.
              example: no_data
            message:
              type: string
              description: Human-readable explanation.
  responses:
    BadRequest:
      description: Request validation failed.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    Unauthorized:
      description: Missing or invalid API key.
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    PaymentRequired:
      description: Out of credits (`insufficient_credits`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
    NotFound:
      description: |
        Unknown symbol, no data available, or none of the requested
        `expirations` exist for the symbol (`code: expiration_not_found`).
      content:
        application/json:
          schema:
            $ref: '#/components/schemas/Error'
  securitySchemes:
    bearerApiKey:
      type: http
      scheme: bearer
      description: |
        Skylit API key in the `Authorization` header
        (`Authorization: Bearer <key>`).

````