datalink.ac

The datalink specification

A draft. It exists to make one idea checkable: a URL can carry data, and a renderer can turn that URL into both a picture for a person and a spec for a machine. Everything below is either a promise a renderer must keep or a question we have not settled yet.

Status: draft v0.1 · last revised 2026-11-12 · discussion is open on the repository issue.

1 · Definitions

datalink
A URL whose parameters carry the complete data required to render something. Not a pointer to data — the data itself.
data spec
The canonical, serialised description of that data: what was measured, in what units, over what.
renderer
A service that turns a datalink into an output for a human, and — by the invariants below — into the same data spec for a machine.
context
What a model is given to reason over. A datalink is context. It does not point at context, and it does not require a fetch-then-describe round trip.

2 · Anatomy

https://datalink.ac/d?type=pie&labels=TS,Py,Go&values=4821,2312,980&v=1
       └─ host ──┘└path┘└────────── parameters ──────────────┘ └ver┘
  • host — the renderer. A different host may implement the same contract.
  • path — the kind of rendering. /d covers the flat-parameter renderers; /d/arch2, /d/seq, /d/erd … cover the structural ones.
  • parameters — flat, named, URL-encoded. They are the data.
  • v — pins the renderer version, making the output immutable.
Two rules about parameters. First, they must be sufficient on their own: a renderer may not need to look anything up, ask anyone, or keep a session in order to draw. Second, they must be safe to publish: a datalink is a public statement of its own contents.

3 · Invariants

These five promises are the specification. A renderer that breaks one is not a datalink renderer.

I1 · Self-contained The link carries the data. Rendering it requires no lookup, no login, no session and no stored state on the server.
I2 · Dual-audience One link yields two readings of the same thing: a rendering for a human and a machine-readable spec for an agent. Neither is derived from the other by a lossy step.
I3 · Parametric The output is a pure function of the parameters and the version. No clock, no randomness, no user profile, no “latest” behaviour hidden behind a stable link.
I4 · Versioned A version can be pinned in the link (v=N). A pinned link renders the same bytes forever; an unpinned link tracks the newest renderer and says so.
I5 · Lossless The output embeds the spec it was rendered from. Parsing the output recovers the spec, so a picture can always be turned back into numbers.

4 · The data spec

The canonical form is JSON. Two encodings are in use, and they must agree:

  • Flat parameters — labels=A,B,C, values=1,2,3. Readable by eye, trivial for an agent to compose, no escaping puzzles. This is the default.
  • d= — URL-encoded JSON, for anything nested. Same spec, one blob.
// one series
{"title":"","data":[{"label":"A","value":1},{"label":"B","value":2}]}

// several series
{"labels":["A","B"],"series":[{"name":"x","values":[1,2]},{"name":"y","values":[3,4]}]}

// a flow
{"labels":["A","B"],"links":[{"from":"A","to":"B","value":30}]}

A spec says what was measured. It does not say how it should be drawn — that is the renderer's business, and it is why one spec can appear as a chart, a table, a calendar or a slide.

5 · Renderers

The registry is open. These are the kinds that exist today:

KindPathParameters
chart/d?type=pie, bar, hbar, line, area, radar, gauge, scatter, combo, sankey, butterflylabels, values, series, title, unit
structure/d/arch2, /d/seq, /d/uc, /d/dataflow, /d/lifecycle, /d/erd, /d/classn=, e=, b=
diagram/d/mindmap, /d/mermaid, /d/ganttn=, m=
table/d?type=tablecols=, rows=
calendar/d?type=calendarstart=, ev=
deck/deckdata= (markdown)

Renderers may add kinds. The invariants are not negotiable: a new kind that cannot satisfy I2 and I5 is not a datalink renderer.

6 · The agent contract

What an agent may rely on, and what it must never do.

May

  • Fetch the link to get a rendering — and then not read it as a picture.
  • Fetch the data view of the same link to get the spec verbatim.
  • Rewrite the parameters to obtain a new link, then fetch that.
  • Quote the link it used, so a human opens exactly what the agent saw.

Must not

  • Recover values from pixels — no OCR, no eyeballing, no “approximately”.
  • Silently round, rescale or re-order the data it was given.
  • Mutate anything on the server to make a link work. Links are pure.
The sentence that carries the whole idea: give the agent the link, and ask for the numbers — not the picture. Everything else is detail.

7 · HTTP semantics

  • GET, cacheable. The renderer decides freshness; unpinned links are short-lived, pinned links are immutable.
  • Version pinning — v=N makes the bytes stable, so a link pasted into a document stays correct.
  • Short links — a renderer may accept the same spec by POST and answer with a short, stable URL. The same data must always yield the same short link; that is what makes them shareable rather than opaque.
  • Errors — a 4xx with plain text and a corrected example. A renderer that cannot explain itself is not usable by an agent.
  • The data view — the spec must be reachable as JSON from the same link. This site exposes it at /d.json; content negotiation on Accept is an open question below.

8 · Privacy

A datalink is public by construction. Anyone holding the string holds the data — and the string travels further than data usually does: chat logs, referrer headers, browser history, CDN caches, screenshots of address bars, issue trackers.

  • Never put secrets, tokens, personal data or internal identifiers in a link.
  • A short link hides the data, not the existence of the data. It is not a privacy tool.
  • Query strings are cached and logged. If a parameter is sensitive, it should not be a parameter.
  • Rule of thumb: if it should not appear in a screenshot of somebody's address bar, it does not belong in a datalink.

This section is a starting point, not a finished policy. The wider question — what a public data link means for the people whose data it describes — is tracked in the repository issue and in the blog.

9 · Open questions

  1. Should the spec be versioned separately from the renderer? A pinned renderer still needs a pinned grammar.
  2. Should a spec be signed — so an agent can tell a chart from a forgery?
  3. What happens to data too large for a URL, and what is the privacy cost of storing it server-side?
  4. Should there be a public registry of renderers, so “a datalink” is a standard rather than a convention?
  5. Should one link negotiate its output by Accept — SVG for a browser, JSON for an agent — instead of a second path?
  6. How do we express uncertainty? A chart of estimates is not a chart of facts, and the spec should be able to say so.

Answering these is the point of the draft. The discussion is open in the repository issue.