Skip to main content

Merge and Split Guide

Combine PDFs into one file, or split one PDF into several, from your own code. For every field and response, see the PDF Tools reference.

Choosing a path

Up to 4 MB of PDFs                         More than 4 MB
───────────────────── ──────────────────────────────────────
POST /pdf/merge → the merged PDF 1. POST /pdf/upload-url (per file)
POST /pdf/split → the PDF, or links 2. PUT the file to upload_url
to every file 3. POST /pdf/jobs → 202 job_id
4. GET /jobs/{job_id} → poll, or webhook
5. GET /jobs/{job_id}/files and /download

The size that matters is the total of the PDFs you send. A merge of five 500 KB invoices is instant; a 12 MB scan goes through an upload and a job.

Page count almost never forces a job on its own: an instant request can process 500 pages, and copying pages is fast. It's the upload size that decides.

Check files first

POST /pdf/inspect returns a file's page count and whether it's encrypted, and doesn't cost anything. It's worth calling when:

  • a person picks the page ranges, so you can validate them before sending the real request
  • files come from systems that sometimes encrypt their exports
  • you split a run into files per person and want to confirm the page count matches the number of people

For a file you've already uploaded, send {"s3_key": "..."} instead of the file itself.

Merge recipes

Everything, in order

curl -X POST https://api.podpdf.com/pdf/merge \
-H "X-API-Key: $KEY" \
-F "files=@1-cover.pdf" -F "files=@2-contract.pdf" -F "files=@3-appendix.pdf" \
-o pack.pdf

Only the pages you need

  -F 'page_ranges=["1", "1-4,9", null]'

The first file contributes page 1, the second pages 1–4 and 9, the third everything.

The same page twice

A cover page in front of two sections: "page_ranges": ["1", "2-end", "1"] with the same file three times, or "1,2-10,1" for one file.

Reverse order

Reverse the files list — there's no reverse option, because the order you send is the order you get.

Split recipes

Goalsplit
Pull out pages 4–7 as one file{"mode": "extract", "pages": "4-7"}
Remove page 2{"mode": "extract", "pages": "1,3-end"}
Chapters at known pages{"mode": "ranges", "ranges": ["1-12", "13-40", "41-end"]}
Two-page statements into one file each{"mode": "every_n", "every_n": 2}
Every page separately{"mode": "each_page"}

Name the files with options.filename_pattern, for example "invoice-{index:03}" for invoice-001.pdf, invoice-002.pdf.

A complete job

This walks through splitting a 90 MB scanned batch into files of 10 pages.

1. Upload

UPLOAD=$(curl -s -X POST https://api.podpdf.com/pdf/upload-url \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d "{\"content_length_bytes\": $(wc -c < batch.pdf)}")

curl -X PUT "$(echo $UPLOAD | jq -r .upload_url)" -H "Content-Type: application/pdf" --data-binary @batch.pdf

2. Check it (optional)

curl -s -X POST https://api.podpdf.com/pdf/inspect \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d "{\"s3_key\": \"$(echo $UPLOAD | jq -r .s3_key)\"}"

3. Submit

curl -s -X POST https://api.podpdf.com/pdf/jobs \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d "{\"operation\": \"split\", \"inputs\": [{\"s3_key\": \"$(echo $UPLOAD | jq -r .s3_key)\", \"filename\": \"batch.pdf\"}], \"split\": {\"mode\": \"every_n\", \"every_n\": 10}}"

4. Wait

Poll GET /jobs/{job_id} every few seconds. While it runs you'll see output_count (how many files it will make) and processed_count (how many are done):

{ "job_id": "5b2d8f40-...", "status": "processing", "job_type": "pdfop", "operation": "split", "input_pages": 214, "output_count": 22, "processed_count": 9 }

Or subscribe a webhook to job.completed and job.failed — the payload has job_type: "pdfop", operation, output_count and files_url.

5. Collect the files

curl -s https://api.podpdf.com/jobs/$JOB/files -H "X-API-Key: $KEY"              # the list
curl -s https://api.podpdf.com/jobs/$JOB/files/0/download -H "X-API-Key: $KEY" # one file
curl -s https://api.podpdf.com/jobs/$JOB/download -H "X-API-Key: $KEY" # all as a ZIP

Each call returns a fresh link valid for one hour. The files are kept for 7 days.

When things go wrong

You seeWhyDo this
PDF_ENCRYPTEDThe file is password-protected or encrypted, even if it opens without a passwordExport it again without protection
INVALID_PDF with reason: "missing_page_objects"The file is incomplete — often an interrupted download or uploadGet the file again
PAGE_OUT_OF_RANGEA range goes past the last pageUse details.total_pages, or end
OUTPUT_TOO_LARGEShared images or fonts would be copied into too many filesSplit into fewer files (every_n with a bigger number)
PDF_JOB_ALREADY_ACTIVE2 jobs are already runningWait for one to finish, then retry
413 with no JSON bodyThe request was larger than the API acceptsUse the upload and job path
A warnings entryForms, bookmarks or signatures couldn't be keptNothing to fix; decide whether the output is still what you need

Failed operations aren't charged.

Next Steps