Skip to main content

API Reference

Complete reference for all Chartly API endpoints. All requests should be made to the base URL https://api.chartly.dev.

Base URL

https://api.chartly.dev

Authentication

All chart rendering endpoints require authentication via one of these methods:

  • API Key Header: X-Api-Key: your_api_key
  • Signed URL: Query parameters with HMAC signature

Note: Account management (creating API keys, viewing usage analytics, billing) is handled through the Chartly Dashboard.

Chart Rendering Endpoints

POST /v1/chart

Render a chart from JSON configuration. Recommended for complex charts and server-side integrations.

Request:

POST /v1/chart
Content-Type: application/json
X-Api-Key: your_api_key

{
"chart": { /* Chart.js config */ },
"width": 600,
"height": 400,
"format": "png",
"backgroundColor": "white"
}

Parameters:

ParameterTypeRequiredDescription
chartobjectComplete Chart.js configuration
widthnumberImage width (1-2000px)
heightnumberImage height (1-2000px)
formatstringOutput format: "png" (default) or "svg"
backgroundColorstringCSS color or "transparent"

Response:

  • Success (200): Binary image data
  • Error (4xx/5xx): JSON error object

Example:

curl -X POST "https://api.chartly.dev/v1/chart" \
-H "Content-Type: application/json" \
-H "X-Api-Key: live_abc123..." \
--output chart.png \
-d '{
"chart": {
"type": "bar",
"data": {
"labels": ["Q1", "Q2", "Q3", "Q4"],
"datasets": [{
"label": "Sales",
"data": [100, 120, 115, 134],
"backgroundColor": "rgba(54, 162, 235, 0.8)"
}]
},
"options": {
"responsive": false
}
},
"width": 600,
"height": 400,
"format": "png"
}'

GET /v1/chart

Render a chart from URL parameters. Perfect for emails, Slack, and quick embeds.

Request:

GET /v1/chart?chart={json}&width=600&height=400&format=png
X-Api-Key: your_api_key

Parameters:

ParameterTypeRequiredDescription
chart or cstringURL-encoded Chart.js JSON
widthnumberImage width (1-2000px)
heightnumberImage height (1-2000px)
formatstringOutput format: "png" or "svg"
backgroundColorstringCSS color or "transparent"
sigstringHMAC signature (for signed URLs)
expnumberExpiration timestamp (for signed URLs)

Response:

  • Success (200): Binary image data
  • Error (4xx/5xx): JSON error object

Example:

# Simple chart via URL parameters
curl "https://api.chartly.dev/v1/chart?chart=%7B%22type%22%3A%22line%22%2C%22data%22%3A%7B%22labels%22%3A%5B%22A%22%2C%22B%22%2C%22C%22%5D%2C%22datasets%22%3A%5B%7B%22data%22%3A%5B1%2C2%2C3%5D%7D%5D%7D%7D&width=400&height=200" \
-H "X-Api-Key: live_abc123..." \
--output chart.png

POST /v1/chart/create

Create a permanent, signed URL for a chart. Perfect for public sharing without exposing your API key.

Request:

POST /v1/chart/create
Content-Type: application/json
X-Api-Key: your_api_key

{
"chart": { /* Chart.js config */ },
"width": 600,
"height": 400,
"format": "png",
"backgroundColor": "white"
}

Response:

{
"url": "https://api.chartly.dev/v1/chart/abc123def456"
}

Example:

curl -X POST "https://api.chartly.dev/v1/chart/create" \
-H "Content-Type: application/json" \
-H "X-Api-Key: live_abc123..." \
-d '{
"chart": {
"type": "doughnut",
"data": {
"labels": ["Red", "Blue", "Yellow"],
"datasets": [{
"data": [300, 50, 100],
"backgroundColor": ["#FF6384", "#36A2EB", "#FFCE56"]
}]
},
"options": { "responsive": false }
},
"width": 400,
"height": 400
}'

GET /v1/chart/{id}

Resolve and serve a chart created with /v1/chart/create. Cached and optimized for sharing.

Request:

GET /v1/chart/{id}

Parameters:

ParameterTypeRequiredDescription
idstringChart ID from create endpoint

Response:

  • Success (200): Cached image data
  • Not Found (404): Chart not found

Example:

curl "https://api.chartly.dev/v1/chart/abc123def456" \
--output chart.png

GET /v1/metrics/{id}

Get analytics for a specific chart including hit counts and performance metrics.

Request:

GET /v1/metrics/{id}
X-Api-Key: your_api_key

Response:

{
"hitCount": 42,
"errorCount": 2,
"avgRenderTime": 45,
"lastAccessed": "2024-01-15T10:30:00.000Z"
}

Example:

curl "https://api.chartly.dev/v1/metrics/abc123def456" \
-H "X-Api-Key: live_abc123..."

Trial API Access

POST /signup/anon

Create a trial API key without registration. Limited usage for testing.

Request:

POST /signup/anon
Content-Type: application/json

{}

Response:

{
"api_key": "trial_abc123def456xyz789"
}

Example:

