Guide
A working example: filling a PDF form from JavaScript, the way the API actually behaves
Most "fill a PDF in JavaScript" snippets are one fetch call with
field names that already match the template. Real forms don't work
that way. A signup page collects applicant_name and
email, someone renames a field in the PDF template six
months later, and the fetch call that used to work now fails with a
vague error, or worse, silently writes nothing. Here is a working
example that discovers the real field names first, handles a typo
the way the API actually reports it, and fills a real PDF.
Ask the PDF what fields it has
Start by asking the PDF what fields it actually has, rather than
guessing from the template design file. A POST to
/api/inspect with the
template returns the field names, types, and current values as
JSON:
const form = new FormData();
form.append("pdf", templateFile); // a Blob/File of the PDF template
const res = await fetch("https://pdfops.dev/api/inspect", {
method: "POST",
body: form,
});
const { fields } = await res.json();
console.log(fields.map((f) => f.name));
Running that against a sample rental application returns eight text
fields: applicant_name, email_addr,
dob, addr_line1, city,
postal_code, phone_no, and
notes. Those are the exact keys the fill call needs,
read straight from the PDF rather than copied from a spec someone
wrote down once.
Fill it with one fetch call, no PDF library
Filling is the same shape: a FormData with the template and a JSON
string of field values, posted to
/api/fill-form. No PDF
library runs in this code at all. The browser or Node's
fetch and FormData do the whole job,
because the PDF engine lives on the server side of the call.
const fields = {
applicant_name: "Jamie Oyelaran",
email_addr: "jamie@example.com",
dob: "1990-04-12",
addr_line1: "44 Birch Lane",
city: "Austin",
postal_code: "73301",
phone_no: "512-555-0199",
notes: "Referred by a current tenant",
};
const form = new FormData();
form.append("pdf", templateFile);
form.append("fields", JSON.stringify(fields));
const res = await fetch("https://pdfops.dev/api/fill-form", {
method: "POST",
body: form,
});
const filledPdf = await res.arrayBuffer(); // the filled PDF, ready to save or stream back
What a typo actually looks like
Send applicant_nam instead of
applicant_name (one dropped letter, the kind of typo
that survives code review) and the API answers with a 400 and this
body:
{
"error": "unknown_field",
"details": "no field named \"applicant_nam\" (did you mean \"applicant_name\", \"addr_line1\"?)"
}
That suggestion comes from the field names /api/inspect
already returned, matched against what was sent. A caller who logs
this response, rather than swallowing the error, finds the typo in
one read instead of diffing the template by hand.
Fix the field name and the same call returns a PDF: the applicant's name, email, date of birth, address, and notes all written into the template's existing fields, with the original layout untouched (the API re-renders field text in Helvetica, so a form built with a different font will not keep it).
Try it
Both calls above ran keyless against the live API, capped at 100
requests per IP per month, enough to build and test an integration
end to end. A free key from
POST /api/signup raises that to 250
requests a month under X-API-Key and works with the
exact same two endpoints, no code change beyond adding the header.