---
title: "Create a chart card from a query or your own data"
method: POST
path: "/v1/charts"
---

# Create a chart card from a query or your own data

`POST /v1/charts`

## Request

- Base URL: `https://api.typesearch.ai`
- URL: `https://api.typesearch.ai/v1/charts`
- Auth: one of:
  - HTTP bearer
  - API key in header `x-api-key`

Ask in plain words («blue dollar this week», «standings last Formula 1 race», «elections in Brazil», «Milei vs Bullrich coverage», «news in The Guardian this week», «prices in my catalog» with `index`). It first works out what you expect to see (`interpretation`, with other readings you can ask for), then gets that data: the finishing positions of the latest race, poll or result shares, wins in the season, coverage, tone, outlets, a timeline or the figures the articles publish, verified against the sources. It never fails while there are articles on the topic: if the exact data is not published or takes too long, it shows the closest thing (`rung`: exact, partial, related, coverage, stories) with a warning, and a stored chart keeps `improving` until the exact data arrives. With `stream: true`, server-sent events: `step`, `result` and `improved`. Or send `data` (series, events, or columns and rows) and it picks the chart, sorts, summarizes and titles it. `type` forces one of 12 types while the data allows. From a query it costs its search (the mode it ended in, one per compared name; free if cached) plus the chart add-on; from your data, the data price (see `x-pricing`, per_1000_charts). The same request within 10 minutes returns the same card, free. No articles at all: 422 `insufficient_data`, not billed.

## Request body

- ChartRequest
  - `query` string: What you want to see, in plain words: «blue dollar this week», «Milei vs Bullrich coverage», «prices in my catalog».
  - `data` object: Your own data: series of points (x, y), or events, or columns and rows.
    - `series` object[]
      - `name` string, required
      - `points` object[], required
        - `x` union, required
          - string
          - number
        - `y` number, required
        - `r` number
        - `label` string
      - `role` 'positive' | 'neutral' | 'negative' | 'other'
    - `x` object
      - `kind` 'time' | 'category' | 'number'
      - `label` string
      - `unit` string
      - `granularity` 'hour' | 'day' | 'week' | 'month' | 'year'
    - `y` object
      - `label` string
      - `unit` string
      - `format` 'number' | 'percent' | 'currency'
      - `currency` string
      - `decimals` integer
      - `higher_is_better` boolean
    - `x_measure` object
      - `label` string
      - `unit` string
      - `format` 'number' | 'percent' | 'currency'
      - `currency` string
      - `decimals` integer
      - `higher_is_better` boolean
    - `events` object[]
      - `date` string, date, required
      - `end` string, date
      - `label` string, required
      - `detail` string
    - `columns` object[]
      - `key` string, required
      - `label` string, required
      - `format` object
        - `label` string
        - `unit` string
        - `format` 'number' | 'percent' | 'currency'
        - `currency` string
        - `decimals` integer
        - `higher_is_better` boolean
    - `rows` object[]
    - `highlight` string
  - `type` 'auto' | 'line' | 'area' | 'bar' | 'bar_horizontal' | 'stacked_bar' | 'pie' | 'donut' | 'scatter' | 'funnel' | 'timeline' | 'kpi' | 'table': The chart type. auto (the default) picks the one that tells the data best; any other forces it while the data allows.
  - `index` string: Build the chart from your custom index (idx_…) instead of the news: prices, ratings, availability and brands.
  - `mode` 'auto' | 'ultra' | 'fast' | 'normal' | 'deep': auto: the cheapest mode that gets the data (coverage in ultra, figures in fast, reading articles only if needed). Or fix it.
  - `compare` string[]: What to compare (2 to 5), if the query does not say it with «vs».
  - `questions` object: One typed question (boolean, choice, score): the chart shows how the answers split across the articles.
  - `days` integer, nullable: The last N days. By default it depends on what is measured: 30 for coverage, share of voice and outlets, 14 for tone, 60 for a timeline, 7 for figures.
  - `published_after` union: Published on or after this date. A bare date is read in Argentina time (UTC−3).
    - string, date
    - string, date-time
  - `published_before` union: Published on or before this date; a bare date includes that whole day.
    - string, date
    - string, date-time
  - `countries` string[]: Only sources from these countries: ISO 3166-1 alpha-2 codes, such as AR or US.
  - `languages` string[]: Only sources that publish in these languages: ISO 639-1 codes, such as es or en (a BCP 47 tag such as pt-BR counts as pt).
  - `include_domains` string[]: Only these domains or paths. A domain includes its subdomains.
  - `exclude_domains` string[]: Never these domains or paths.
  - `timezone` string: IANA time zone that decides what day «today» is. Defaults to Argentina (America/Argentina/Buenos_Aires).
  - `title` string: Your title. Without one, the chart gets a title that states the finding.
  - `subtitle` string
  - `source` string: The source line in the footer, for your own data.
  - `theme` 'light' | 'dark' | 'editorial' | 'electric': light, dark, editorial (warm paper, for media) or electric (deep blue, for presentations).
  - `locale` 'en' | 'es': Language of titles, labels and numbers. Defaults to Accept-Language.
  - `interpretation` string: One of `interpretation.alternatives` from a previous response: chart that reading of the query instead.
  - `plan_only` boolean: Only the plan: what we understood, what would be measured, the chart type and the data needed. Free, without searching.
  - `stream` boolean: Server-sent events: `step` while it works, `result` with the chart and, if a better chart arrives after the deadline, `improved`.
  - `store` boolean: false: nothing is stored (no embed_url); the SVG comes in the response.
  - `include_svg` boolean: Include the SVG in the response.