curl -X POST "https://api.chartly.dev/signup/anon"

Webhooks

POST /billing/webhook

Webhook endpoint for Stripe billing events. This endpoint is called automatically by Stripe to handle subscription updates and payment events.

Health & Status

GET /v1/status

Service health check and system information.

Request:

GET /v1/status

Response:

{
"status": "healthy",
"buildHash": "abc123def456",
"kvLatency": 12,
"timestamp": "2024-01-15T10:30:00.000Z"
}

Example:

curl "https://api.chartly.dev/v1/status"

Error Responses

All error responses follow this format:

{
"error": "error_code",
"detail": "Human-readable error message"
}

Common Error Codes

CodeStatusDescription
invalid_input400Invalid request parameters
chart_required400Chart configuration missing
invalid_dimensions400Width/height out of range
unauthorized401Invalid or missing API key
forbidden403Access denied
not_found404Resource not found
rate_limit_exceeded429Too many requests
trial_limit_reached429Trial usage exhausted
internal_error500Server error
render_failed500Chart rendering failed

Rate Limiting

Rate limits vary by plan:

  • Trial: 100 total requests
  • Starter: 1,000 requests/day
  • Pro: 50,000 requests/month
  • Enterprise: Custom limits

Rate limit headers are included in responses:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 999
X-RateLimit-Reset: 1642262400

When rate limited:

HTTP/1.1 429 Too Many Requests
Retry-After: 3600

{
"error": "rate_limit_exceeded",
"detail": "Rate limit exceeded. Try again in 1 hour."
}

HTTP Request Examples

Since Chartly uses a simple REST API, you can integrate it using any HTTP client in any programming language. Here are examples for popular languages:

JavaScript/Node.js

// Using fetch (modern browsers and Node.js 18+)
const response = await fetch('https://api.chartly.dev/v1/chart', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': 'your_api_key'
},
body: JSON.stringify({
chart: {
type: 'bar',
data: {
labels: ['Q1', 'Q2', 'Q3', 'Q4'],
datasets: [{
label: 'Revenue',
data: [100, 120, 115, 134]
}]
},
options: { responsive: false }
},
width: 600,
height: 400,
format: 'png'
})
});

const chartBuffer = await response.arrayBuffer();

Python

import requests
import json

response = requests.post(
'https://api.chartly.dev/v1/chart',
headers={
'Content-Type': 'application/json',
'X-Api-Key': 'your_api_key'
},
json={
'chart': {
'type': 'line',
'data': {
'labels': ['Jan', 'Feb', 'Mar', 'Apr'],
'datasets': [{
'label': 'Sales',
'data': [12, 19, 3, 5]
}]
},
'options': {'responsive': False}
},
'width': 600,
'height': 400,
'format': 'png'
}
)

if response.status_code == 200:
with open('chart.png', 'wb') as f:
f.write(response.content)

Go

package main

import (
"bytes"
"encoding/json"
"io"
"net/http"
"os"
)

func main() {
chartConfig := map[string]interface{}{
"chart": map[string]interface{}{
"type": "pie",
"data": map[string]interface{}{
"labels": []string{"Red", "Blue", "Yellow"},
"datasets": []map[string]interface{}{
{
"data": []int{300, 50, 100},
"backgroundColor": []string{"#FF6384", "#36A2EB", "#FFCE56"},
},
},
},
"options": map[string]interface{}{"responsive": false},
},
"width": 400,
"height": 400,
"format": "png",
}

jsonData, _ := json.Marshal(chartConfig)

req, _ := http.NewRequest("POST", "https://api.chartly.dev/v1/chart", bytes.NewBuffer(jsonData))
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-Api-Key", "your_api_key")

client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
panic(err)
}
defer resp.Body.Close()

file, _ := os.Create("chart.png")
defer file.Close()
io.Copy(file, resp.Body)
}

PHP

<?php
$chartConfig = [
'chart' => [
'type' => 'doughnut',
'data' => [
'labels' => ['Desktop', 'Mobile', 'Tablet'],
'datasets' => [[
'data' => [60, 30, 10],
'backgroundColor' => ['#FF6384', '#36A2EB', '#FFCE56']
]]
],
'options' => ['responsive' => false]
],
'width' => 500,
'height' => 500,
'format' => 'png'
];

$ch = curl_init('https://api.chartly.dev/v1/chart');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($chartConfig));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'X-Api-Key: your_api_key'
]);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);

$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($httpCode === 200) {
file_put_contents('chart.png', $response);
}
?>

OpenAPI Specification

For the most up-to-date and comprehensive API documentation, including interactive examples, visit our OpenAPI documentation:

🌐 Interactive Documentation: https://api.chartly.dev

You can also download the complete OpenAPI 3.0 specification:

The OpenAPI documentation includes:

  • Interactive API explorer - Test endpoints directly in your browser
  • Complete request/response examples - For every endpoint and parameter
  • Schema definitions - Detailed parameter and response structures
  • Authentication examples - All supported auth methods
  • Error code references - Complete error handling guide

Questions? Check the troubleshooting guide or contact support.