---
title: "What each tier promises"
method: GET
path: "/v1/tiers"
tags: ["meta"]
---

# What each tier promises

`GET /v1/tiers`

## Request

- Base URL: `https://api.hyperresearch.ai`
- URL: `https://api.hyperresearch.ai/v1/tiers`
- Auth: none required

Unauthenticated. Lists exactly the tiers `POST /v1/runs` will accept, in ladder order, each with the `display_name` to print, the `purpose` line to show on its card and a `recommended` flag (false on every tier while the ladder is Light and Deep). The ENFORCED numbers are the pipeline’s own: `sources.target_high` is the fetch budget the width sweep enforces, and `duration_estimate` is the research profile’s estimate. What a card should PRINT is served beside them: `duration_display`, `sources_display` (from `sources.typical_low`–`typical_high`), `words.typical_min`–`typical_max` and `description`, which carry a measured envelope where one exists (Light, 2026-09-23) and otherwise repeat the enforced numbers. A client that renders a tier card must read it from here rather than hardcoding a band, which is how a Light run came to report 66 sources against an advertised 15–25 (E2E4-16).

## Response `200`

Tiers

- Tiers
  - `data` Tier[], required
    - `tier` string, required: The tier id, which is what `POST /v1/runs` takes and what every stored run, receipt and plan hash carries. Never shown to a person: use `display_name`.
    - `display_name` string, required: What this tier is called in customer-facing text. Not always the id title-cased — `premier` is shown as "Deep". Anything that prints a tier word to a person must print this.
    - `purpose` string, required: One line saying what this tier is FOR: the copy on its card.
    - `recommended` boolean, required: True for a tier a client should show as a highlighted default. While the ladder is two rungs (Light and Deep) NO tier is marked and this is false on every row: a badge between one cheap tier and one deep one is a thumb on a scale the customer can read for themselves. The field stays so the schema does not change when a badge comes back. A client pre-selects the cheapest listed tier, not the recommended one.
    - `price_cents` integer, required: List price for one run at this tier.
    - `sources` TierSources, required
      - `min` integer, required: The floor the pipeline gates on: a run that cannot reach it does not proceed to drafting.
      - `target_low` integer, required
      - `target_high` integer, required: The number the fetch budget is set to. `budget.sources_max` defaults to exactly this, and the width sweep stops here — so the advertised ceiling IS the enforced one (E2E4-16).
      - `max_requestable` integer, required: The highest `budget.sources_max` this API will accept from a caller who names one. Always >= `target_high`; a caller who names nothing gets `target_high`.
      - `typical_low` integer, required: The low end of how many sources a finished run at this tier typically reads — what a card should print. Display only: it can exceed `target_high`, because later stages (claim check, source lanes) read past the width sweep. Equal to `target_low` when the tier has no measured envelope.
      - `typical_high` integer, required: The high end of `typical_low`’s band. Equal to `target_high` when the tier has no measured envelope.
    - `sources_display` string, required: The source band as a card prints it, e.g. "about 20–50 sources". Built from `typical_low`–`typical_high`.
    - `duration_estimate` string, required: The research profile’s own estimate, which is part of every run’s frozen plan. For what to PRINT, read `duration_display`.
    - `duration_display` string, required: How long a run takes, as a card prints it. The measured envelope where one exists (Light: "about 30–40 min"), otherwise `duration_estimate`.
    - `steps` integer, required: Pipeline steps this tier executes.
    - `requires_card` boolean, required: True when this tier cannot be started by a PAYG account with no card on file. Deep commits hours of research and over a hundred sources before there is a report to show for it, so it is card-required; an invoiced Enterprise plan satisfies the same gate. A client that renders a tier card must read this rather than hardcoding the tier names, and must say what to do about it — the API’s own refusal does.
    - `trial_eligible` boolean, required: True when an included run can ever be claimed at this tier. Two tiers can: Deep, which a first card attach grants one of, and Light, which accounts created before 2026-10-15 were given two of with no card (a new account gets no included Light run, so its Light runs are charged from the first). A Deep allowance is GRANTED rather than stamped at sign-up, so `trial_eligible` being true does not mean this account has one — it means the column exists to be spent. Every other tier is charged in full. This is not the opposite of `requires_card`: a free Deep needs a card on file to start, because the card is what earned it.
    - `chapters` object, nullable, required: How many chapters a run at this tier is partitioned into, or null when the report is written as one piece. A chaptered run researches each chapter separately and then writes the report section by section, which is why it takes hours rather than minutes.
      - `min` integer, required
      - `max` integer, required
    - `words` object, required: `min`/`max`: the length band the ship gate measures the finished report against. `typical_min`/`typical_max`: what a finished report typically runs to, which is what to print.
      - `min` integer, required
      - `max` integer, required
      - `typical_min` integer, required: The low end of how long a finished report at this tier typically runs, in words — what a card should print. Equal to `min` when the tier has no measured envelope.
      - `typical_max` integer, required: The high end of `typical_min`’s band.
    - `description` string, required: One sentence describing the tier. The measured display copy where one exists, otherwise the research profile’s own description.

## Other responses

- `429`: Too many requests from this network; wait `Retry-After` seconds
- `500`: Internal error

---

[API](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api.md) · [All operations](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/llms.txt) · [OpenAPI document](https://skmtc.dev/hyperresearch/apis/hyperresearch-cloud-api/revisions/726ef831ebf4?raw)
