Merge PDF files online in the order you choose
Merge PDF Files combines two or more PDF file references into one downloadable document while preserving the exact order supplied.
Run — free
Runs in your browser. Free, unlimited — your data never leaves this page.
It also reports the total number of pages in the finished file, making the result easy to validate inside an automated workflow. The operation is deterministic, runs without a network request or external model, and rejects incomplete requests before processing. Use it when several independently produced documents must become one predictable handoff, archive item, submission, or customer download.
Put every source file in the intended order
Begin by collecting the PDF references that belong in the final document. The position of each reference matters: every page from the first file comes first, followed by every page from the second file, and so on through the list. This makes the input suitable for document packs whose sequence carries meaning, such as a cover sheet followed by a contract, appendices, and a signature record. Review the list before running the merge because the capability does not guess a preferred order from filenames, creation metadata, or page contents. At least two files are required; a single file is rejected because no merge would occur. Each reference must identify PDF data that the deterministic parser can read. Keeping that contract explicit avoids silent sorting and makes repeated automation predictable. If a workflow builds the array programmatically, assign the order at the point where business rules are known rather than relying on directory listings, upload timing, or incidental object-key order.
Understand how pages and output are handled
The merger reads the page objects in each source, carries their page dimensions and content into a newly serialized PDF, and builds a fresh page tree and cross-reference table for the combined document. It does not contact a conversion service, introduce randomness, or stamp the current date into the result, so identical inputs in the same sequence produce identical output. The response includes the merged PDF as a file-compatible data reference, the number of input files, and the total page count. That page total is calculated from the pages actually accepted into the output, not copied from a client-provided claim. The initial beta implementation deliberately accepts self-contained pages without external page resources; it rejects structures that it cannot preserve safely instead of returning a document with missing fonts or graphics. This constraint makes failures clear and prevents a superficially valid but visually incomplete result. When a source is rejected, inspect how that PDF was produced or normalize it before trying the merge again.
Validate and automate the finished document
After a successful call, compare total_page_count with the number expected by the upstream workflow. A contract package assembled from a two-page agreement, a four-page schedule, and a one-page signature sheet should report seven pages. That small check catches missing sources before the merged document is archived, emailed, or sent for signature. The file_count field offers a second validation point for systems that know how many components should have arrived. Because the operation is pure and deterministic, it is also easy to place behind a retry: the same ordered input will not produce a differently ordered document. API automation costs $0.002 per request, while the browser path can use the same core logic. Keep original files until downstream acceptance is confirmed, give the combined file a meaningful name in the receiving system, and log the ordered reference identifiers rather than the complete PDF data when an audit trail is required. Sensitive document contents should not be copied into ordinary application logs.
What you can do with it
Assemble a contract package
Combine an agreement, its schedules, and the signature sheet in the legally reviewed order, then verify the resulting page total.
Create one customer download
Join a cover letter, invoice, and supporting statements so a customer downloads one organized PDF instead of several attachments.
Prepare an archive submission
Merge independently generated reports into a single retention item and record both the source-file count and final page count.
FAQ
How many PDF files are required?
At least two PDF references are required. Requests containing zero files, one file, or a non-array value return an invalid input error.
Does the order of the input list matter?
Yes. Files are processed from first to last, and every page from each file is placed before pages from the next file.
How is the total page count calculated?
The parser counts the readable page objects accepted from every source and reports their sum as total_page_count.
What does an automated merge cost?
Each API request costs $0.002. There is no per-page surcharge declared for this capability.
Will unsupported PDF structures be ignored?
No. The beta parser rejects page structures it cannot preserve safely, which prevents incomplete or misleading output.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, by email and from Telegram — and soon from our app too.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/pdf/merge-files \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"files":["https://ejemplo.com/archivo.bin","https://ejemplo.com/archivo-2.bin"]}'const res = await fetch("https://api.kit.forhosting.com/pdf/merge-files", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"files": [
"https://ejemplo.com/archivo.bin",
"https://ejemplo.com/archivo-2.bin"
]
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/pdf/merge-files",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"files": [
"https://ejemplo.com/archivo.bin",
"https://ejemplo.com/archivo-2.bin"
]
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/pdf/merge-files", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"files":["https://ejemplo.com/archivo.bin","https://ejemplo.com/archivo-2.bin"]}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"files":["https://ejemplo.com/archivo.bin","https://ejemplo.com/archivo-2.bin"]}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/pdf/merge-files", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"files": [
"https://ejemplo.com/archivo.bin",
"https://ejemplo.com/archivo-2.bin"
]
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "pdf.merge_files",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_mb | 25 |
max_pages | 200 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |