Language examples

Render the same current request from TypeScript or any HTTP client.

Every example sends the same ChartDocument. Keep API keys server-side and use POST /validate when you want structured diagnostics without consuming a render.

Node / TypeScript SDK

pnpm add @szum-io/sdk
import { writeFile } from "node:fs/promises";

import { Szum, type ChartDocument } from "@szum-io/sdk";

const request = {
  "config": {
    "type": "column",
    "category": {
      "field": "quarter"
    },
    "values": {
      "type": "long",
      "field": "revenue"
    }
  },
  "data": [
    {
      "quarter": "Q1",
      "revenue": 42
    },
    {
      "quarter": "Q2",
      "revenue": 58
    }
  ],
  "output": {
    "format": "svg"
  }
} satisfies ChartDocument;

const apiKey = process.env.SZUM_API_KEY;

if (!apiKey) {
  throw new Error("SZUM_API_KEY is required");
}

const szum = new Szum({ apiKey });
const image = await szum.render(request);
await writeFile("chart.svg", image);

The SDK adds the current chart version it was generated with when config.version or version is omitted.

Save and update a document

const saved = await szum.charts.create(request);

const state = await szum.charts.getDocumentState(saved.id);

if (state.document) {
  await szum.charts.update(saved.id, {
    ...state.document,
    config: { ...state.document.config, title: "Updated revenue" },
  });
}

Python

import json
import os
import requests

document = json.loads(r"""{
  "version": "2026-09-26",
  "config": {
    "version": "2026-09-26",
    "type": "column",
    "category": {
      "field": "quarter"
    },
    "values": {
      "type": "long",
      "field": "revenue"
    }
  },
  "data": [
    {
      "quarter": "Q1",
      "revenue": 42
    },
    {
      "quarter": "Q2",
      "revenue": 58
    }
  ],
  "output": {
    "format": "svg"
  }
}""")

response = requests.post(
    "https://szum.io/chart",
    headers={"Authorization": f"Bearer {os.environ['SZUM_API_KEY']}"},
    json=document,
    timeout=30,
)
response.raise_for_status()

with open("chart.svg", "wb") as output:
    output.write(response.content)

Go

package main

import (
  "bytes"
  "fmt"
  "io"
  "net/http"
  "os"
  "time"
)

func main() {
  body := []byte(`{
  "version": "2026-09-26",
  "config": {
    "version": "2026-09-26",
    "type": "column",
    "category": {
      "field": "quarter"
    },
    "values": {
      "type": "long",
      "field": "revenue"
    }
  },
  "data": [
    {
      "quarter": "Q1",
      "revenue": 42
    },
    {
      "quarter": "Q2",
      "revenue": 58
    }
  ],
  "output": {
    "format": "svg"
  }
}`)

  apiKey := os.Getenv("SZUM_API_KEY")
  if apiKey == "" {
    panic("SZUM_API_KEY is required")
  }

  request, err := http.NewRequest(http.MethodPost, "https://szum.io/chart", bytes.NewReader(body))
  if err != nil {
    panic(err)
  }
  request.Header.Set("Authorization", "Bearer "+apiKey)
  request.Header.Set("Content-Type", "application/json")

  client := &http.Client{Timeout: 30 * time.Second}
  response, err := client.Do(request)
  if err != nil {
    panic(err)
  }
  defer response.Body.Close()
  if response.StatusCode != http.StatusOK {
    panic(fmt.Errorf("render failed: %s", response.Status))
  }

  chart, err := io.ReadAll(response.Body)
  if err != nil {
    panic(err)
  }
  if err := os.WriteFile("chart.svg", chart, 0o644); err != nil {
    panic(err)
  }
}

Ruby

require "net/http"

uri = URI("https://szum.io/chart")
request = Net::HTTP::Post.new(uri)
request["Authorization"] = "Bearer #{ENV.fetch('SZUM_API_KEY')}"
request["Content-Type"] = "application/json"
request.body = <<~'JSON'
  {
    "version": "2026-09-26",
    "config": {
      "version": "2026-09-26",
      "type": "column",
      "category": {
        "field": "quarter"
      },
      "values": {
        "type": "long",
        "field": "revenue"
      }
    },
    "data": [
      {
        "quarter": "Q1",
        "revenue": 42
      },
      {
        "quarter": "Q2",
        "revenue": 58
      }
    ],
    "output": {
      "format": "svg"
    }
  }
JSON

response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) do |http|
  http.request(request)
end
raise response.body unless response.is_a?(Net::HTTPSuccess)

File.binwrite("chart.svg", response.body)

curl

curl 'https://szum.io/chart' \
  --fail \
  --max-time 30 \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
  "version": "2026-09-26",
  "config": {
    "version": "2026-09-26",
    "type": "column",
    "category": { "field": "quarter" },
    "values": { "type": "long", "field": "revenue" }
  },
  "data": [
    { "quarter": "Q1", "revenue": 42 },
    { "quarter": "Q2", "revenue": 58 }
  ],
  "output": { "format": "svg" }
}' \
  --output 'chart.svg'

Embedding as an image

Save a document once, then use its stable image URL anywhere an image works:

<img
  src="https://szum.io/c/CHART_ID.svg"
  alt="Quarterly revenue increased from Q1 to Q2"
  width="720"
  height="480"
/>

Use /e/CHART_ID in an iframe for a responsive interactive chart. Updating the saved document keeps both URLs stable.

Any language that can send JSON and read image bytes can use the HTTP API. Generate the current config type from the ChartConfig JSON Schema, then place it inside the document envelope shown above.

On this page