WPD to PDF API
POST /v2/convert/wpd/to/pdf opens a WordPerfect document and returns a PDF with real, selectable text. Our 1,800-byte WordPerfect 5.1 hearing notice comes back as a 47,215-byte PDF on two US Letter pages, with its justification, strikeout, superscript and fine print in place.
- Endpoint
- POST /v2/
convert/ wpd/ to/ pdf - Accepts
- wpd
- Sample timing
- 0.521 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/wpd/to/pdf \
-H "Authorization: Bearer $PDFCONVERSIONAPI_KEY" \
-F File=@hearing-notice.wpd \
-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/wpd/to/pdf",
headers={"Authorization": f"Bearer {key}"},
files=[("File", open("hearing-notice.wpd", "rb"))],
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 = "hearing-notice.wpd";
form.append("File", new Blob([await readFile(file)]), file);
const url = "https://api.pdfconversionapi.com/v2/convert/wpd/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.521,
"Files": [
{
"FileName": "hearing-notice.pdf",
"FileExt": "pdf",
"FileSize": 47215,
"FileData": "JVBERi0xLjcKJcOkw7zDtsOf…"
}
]
}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
- hearing-notice.wpd (1.8 KB)
- Output
- hearing-notice.pdf (46 KB)
- Source
- A two-page WordPerfect 5.1 public hearing notice for a fictional township, which we wrote byte by byte from the file format description (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 |
|---|---|
PageRangestring | Pages to keep from the finished PDF. PageRange=2 returns the one-page hearing procedure (35,748 bytes); PageRange=3 returns 400 "PageRange asks for page 3, but the document has 2 pages".Values: Page numbers and ranges, such as 1 or 2- |
Pdfaboolean, default false | true writes PDF/A-1b. The sample then comes out as a PDF 1.4 file of about 56 KB (56,144 or 56,145 bytes in our runs), marked part 1, conformance B, in its metadata. |
PdfaVersionenum, default none | Choose the PDF/A part. pdfA2b and pdfA3b each gave a PDF 1.7 file of about 56 KB (56,158 bytes). It decides when both are sent: Pdfa=true with PdfaVersion=pdfA2b gave part 2.Values: none, pdfA1b, pdfA2b, pdfA3b |
FileNamestring | Name of the PDF without the extension. FileName=riverbend-notice returned riverbend-notice.pdf instead of hearing-notice.pdf. |
StoreFileboolean, default false | Answer with a link to the stored PDF instead of the file itself. The link expires after 3 hours. |
Not supported yet
Setting one of these to anything but its default returns 400.
| Option | What to do instead |
|---|---|
IncludeMarkup | true returns 400 "IncludeMarkup is not supported yet for WPD files". |
IncludeStructureTags | The PDF is tagged anyway: the sample has a structure tree with 22 paragraph elements and the language en-US. Sending true still returns 400 for now. |
IncludeMetadata | XMP metadata is always written; false returns 400. |
BookmarkMode | Values other than headings return 400. The sample PDF has no bookmarks. |
UpdateTableOfContents | true returns 400. |
SubsetFonts | Fonts are already embedded as subsets (the sample's three faces). true returns 400 "SubsetFonts is not supported yet for WPD → PDF". |
What carries over, and what doesn't
Kept
- The page setup in the file, or WordPerfect's defaults when it has none: the sample sets no page codes and prints on US Letter (612 × 792 pt) with 1-inch margins
- Alignment per paragraph: the centered title, full justification on page 1 (each full line ends at the right margin), the right-aligned posting date and the ragged-right page 2
- Relative sizes: the large title at 14.4 pt, body text at 12 pt, the fine-print disclaimer at 7.2 pt, and the raised 7 pt 'nd' in '2nd floor'
- Bold, italic and underline, and strikeout drawn as a line through 'January 12, 2027', even where the date wraps onto the next line
- WordPerfect's extended characters as text: é and è, the § sign, curly quotes and the apostrophe in 'applicant’s'
- The hard page break, so page 2 starts with 'Hearing procedure'
- Searchable text in embedded font subsets, plus a tagged structure and the language en-US
Lost or not yet supported
- The font the document asks for. With no font codes, the text is read as Times New Roman and printed in Liberation Serif, a face drawn to the same character widths.
- Bookmarks: the PDF has no outline.
- Password-protected files. A WordPerfect file whose header carries an encryption key returns 422, with or without
Password.
Limits
- Page setup and Word options such as
PageSize,PageOrientation,EmbedFontsandPdfTitlereturn 400 "... is not supported yet for WPD files". - The route reads the content, not the name: a text file or an Apple Pages file sent here returns 422 "the input file could not be read: it could not be opened as WPD", while our WordPerfect file renamed
notice.txtconverted normally. - Requests up to 10 MB on the Free plan or 100 MB on paid plans, all files and fields together, and 120 seconds per conversion; after that the API returns 504.
Where teams use it
Reading old WordPerfect archives
Archives of .wpd letters, briefs and notices can't be shown in a browser. Converting them, one request per file, gives PDFs that open on any device and whose text can be searched.
PDF/A for a records system
PdfaVersion=pdfA2b turns a WordPerfect document into PDF/A for retention. Convert the whole file: a PageRange that drops pages can't be combined with PDF/A and returns 400.
Feeding search and review tools
Indexing and e-discovery tools that can't parse WordPerfect can read the PDF's text. In the sample, 'Café Lumière' and the section sign in 'Zoning Code § 410-22' come through as characters, not pictures.
Questions
Which WordPerfect versions can I send?
Our sample is a WordPerfect 5.1 file, written byte by byte from the format's description. We also sent a 3,587-byte WordPerfect 6 test file, which came back as a 2-page A4 PDF with its page header text at the top of each page.
Can I convert a password-protected .wpd file?
Not yet. A WordPerfect file whose header marks it as protected returned 422 "it could not be opened as WPD", and sending Password made no difference. Save it without the password first.
Do I need WordPerfect on my server?
No. Your code uploads the .wpd file and receives the PDF in the response; the document is opened on our side.
Can I send .wpd files to office/to/pdf instead?
Yes. /v2/convert/office/to/pdf and /v2/convert/file/to/pdf take a file whose name ends in .wpd and convert it the same way; the sample came back at the same 47,215 bytes. Under another extension, such as .wp5, office/to/pdf returns 400, so use this route.
Convert your first WPD file in a minute.