PDF Merger
API Documentation
Merge multiple PDF files with three merging strategies โ sequential, specific pages, and alternate pages โ over a simple REST API. Perfect for document assembly, report generation, and content organization.
Overview
The PDF Merger API combines multiple PDF documents into a single output file. It supports three merging strategies: sequential (append all documents in order), specific (extract selected pages from each document), and alternate (interleave pages across documents). Upload your files as multipart/form-data and receive the merged PDF as a download.
Base URL & Authentication
Base URL
Base URL
https://api.chemhub.com/api/v1
Authentication
Include your API credentials in every request header. The health check endpoint does not require authentication.
Headers
X-API-Key: your_api_key
X-API-Secret: your_secret
Content-Type: application/json
Get API Keys
Follow these steps to obtain your API credentials:
Access Your Profile
Once you log in, click on your profile picture in the top-right corner, then click on "Your profile" from the dropdown menu.
Create API Key
From your profile page, proceed to the "API Keys" section and create a key by filling in a name you prefer.
"Report assembler" or "Document merger bot"
Save Your Credentials
Click on "Create API Key" to generate your credentials, then immediately copy and save both the API Key and Secret.
Your secret key will only be displayed once! Copy it immediately and store it securely. You won't be able to see it again.
Never share your API keys publicly or commit them to version control. Treat them like passwords โ regenerate immediately if compromised.
Free tier: 150 requests/day | Pro tier: 1000 requests/day. Check your dashboard for current usage and limits.
Endpoints
GET /pdf/healthPOST /pdf/mergeHealth Check
Health check endpoint to verify the PDF processing service status. This endpoint does not require authentication.
Response
Success Response
{
"success": true,
"status": "healthy",
"pdf_backends": {
"pypdf": true
},
"supported_formats": [".pdf"],
"max_file_size_mb": 50,
"max_files": 10,
"timestamp": "2026-07-23T12:00:00"
}
Code Examples
Python
import requests
url = "https://api.chemhub.com/api/v1/pdf/health"
res = requests.get(url)
print(res.json())
cURL
curl -X GET https://api.chemhub.com/api/v1/pdf/health
JavaScript
fetch('https://api.chemhub.com/api/v1/pdf/health')
.then(res => res.json())
.then(console.log);
Merge PDFs
Merge multiple PDF files into a single document. Upload the files as multipart/form-data.
Form Parameters
| Field | Type | Default | Description |
|---|---|---|---|
files | File[] | โ | PDF files to merge (required, 2โ10 files) |
merge_type | string | sequential | Merging strategy โ sequential, specific, alternate |
page_specs | string | โ | Required for specific โ JSON mapping file index to 0-indexed pages (e.g. {"0":[0,2],"1":[1,3]}) |
On success the endpoint returns the merged PDF bytes directly with Content-Type: application/pdf as a download named merged.pdf.
Page numbers in page_specs are 0-indexed (page 1 = 0). File indices correspond to the order files were uploaded ("0" = first file).
cURL Example (Sequential)
cURL
curl -X POST "https://api.chemhub.com/api/v1/pdf/merge" \
-H "X-API-Key: your_api_key" \
-H "X-API-Secret: your_secret" \
-F "files=@document1.pdf" \
-F "files=@document2.pdf" \
-F "merge_type=sequential" \
--output merged.pdf
cURL Example (Specific Pages)
cURL
curl -X POST "https://api.chemhub.com/api/v1/pdf/merge" \
-H "X-API-Key: your_api_key" \
-H "X-API-Secret: your_secret" \
-F "files=@document1.pdf" \
-F "files=@document2.pdf" \
-F "merge_type=specific" \
-F 'page_specs={"0":[0,2],"1":[1,3]}' \
--output custom_merged.pdf
Code Examples
Python
import requests
url = "https://api.chemhub.com/api/v1/pdf/merge"
headers = {
"X-API-Key": "your_api_key",
"X-API-Secret": "your_secret"
}
# Sequential merge
files = [
("files", open("document1.pdf", "rb")),
("files", open("document2.pdf", "rb")),
]
data = {"merge_type": "sequential"}
response = requests.post(url, headers=headers, files=files, data=data)
if response.status_code == 200:
with open("merged.pdf", "wb") as out:
out.write(response.content)
print("PDFs merged successfully!")
else:
print(response.json())
JavaScript
const form = new FormData();
form.append('files', fileInput1.files[0]);
form.append('files', fileInput2.files[0]);
form.append('merge_type', 'sequential');
fetch('https://api.chemhub.com/api/v1/pdf/merge', {
method: 'POST',
headers: {
'X-API-Key': 'your_api_key',
'X-API-Secret': 'your_secret'
},
body: form
})
.then(async res => {
if (res.ok) {
const blob = await res.blob();
const url = URL.createObjectURL(blob);
console.log('Merged PDF:', url);
} else {
console.log(await res.json());
}
});
Merge Strategies
Select the merging strategy with the merge_type form parameter.
Sequential (default)
Appends all uploaded PDFs end-to-end in the order they were provided, creating a single continuous document.
Specific
Extracts only the selected pages from each document. Requires the page_specs parameter as a JSON object mapping file index (in upload order, starting at "0") to an array of 0-indexed page numbers.
page_specs Format
{
"0": [0, 2],
"1": [1, 3]
}
Alternate
Interleaves pages across all documents โ takes the first page of each file, then the second page of each, and so on. Ideal for custom interleaved layouts.
Use sequential for assembling complete documents, specific for selective content extraction, and alternate for interleaving content from multiple sources.
Python SDK
Complete Python SDK covering health checks and all three merge strategies.
Complete SDK Class
import requests
import os
BASE_URL = "https://api.chemhub.com/api/v1"
API_KEY = "YOUR_API_KEY"
API_SECRET = "YOUR_API_SECRET"
headers = {
"X-API-Key": API_KEY,
"X-API-Secret": API_SECRET
}
# --- Health Check (no auth required) ---
def check_health():
return requests.get(f"{BASE_URL}/pdf/health").json()
# --- Merge PDFs ---
def merge_pdfs(pdf_files, merge_type="sequential", page_specs=None, output_path="merged.pdf"):
files = [("files", open(pdf, "rb")) for pdf in pdf_files]
data = {"merge_type": merge_type}
if merge_type == "specific" and page_specs:
data["page_specs"] = page_specs
response = requests.post(
f"{BASE_URL}/pdf/merge",
headers=headers,
files=files,
data=data
)
if response.status_code == 200:
with open(output_path, "wb") as f:
f.write(response.content)
print(f"Merged PDF saved to: {output_path}")
return output_path
else:
print(f"Error: {response.status_code} - {response.text}")
return None
# --- Test all strategies ---
if __name__ == "__main__":
print("=== PDF MERGER API TEST ===")
health = check_health()
print(f"Health: {health.get('status', 'unknown')}")
pdfs = ["document1.pdf", "document2.pdf"]
print("\n1. Sequential merge:")
merge_pdfs(pdfs, merge_type="sequential", output_path="merged_sequential.pdf")
print("\n2. Specific pages merge:")
merge_pdfs(pdfs, merge_type="specific",
page_specs='{"0":[0,2],"1":[1,3]}',
output_path="merged_specific.pdf")
print("\n3. Alternate pages merge:")
merge_pdfs(pdfs, merge_type="alternate", output_path="merged_alternate.pdf")
Errors & Status Codes
Error Response Format
Error Response
{
"success": false,
"error": "Invalid merge type",
"message": "Supported types: sequential, alternate, specific"
}
Status Codes
200Success โ merged PDF returned400Bad request / invalid merge_type / invalid page_specs / unsupported file format401Invalid or missing API key/secret429Rate limit exceeded500Internal server error / merge failed503PDF merger service unavailable on this server