The whole API
Two URLs per chart: one that writes, one that reads. No SDK and no header to set — the write key is in the path, and everything below is curl.
Sending readings
One call is one sample: one slot on the x axis, carrying a number for each name it mentions. Every name is a series and a name the chart has not seen makes one, so there is nothing to declare first — and one number is just a call that names one.
/i/{write_key} curl -fsS 'https://sparkline.ivashkin.dev/i/KEY?api=41&web=17&worker=8' curl -fsS -d api=41 -d web=17 https://sparkline.ivashkin.dev/i/KEY curl -fsS -H 'content-type: application/json' -d '{"api":41,"web":17}' https://sparkline.ivashkin.dev/i/KEY In JSON the names may also sit nested under values. It means the same thing.
/i/{write_key} The same endpoint, short enough for a Makefile. With numbers it records a sample; with none it reports how full the chart is and writes nothing.
curl -fsS 'https://sparkline.ivashkin.dev/i/KEY?api=41&web=17' /i/{write_key} Empties the chart and keeps everything else: both URLs, the series, their colors, and anything embedding it.
curl -fsS -X DELETE https://sparkline.ivashkin.dev/i/KEY - api=-
- A dash, or an empty value, is a gap rather than a zero: the line breaks across it and the stack leaves no segment. So
?cpu=$CPUwithCPUunset records the moment rather than a floor nobody measured. - key
- The one name that is not a series — it is the write key, and it arrives in the same bag as the readings.
- when
- Not yours to send. The x axis is the clock, which is what lets a call be nothing but the numbers it carries.
What comes back
The same shape whether it worked or not, so jq -e .ok is a complete health check.
{
"ok": true,
"chart": "requests by service",
"values": { "api": 41.0, "web": 17.0 },
"created": ["web"],
"points": 88,
"capacity": 256,
"series": ["api", "web"],
"url": "https://sparkline.ivashkin.dev/g/k3n8pq7wv2xa"
} values is what that call recorded, always a map — one name or six — and absent where it recorded nothing. created names the series that call invented, which is the line to watch when a chart grows a track nobody meant. points counts samples rather than numbers, so a chart of four series still holds this many moments.
- 404
- No chart has that write key — and the same answer for a key of the wrong shape, deliberately.
- 422
- Nothing usable to record. Infinities and
NaNare refused rather than stored, as is a call naming more series than the chart may have — that one is refused whole, and the body lists the names the chart already has. - 429
- Too fast. Carries
Retry-Afterand aretry_afterin seconds, sosleep $(curl -s … | jq -r .retry_after)is a complete backoff.
Reading a chart
The read code is public and cannot write. One address, four representations, chosen by the extension on it.
https://sparkline.ivashkin.dev/g/CODE https://sparkline.ivashkin.dev/g/CODE.svg https://sparkline.ivashkin.dev/g/CODE.json https://sparkline.ivashkin.dev/g/CODE.js ?w= and ?h= fit it where it is going, clamped rather than refused; below about 320 × 120 the axis labels are dropped, since at that size they are larger than the plot. ?theme=light repaints the furniture for a pale page, and the data keeps its hue.
 The JSON is a table: series names the columns, samples is a row per call, and null is a series that call did not measure.
Live on a page
Where an <img> will not do — a status page, a dashboard, a wiki — one tag draws the chart rather than a picture of it, and hovering a sample gives its moment and a reading per series.
<script src="https://sparkline.ivashkin.dev/g/CODE.js"></script> The chart is inside what that address answers, so it appears where the tag stands rather than a moment later, in a shadow root the page's stylesheet cannot reach into. Several tags on one page each work.
Nothing is read off the tag. The three knobs above work here too, plus ?refresh=60 to fetch it again every minute — floored at ten seconds, paused in a background tab — and ?fill=1 to take the width it is given.
Limits, and why
- Samples a chart
- A new chart holds 256, and each carries its own from there — set in its editor, up to 256 on the free plan and 4096 on Premium. The oldest is dropped as the next arrives, in the same transaction, so a chart is never briefly over its window.
- Series a chart
- 3 on the free plan, 12 on Premium. A key with more entries than that is longer than the chart it describes.
- How fast
- 120 calls at once, then 120 a minute per write key — calls rather than numbers, so one carrying six series costs what one carrying a single number costs.
- Name lengths
- 40 characters for a series name. Longer ones are cut, not refused.
- Authentication
- The write key, and nothing else. Anybody holding one can add readings to that chart and do nothing else with it. Rotating it is one click.