Endpoint reference

POST /api/set-metadata

Write the Info fields of a PDF: title, author, subject, keywords and creator. Send any of them. Returns the updated PDF as application/pdf.

Request

Method: POST. URL: https://pdfops.dev/api/set-metadata. Body: multipart/form-data.

FieldTypeRequiredDescription
pdfFile (PDF binary)YesExactly one PDF, up to 4 MB and 2,000 pages. The whole request must stay under 4.5 MB, Vercel's platform request limit.
titleStringAt least one of the fiveUp to 1,000 characters.
authorStringAt least one of the fiveUp to 1,000 characters.
subjectStringAt least one of the fiveUp to 1,000 characters.
keywordsStringAt least one of the fiveComma list. Items are trimmed and empty ones dropped. Up to 1,000 characters.
creatorStringAt least one of the fiveUp to 1,000 characters.
passwordStringNoOpens a PDF that needs a user password. Not needed for owner-locked files with an empty user password.

The optional X-API-Key header works as on /api/merge: no header is anonymous, 100 requests per IP per month; a valid key uses your tier's quota; an invalid or revoked key returns 401 invalid_api_key. A successful (2xx) call counts 1 request. Check consumption with GET /api/usage.

Response

On success: 200 OK, Content-Type: application/pdf, body is the updated PDF.

On any failure: 4xx or 500, Content-Type: application/json, body is { "error": "<code>", "details": "<explanation>" }.

Error codes

Error codeStatusTrigger
invalid_multipart400Request body could not be parsed as multipart/form-data.
missing_pdf400The request does not have exactly one pdf file field.
pdf_too_large400The pdf file is over 4 MB.
invalid_pdf400The PDF could not be parsed (corrupt, or not a PDF).
encrypted_pdf400The PDF needs a password we were not given. Owner-locked files with an empty user password (most government blanks) open on their own; for a real user password send it as the password form field.
decompressed_too_large400Object streams inside the PDF decompress to over 32 MB.
too_many_pages400The PDF has over 2,000 pages.
no_fields400None of title, author, subject, keywords, creator was sent.
field_too_long400A field is over 1,000 characters. details names it.
save_failed500PDF serialization failed. Retryable.
request_too_large413The whole request body is over 4.5 MB (Vercel's platform request limit). Rejected before anything is parsed.
invalid_api_key401An X-API-Key header was sent but the key is unknown or revoked. No fallback to the anonymous IP cap. Get a fresh key at /pricing.
rate_limited (anonymous)429No X-API-Key header and the per-IP limit (100/month) is exhausted. Retry-After gives seconds until next calendar month.
rate_limited (keyed)429Your key's tier quota (Free 250 / Indie 4,000 / Pro 25,000 per month) is exhausted. Retry-After gives seconds until next calendar month.

Example

curl -X POST https://pdfops.dev/api/set-metadata \
  -F "pdf=@report.pdf" \
  -F "title=Q3 report" \
  -F "author=Finance team" \
  -F "keywords=quarterly, finance" \
  -o report-tagged.pdf \
  -H "X-API-Key: pdfops_live_..."  # optional, raises your quota to your tier

Keyless calls work: 100 requests per IP per month with no key.

Using this for real? A free API key raises the keyless 100 calls per IP to 250 requests a month, with no card.

Get a free API key

Code examples

Have an API key? Add an X-API-Key header to any request. It is optional, and it raises your quota from 100/IP/month to your tier's.

JavaScript (Node.js 22+) — built-in fetch + FormData
import { readFile, writeFile } from 'node:fs/promises';

const fd = new FormData();
fd.append('pdf', new Blob([await readFile('report.pdf')], { type: 'application/pdf' }), 'report.pdf');
fd.append('title', 'Q3 report');
fd.append('author', 'Finance team');
fd.append('keywords', 'quarterly, finance');

const res = await fetch('https://pdfops.dev/api/set-metadata', {
  method: 'POST',
  headers: { 'X-API-Key': process.env.PDFOPS_API_KEY }, // optional
  body: fd,
});
if (!res.ok) {
  const err = await res.json();
  throw new Error(`PDFops set-metadata failed: ${err.error}: ${err.details}`);
}
await writeFile('report-tagged.pdf', Buffer.from(await res.arrayBuffer()));

Behavioral notes

FAQ

Can I set the dates or the producer?

No. The modification date and producer are pinned by the service, and an existing creation date is kept.

How do I read the current values first?

Call /api/metadata.

Related: Read PDF properties · Remove restrictions · Stamp page numbers.

Get a free API key. Keyless calls get 100 requests per IP per month; a free key raises that to 250, with no card. Enter your email and the key arrives in your inbox.

Get a free API key