---
title: "Resolve AND execute — return the actual table or chart"
method: GET
path: "/v1/data"
tags: ["Resolution"]
---

# Resolve AND execute — return the actual table or chart

`GET /v1/data`

## Request

- Base URL: `https://api.stackdata.io`
- URL: `https://api.stackdata.io/v1/data`
- Auth: one of:
  - none
  - API key in header `X-API-Key`

Carries a ready plan through to the data. Everything the plan would refuse still
refuses here (a licence-blocked source never reaches the fetch).

The `200` body is a **status-tagged object**. Common `status` values:
`ok`, `ok_correlation`, `ok_coverage` (success); `empty`, `no_candidates`,
`dsd_unavailable`, `multi_concept_unparsed`, `language_unsupported`,
`tariff_redirect`, `unit_mismatch` (honest non-answers). `tariff_redirect`: the
prompt names a goods code (`HS 8542.31`), so it is a tariff question; `try` holds the
`/v1/tariff` call and `needs` any parameter the prompt did not state. `unit_mismatch`:
the prompt asks per capita and no matched dataset states per capita. Both are decided
before any fetch and are never metered. With `format=html` the response is a self-contained HTML chart
(`text/html`) instead of JSON.

**Metered.** Over-quota keyed callers get `429`. Over-quota **anonymous** callers may
instead get `402` with x402 payment terms (only when the server has x402 configured).

## Query parameters

- `q` string, required
- `start` integer
- `end` integer
- `format` 'json' | 'html'
- `dataset` string

## Headers

- `X-PAYMENT` string

## Response `200`

The answer. JSON by default; HTML when `format=html`. On a settled x402 payment,
an `X-PAYMENT-RESPONSE` header carries the receipt and the body gains a `payment` object.

- DataResponse: Status-tagged answer. `status` names the outcome — success (`ok`, `ok_correlation`, `ok_coverage`) or an honest non-answer (`empty`, `no_candidates`, `dsd_unavailable`, `multi_concept_unparsed`, `language_unsupported`, `tariff_redirect`, `unit_mismatch`, …). `billing.charged` says whether an uncached fetch was paid for. `interpreted_as` appears when an LLM rewrote the prompt. When `status` is `empty`, `reason` may begin `pin_unavailable:` — the source's serve set pins a statistic that this request cannot hold, and no other member is substituted.
  - `status` string
  - `pin_unavailable` object[]: Present on a non-ok answer when one or more candidate datasets were skipped because their serve-set pin could not hold. It accompanies the answer's own `reason` and never replaces it.
    - `dataset` string
    - `dimension` string
    - `code` string
    - `why` string
  - `pinned` object[]: Present when the answer was served under a serve-set pin (the source declares one member per dimension for this dataset). Each cell also carries `pinned_by` and `pins`.
    - `dimension` string
    - `code` string
    - `rule` 'serve.pin'
  - `billing` object
    - `charged` boolean
  - `scope_note` string, nullable: Present when the country on the series did not come from a code in the data. Either a named region is the publisher's own aggregate (not a sum of members), or the source publishes exactly one country and this dataflow carries no geography dimension, so every value is that country's by the publisher's declared scope (cells then carry `country_binding: source_scope`).
  - `fallback` object, nullable: Present when the top-ranked candidate refused by its own declared structure (for example a PxWeb table declared out of scope, or one whose time axis cannot be read) and a lower candidate answered. `skipped` is the refused dataset id and `why` its refusal. When no lower candidate answers, the response is the top candidate's own `dsd_unavailable`, with `fallback_tried` listing the ids tried.
    - `skipped` string
    - `why` string
    - `note` string
  - `fallback_tried` string[], nullable
  - `coverage` object
  - `withheld` object, nullable: Present and non-null only when the publisher HOLDS observations in this window and states they may not be shown as numbers — today, Statistics Canada cells suppressed under the Statistics Act (`securityLevelCode` 1) or flagged too unreliable to be published (`statusCode` 8). Those points are absent from `series`, and absent is not zero, so the count, the publisher's own stated reasons and the affected periods are reported rather than left as a gap. `null` for every source that flags nothing. It also appears on `status: "empty"`, where it is the difference between "the source holds nothing" and "the source holds it and may not show it" — and the `reason` then says so.
    - `count` TypedCount: A count that states whether it is exact — never a bare integer.
      - `value` integer, required
      - `exact` boolean, required
    - `note` string, nullable
    - `reasons` string[]: The publisher's own wording, never paraphrased.
    - `periods` string[]
  - `interpreted_as` object
  - `payment` object: Present only on the x402 path — settlement outcome for the answer.
  - `meta` Meta: Attached to every JSON response. `harvest` maps each source id to its last successful harvest timestamp.
    - `harvest` object
    - `api_version` string

## Other responses

- `400`: An unknown query parameter was supplied. Unknown parameters are **rejected, never silently ignored** — the error names the offenders and lists what is allowed.
- `402`: Payment required (x402). Returned to anonymous, over-quota callers when the server has x402 configured. The body carries the payment terms; reissue with an `X-PAYMENT` header. Also returned if a supplied payment is invalid, already used, or fails to settle.
- `429`: Daily free-tier limit reached (or credits exhausted). The body includes current usage.
- `502`: Upstream source failed while fetching the data. Distinct from an honest empty.

---

[API](https://skmtc.dev/stackdata/apis/stackdata-api.md) · [All operations](https://skmtc.dev/stackdata/apis/stackdata-api/llms.txt) · [OpenAPI document](https://skmtc.dev/stackdata/apis/stackdata-api/revisions/91358ae3f6e8?raw)
