Add Outlines and Bookmarks to PDFs
Add bookmarks to new PDF and existing PDFs using the pdf endpoint.
The DynamicPDF API's pdf
endpoint makes adding bookmarks to a PDF straight-forward. You can create new bookmarks and attach pre-existing bookmarks. The following example illustrates both ways to create bookmarks.
Check out Getting Started and Task Roadmap if you are new to The DynamicPDF API.
Refer to the documentation for more information on working with outlines (JSON Instructions Schema - outlines).
Calling Endpoint Directly
The following JSON instructions document illustrates creating three new PDFs and adding new bookmarks. It also merges an existing PDF containing an outline and adds it to the newly created one. The following instructions document defines the following processing instructions:
- defines three
page
inputs that each creates a single-page PDF, - defines a
pdf
input that uploads an existing PDF with a pre-existing outline, - defines an outline that creates three new bookmarks for the three created PDFs,
- appends the existing PDF's outline to the created outline,
- and then merge the four documents into one combined PDF containing the new outline.
"inputs": [
{
"type": "page",
"pageWidth": 612,
"pageHeight": 792,
"elements": [
{
"type": "text",
"text": "Hello World 1",
"placement": "topCenter"
}
],
"id": "a"
},
{
"type": "page",
"pageWidth": 612,
"pageHeight": 792,
"elements": [
{
"type": "text",
"text": "Hello World 2",
"placement": "topCenter"
}
],
"id": "b"
},
{
"type": "page",
"pageWidth": 612,
"pageHeight": 792,
"elements": [
{
"type": "text",
"text": "Hello World 3",
"placement": "topCenter"
}
],
"id": "c"
},
{
"type": "pdf",
"mergeOptions": {
"outlines": false
},
"resourceName": "PdfOutlineInput.pdf",
"id": "pdfoutlineinput"
}
],
"outlines": [
{
"text": "Root Outline",
"children": [
{
"text": "Page 1",
"linkTo": {
"inputID": "a",
"pageOffset": 0,
"pageZoom": "fitPage"
}
},
{
"text": "Page 2",
"linkTo": {
"inputID": "b",
"pageOffset": 0,
"pageZoom": "fitPage"
}
},
{
"text": "Page 3",
"linkTo": {
"inputID": "c",
"pageOffset": 0,
"pageZoom": "fitPage"
}
},
{
"fromInputID": "pdfoutlineinput"
}
]
}
]
}
curl --location 'https://api.dpdf.io/v1.0/pdf'
--header 'Authorization: Bearer DP--api-key--
--form 'Instructions=@C:/temp/solutions/outlines/instructions.json'
--form 'Resource=@C:/temp/solutions/outlines/PdfOutlineInput.pdf'
You can also add other elements to an outline such as URLs, using the linkTo
property.
Calling Endpoint Using Client Library
You can also use one of the client libraries rather than calling the pdf
endpoint directly. The following example illustrates.
- C# (.NET)
- Java
- Node.js
- PHP
- GO
- Python
public static void Run(string apiKey, string basePath, string outputPath)
{
Pdf pdf = new Pdf();
pdf.ApiKey = apiKey;
PageInput pageInput = pdf.AddPage();
TextElement element = new TextElement("Hello World 1", ElementPlacement.TopCenter);
pageInput.Elements.Add(element);
PageInput pageInput1 = pdf.AddPage();
TextElement element1 = new TextElement("Hello World 2", ElementPlacement.TopCenter);
pageInput1.Elements.Add(element1);
PageInput pageInput2 = pdf.AddPage();
TextElement element2 = new TextElement("Hello World 3", ElementPlacement.TopCenter);
pageInput2.Elements.Add(element2);
var inputA = pdf.AddPdf(new PdfResource(basePath + "PdfOutlineInput.pdf"));
inputA.Id = "pdfoutlineinput";
Outline rootOutline = pdf.Outlines.Add("Root Outline");
rootOutline.Children.Add("Page 1", pageInput);
rootOutline.Children.Add("Page 2", pageInput1);
rootOutline.Children.Add("Page 3", pageInput2);
rootOutline.Children.AddPdfOutlines(inputA);
PdfResponse pdfResponse = pdf.Process();
if (pdfResponse.IsSuccessful)
{
File.WriteAllBytes(outputPath + "/outlines-output.pdf", pdfResponse.Content);
}
else
{
Console.WriteLine(pdfResponse.ErrorJson);
}
}
static async Run() {
var basePath = "C:/temp/dynamicpdf-api-samples/outlines/";
var apiKey = "DP.--api-key--";
var pdf = new Pdf();
pdf.basePath = "https://api.dpdf.io/";
pdf.apiKey = apiKey;
var pageInput1 = pdf.addPage();
var element1 = new TextElement("Hello World 2", elementPlacement.topCenter);
pageInput1.elements.push(element1);
var pageInput2 = pdf.addPage();
var element2 = new TextElement("Hello World 3", elementPlacement.topCenter);
pageInput2.elements.push(element2);
var inputA = pdf.addPdf(new PdfResource(basePath + "PdfOutlineInput.pdf"));
var res = await pdf.process();
if (res.isSuccessful) {
var outFile = basePath + "outlines-output.pdf";
var outStream = fs.createWriteStream(outFile);
outStream.write(res.content);
outStream.close();
}
}
public static void Run(String apiKey, String basePath) {
Pdf pdf = new Pdf();
pdf.setApiKey(apiKey);
PageInput pageInput = pdf.addPage();
TextElement element = new TextElement("Hello World 1", ElementPlacement.TOPCENTER);
pageInput.getElements().add(element);
PageInput pageInput1 = pdf.addPage();
TextElement element1 = new TextElement("Hello World 2", ElementPlacement.TOPCENTER);
pageInput1.getElements().add(element1);
PageInput pageInput2 = pdf.addPage();
TextElement element2 = new TextElement("Hello World 3", ElementPlacement.TOPCENTER);
pageInput2.getElements().add(element2);
PdfInput inputA = pdf.addPdf(new PdfResource(basePath + "PdfOutlineInput.pdf"));
inputA.setId("pdfoutlineinput");
Outline rootOutline = pdf.getOutlines().add("Root Outline");
rootOutline.getChildren().add("Page 1", pageInput);
rootOutline.getChildren().add("Page 2", pageInput1);
rootOutline.getChildren().add("Page 3", pageInput2);
rootOutline.getChildren().addPdfOutlines(inputA);
PdfResponse response = pdf.process();
if(response.getIsSuccessful())
{
try {
FileUtils.writeByteArrayToFile(new File(DynamicPdfCloudApiExamples.OUTPUT_PATH + "/outlines-output.pdf"),
response.getContent());
} catch (IOException e) {
e.printStackTrace();
}
} else
{
System.out.println(response.getErrorJson());
}
}
public static function Run(string $apikey, string $path, string $outputPath)
{
$pdf = new Pdf();
$pdf->Author = "John Doe";
$pdf->Title = "Sample Pdf";
$pdf->ApiKey =$apikey;
$pageInput = $pdf->AddPage();
$element = new TextElement("Hello World 1", ElementPlacement::TopCenter);
array_push($pageInput->Elements, $element);
$pageInput1 = $pdf->AddPage();
$element1 = new TextElement("Hello World 2", ElementPlacement::TopCenter);
array_push($pageInput1->Elements, $element1);
$pageInput2 = $pdf->AddPage();
$element2 = new TextElement("Hello World 3", ElementPlacement::TopCenter);
array_push($pageInput2->Elements, $element2);
$rootOutline = $pdf->Outlines->Add("Root Outline");
$rootOutline->Children->Add("Page 1", $pageInput);
$rootOutline->Children->Add("Page 2", $pageInput1);
$rootOutline->Children->Add("Page 3", $pageInput2);
$inputA = $pdf->AddPdf(new PdfResource($path . "PdfOutlineInput.pdf"));
$rootOutline->Children->AddPdfOutlines($inputA);
$pdfResponse = $pdf->Process();
if($pdfResponse->IsSuccessful)
{
echo($pdfResponse->ErrorMessage);
}
file_put_contents($outputPath . "outlines-output.pdf", $pdfResponse->Content);
}
func main() {
pr := endpoint.NewPdf()
pr.Endpoint.ApiKey = apiKey
pageInput := pr.AddPage()
textElement := element.NewText("Hello World 1", element.TopCenter, 0, 0)
pageInput.Elements = append(pageInput.Elements, textElement)
pageInput2 := pr.AddPage()
textElement2 := element.NewText("Hello World 2", element.TopCenter, 0, 0)
pageInput2.Elements = append(pageInput2.Elements, textElement2)
pageInput3 := pr.AddPage()
textElement3 := element.NewText("Hello World 3", element.TopCenter, 0, 0)
pageInput3.Elements = append(pageInput3.Elements, textElement3)
outline := pr.Outlines.Add("Root Outline")
outline.Children().AddWithInputValue("Page 1", pageInput.Input, 0, endpoint.FitPage)
outline.Children().AddWithInputValue("Page 2", pageInput2.Input, 0, endpoint.FitPage)
outline.Children().AddWithInputValue("Page 3", pageInput3.Input, 0, endpoint.FitPage)
pdfResource := resource.NewPdfResourceWithResourcePath(basePath+"PdfOutlineInput.pdf", "PdfOutlineInput.pdf")
mergeOptions := input.NewMergeOptions()
outlines := false
mergeOptions.Outlines = &outlines
pdfInput := pr.AddPdf(pdfResource, mergeOptions)
pdfInput.Input.SetId("pdfoutlineinput")
outline.Children().AddPdfOutlines(*pdfInput)
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.Remove(outputPath)
os.WriteFile(outputPath, res.Content().Bytes(), os.ModeType)
}
}
def outlines_solution(apikey, full_path):
pdf = Pdf()
pdf.api_key = apikey
pdf.author = "John Doe"
pdf.title = "Sample Pdf"
pageInput = pdf.add_page()
element = TextElement("Hello World 1", ElementPlacement.TopCenter)
pageInput.elements.append(element)
pageInput1 = pdf.add_page()
element1 = TextElement("Hello World 2", ElementPlacement.TopCenter)
pageInput2 = pdf.add_page()
element2 = TextElement("Hello World 3", ElementPlacement.TopCenter)
pageInput2.elements.append(element2)
rootOutline = pdf.outlines.add("Root Outline")
rootOutline.children.add("Page 1", pageInput)
rootOutline.children.add("Page 2", pageInput1)
rootOutline.children.add("Page 3", pageInput2)
inputA = pdf.add_pdf(PdfResource(full_path + "PdfOutlineInput.pdf"))
inputA.id = "pdfoutlineinput"
rootOutline.children.add_pdf_outlines(inputA)
response = pdf.process()
if response.is_successful:
with open(output_path + "outlines-output.pdf", "wb") as output_file:
output_file.write(response.content)
else:
print(response.error_id)
The pdf
endpoint takes a JSON instructions document that provides instructions for creating, transforming, merging, and formatting inputs into a combined PDF. Refer to documentation on the instructions schema for information on how to use the pdf
endpoint.