ODC to JPG API
POST /v2/convert/odc/to/jpg renders a standalone OpenDocument chart as a single JPEG. The sample asks for ImageWidth=1200 and gets a 1,200 × 667 image of 78,569 bytes, the chart's 18:10 shape at the width a newsletter column or social card needs.
- Endpoint
- POST /v2/
convert/ odc/ to/ jpg - Accepts
- odc
- Sample timing
- 0.551 s median of 5 runsHow we measure
- Request size
- Up to 10 MB on the Free plan or 100 MB on paid plans, all files together
Request and response
Every sample below ran against the API before this page was published. Set PDFCONVERSIONAPI_KEY to your key and run it as is.
curl -sS -X POST \
https://api.pdfconversionapi.com/v2/convert/odc/to/jpg \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@garden-water-use.odc \
--form-string ImageWidth=1200 \
-o response.json
# FileData is base64. Save the first file in converted/,
# or print the JSON error.
if jq -e '.Files' response.json > /dev/null; then
mkdir -p converted
name=$(jq -r '.Files[0].FileName' response.json)
jq -r '.Files[0].FileData' response.json \
| base64 --decode > "converted/$name"
else
cat response.json
fiimport base64
import os
import requests
key = os.environ["PDFCONVERSIONAPI_KEY"]
response = requests.post(
"https://api.pdfconversionapi.com/v2/convert/odc/to/jpg",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("garden-water-use.odc", "rb"))],
data={
"ImageWidth": "1200",
},
timeout=180,
)
result = response.json()
if not response.ok:
raise SystemExit(f"{result['Code']}: {result['Message']}")
os.makedirs("converted", exist_ok=True)
for file in result["Files"]:
path = os.path.join("converted", file["FileName"])
with open(path, "wb") as out:
out.write(base64.b64decode(file["FileData"]))
print(path, file["FileSize"], "bytes")
import { mkdir, readFile, writeFile } from "node:fs/promises";
import { join } from "node:path";
const form = new FormData();
const file = "garden-water-use.odc";
form.append("File", new Blob([await readFile(file)]), file);
form.append("ImageWidth", "1200");
const url = "https://api.pdfconversionapi.com/v2/convert/odc/to/jpg";
const key = process.env.PDFCONVERSIONAPI_KEY;
const response = await fetch(url, {
method: "POST",
headers: { Authorization: `Bearer ${key}` },
body: form,
});
const result = await response.json();
if (!response.ok) {
throw new Error(`${result.Code}: ${result.Message}`);
}
await mkdir("converted", { recursive: true });
for (const file of result.Files) {
const path = join("converted", file.FileName);
await writeFile(path, Buffer.from(file.FileData, "base64"));
console.log(path, file.FileSize, "bytes");
}
{
"ConversionCost": 1,
"ConversionTime": 0.551,
"Files": [
{
"FileName": "garden-water-use-1.jpg",
"FileExt": "jpg",
"FileSize": 78569,
"FileData": "/9j/4AAQSkZJRgABAgAAAQAB…"
}
]
}Response from our test run on 2026-11-03. ConversionTime shows the median of 5 runs. FileData is shortened here; the real response carries the whole file as base64.
The sample, converted
The same file the code sends. Download the input and the output and compare them yourself.

- Input
- garden-water-use.odc (2.7 KB)
- Output
- garden-water-use-1.jpg (77 KB)
- Source
- A line chart of a fictional community garden's daily water use, 2025 against 2026, which we wrote as an OpenDocument chart by hand (CC0-1.0). How it was made
- Made by
- 2026-11-04, API build
9eeeb0640aba
Parameters
Send these as form fields next to the file. Names are case-insensitive. If you set one of the documented options below that we don't support yet, the request fails with a 400 that names it instead of returning a file made without it.
| Parameter | What it does |
|---|---|
ImageQualityinteger, default 85 | JPEG quality. ConvertAPI documents 75 as its default for this pair. At 150 DPI the chart was 66,149 bytes at 85 and 45,518 at 60; at 1,200 wide, quality 95 gave 118,613 bytes.Values: 1–100 |
ImageWidthinteger | Exact width in pixels, with the height from the chart's shape: 1200 gives 1,200 × 667.Values: 1–20000 |
ImageHeightinteger | Exact height in pixels; both together set a box the chart fits into.Values: 1–20000 |
ImageResolutioninteger, default 150 | DPI when no width or height is sent, and the density stored in the JPEG. ConvertAPI's documented default is 200, which gives 1,417 × 787 and 102,782 bytes here.Values: 36–600 |
ScaleProportionsboolean, default true | false lets ImageWidth × ImageHeight distort the chart. |
ScaleImageboolean, default true | false crops instead of scaling. A 600 × 600 crop came back 600 × 590, since the chart is only 590 pixels tall at 150 DPI. |
ScaleIfLargerboolean, default false | true never enlarges the chart beyond its 150 DPI size. |
ColorSpaceenum, default default | gray writes a one-channel JPEG: 55,414 bytes at 1,200 wide.Values: default, rgb, gray, monochrome |
FileNamestring | Stem for the output, which ends in -1.jpg. |
StoreFileboolean, default false | Return a link to the stored JPEG, valid for 3 hours. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
PageSize | 400 "PageSize is not supported yet for ODC files". |
What carries over, and what doesn't
Kept
- The chart only, cut to its own edges, with its 18:10 shape
- Series colors, markers, gridlines and every label, flattened onto the chart's white background
- The DPI as JPEG density when
ImageResolutionis sent (200 × 200 in the 200 DPI probe); the sample sets a width instead and records none
Lost or not yet supported
- Transparency: JPEG can't hold it, and the chart background is white.
- Exact pixels: at the default quality and 150 DPI (1,062 × 590), 310,675 of the 626,580 pixels differ from the PNG of the same chart, by at most 39 of 255 levels; 1,582 differ by more than 16.
- Text as text.
Limits
- 100,000,000 pixels and 16,000 pixels per side; larger sizes return 413.
- One image per chart;
PageRangeaccepts only1. - Up to 10 MB on the Free plan or 100 MB on paid plans per request and 120 seconds per conversion.
- Password-protected charts can't be opened yet: without
Passwordthey return 422 "the input file is password-protected", with it 400 "password-protected ODC files are not supported yet".Passwordsent with an unprotected chart changes nothing.
Where teams use it
Charts in email newsletters
A monthly figure such as the garden's water use can go into an email as a 1,200-pixel JPEG of about 79 KB, small enough to embed in the message.
Social cards and blog posts
Publish the chart where uploads must be JPEG: set ImageWidth to the slot's width and ImageQuality to the size budget.
Image fields that take JPEG
When a catalog or news system stores pictures as JPEG, the converted chart can go into that field without a second conversion step.
Questions
How do I get a chart image for a 1,200-pixel slot?
Send ImageWidth=1200, as the sample does. The height follows the chart's shape, 667 pixels here, and the chart is drawn at that size rather than enlarged from a smaller one.
How does your default quality compare with ConvertAPI's?
ConvertAPI documents ImageQuality 75 and ImageResolution 200 for this pair; ours are 85 and 150. Send both values explicitly if you want the same settings.
Can the JPEG be gray?
Yes: ColorSpace=gray returns a one-channel JPEG, 55,414 bytes at 1,200 wide instead of 78,569.
Convert your first ODC file in a minute.