Bytefusedocs

Organise

Merge PDF

Combine two or more PDFs into a single document. Each source contributes a top-level bookmark named from its original filename, so the merged outline stays navigable.

Free to try — no key required 10 credits / callSynchronous

Overview

Upload the files in the order you want them combined; receive a public R2 URL for the merged PDF. On the free-try path — callable with no key.

POSThttps://api.bytefuse.in/api/v1/pdf/merge/merge

The path segment is doubled

The router is mounted at /pdf/merge and the route is /merge, so the real path is /api/v1/pdf/merge/merge — not /api/v1/pdf/merge. Easy to get wrong.

Request

Content type multipart/form-data:

filesfile[]required
The PDFs to merge, sent as repeated files parts. At least two are required; each filename must end in .pdf. Order is preserved.
optionsstring (JSON)optional
Reserved for merge options, but currently ignored — the merge runs with a fixed config (bookmarks, metadata and forms preserved, output compressed). Malformed JSON returns 400.Default: {}
async_processingbooleanoptional
Accepted but ignored — the merge always runs synchronously.Default: false

No enforced size or count caps

Only the “at least two PDFs” rule is enforced on this endpoint. Per-tier file/size limits are not applied here, so don’t rely on them.

Response

200 OK, application/json:

200 OK
{
  "job_id": "550e8400-e29b-41d4-a716-446655440000",
  "status": "completed",
  "output_url": "https://<r2-host>/merged/20260704/<uuid>.pdf",
  "pages": 42,
  "size": 1048576,
  "compression_ratio": null,
  "processing_time": 0.85,
  "message": "Merged successfully"
}
job_idstringoptional
A fresh UUID. Not queryable — the sync path stores no job, so the /{job_id}/status endpoint won’t resolve it. Download from output_url.
statusstringoptional
Always "completed".
output_urlstringoptional
Public R2 URL of the merged PDF. No expires_at is returned; the link is permanent under the default config.
pagesint | nulloptional
Total pages in the merged document.
sizeint | nulloptional
Output size in bytes.
compression_rationulloptional
Present in the schema but not set by this endpoint.
processing_timefloat | nulloptional
Seconds spent merging.
messagestringoptional
"Merged successfully".

The response header X-Credits-Charged reports the credits billed — 10 authenticated, 0 anonymous.

Examples

curl -X POST https://api.bytefuse.in/api/v1/pdf/merge/merge \
  -H "X-API-Key: dt_live_your_key" \
  -F "files=@chapter1.pdf" \
  -F "files=@chapter2.pdf" \
  -F "files=@chapter3.pdf"
# Omit the X-API-Key header to use the anonymous free-try path.

Errors

400Fewer than two files, a non-.pdf file, or malformed options JSON.
402 / 429 / 503Insufficient credits, rate limited, or capacity/config error.
500The merge engine failed unexpectedly.

See Split PDF for the inverse operation.