Docs menu
JavaScript SDK
Draw charts, sign chart URLs and store charts from JavaScript or TypeScript, and put charts in React emails.
The JavaScript and TypeScript SDK draws charts, signs chart URLs and stores charts with your key. It has no dependencies and runs on your server: Node 20 and up, and edge runtimes such as Vercel's and Cloudflare Workers. It's published as ES modules only (import, or require() on Node 20.19 and up) and its types need TypeScript 5 and up.
npm install @lglab/chartshotSet up the client
Create a key on the Keys page and keep its secret key and public id in your server's environment, as CHARTSHOT_SECRET_KEY and CHARTSHOT_PUBLIC_ID. Then make one client, in a file such as charts.ts:
import { Charts, type ChartSpec } from "@lglab/chartshot";
export const charts = new Charts({
secretKey: process.env.CHARTSHOT_SECRET_KEY!,
publicId: process.env.CHARTSHOT_PUBLIC_ID,
});The public id is needed only to sign URLs. The secret key must stay on your server, so use the SDK in server code only, never in a browser bundle.
ChartSpec types every field of the spec, with each field's description, so your editor completes and checks specs as you write them:
const spec: ChartSpec = {
type: "line",
data: {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
series: [{ name: "Signups", values: [12, 18, 15, 22, 30] }],
},
options: { title: "Weekly signups" },
};Draw a chart
render sends the spec to POST /v1/render and returns the image's bytes, for code that attaches, uploads or saves it:
import { writeFile } from "node:fs/promises";
const { image, alt } = await charts.render(spec);
await writeFile("signups.png", image);alt describes the chart in words. Use it as the image's alt text.
Sign a URL
signUrl returns a chart URL signed with your key, for an <img> in an email, a Slack message or a page. It needs no request, so it's instant:
const url = charts.signUrl(spec); // works for 90 days
const short = charts.signUrl(spec, { expiresIn: "7d" });
const forever = charts.signUrl(spec, { expiresIn: null });expiresIn takes seconds, or a number with s, m, h or d. The 90-day default means a URL that leaks stops drawing on your plan. Signed URLs come with Pro and up; see keys and signed URLs for how they work.
A URL over 8 KB throws, since some email clients refuse long URLs. Store the chart instead.
Store a chart
create draws the chart, stores the image and returns a short URL. It's the best choice for emails: the URL is short, the image is drawn once, and it keeps working after you change your key.
const chart = await charts.create(spec);
// { id, url: "https://c.chartshot.dev/….png", format, width, height, alt, expiresAt }
await charts.deleteChart(chart.id);Stored charts come with Pro and up, and are kept for 90 days on Pro and a year on Team and Business.
Charts in React and react-email
ChartImage renders an <img> with a signed URL, the chart's width and height, and alt text:
import { ChartImage } from "@lglab/chartshot/react";
import { Body, Html, Text } from "@react-email/components";
import { charts } from "./charts";
export default function WeeklyReport({ signups }: { signups: number[] }) {
return (
<Html>
<Body>
<Text>Here are this week's signups.</Text>
<ChartImage
charts={charts}
spec={{
type: "bar",
preset: "email",
data: {
labels: ["Mon", "Tue", "Wed", "Thu", "Fri"],
series: [{ name: "Signups", values: signups }],
},
options: { title: "Weekly signups" },
}}
/>
</Body>
</Html>
);
}It signs as it renders, with no request, so it works anywhere React renders on a server. The alt text is the alt prop if you pass one, else the spec's alt, else the chart's type and title, such as "Bar chart: Weekly signups". render and create return a fuller description. Other props, such as style, go to the <img>.
Usage
const usage = await charts.usage();
// { plan: "pro", renders: { used: 1240, included: 10000, limit: 11000, remaining: 8760 }, … }It returns the same as GET /v1/usage.
Errors and warnings
When the API refuses a request, the SDK throws a ChartshotError with the API's code and message, the HTTP status, issues listing each field at fault, the requestId to quote to support, and retryAfter in seconds for rate_limited:
import { ChartshotError } from "@lglab/chartshot";
try {
await charts.render(spec);
} catch (error) {
if (error instanceof ChartshotError && error.code === "invalid_spec") {
console.error(error.issues); // [{ path: "data.series[0].values", message: "…" }]
}
throw error;
}The error codes are in the API reference.
Fields the spec sets that Chartshot doesn't know don't stop the chart. They are ignored, returned as warnings from render and create, and logged with console.warn. Pass onWarnings to the client to handle them yourself:
const charts = new Charts({
secretKey: process.env.CHARTSHOT_SECRET_KEY!,
onWarnings: (warnings) => logger.warn({ warnings }, "chart spec has unknown fields"),
});Options
| Option | What it does |
|---|---|
secretKey | Your secret key, sk_live_…. Required. |
publicId | Your key's public id, pk_live_…. Needed by signUrl and ChartImage. |
baseUrl | The API's address. Defaults to https://api.chartshot.dev. |
fetch | The fetch to call the API with. Defaults to the global one. |
onWarnings | Called with the fields a spec set that were ignored. Defaults to console.warn. |