Merging PDFs
Use the pdf endpoint to easily merge PDF documents into a combined PDF document.This tutorial uses the pdf endpoint to merge three pre-existing PDFs into a new combined PDF.
We first call the pdf endpoint directly using cURL from the command-line. We then use the DynamicPDF client libraries to illustrate merging using C#, Java, Node.js, PHP, GO, and Python.
Required Resources
To complete this tutorial, you must add the merge-pdfs-pdf-endpoint sample to your samples folder in your cloud storage space using the File Manager. After adding the sample resources, you should see a samples/merge-pdfs-pdf-endpoint folder containing the resources for this tutorial.
| Sample | Sample Folder | Resources |
|---|---|---|
| Merge PDFs | samples/merge-pdfs-pdf-endpoint | DocumentA.pdf, DocumentB.pdf, DocumentC.pdf, instructions.json |
- From you cloud storage space, use the File Manager to download
DocumentA.pdf,DocumentB.pdf, andinstructions.jsonto your local system; here we assume/temp/dynamicpdf-api-samples. - After downloading, delete the documents and instructions from
samples/merge-pdfs-pdf-endpointusing the File Manager. Be certain not to deleteDocumentC.pdf.
| Resource | Cloud/Local |
|---|---|
DocumentA.pdf | local |
DocumentB.pdf | local |
DocumentC.pdf | cloud |
instructions.json | local |
See Sample Resources for instructions on adding sample resources.
Obtaining API Key
This tutorial assumes a valid API key. Refer to the following for instructions on getting an API key.
If you are not familiar with the File Manager or Apps and API Keys, refer to the following tutorial and relevant Users Guide pages.
Calling API Directly Using POST
Merging resources into a new PDF requires using the pdf endpoint. The pdf endpoint uses an instructions JSON document you send to the endpoint. The endpoint then processes the instructions to create the resultant PDF. When you call the pdf endpoint directly, you must create an instructions document. When you use one of the DynamicPDF client libraries, then the client library hides the complexities of creating the instructions document from you.
Let's call the endpoint directly using an instructions document.
Instructions JSON
- Open the
instructions.jsondocument that you downloaded earlier in a text editor.
{
"author": "Alex Smith",
"inputs": [
{
"type": "pdf",
"resourceName": "DocumentA.pdf",
"startPage": 1,
"pageCount": 1
},
{
"type": "pdf",
"resourceName": "DocumentB.pdf"
},
{
"type": "pdf",
"resourceName": "samples/merge-pdfs-pdf-endpoint/DocumentC.pdf"
}
]
}
The most important part of an instructions document is the inputs array. This array is where you specify the inputs to the pdf endpoint. Here we are specifying that three PDF documents as the inputs. The first two we refer to by name only, as you will download them from your cloud storage space to your local system and then use them locally. Dynamic resources that change with every request should be uploaded with the request and not reside in your cloud storage. The last document you refer to by the resources' path in your cloud storage space using the File Manager.
As you see in the next section, when referring to a resource locally, you specify the resource's name in the instructions document and its path in the call to the endpoint. When referring to a resource in your cloud storage space, you specify the path of the resource in the File Manager.
Refer to JSON Instructions Schema or Instructions Schema Diagram for more information on creating instruction documents.
cURL Command
The pdf endpoint takes a POST request. When using cURL, you specify the endpoint, the HTTP command, the API key, any local resources required, and the instructions document. The following cURL command illustrates.
The tutorial's video uses Postman rather than the cURL command.
curl -X POST https://api.dpdf.io/v1.0/pdf
-H "Authorization:Bearer DP.xxx-api-key-xxx"
-F "Resource=@C:/temp/dynamicpdf-api-samples/DocumentA.pdf"
-F "Resource=@C:/temp/dynamicpdf-api-samples/DocumentB.pdf"
-F "Instructions=@C:/temp/dynamicpdf-api-samples/instructions.json"
-o merge-output.pdf
The cURL command places any errors in the output.pdf rather than command-line. If you cannot open the created PDF, try opening the PDF in a text editor to view the error message.
In the preceding command, the -H parameter specifies that a header variable named Authorization is sent to the endpoint. The two -F parameters specify that they are form fields with the name of Resource and then the value. The value of the two parameters specify the paths of both local resources.
If a filename in the cURL command does not match the filename in the instructions document, then add the filename by using a semicolon followed by the filename from the instructions document.
"Resource=@C:/temp/dynamicpdf-api-samples/DocumentB.pdf;MyDocument"
The -o parameter specifies the output file to write the response to.
- Execute the cURL command and the PDF is saved to your local system.

