QOI to PDF API
POST a QOI to /v2/convert/qoi/to/pdf and get a one-page PDF holding the exact pixels. The sample puts the 400 × 300 card on a landscape Letter sheet, centered at its natural size.
- Endpoint
- POST /v2/
convert/ qoi/ to/ pdf - Accepts
- qoi
- Sample timing
- 5 ms 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/qoi/to/pdf \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@trail-map-card.qoi \
--form-string PageSize=letter \
--form-string PageOrientation=landscape \
-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/qoi/to/pdf",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("trail-map-card.qoi", "rb"))],
data={
"PageSize": "letter",
"PageOrientation": "landscape",
},
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 = "trail-map-card.qoi";
form.append("File", new Blob([await readFile(file)]), file);
form.append("PageSize", "letter");
form.append("PageOrientation", "landscape");
const url = "https://api.pdfconversionapi.com/v2/convert/qoi/to/pdf";
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.005,
"Files": [
{
"FileName": "trail-map-card.pdf",
"FileExt": "pdf",
"FileSize": 49085,
"FileData": "JVBERi0xLjcKJYCAgIAKMSAw…"
}
]
}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
- trail-map-card.qoi (66 KB)
- Output
- trail-map-card.pdf (48 KB)
- Source
- A 400 x 300 trail map card with a sunrise sky, rounded transparent corners and a soft drop shadow, drawn by us and saved as a 4-channel QOI. (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 |
|---|---|
PageSizeenum, default default | Without it the page matches the image at 96 px per inch: 300 × 225 pt for the card. A named sheet keeps that size and centers the image, shrinking it only if it does not fit.Values: default, auto, a3, a4, a5, letter, legal |
PageOrientationenum, default default | landscape turns a named sheet sideways; the sample's Letter page is 792 × 612 pt. Ignored when the page is sized to the image.Values: default, portrait, landscape |
Rotateinteger | Turns the card clockwise about its center, and an image-sized page grows to hold it: 90 gave a 225 × 300 pt page with the sky along the right edge, 45 a 371.23 pt square. QOI has no orientation tag, so leaving it empty draws the card as stored; 12.5 gets a 400.Values: -360 to 360 whole degrees, or none |
MarginHorizontalinteger, default 0 | Millimeters kept clear at the left and right. On the image-sized page it adds width: 10 turned the 300 pt card page into 356.69 pt. On a named sheet the picture is shrunk when it would cross them: the 4000 × 3001 test QOI on A4 with 20 mm each way was drawn 481.89 pt wide.Values: 0–500 (mm) |
MarginVerticalinteger, default 0 | Millimeters kept clear above and below; 5 made the image-sized page 253.35 pt tall. When the margins leave under 1 pt for the card, such as MarginHorizontal=200 on A5, the reply is 400 'MarginHorizontal and MarginVertical leave no room for the image on the page'.Values: 0–500 (mm) |
FileNamestring | Name of the PDF, without extension. |
StoreFileboolean, default false | true stores the PDF for 3 hours and returns a link. |
What carries over, and what doesn't
Kept
- The pixels: RGB data and soft mask extracted from the PDF equal the QOI's 120,000 RGBA values
- Partial transparency, as an 8-bit soft mask over the image
- Full resolution on any sheet: a 4000 × 3001 test image on A4 was drawn 595 pt wide and still stored at 4000 × 3001
Lost or not yet supported
- The QOI bytes themselves. The PDF holds its own deflate-compressed pixels; the sample PDF is 49,085 bytes against 67,304 for the QOI.
- Image options.
ImageWidth,ColorSpaceand the like are not read on this route and change nothing. - Clearance you didn't ask for: with no margins, the 4000 × 3001 test image shrunk onto A4 touched the left and right edges of the page.
- The colorspace byte. A copy of the card flagged as linear gave a PDF byte for byte the same as the sRGB one.
Limits
- One QOI per request, one page per PDF.
- Never enlarged: a small QOI on A3 stays its own size in the middle of the sheet.
Rotatetakes whole degrees from -360 to 360; each margin 0 to 500 mm.- 100,000,000 pixels per image; requests up to 10 MB on the Free plan or 100 MB on paid plans.
- 120 seconds per conversion.
Where teams use it
Reports with QOI screenshots
Test rigs or emulators that capture QOI frames can turn each one into a PDF page with exact pixels, then join the pages with the merge tool for a report.
Printable handouts from QOI art
A named sheet such as A4 or Letter centers the image with white around it, and MarginHorizontal keeps a large capture away from the trim, while the soft edges still blend into the paper.
Questions
What page size do I get without PageSize?
The image's own size, counting 96 pixels per inch: 400 × 300 px becomes 300 × 225 pt, which is 4.17 by 3.13 inches.
Where does the image sit on a Letter sheet?
In the middle at its natural size. On the sample's landscape Letter page (792 × 612 pt) the 300 × 225 pt card starts 246 pt from the left and 193.5 pt from the bottom.
Can a wide capture fill a portrait sheet?
Turn it with Rotate=90 before it is fitted. On portrait A4 the 4000 × 3001 test QOI covered 595 × 793 pt turned, against 595 × 447 pt upright, and the PDF still stores all 4000 × 3001 pixels.
Can I convert several QOI files into one PDF?
This route takes a single file. /v2/convert/images/to/pdf accepts several images and makes one page per image.
Convert your first QOI file in a minute.