## Response `200`

With plan_only, store: false, or the same request within 10 minutes (cached: true). With stream: true, text/event-stream: `step`, `result` (a Chart), `improved` (a Chart) or `error` (a Problem).

- Chart
  - `id` string, nullable, required: chart_…; null with store: false or plan_only.
  - `object` 'chart', required
  - `type` 'line' | 'area' | 'bar' | 'bar_horizontal' | 'stacked_bar' | 'pie' | 'donut' | 'scatter' | 'funnel' | 'timeline' | 'kpi' | 'table', nullable, required
  - `theme` 'light' | 'dark' | 'editorial' | 'electric', required
  - `locale` 'en' | 'es', required
  - `chart` object, nullable, required: What is drawn: series, key figures, annotations, sources. Null with plan_only.
    - `type` 'line' | 'area' | 'bar' | 'bar_horizontal' | 'stacked_bar' | 'pie' | 'donut' | 'scatter' | 'funnel' | 'timeline' | 'kpi' | 'table', required
    - `title` string, required: States the finding: «The blue dollar rose 4.1% this week».
    - `subtitle` string
    - `x` object, required
      - `kind` 'time' | 'category' | 'number', required
      - `label` string
      - `unit` string
      - `granularity` 'hour' | 'day' | 'week' | 'month' | 'year'
    - `y` object, required
      - `label` string
      - `unit` string
      - `format` 'number' | 'percent' | 'currency'
      - `currency` string
      - `decimals` number
      - `higher_is_better` boolean
    - `x_measure` object
      - `label` string
      - `unit` string
      - `format` 'number' | 'percent' | 'currency'
      - `currency` string
      - `decimals` number
      - `higher_is_better` boolean
    - `series` object[], required
      - `name` string, required
      - `role` 'positive' | 'neutral' | 'negative' | 'other'
      - `points` object[], required
        - `x` union, required
          - string
          - number
        - `y` number, required
        - `r` number
        - `label` string
        - `sources` integer[]: Indexes in `sources`: where this value was published.
    - `events` object[]
      - `date` string, required
      - `end` string
      - `label` string, required
      - `detail` string
      - `sources` integer[]
    - `columns` object[]
      - `key` string, required
      - `label` string, required
      - `format` object
        - `label` string
        - `unit` string
        - `format` 'number' | 'percent' | 'currency'
        - `currency` string
        - `decimals` number
        - `higher_is_better` boolean
    - `rows` object[]
    - `kpis` object[]: The key figures above the chart: latest, change, high.
      - `label` string, required
      - `value` number, required
      - `format` object
        - `label` string
        - `unit` string
        - `format` 'number' | 'percent' | 'currency'
        - `currency` string
        - `decimals` number
        - `higher_is_better` boolean
      - `change` object
        - `value` number, required
        - `percent` boolean, required
    - `annotations` object[]
      - `x` union, required
        - string
        - number
      - `y` number
      - `series` string
      - `text` string, required
      - `kind` 'peak' | 'max' | 'min' | 'last' | 'event', required
    - `highlight` string
    - `total` number
    - `part_of_whole` boolean
    - `scale` 'linear' | 'log'
    - `smoothing` integer: Moving average drawn over the raw series, in points.
    - `attribution` string
  - `compatible_types` string[], required: The chart types this data supports.
  - `plan` object, nullable, required: From a query: what was measured and why this chart. Null for your own data.
    - `recipe` 'coverage' | 'coverage_compare' | 'share_of_voice' | 'tone' | 'tone_compare' | 'outlets' | 'timeline' | 'figure_trend' | 'figure_compare' | 'answers' | 'index_prices' | 'index_scatter' | 'index_availability' | 'index_brands' | 'data' | 'series' | 'people' | 'outlet' | 'stories', required: What was measured: coverage, share_of_voice, tone, outlets, timeline, figure_trend, figure_compare, answers, or index_* from your custom index.
    - `intent` string, required
    - `measure` string, required
    - `x_axis` string, required
    - `type` 'line' | 'area' | 'bar' | 'bar_horizontal' | 'stacked_bar' | 'pie' | 'donut' | 'scatter' | 'funnel' | 'timeline' | 'kpi' | 'table', required
    - `part_of_whole` boolean, required
    - `confidence` number, required
    - `alternatives` object[], required: Other chart types that fit: switch with PATCH, free.
      - `type` 'line' | 'area' | 'bar' | 'bar_horizontal' | 'stacked_bar' | 'pie' | 'donut' | 'scatter' | 'funnel' | 'timeline' | 'kpi' | 'table', required
      - `probability` number, required
    - `topic` string, required
    - `entities` string[], required
    - `needs` object, required: The data it needs before drawing.
      - `queries` string[], required
      - `mode` 'ultra' | 'fast' | 'normal' | 'deep', required
      - `days` number, required
      - `min_points` number, required
      - `max_results` number, required
  - `interpretation` object, nullable, required: From a query in words. Null for your own data, a custom index or a typed question.
    - `label` string, required: What we understood you expect to see: «Finishing positions of the last Formula 1 race».
    - `confidence` number, required
    - `alternatives` object[], required: Other readings of the query: pass one as `interpretation` to chart it instead.
      - `label` string, required
      - `probability` number, required
  - `rung` 'exact' | 'partial' | 'related' | 'coverage' | 'stories', nullable, required: How close the chart is to what was asked. exact: the data itself, complete and verified; partial: a verified part (the podium); related: another view of the same question (the most mentioned names); coverage: the coverage or the timeline; stories: the top stories. Null for your own data.
  - `improving` boolean, required: Still looking for what was asked: the stored chart (embed, image) updates itself if it arrives. Poll GET /v1/charts/{id} or use stream: true.
  - `sources` object[], required
    - `url` string, required
    - `title` string, required
    - `source` string, nullable, required
    - `published_at` string, nullable, required
  - `embed_url` string, nullable, required: An iframe that adapts to its width, with tooltips. Add ?theme= to change the theme.
  - `image_url` string, nullable, required: PNG at twice the resolution, for chat, email or slides.
  - `svg_url` string, nullable, required
  - `svg` string, nullable, required: The SVG, with include_svg or store: false.
  - `created_at` string, nullable, required
  - `expires_at` string, nullable, required
  - `cached` boolean, required: The same request in the last 10 minutes: the same chart, not billed.
  - `usage` object, required
    - `cost_usd` number, required
    - `mode` 'ultra' | 'fast' | 'normal' | 'deep' | 'data', nullable, required
    - `queries` integer, required
    - `duration_ms` integer, required
  - `warnings` object[], required
    - `code` string, required
    - `message` string, required

## Other responses

- `201`: The chart that was created.
- `402`: Payment required: `insufficient_credits` (no credit left), `spend_limit_reached` (the key hit its monthly limit) or `budget_too_small`.
- `422`: `insufficient_data`: no articles about the topic in the period. Not billed.
- `default`: Error (RFC 9457). In English unless the request sends `Accept-Language: es`.

---

[API](https://skmtc.dev/typesearch/apis/typesearch-news-search-api.md) · [All operations](https://skmtc.dev/typesearch/apis/typesearch-news-search-api/llms.txt) · [OpenAPI document](https://skmtc.dev/typesearch/apis/typesearch-news-search-api/revisions/b270b9a9c6a5?raw)
