[{"data":1,"prerenderedAt":141},["ShallowReactive",2],{"$f1jq9a8u9eicwa":3},{"site":4,"operations":5,"renders":134,"cacheMinutes":137,"dataMax":138,"dataCsv":139,"keys":140},"https:\u002F\u002Fchartjuice.com",{"render_template":6,"render_image":73,"create_image_url":108},{"name":7,"title":8,"description":9,"method":10,"path":11,"fields":12,"errors":58,"samples":68,"response":72},"render_template","Render a chart with new data","A saved chart drawn with data you send, in place of its own. Design the chart once in the editor, then send new numbers whenever you need the picture: it keeps its type, colors, titles and steps. The saved chart is not changed. The new data's columns are matched to the chart's by name, so it needs every column the chart is drawn from, under the same names; when one is missing the answer is `invalid_request` and names them. `ops` are applied for this image only. The answer is the image itself; send `Accept: application\u002Fjson` to get it base64-encoded in JSON instead. Counts toward the month's image renders, not the daily renders. Each different picture counts once a month: the same chart with the same data again costs nothing more.","POST","\u002Fcharts\u002F{id}\u002Frender",[13,19,24,29,33,36,41,46,50,53],{"name":14,"in":15,"type":16,"required":17,"description":18},"id","path","string",true,"The chart's id.",{"name":20,"in":21,"type":22,"required":17,"description":23},"data","body","string or array","The data to draw the chart with, in place of its own. Its columns are matched to the chart's by name. CSV or TSV as one string with a header row, or JSON rows: an array of objects (`[{\"Month\":\"Jan\",\"Sales\":4200}]`) or an array of arrays whose first row is the header.",{"name":25,"in":21,"type":26,"required":27,"description":28},"data_format","\"csv\" | \"tsv\" | \"json\"",false,"How to read `data`. Left out, a string is read as CSV or TSV (the delimiter is detected) and an array as JSON rows. `json` also takes a string holding JSON.",{"name":30,"in":21,"type":31,"required":27,"description":32},"ops","array of objects","Ops to apply after the data is in, for this image only. All apply or none do. See the op catalog (`get_op_catalog`).",{"name":34,"in":21,"type":16,"required":27,"description":35},"name","A name for the image file, used when the image is downloaded. Left out, it is `chart`.",{"name":37,"in":21,"type":38,"required":27,"description":39,"default":40},"format","\"png\" | \"svg\"","The image format.","\"png\"",{"name":42,"in":21,"type":43,"required":27,"description":44,"default":45},"scale","1 | 2 | 4","PNG only: 1, 2 or 4 times the canvas size. The image can be up to 4,000 px on a side.","1",{"name":47,"in":21,"type":48,"required":27,"description":49},"width","integer, 100 to 4,000","The canvas width in pixels, in place of the chart's own. The image is this times `scale`.",{"name":51,"in":21,"type":48,"required":27,"description":52},"height","The canvas height in pixels, in place of the chart's own. The image is this times `scale`.",{"name":54,"in":21,"type":55,"required":27,"description":56,"default":57},"transparent","boolean","Leave out the background.","false",[59,62,65],{"code":60,"status":61},"not_found",404,{"code":63,"status":64},"invalid_ops",400,{"code":66,"status":67},"image_limit_reached",429,{"curl":69,"javascript":70,"python":71},"curl -X POST \"https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Fcharts\u002F7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21\u002Frender\" \\\n  -H \"Authorization: Bearer $CHARTJUICE_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n  \"data\": [\n    {\n      \"Month\": \"Apr\",\n      \"Sales\": 6300\n    },\n    {\n      \"Month\": \"May\",\n      \"Sales\": 7100\n    }\n  ],\n  \"scale\": 2\n}' \\\n  -o chart.png","const response = await fetch('https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Fcharts\u002F7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21\u002Frender', {\n  method: 'POST',\n  headers: { Authorization: `Bearer ${process.env.CHARTJUICE_API_KEY}`, 'Content-Type': 'application\u002Fjson' },\n  body: JSON.stringify({\n    \"data\": [\n      {\n        \"Month\": \"Apr\",\n        \"Sales\": 6300\n      },\n      {\n        \"Month\": \"May\",\n        \"Sales\": 7100\n      }\n    ],\n    \"scale\": 2\n  }),\n})\nconst image = Buffer.from(await response.arrayBuffer())","import json\nimport os\nimport urllib.request\n\nrequest = urllib.request.Request(\n    \"https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Fcharts\u002F7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21\u002Frender\",\n    method=\"POST\",\n    headers={\"Authorization\": \"Bearer \" + os.environ[\"CHARTJUICE_API_KEY\"], \"Content-Type\": \"application\u002Fjson\"},\n    data=json.dumps({\"data\": [{\"Month\": \"Apr\", \"Sales\": 6300}, {\"Month\": \"May\", \"Sales\": 7100}], \"scale\": 2}).encode(),\n)\nwith urllib.request.urlopen(request) as response:\n    image = response.read()",null,{"name":74,"title":75,"description":76,"method":10,"path":77,"fields":78,"errors":98,"samples":104,"response":72},"render_image","Render a chart from data","An image of a chart you describe in the request, with nothing saved: a chart type and your data, or a whole chart spec. Use it for a picture you need once, in a report or a message, where there is no chart to keep. `ops` style it before it is drawn, as they do in `create_chart`. The answer is the image itself; send `Accept: application\u002Fjson` to get it base64-encoded in JSON instead. Counts toward the month's image renders: 100 on the Free plan and 1,000 on Pro (`image_limit_reached` after that). Each different picture counts once a month, so asking for the identical image again costs nothing more. On the Free plan the image carries a small chartjuice.com mark.","\u002Frender",[79,83,85,86,90,92,93,94,95,96,97],{"name":80,"in":21,"type":81,"required":27,"description":82},"type","\"bar\" | \"line\" | \"pie\" | \"scatter\" | \"histogram\" | \"boxplot\" | \"dotplot\" | \"sankey\" | \"radar\" | \"heatmap\"","The chart type, with `data`.",{"name":20,"in":21,"type":22,"required":27,"description":84},"The data. CSV or TSV as one string with a header row, or JSON rows: an array of objects (`[{\"Month\":\"Jan\",\"Sales\":4200}]`) or an array of arrays whose first row is the header (`[[\"Month\",\"Sales\"],[\"Jan\",4200]]`).",{"name":25,"in":21,"type":26,"required":27,"description":28},{"name":87,"in":21,"type":88,"required":27,"description":89},"spec","object","A whole chart spec, in place of `type` and `data`: what `get_chart` returns with `include=spec`. Its `advanced` must be `null`.",{"name":30,"in":21,"type":31,"required":27,"description":91},"Ops to apply, in order. All apply or none do. See the op catalog (`get_op_catalog`).",{"name":34,"in":21,"type":16,"required":27,"description":35},{"name":37,"in":21,"type":38,"required":27,"description":39,"default":40},{"name":42,"in":21,"type":43,"required":27,"description":44,"default":45},{"name":47,"in":21,"type":48,"required":27,"description":49},{"name":51,"in":21,"type":48,"required":27,"description":52},{"name":54,"in":21,"type":55,"required":27,"description":56,"default":57},[99,100,101],{"code":63,"status":64},{"code":66,"status":67},{"code":102,"status":103},"too_large",413,{"curl":105,"javascript":106,"python":107},"curl -X POST \"https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Frender\" \\\n  -H \"Authorization: Bearer $CHARTJUICE_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n  \"type\": \"bar\",\n  \"data\": \"Month,Sales\\nJan,4200\\nFeb,5100\\nMar,4800\",\n  \"ops\": [\n    {\n      \"op\": \"setTitle\",\n      \"title\": {\n        \"text\": \"Monthly sales\"\n      }\n    }\n  ],\n  \"scale\": 2\n}' \\\n  -o chart.png","const response = await fetch('https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Frender', {\n  method: 'POST',\n  headers: { Authorization: `Bearer ${process.env.CHARTJUICE_API_KEY}`, 'Content-Type': 'application\u002Fjson' },\n  body: JSON.stringify({\n    \"type\": \"bar\",\n    \"data\": \"Month,Sales\\nJan,4200\\nFeb,5100\\nMar,4800\",\n    \"ops\": [\n      {\n        \"op\": \"setTitle\",\n        \"title\": {\n          \"text\": \"Monthly sales\"\n        }\n      }\n    ],\n    \"scale\": 2\n  }),\n})\nconst image = Buffer.from(await response.arrayBuffer())","import json\nimport os\nimport urllib.request\n\nrequest = urllib.request.Request(\n    \"https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Frender\",\n    method=\"POST\",\n    headers={\"Authorization\": \"Bearer \" + os.environ[\"CHARTJUICE_API_KEY\"], \"Content-Type\": \"application\u002Fjson\"},\n    data=json.dumps({\n        \"type\": \"bar\",\n        \"data\": \"Month,Sales\\nJan,4200\\nFeb,5100\\nMar,4800\",\n        \"ops\": [{\"op\": \"setTitle\", \"title\": {\"text\": \"Monthly sales\"}}],\n        \"scale\": 2,\n    }).encode(),\n)\nwith urllib.request.urlopen(request) as response:\n    image = response.read()",{"name":109,"title":110,"description":111,"method":10,"path":112,"fields":113,"errors":127,"samples":129,"response":133},"create_image_url","Create an image link","A link that shows a saved chart as an image to anyone who has it, with no key and no sign-in: for an `\u003Cimg>` tag in an email, a doc, a dashboard or another site's page. The link is a live image. It shows the chart as it is now and changes when the chart is edited, so the picture in the email stays current. With `data`, the link draws the chart with that data in place of its own. The link is signed, so nobody can change it to show another chart. It works until its signing key is rotated or revoked on the account page, or for `expires_in` seconds if you give that. The link is for the site it was made on. Making a link costs nothing. Its picture counts toward the month's image renders once each time the chart changes, and once at the start of each month, however many people open it. On the Free plan the image carries a small chartjuice.com mark.","\u002Fimage-urls",[114,115,116,117,118,119,120,122,123],{"name":14,"in":21,"type":16,"required":17,"description":18},{"name":37,"in":21,"type":38,"required":27,"description":39,"default":40},{"name":42,"in":21,"type":43,"required":27,"description":44,"default":45},{"name":47,"in":21,"type":48,"required":27,"description":49},{"name":51,"in":21,"type":48,"required":27,"description":52},{"name":54,"in":21,"type":55,"required":27,"description":56,"default":57},{"name":20,"in":21,"type":22,"required":27,"description":121},"Data to draw the chart with in place of its own. It travels in the link, so it has to be small: up to 4,000 characters once encoded, about 3,000 characters of CSV. Its columns are matched to the chart's by name. Left out, the link is a live image of the chart: it shows the chart as it is now and changes when the chart is edited.",{"name":25,"in":21,"type":26,"required":27,"description":28},{"name":124,"in":21,"type":125,"required":27,"description":126},"expires_in","integer, 60 to 315,360,000","Seconds until the link stops working, from one minute to ten years. Left out, it works until its signing key is rotated or revoked.",[128],{"code":60,"status":61},{"curl":130,"javascript":131,"python":132},"curl -X POST \"https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Fimage-urls\" \\\n  -H \"Authorization: Bearer $CHARTJUICE_API_KEY\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\n  \"id\": \"7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21\",\n  \"scale\": 2\n}'","const response = await fetch('https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Fimage-urls', {\n  method: 'POST',\n  headers: { Authorization: `Bearer ${process.env.CHARTJUICE_API_KEY}`, 'Content-Type': 'application\u002Fjson' },\n  body: JSON.stringify({\n    \"id\": \"7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21\",\n    \"scale\": 2\n  }),\n})\nconst result = await response.json()","import json\nimport os\nimport urllib.request\n\nrequest = urllib.request.Request(\n    \"https:\u002F\u002Fchartjuice.com\u002Fapi\u002Fv1\u002Fimage-urls\",\n    method=\"POST\",\n    headers={\"Authorization\": \"Bearer \" + os.environ[\"CHARTJUICE_API_KEY\"], \"Content-Type\": \"application\u002Fjson\"},\n    data=json.dumps({\"id\": \"7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21\", \"scale\": 2}).encode(),\n)\nwith urllib.request.urlopen(request) as response:\n    result = json.load(response)","{\n  \"url\": \"https:\u002F\u002Fchartjuice.com\u002Fimg\u002F7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21.png?kid=3d2a1b0c-9e8f-4a7b-8c6d-5e4f3a2b1c0d&scale=2&sig=d2bd5b97a1f538c7cb8c860665879d38b7d5a75248202d534d21c3ed3cf0931f\",\n  \"expires_at\": null,\n  \"chart\": {\n    \"id\": \"7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21\",\n    \"name\": \"Monthly sales\",\n    \"type\": \"bar\",\n    \"url\": \"https:\u002F\u002Fchartjuice.com\u002Fcharts\u002F7b0c9f1e-6c1d-4c57-9a47-2f1f0a3b8e21\",\n    \"created_at\": \"2026-10-10T14:03:12.481923+00:00\",\n    \"updated_at\": \"2026-10-10T14:05:40.118264+00:00\"\n  }\n}",{"free":135,"pro":136},"100","1,000",5,"4,000","3,000",3,1791741570929]