Chartlink Brands API
The Brands API from Chartlink — 10 operation(s) for brands.
The Brands API from Chartlink — 10 operation(s) for brands.
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-brands-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 Brands 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: Brands
paths:
/api/brands/schema:
get:
operationId: getBrandTokensSchema
summary: Brand settings JSON Schema — the machine-readable truth for every setting
description: 'A brand is DEFAULT SETTINGS: the same shape as a chart''s config, minus the two things a brand cannot own — the words, and the type-specific chart options.'
responses:
'200':
description: JSON Schema for brand settings
tags:
- Brands
/api/brands:
get:
operationId: listBrands
summary: 'List brands: the workspace''s own, then those shared with it (access: owner |…'
responses:
'200':
description: Brands
tags:
- Brands
post:
operationId: createBrand
summary: Create a brand
requestBody:
content:
application/json:
schema:
type: object
properties:
slug:
type: string
pattern: ^[a-z0-9-]+$
description: Stable handle agents pass as `brand`
name:
type: string
minLength: 1
tokens:
type: object
additionalProperties:
nullable: true
default: {}
description: Default settings for every chart using this brand — the same shape as a chart config, minus the words and the type-specific chart options — GET /brands/schema for the full shape. A chart's own config overrides these key by key.
isDefault:
type: boolean
default: false
description: The workspace's default brand. A workspace's first brand is its default either way
start:
type: string
enum:
- starter
- blank
- clean
- pop
- dark
- warm-serif
- swiss
- forest
- sunset
- newsroom
- midnight-serif
- vintage
- candy
- neon
- soft
- academic
- tropical
- mono
default: starter
description: 'Where a brand with no settings of its own begins: a starter look to change from there — "clean" (crisp sans on white), "pop" (sunflower yellow, black type, punchy colours), "dark" (deep navy canvas, bright data), "warm-serif" (heavy serif headlines on warm paper), "swiss" (heavy grotesque, black and red), "forest" (deep green canvas, warm serif), "sunset" (peach canvas, vivid warm colours), "newsroom" (bold condensed headlines, a red accent), "midnight-serif" (charcoal and gold, elegant serif), "vintage" (slab serif on cream, retro colours), "candy" (rounded type, bright candy colours), "neon" (black canvas, monospace, glowing colours), "soft" (rounded type, pastel colours), "academic" (book serif, quiet greys and one blue), "tropical" (deep teal canvas, tropical colours), "mono" (monospace, framed, technical); "starter" is "clean" (the default); "blank" is the engine''s bare defaults. GET /api/try/looks draws them. Ignored when tokens or templates are given'
darkEnabled:
nullable: true
description: 'Removed (2026-10-27): a brand has one look — sending it is refused with what to do instead'
dark:
nullable: true
description: 'Removed (2026-10-27): a brand has one look — sending it is refused with what to do instead'
templates:
type: object
additionalProperties:
type: object
additionalProperties:
nullable: true
default: {}
description: 'Per starter template (bar, line, choropleth, …): settings charts from that template get over the brand — any key the chart type takes, style only.'
required:
- slug
- name
responses:
'201':
description: Created brand
tags:
- Brands
/api/brands/{idOrSlug}:
get:
operationId: getBrand
summary: Get a brand by id or slug
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
responses:
'200':
description: Brand
tags:
- Brands
patch:
operationId: updateBrand
summary: 'Update a brand (tokens and templates deep-merge; replace: true replaces them)'
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
expectedVersion:
type: integer
minimum: 1
name:
type: string
tokens:
type: object
additionalProperties:
nullable: true
templates:
type: object
additionalProperties:
type: object
additionalProperties:
nullable: true
isDefault:
type: boolean
dark:
nullable: true
description: 'Removed (2026-10-27): a brand has one look — sending it is refused with what to do instead'
darkEnabled:
nullable: true
description: 'Removed (2026-10-27): a brand has one look — sending it is refused with what to do instead'
changes:
type: array
items:
type: object
properties:
path:
type: string
value:
nullable: true
required:
- path
description: 'The changes setup or POST /brands/{slug}/vet returned, as they are: [{path, value}] — "family.<id>.…" a chart type, the rest the base; null removes. Instead of tokens/templates'
replace:
type: boolean
default: false
description: 'true: tokens and templates REPLACE what is stored instead of deep-merging — how a key is removed.'
required:
- expectedVersion
responses:
'200':
description: Updated brand
'409':
description: Version conflict
tags:
- Brands
delete:
operationId: deleteBrand
summary: Soft-delete a brand (assets fall back to the default brand)
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
responses:
'200':
description: Deleted
tags:
- Brands
/api/brands/{idOrSlug}/guide:
get:
operationId: brandGuide
summary: Every brand setting by path — kind, range, default, what it also sets — and…
description: 'The same catalogue the studio''s own AI works from. family= lists one chart type''s settings (family..… paths), family=all every type''s; without it, the base settings and the list of chart types. Change settings by path with POST /brands/{slug}/vet then PATCH with the vetted changes (MCP: edit_brand does both).'
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
- schema:
type: string
required: false
name: family
in: query
responses:
'200':
description: The guide
tags:
- Brands
/api/brands/{idOrSlug}/vet:
post:
operationId: vetBrandChanges
summary: Check brand changes by path as the studio does — nothing is saved; PATCH the…
description: 'Each change is checked against the settings guide: fonts against Google Fonts (and their weights), values against the setting''s kind, logos fetched from a public URL. Paths that also set others are expanded. Returns the changes to PATCH, what was applied, what was refused and why, and weights adjusted to ones the family ships.'
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
changes:
type: array
items:
type: object
properties:
path:
type: string
value:
nullable: true
required:
- path
minItems: 1
maxItems: 200
required:
- changes
responses:
'200':
description: Vetted changes
tags:
- Brands
/api/brands/{idOrSlug}/preview:
post:
operationId: previewBrandExample
summary: Draw one of the brand's example charts as a PNG — from the stored brand, or…
description: 'Examples: line-annotated, line-multi, line-highlight, line-projection, line-band, area-surplus, area-single, area-stacked, area-share, area-overlap, area-highlight, area-stream, bar-columns, bar-grouped, bar-ranked, bar-stacked, bar-share, bar-change, bar-pyramid, bar-histogram, scatter-all, scatter-plain, scatter-bubbles, scatter-emphasis, scatter-reference, scatter-connected, dumbbell-change, dumbbell-three, dot-plot, lollipop, map-world, map-europe, map-us-states, map-africa, map-us-counties, map-uk-houses, map-classes, map-labels, map-diverging, map-pins, map-symbols, slope-change, pie-donut, waterfall-steps, heatmap-grid, candle-daily. The same picture the studio shows; look at it before saving a brand.'
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
example:
type: string
aspect:
type: string
enum:
- '2:1'
- '16:9'
- '3:2'
- '4:3'
- '1:1'
- '4:5'
- '3:4'
- '9:16'
default: '4:3'
width:
type: integer
minimum: 320
maximum: 1600
default: 800
tokens:
type: object
additionalProperties:
nullable: true
templates:
type: object
additionalProperties:
type: object
additionalProperties:
nullable: true
changes:
type: array
items:
type: object
properties:
path:
type: string
value:
nullable: true
required:
- path
description: 'Changes from setup or vet, laid over the settings above (or the stored brand): see them before PATCHing them'
required:
- example
responses:
'200':
description: image/png
'400':
description: Unknown example or invalid settings
tags:
- Brands
/api/brands/{idOrSlug}/setup:
post:
operationId: setupBrand
summary: 'Set a brand up in one go from screenshots, words, a logo or a website: a strong…'
description: 'Give any mix of: screenshots of anything (charts you like, your own old charts, a page, slides, a style guide; data: URLs, at most 6, ~1.5 MB each), text (instructions; they win when inputs disagree), a logo (data: URL) and a website (read for fonts, colours and a logo). A strong model works through every group of settings in order (Canvas, Colours, Layout, Kicker, Title, Title marker, Description, Axis labels, Unit labels, Grid, Data labels, Numbers, Legends, Annotations, Source, Brand, Bar charts, Line charts, Area charts, Slope charts, Pie and donut charts, Scatter plots, Dot and dumbbell charts, Waterfall charts, Candlestick charts, Heatmaps, Maps) and ends each with a decision, then renders examples, compares and fixes. It takes one to three minutes. Returns the {path, value} changes ("family.." family settings), a decision per group, what was refused and why, and a short reply. Nothing is saved: apply the changes and PATCH the brand when happy. 10 setups per workspace per day, within the monthly AI allowance.'
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
text:
type: string
maxLength: 8000
default: ''
images:
type: array
items:
type: string
maxLength: 2000000
maxItems: 6
default: []
url:
type: string
format: uri
logo:
type: string
maxLength: 1000000
measured:
type: string
maxLength: 1500
description: 'Colours measured from the screenshots'' pixels (the studio measures them): taken as exact'
tokens:
type: object
additionalProperties:
nullable: true
description: The settings being edited (the unsaved draft); default the stored brand
templates:
type: object
additionalProperties:
type: object
additionalProperties:
nullable: true
responses:
'200':
description: Changes and decisions
'400':
description: Nothing given
'403':
description: View-only brand
'429':
description: Daily limit or AI allowance
'503':
description: AI not set up
tags:
- Brands
/api/brands/{idOrSlug}/shares:
get:
operationId: listBrandShares
summary: Who this brand is shared with, and pending invitations (the owning workspace)
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
responses:
'200':
description: Shares
tags:
- Brands
post:
operationId: shareBrand
summary: Share this brand with someone by email (owners of the brand's workspace).
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
requestBody:
content:
application/json:
schema:
type: object
properties:
email:
type: string
format: email
role:
type: string
enum:
- editor
- viewer
default: viewer
required:
- email
responses:
'201':
description: 'Invited: the link, and whether it was emailed'
tags:
- Brands
/api/brands/{idOrSlug}/shares/{shareId}:
delete:
operationId: unshareBrand
summary: 'End a share: the owner takes it back, or the receiving workspace lets it go'
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
- schema:
type: string
required: true
name: shareId
in: path
responses:
'200':
description: Ended
tags:
- Brands
/api/brands/{idOrSlug}/invites/{inviteId}:
delete:
operationId: revokeBrandInvite
summary: Withdraw a pending brand invitation
parameters:
- schema:
type: string
required: true
name: idOrSlug
in: path
- schema:
type: string
required: true
name: inviteId
in: path
responses:
'200':
description: Withdrawn
tags:
- Brands