Convert a file
Convert a Word document to PDF through the API: upload, run, wait and download, in curl, JavaScript and Python.
Before you start
- An API key with the
tools:runscope to upload and run, andjobs:readto follow the run and download the result. Authentication shows how to make one. - A Team, Business or Enterprise account. The API is included in those plans. The largest file and the number of files in one run follow the plan: for the Team plan, 250 MB and 50. The rate limits page lists every plan.
- The tool id is
word-to-pdf.GET https://api.pdfloft.com/v1/tools/word-to-pdfreturns the files and options it takes, and the Tools and options page lists them all.
The whole script
The script uploads a Word document, starts a run of word-to-pdf, waits for it and saves the first result. Upload and run are separate calls: POST /v1/files returns a file id, and POST /v1/tools/word-to-pdf/runs takes the ids. The Idempotency-Key header lets you send the run call again after a network failure without starting a second run. A run is queued, running, then succeeded, failed or cancelled.
FILE0=$(curl -s -X POST https://api.pdfloft.com/v1/files \
-H "Authorization: Bearer $PDFLOFT_API_KEY" \
-H "Content-Type: application/vnd.openxmlformats-officedocument.wordprocessingml.document" \
--data-binary @report.docx | jq -r .id)
JOB=$(curl -s -X POST https://api.pdfloft.com/v1/tools/word-to-pdf/runs \
-H "Authorization: Bearer $PDFLOFT_API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"files":["'"$FILE0"'"],"options":{}}' | jq -r .id)
until [ "$(curl -s https://api.pdfloft.com/v1/jobs/$JOB -H "Authorization: Bearer $PDFLOFT_API_KEY" | jq -r .status)" = "succeeded" ]; do sleep 1; done
URL=$(curl -s https://api.pdfloft.com/v1/jobs/$JOB/results/0 -H "Authorization: Bearer $PDFLOFT_API_KEY" | jq -r .url)
curl -s -o report.pdf "$URL"import { readFile, writeFile } from 'node:fs/promises';
const apiKey = '<your API key>'; // read it from your secret store, never from source
const headers = { Authorization: `Bearer ${apiKey}` };
async function upload(path, contentType) {
const response = await fetch('https://api.pdfloft.com/v1/files', {
method: 'POST',
headers: { ...headers, 'Content-Type': contentType },
body: await readFile(path),
});
return response.json();
}
const file0 = await upload('report.docx', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document');
let job = await fetch('https://api.pdfloft.com/v1/tools/word-to-pdf/runs', {
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json', 'Idempotency-Key': crypto.randomUUID() },
body: JSON.stringify({ files: [file0.id], options: {} }),
}).then((r) => r.json());
while (job.status === 'queued' || job.status === 'running') {
await new Promise((resolve) => setTimeout(resolve, 1000));
job = await fetch(`https://api.pdfloft.com/v1/jobs/${job.id}`, { headers }).then((r) => r.json());
}
if (job.status !== 'succeeded') throw new Error(`The run ended as ${job.status}: ${job.error}`);
const link = await fetch(`https://api.pdfloft.com/v1/jobs/${job.id}/results/0`, { headers }).then((r) => r.json());
await writeFile('report.pdf', Buffer.from(await fetch(link.url).then((r) => r.arrayBuffer())));import os
import time
import uuid
import requests
headers = {"Authorization": f"Bearer {os.environ['PDFLOFT_API_KEY']}"}
def upload(path, content_type):
with open(path, "rb") as handle:
return requests.post("https://api.pdfloft.com/v1/files", headers={**headers, "Content-Type": content_type}, data=handle).json()
file0 = upload("report.docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document")
job = requests.post(
"https://api.pdfloft.com/v1/tools/word-to-pdf/runs",
headers={**headers, "Idempotency-Key": str(uuid.uuid4())},
json={"files": [file0["id"]], "options": {}},
).json()
while job["status"] in ("queued", "running"):
time.sleep(1)
job = requests.get(f"https://api.pdfloft.com/v1/jobs/{job['id']}", headers=headers).json()
if job["status"] != "succeeded":
raise RuntimeError(f"The run ended as {job['status']}: {job['error']}")
link = requests.get(f"https://api.pdfloft.com/v1/jobs/{job['id']}/results/0", headers=headers).json()
open("report.pdf", "wb").write(requests.get(link["url"]).content)Other conversions
Change the tool id and the file. excel-to-pdf, ppt-to-pdf, html-to-pdf, jpg-to-pdf and zpl-to-pdf make a PDF. pdf-to-word, pdf-to-excel, pdf-to-ppt, pdf-to-jpg and pdf-to-png read a PDF. When a tool is given several files it makes one result for each, so download /v1/jobs/{jobId}/results/1 and the indexes after it. The results field of the run says how many there are. A conversion of a PDF to pictures returns one picture for a one page document and otherwise one ZIP.
If a call fails
file.type_refused: the file is not a type the tool reads. Send a .docx, .doc, .odt or .rtf file to word-to-pdf, and set the Content-Type header to match.file.too_large: the file is larger than the plan allows. The details give maxBytes.tasks.exhausted: the account has used its tasks for the period. The details give when it resets.- Every error code is listed on the errors page, and a run that failed carries its code in the
errorfield of the run.