Chartlink Data API
The Data API from Chartlink — 1 operation(s) for data.
The Data API from Chartlink — 1 operation(s) for data.
Every API here is available over the APIs.io API and to AI agents over MCP.
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
find_apisBrowse and filter every API in the catalog.get_api_artifactsOne API's artifacts, grouped by type.get_openapiThe primary OpenAPI for this API.find_similar_apisAPIs that look like this one.apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.resolveTurn a domain, URL or GitHub org into the provider it belongs to.find_cohortsEvery scored population of providers in the catalog.curl "https://apis.io/api/v1/apis/chartlink-app:chartlink-app-data-api"
curl "https://apis.io/api/v1/apis?limit=25"
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Free tier, no form to fill in. Signing in shares your email address with us — we store it to create your key and to recognise you if you sign in with another provider. See our Privacy Policy and Terms.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: chartlink Data API
version: 0.1.0
description: 'chartlink — a platform for charts and maps, made in your brand, with live-updating embed links. NOT CONNECTED YET? In an AI app that takes MCP connectors (Claude and others): your human adds https://chartlink.app/mcp as a
connector, signs in and picks a workspace — no key, nothing pasted into the chat. In Claude Code or a script:
an API key from their studio (Workspace → API keys for Claude Code and scripts), sent as Authorization: Bearer. Either way you work in their workspace — their brands and charts. Every chart carries urls.studio, where they
fine-tune it. A share URL is one published chart. Credits are GET
/api/billing-info and a checkout link from POST /api/checkout-link, which you hand to your human. WHAT AN ASSET IS
CHART TYPES: line, bar, area, scatter, dumbbell, slope, heatmap, choropleth, symbol-map, pie, treemap, waterfall, candlestick
(GET /api/asset-types describes each; GET /api/asset-types/{type}/schema is the contract — read it before the first create.)
An asset = type + data + config (+ brand). data holds typed columns and row-arrays; config holds
everything about presentation (title and the other text elements, encoding, chart options). They are updated independently:
PUT /assets/{id}/data replaces the numbers; PATCH /assets/{id} deep-merges config. Never resend
what you are not changing. There is no table type (removed): a ranking is a sorted "bar" chart with
value labels, a row-by-row comparison a "dumbbell" (one point per row = a dot plot) with row labels. KICKER AND TITLE MARKER: kicker {text, font, align, box} is a short line above the title (a section or topic
that ties charts together; default a small bold line in the emphasis colour). title.marker {position: "top" |
"left" | "end" | "none", shape: "bar" | "dot" | "square", hang, color, length, thickness, gap} draws one mark
above the title, beside it (a bar spans the title, a dot or square sits at its first line; hang: true puts it
in the margin instead of pushing the text right) or after the last word ("end"; skipped when the title already
ends in . ? ! … : ; so never type a mark into the title). gap is the space to the text everywhere. Both are
brand-settable (kicker''s style, the marker); the kicker''s words are per chart. kicker.show: false (usually on
a brand) hides kickers whatever their text; description.show: false does the same for descriptions. POINTS (line, area): chart.points is the one way to put dots on series — a list of rules {series?, at, label?,
labelPosition?, align?, font?, fill?, ring?, radius?}. A label uses the brand''s data-label style; font overrides it
key by key, and font.color "series" (here or in the brand''s data-label colour) takes the series'' colour. A note in
words with the annotation look is an annotation, not a point label. at: "all" | "first" | "last" | "max" | "min" | [x values]. label fills in
{value}, {series}, {x}: [{at: "max", label: "Peak {value}"}], [{at: [2008, 2020], label: "{x}"}]. markers
("none" | "end" | "all") is the end dot, the brand''s house style (default "end"): a chart''s own points are added to it,
so set markers "none" to drop it; points: [] draws no points at all. LINE BREAKS: "
" breaks a line in the words you write — title, kicker, description, source, annotations,
reference-line and highlight labels, point labels, and series names in line/area end labels (which then take
the room of their lines). A multi-line point label aligns by its side (centred above/below) unless
points[].align says "left" | "center" | "right"; annotations and free text have align too. Legends and
tooltips show a series name on one line. AXES: a value axis takes min/max, ticks {count | values: [0, 50, 100] — ticks and gridlines exactly there}, ticks.format,
ticks.labels.text: the words at those values, one per value (["", "50", "100%"]; "" leaves a tick unlabelled, its
gridline stays) — omit it for each value formatted.'
servers:
- url: https://chartlink.app
tags:
- name: Data
paths:
/api/data/tidy:
post:
operationId: tidyData
summary: Read messy pasted text (a table copied from a page, a PDF, prose with numbers)…
description: 'An AI model moves the values into a header row and rows, one column per series — no unit conversion, no computed values. Numbers use ''.'' decimals and no separators; dates are YYYY, YYYY-MM or YYYY-MM-DD; names (places included) as written. notInSource lists every number in the result that does not appear in the text — check those before charting. title is the text''s own heading and unit the unit the values share (taken out of the column names). draft is a first take on the chart — view (a starting point id), title, description, emphasize, alternatives (no notes) — each checked against the text (a number or name it lacks is dropped); use a view only if the table fits it. Send the table to POST /assets as data. At most 20,000 characters and 60 calls per workspace per hour. Text that is already tab- or comma-separated with a header row does not need this. Send for: a starting point id to have the table arranged for that chart (what it needs is its contract line).'
requestBody:
content:
application/json:
schema:
type: object
properties:
text:
type: string
minLength: 1
for:
type: string
description: 'A starting point id: arrange the table for that chart'
required:
- text
responses:
'200':
description: The table
'400':
description: Empty or too long
'422':
description: No table in the text
'429':
description: Hourly limit reached
'502':
description: The AI service failed
'503':
description: AI tidying not set up
tags:
- Data