---
title: "Query workflow-plane data"
method: GET
path: "/query"
tags: ["Data Query"]
---

# Query workflow-plane data

`GET /query`

## Request

- Base URL: `https://api.indexone.io`
- URL: `https://api.indexone.io/query`
- Auth: API key in header `x-api-key` and API key in header `Authorization`

The main data-read path for `idx_...` indices. It exposes the underlying DynamoDB tables directly as a keyed query: you pick a table, give a partition key (`pk` — the workflow or delivery id) and get back rows in sort-key order.

**Tables** (`table`): `index-parameters` (the workflow definition itself, no sort key), `index-holdings`, `index-values-eod`, `index-weightings`, `index-universes`, `index-corporate-actions` (all sorted by `time`), and `deliveries` (no sort key).

**Narrowing the read.** `sk` pins one exact sort-key value — the fastest way to fetch a single snapshot. `attributes` is a projection: only the named top-level fields come back, which matters because holdings and universe rows are large. `order=descending` with `limit` is the idiom for "most recent N".

**Paging.** `cursor` is an opaque base64-encoded DynamoDB `LastEvaluatedKey`; never parse or construct it. It is returned only when `limit` was reached and more rows exist. Without `limit` the handler pages internally and returns the whole partition in one response — safe for values, expensive for holdings.

**Symbols.** `map_symbols=true` adds a `figi_symbols` map covering every identifier that appears anywhere in the payload, so you can render tickers without a second lookup.

**Access control.** `pk` must be a workflow or delivery id belonging to one of the caller's teams (site admins bypass this). This is the only authorization check — there is no per-table permission.

## Query parameters

- `table` 'index-parameters' | 'index-holdings' | 'index-values-eod' | 'index-weightings' | 'index-universes' | 'index-corporate-actions' | 'deliveries', required
- `pk` string, required
- `sk` string
- `attributes` string
- `order` 'ascending' | 'descending'
- `limit` integer
- `cursor` string
- `map_symbols` boolean

## Response `200`

The matching rows.

- QueryResponse: Response envelope of `GET /query`.
  - `items` object[]: The matching rows, in sort-key order (ascending unless `order=descending`).
  - `count` integer: Number of rows in `items` (not the total matching count).
  - `cursor` string, nullable: Opaque base64 continuation token. Present only when `limit` was reached and more rows exist; pass it back as `cursor` to resume. `null` means the partition was exhausted.
  - `figi_symbols` object: Only present when `map_symbols=true`: FIGI to ticker-symbol lookup covering every identifier found anywhere in `items`.

## Other responses

- `400`: `table and pk required`, or `unknown table <alias>` when `table` is not one of the seven allowed aliases.
- `401`: Missing or invalid id token.
- `403`: `pk` is not a workflow or delivery owned by one of the caller's teams.
- `429`: API key usage-plan rate limit exceeded.

---

[API](https://skmtc.dev/indexone/apis/index-one-rest-api.md) · [All operations](https://skmtc.dev/indexone/apis/index-one-rest-api/llms.txt) · [OpenAPI document](https://skmtc.dev/indexone/apis/index-one-rest-api/revisions/df5a92216a9c?raw)
