For your report scripts
Chart Doctor API
Send a chart. Get a better chart back. Use your own OpenRouter account.
Verify your email below to get a Chart Doctor token. You also need an OpenRouter API key with credits. Model usage is billed to your OpenRouter account; API hosting is free during beta.
20 charts per rolling 24 hours, one active repair per account. Upload PNG or JPEG up to 8 MB. Results expire after 24 hours.
Let your coding agent set it up
Copy this prompt into your coding agent. It can install a client in your project and connect it to your report workflow. Get your token below and set your keys privately in your environment.
Set up Chart Doctor's hosted BYOK API in this project. Read https://dataviz.karthiks.co/api/guide.md for setup instructions and the full API contract. Use https://dataviz.karthiks.co/api/example.py as the Python reference. Inspect this project's language and dependency manager, then add a client that accepts a chart image, output path and optional instructions. Read CHART_DOCTOR_API_TOKEN and OPENROUTER_API_KEY from the environment; never print or commit their values. Tell me which variables to set if they are missing. I will verify my email at https://dataviz.karthiks.co/api to get my token. Handle submission, polling, PNG download and resuming a job. Preserve the original chart, reuse idempotency keys across network retries, and surface fallback results and review issues. Verify setup without paid requests, then show me the exact command to use it with my reports.
Read the Markdown setup and API guide · Agent discovery index
Get your API token
Already have a token? Verifying again replaces it. Your old token stops working; your job access and usage limits carry over.
Save this token now. It is shown only once. Keep it private and use it as CHART_DOCTOR_API_TOKEN in your script.
Use it in your report
- Install Python's
requestspackage:pip install requests. - Set
CHART_DOCTOR_API_TOKENandOPENROUTER_API_KEYin your environment. - Save your chart as
chart.png, then run the script below. It saves the result asimproved.png.
import os
import time
import uuid
import requests
base = "https://dataviz.karthiks.co"
headers = {"Authorization": f"Bearer {os.environ['CHART_DOCTOR_API_TOKEN']}"}
submission_headers = {
**headers,
"X-OpenRouter-Key": os.environ["OPENROUTER_API_KEY"],
"Idempotency-Key": uuid.uuid4().hex,
}
# Retain submission_headers across network retries of this same submission.
with open("chart.png", "rb") as chart:
response = requests.post(
f"{base}/api/v1/jobs", headers=submission_headers,
files={"chart": ("chart.png", chart, "image/png")},
data={"prompt": "Make the comparison easier to read"}, timeout=60,
)
response.raise_for_status()
job = response.json()
deadline = time.monotonic() + 1800
while job["status"] in {"queued", "processing"}:
if time.monotonic() > deadline:
raise TimeoutError(f"Job still running: {job['job_id']}")
time.sleep(3)
response = requests.get(base + job["status_url"], headers=headers, timeout=30)
response.raise_for_status()
job = response.json()
if job["status"] != "ready":
raise RuntimeError(job.get("error") or "Repair failed to start")
response = requests.get(base + job["download_url"], headers=headers, timeout=60)
response.raise_for_status()
with open("improved.png", "wb") as output:
output.write(response.content)
print(job["result_kind"], job.get("error"), job.get("usage"))
Submit to POST /api/v1/jobs; poll GET /api/v1/jobs/{id}; download GET /api/v1/jobs/{id}/chart. Use your Chart Doctor token for all three. Your OpenRouter key is needed only when submitting.
Keep the same Idempotency-Key when retrying a submission after a network error. This prevents duplicate jobs. Different input with that key returns 409. Busy capacity or exhausted allowance returns 429.
The API uses Chart Doctor's current model defaults. Review the output before publishing: image reading can miss values, and maps are unsupported. If repair fails, the best available image is delivered, which may be the original. Check result_kind and error in the response.