Figure 1. The merged PDF after the pdf endpoint processed.
Calling Endpoint Using Client Library
To simplify your development, you can also use one of the DynamicPDF API client libraries. Use the client library of your choice to complete this tutorial section.
Complete Source
You can access the complete source for this project at one of the following GitHub projects.
| Language | File Name | Location (package/namespace/etc.) | GitHub Project |
|---|---|---|---|
| Java | MergePdfs.java | com.dynamicpdf.api.examples | https://github.com/dynamicpdf-api/java-client-examples |
| C# | Program.cs | MergePdfs | https://github.com/dynamicpdf-api/dotnet-client-examples |
| Nodejs | MergePdfs.js | nodejs-client-examples | https://github.com/dynamicpdf-api/nodejs-client-examples |
| PHP | MergePdfs.php | php-client-examples | https://github.com/dynamicpdf-api/php-client-examples |
| GO | merge-pdfs.go | go-client-examples | https://github.com/dynamicpdf-api/go-client-examples/tree/main |
| Python | MergePdfs.py | python-client-examples | https://github.com/dynamicpdf-api/python-client-examples |
Click on the language tab of choice to view the tutorial steps for the particular language.
- C# (.NET)
- Java
- Node.js
- PHP
- GO
- Python
Available on NuGet:
Install-Package DynamicPDF.API
- Create a new Visual Studio C# Console App (.NET Core) project named
MergePdfs. - Add the DynamicPdf.Api Nuget package to the project.
- Create a new static method named
Runthat takes the API key and base path as strings. - Add the call to
RuntoMain. - In
Runcreate a newPdfinstance. - Add
DocumentA.pdfto thePdfinstance and get a reference to the returnedPdfInputinstance. - Set the
PdfInputinstance'sStartPageproperty to one and itsEndPageproperty to one. - Create a new
PdfResourceinstance and in its constructor set the path toDocumentC.pdf
Note the difference between how you add the PDFs. Use the AddPdf method to add a PDF that resides in your cloud storage space but use PdfResource to add a resource from the local system.
-
Create a call to the
Processmethod to return aPdfResponseinstance. -
Check to ensure the call is successful and then write the response's
Contentto a file.
using System;
using System.IO;
namespace MergePdfs
{
class Program
{
static void Main(string[] args)
{
Run("DP.xxx-api-key-xxx", "C:/temp/dynamicpdf-api-samples/");
}
public static void Run(String apiKey, String basePath)
{
// create new pdf instance and set api key
Pdf pdf = new Pdf();
pdf.ApiKey = apiKey;
//add pdf and get reference to PdfInput then set pages to append
var inputA = pdf.AddPdf(new PdfResource(basePath + "DocumentA.pdf"));
inputA.StartPage = 1;
inputA.PageCount = 1;
// add all of pdf from local system
pdf.AddPdf(new PdfResource(basePath + "DocumentB.pdf"));
// add pdf from cloud in resource manager
pdf.AddPdf("/samples/merge-pdfs-pdf-endpoint/DocumentC.pdf");
//call the pdf endpoint and get response
PdfResponse pdfResponse = pdf.Process();
// if successful, save merged pdf to file otherwise print JSON error
if(pdfResponse.IsSuccessful)
{
File.WriteAllBytes(Path.Combine(basePath, "merge-pdfs-output.pdf"), pdfResponse.Content);
} else
{
Console.WriteLine(pdfResponse.ErrorJson);
}
// process and get response from pdf endpoint
PdfResponse pdfResponse = pdf.Process();
// if the response is successful, save merged pdf to file if error, then printout JSON error
if(pdfResponse.IsSuccessful)
{
File.WriteAllBytes(Path.Combine(basePath, "merge-output.pdf"), pdfResponse.Content);
} else
{
Console.WriteLine(pdfResponse.ErrorJson);
}
}
}
- Run the application and the merged PDF is saved to your local system.
Available on NPM:
npm i @dynamicpdf/api
-
Use npm to install the DynamicPDF API module.
-
Create a new class named
MergePdfs. -
Create a static
Runmethod. -
Add a new instance of a
Pdfclass. -
Add
DocumentA.pdfto thePdfinstance and get a reference to the returnedPdfInputinstance. -
Set the
PdfInputinstance'sstartPageproperty to one and itsendPageproperty to one. -
Create a new
PdfResourceinstance and in its constructor set the path toDocumentC.pdf
Note the difference between how you add the PDFs. Use the AddPdf method to add a PDF that resides in your cloud storage space but use PdfResource to add a resource from the local system.
- Call
processto return aPdfResponseinstance. - Check to ensure the call is successful and then write the response's
contentto a file. - Add the
Runmethod call below theMergePdfclass definition.
import fs from 'fs';
import {
Pdf,
PdfResource,
PdfInput,
Endpoint
} from "@dynamicpdf/api"
export class MergePdfs {
static async Run() {
var pdf = new Pdf();
pdf.apiKey = "DP.xxx-api-key-xxx";
//add pdf from local system and obtain the reference to the pdfInput
var pdfInput = pdf.addPdf(new PdfResource("C:/temp/dynamicpdf-api-samples/DocumentA.pdf"));
//set the start page and page count so it returns one page
pdfInput.startPage = 1;
pdfInput.pageCount = 1;
//add the pdf from local system
pdf.addPdf(new PdfResource("C:/temp/dynamicpdf-api-samples/DocumentB.pdf"));
//add the pdf from File Manager
pdf.addPdf("samples/merge-pdfs-pdf-endpoint/DocumentC.pdf");
//call the endpoint and get response
var res = await pdf.process();
//if succsessful write response pdf to file otherwise print failure JSON
if (res.isSuccessful) {
var outFile = "C:/temp/dynamicpdf-api-samples/merge-pdfs-output.pdf";
var outStream = fs.createWriteStream(outFile);
outStream.write(res.content);
outStream.close();
} else {
console.log(res.errorJson);
}
}
}
await MergePdfs.Run();
- Run the application
node MergePdfs.jsand the merged PDF is written to your filesystem.
Available on Maven:
https://search.maven.org/search?q=g:com.dynamicpdf.api
<dependency>
<groupId>com.dynamicpdf.api</groupId>
<artifactId>dynamicpdf-api</artifactId>
<version>1.8.0</version>
</dependency>
- Create a new Maven project and add the DynamicPDF API as a dependency, also add the Apache Commons IO library.
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.8.0</version>
</dependency>
-
Create a new class named
MergePdfswith amainmethod. -
Create a new method named
Run. -
Add the
Runmethod call tomain. -
In
Runcreate a newPdfinstance. -
Add
DocumentA.pdfto thePdfinstance and get a reference to the returnedPdfInputinstance. -
Set the
PdfInputinstance'sStartPageproperty to one and itsEndPageproperty to one. -
Create a new
PdfResourceinstance and in its constructor set the path toDocumentC.pdfto add the PDF from your cloud storage space.
Note the difference between how you add the PDFs. Use the AddPdf method to add a PDF that resides in your cloud storage but use PdfResource to add a resource from the local system.
-
Create a call to the
processmethod to return aPdfResponseinstance. -
Check to ensure the call was successful and write the response's
Contentto a file.
package com.dynamicpdf.api.examples;
import java.io.File;
import java.io.IOException;
import org.apache.commons.io.FileUtils;
import com.dynamicpdf.api.Pdf;
import com.dynamicpdf.api.PdfInput;
import com.dynamicpdf.api.PdfResource;
import com.dynamicpdf.api.PdfResponse;
public class MergePdfs {
public static void main(String[] args) {
MergePdfs.Run("DP.xxx-api-key-xxx",
"C:/temp/dynamicpdf-api-samples/");
}
public static void Run(String apiKey, String basePath) {
// create new pdf instance and set api key
Pdf pdf = new Pdf();
pdf.setApiKey(apiKey);
// add pdf from local system where specify that only one page
// from DocumentA is to be merged.
PdfInput pdfInput = pdf.addPdf(new PdfResource(basePath + "DocumentA.pdf"));
pdfInput.setStartPage(1);
pdfInput.setPageCount(1);
// add all of DocumentB to the PDF to be created
pdf.addPdf(new PdfResource(basePath + "DocumentB.pdf"));
// add DocumentC from the cloud in File Manager
pdf.addPdf("samples/merge-pdfs-pdf-endpoint/DocumentC.pdf");
// call the endpoint and return the results
PdfResponse pdfResponse = pdf.process();
// if the response is successful, save merged pdf to file. if error, then
// printout JSON error
if (pdfResponse.getIsSuccessful()) {
try {
FileUtils.writeByteArrayToFile(new File(basePath + "merge-pdfs-output.pdf"), pdfResponse.getContent());
} catch (IOException e) {
e.printStackTrace();
}
} else {
System.out.println(pdfResponse.getErrorJson());
}
}
}
- Run the application and the merged PDF is saved to your local system.
Available as a Composer package:
composer require dynamicpdf/api
-
Use composer to ensure you have the required PHP libraries.
-
Create a new class named
MergePdfs. -
Add a
Runmethod. -
In
Runcreate a newPdfinstance. -
Add
DocumentA.pdfto aPdfResourceinstance and then add it to thePdfinstance -
Get a reference to the returned
PdfInputinstance. -
Set the
PdfInputinstance'sStartPageproperty to one and itsEndPageproperty to one. -
Add
DocumentB.pdfto aPdfResourceinstance and then add it to thePdfinstance. -
Add
DocumentC.pdfto thePdfinstance directly, as the PDF comes from your cloud storage.
Note the difference between how you add the PDFs. Use the AddPdf method to add a PDF that resides in the cloud in the File Manager but use PdfResource to add a resource from the local system.
-
Create a call to the
Processmethod to return aPdfResponseinstance. -
Ensure the call is successful and write the response's
Contentto a file.
require __DIR__ . '/vendor/autoload.php';
include_once("constants.php");
use DynamicPDF\Api\Pdf;
use DynamicPDF\Api\PdfResource;
class MergePdfs
{
public static function Run(string $apikey, string $path, string $output_path)
{
$pdf = new Pdf();
$pdf->ApiKey = $apikey;
$pdf->BaseUrl = "https://api-euw.dpdf.io/";
$pdfInput = $pdf->AddPdf(new PdfResource($path . "DocumentA.pdf"));
$pdfInput->StartPage = 1;
$pdfInput->PageCount = 1;
$pdf->AddPdf(new PdfResource($path . "DocumentB.pdf"));
$pdf->AddPdf("samples/merge-pdfs-pdf-endpoint/DocumentC.pdf");
$response = $pdf->Process();
if($response->IsSuccessful)
{
file_put_contents($output_path . "merge-pdfs-php-output.pdf", $response->Content);
} else {
echo("Error: ");
echo($response->StatusCode);
echo($response->ErrorJson);
}
}
}
MergePdfs::Run(CLIENT_EXAMPLES_API_KEY, CLIENT_EXAMPLES_BASE_PATH . "/merge-pdfs-pdf-endpoint/", CLIENT_EXAMPLES_OUTPUT_PATH);
- Run the application
php MergePdfs.phpand the merged PDF is saved to your local system.
Available a GO package: https://pkg.go.dev/github.com/dynamicpdf-api/go-client
- Ensure you have the required GO libraries
- Create a new class named
MergePdfs. - Add a
mainmethod. - In
maincreate a newPdfinstance. - Add
DocumentA.pdfto aPdfResourceinstance and then add it to thePdfinstance. - Get a reference to the returned
PdfInputinstance. - Set the
PdfInputinstance'sStartPageproperty to one and itsEndPageproperty to one. - Add
DocumentB.pdfto aPdfResourceinstance and then add it to thePdfinstance. - Add
DocumentC.pdfto thePdfinstance directly, as the PDF comes from your cloud storage. - Create a call to the
Processmethod to return aPdfResponseinstance. - Ensure the call is successful and write the response's
Contentto a file. - Run the application
go run MergePdfs.goand the merged PDF is saved to your local system.
package main
import (
"fmt"
"os"
"github.com/dynamicpdf-api/go-client/endpoint"
"github.com/dynamicpdf-api/go-client/input"
"github.com/dynamicpdf-api/go-client/resource"
)
func main() {
pr := endpoint.NewPdf()
pr.Endpoint.BaseUrl = "https://api.dpdf.io/"
pr.Endpoint.ApiKey = "DP.xxx-api-key-xxx"
basePath := "c:/temp/dynamicpdf-api-samples/"
pdfResource := resource.NewPdfResourceWithResourcePath(basePath+"DocumentA.pdf", "DocumentA.pdf")
prInput := input.NewPdfWithResource(pdfResource)
prInput.StartPage = 1
prInput.PageCount = 1
pr.Inputs = append(pr.Inputs, prInput)
pdfResource2 := resource.NewPdfResourceWithResourcePath(basePath+"DocumentB.pdf", "DocumentB.pdf")
prInput2 := input.NewPdfWithResource(pdfResource2)
pr.Inputs = append(pr.Inputs, prInput2)
mergeOption := input.NewMergeOptions()
prInput3 := input.NewPdfWithCloudPath("samples/merge-pdfs-pdf-endpoint/DocumentC.pdf", mergeOption)
pr.Inputs = append(pr.Inputs, prInput3)
resp := pr.Process()
res := <-resp
if res.IsSuccessful() == false {
if res.ClientError() != nil {
fmt.Print("Failed with error: " + res.ClientError().Error())
} else {
fmt.Print("Failed with error: " + res.ErrorJson())
}
} else {
os.WriteFile(basePath+"merge-pdfs-output.pdf",
res.Content().Bytes(), os.ModeType)
}
}
Available at: pip install dynamicpdf-api
- Ensure you have the required Python libraries
- Create a new file named
MergePdfs.py. - Add a
merge_pdfsmethod. - Create a new
Pdfinstance. - Add
DocumentA.pdfto aPdfResourceinstance and then add it to thePdfinstance. - Get a reference to the returned
PdfInputinstance. - Set the
PdfInputinstance'sStartPageproperty to one and itsEndPageproperty to one. - Add
DocumentB.pdfto aPdfResourceinstance and then add it to thePdfinstance. - Add
DocumentC.pdfto thePdfinstance directly, as the PDF comes from your cloud storage. - Create a call to the
Processmethod to return aPdfResponseinstance. - Ensure the call is successful and write the response's
Contentto a file. - Add the call to
merge_pdfs. - Run the application
python MergePdfs.pyand the merged PDF is saved to your local system.
from dynamicpdf_api.pdf import Pdf
from dynamicpdf_api.pdf_resource import PdfResource
def merge_pdfs():
basePath = "C:/temp/dynamicpdf-api-samples/"
pdf=Pdf()
pdf.api_key="DP.xxx-api-key-xxx"
inputA = pdf.add_pdf(PdfResource(basePath + "DocumentA.pdf"))
inputA.start_page = 1
inputA.page_count = 2
pdf.add_pdf(PdfResource(basePath + "DocumentB.pdf"))
pdf.add_pdf("samples/merge-pdfs-pdf-endpoint/DocumentC.pdf")
response = pdf.process()
if response.is_successful:
with open(basePath + "merge-pdfs-output-python.pdf", "wb") as output_file:
output_file.write(response.content)
else:
print(response.error_id)
print(response.error_message)
print(response.error_json)
merge_pdfs()
In all six languages, the steps were similar. First, we created a new instance of the Pdf class, which abstracts the pdf endpoint. This Pdf instance holds the merged PDF after processing. We then added two local resources, DocumentA.pdfand DocumentB.pdf, to the pdf endpoint. We first created a PdfResource instance to add these local resources and then added the PdfResource instance to the Pdf instance. Because we only wanted the first page of DocumentA.pdf, we obtained a reference to the returned PdfInput. By getting a reference to the PdfInput object containing DocumentA.pdf, we could add merge instructions specifying only to use the first page.
We then added DocumentC.pdf, but rather than first creating a PdfResource instance, we added the resource directly to the Pdf instance using its AddPdf method.
The difference between adding local resources and adding cloud resources in the File Manager bears repeating. Add local resources by first creating a PdfResource instance that loads the resource and then adding the PdfResource instance to the Pdf instance using its AddPdf method. Add cloud resources in File Manager by calling AddPdf and passing the path in File Manager as a string.
After adding all the resources to the Pdf instance, we then call the endpoint using the Process method and obtain the response from the endpoint. Finally, we ensured the call was successful and wrote the response's content to a PDF file.