Programmatically import annotations into your PDF documents with our Instant JSON import API.
Add highlights, sticky notes, text boxes, shapes, and more with precise control over position, color, and page placement using a simple JSON format.
Automatically add annotations to PDF files in Google Drive using our Zapier integration. Just supply your annotation instructions in JSON, and the Nutrient API takes care of the rest.
Automate the annotation process across entire document workflows. Perfect for feedback loops, quality control, or digital signing preparation.
This example will import Instant JSON with annotations to PDF.
Try it out in three steps
annotations.pdf and annotations.json to your project folder.result.pdf to see the output.curl -X POST https://api.nutrient.io/build \ -H "Authorization: Bearer your_api_key_here" \ -o result.pdf \ --fail \ -F document=@document.pdf \ -F annotations.json=@annotations.json \ -F instructions='{ "parts": [ { "file": "document" } ], "actions": [ { "type": "applyInstantJson", "file": "annotations.json" } ] }'curl -X POST https://api.nutrient.io/build ^ -H "Authorization: Bearer your_api_key_here" ^ -o result.pdf ^ --fail ^ -F document=@document.pdf ^ -F annotations.json=@annotations.json ^ -F instructions="{\"parts\": [{\"file\": \"document\"}], \"actions\": [{\"type\": \"applyInstantJson\", \"file\": \"annotations.json\"}]}"package com.example.pspdfkit;
import java.io.File;import java.io.IOException;import java.nio.file.FileSystems;import java.nio.file.Files;import java.nio.file.StandardCopyOption;
import org.json.JSONArray;import org.json.JSONObject;
import okhttp3.MediaType;import okhttp3.MultipartBody;import okhttp3.OkHttpClient;import okhttp3.Request;import okhttp3.RequestBody;import okhttp3.Response;
public final class PspdfkitApiExample { public static void main(final String[] args) throws IOException { final RequestBody body = new MultipartBody.Builder() .setType(MultipartBody.FORM) .addFormDataPart( "document", "document.pdf", RequestBody.create( MediaType.parse("application/pdf"), new File("document.pdf") ) ) .addFormDataPart( "annotations.json", "annotations.json", RequestBody.create( MediaType.parse("application/json"), new File("annotations.json") ) ) .addFormDataPart( "instructions", new JSONObject() .put("parts", new JSONArray() .put(new JSONObject() .put("file", "document") ) ) .put("actions", new JSONArray() .put(new JSONObject() .put("type", "applyInstantJson") .put("file", "annotations.json") ) ).toString() ) .build();
final Request request = new Request.Builder() .url("https://api.nutrient.io/build") .method("POST", body) .addHeader("Authorization", "Bearer your_api_key_here") .build();
final OkHttpClient client = new OkHttpClient() .newBuilder() .build();
final Response response = client.newCall(request).execute();
if (response.isSuccessful()) { Files.copy( response.body().byteStream(), FileSystems.getDefault().getPath("result.pdf"), StandardCopyOption.REPLACE_EXISTING ); } else { // Handle the error throw new IOException(response.body().string()); } }}using System;using System.IO;using System.Net;using RestSharp;
namespace PspdfkitApiDemo{ class Program { static void Main(string[] args) { var client = new RestClient("https://api.nutrient.io/build");
var request = new RestRequest(Method.POST) .AddHeader("Authorization", "Bearer your_api_key_here") .AddFile("document", "document.pdf") .AddFile("annotations.json", "annotations.json") .AddParameter("instructions", new JsonObject { ["parts"] = new JsonArray { new JsonObject { ["file"] = "document" } }, ["actions"] = new JsonArray { new JsonObject { ["type"] = "applyInstantJson", ["file"] = "annotations.json" } } }.ToString());
request.AdvancedResponseWriter = (responseStream, response) => { if (response.StatusCode == HttpStatusCode.OK) { using (responseStream) { using var outputFileWriter = File.OpenWrite("result.pdf"); responseStream.CopyTo(outputFileWriter); } } else { var responseStreamReader = new StreamReader(responseStream); Console.Write(responseStreamReader.ReadToEnd()); } };
client.Execute(request); } }}// This code requires Node.js. Do not run this code directly in a web browser.
const axios = require('axios')const FormData = require('form-data')const fs = require('fs')
const formData = new FormData()formData.append('instructions', JSON.stringify({ parts: [ { file: "document" } ], actions: [ { type: "applyInstantJson", file: "annotations.json" } ]}))formData.append('document', fs.createReadStream('document.pdf'))formData.append('annotations.json', fs.createReadStream('annotations.json'))
;(async () => { try { const response = await axios.post('https://api.nutrient.io/build', formData, { headers: formData.getHeaders({ 'Authorization': 'Bearer your_api_key_here' }), responseType: "stream" })
response.data.pipe(fs.createWriteStream("result.pdf")) } catch (e) { const errorString = await streamToString(e.response.data) console.log(errorString) }})()
function streamToString(stream) { const chunks = [] return new Promise((resolve, reject) => { stream.on("data", (chunk) => chunks.push(Buffer.from(chunk))) stream.on("error", (err) => reject(err)) stream.on("end", () => resolve(Buffer.concat(chunks).toString("utf8"))) })}import requestsimport json
response = requests.request( 'POST', 'https://api.nutrient.io/build', headers = { 'Authorization': 'Bearer your_api_key_here' }, files = { 'document': open('document.pdf', 'rb'), 'annotations.json': open('annotations.json', 'rb') }, data = { 'instructions': json.dumps({ 'parts': [ { 'file': 'document' } ], 'actions': [ { 'type': 'applyInstantJson', 'file': 'annotations.json' } ] }) }, stream = True)
if response.ok: with open('result.pdf', 'wb') as fd: for chunk in response.iter_content(chunk_size=8096): fd.write(chunk)else: print(response.text) exit()<?php
$FileHandle = fopen('result.pdf', 'w+');
$curl = curl_init();
curl_setopt_array($curl, array( CURLOPT_URL => 'https://api.nutrient.io/build', CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_RETURNTRANSFER => true, CURLOPT_ENCODING => '', CURLOPT_POSTFIELDS => array( 'instructions' => '{ "parts": [ { "file": "document" } ], "actions": [ { "type": "applyInstantJson", "file": "annotations.json" } ] }', 'document' => new CURLFILE('document.pdf'), 'annotations.json' => new CURLFILE('annotations.json') ), CURLOPT_HTTPHEADER => array( 'Authorization: Bearer your_api_key_here' ), CURLOPT_FILE => $FileHandle,));
$response = curl_exec($curl);
curl_close($curl);
fclose($FileHandle);POST https://api.nutrient.io/build HTTP/1.1Content-Type: multipart/form-data; boundary=--customboundaryAuthorization: Bearer your_api_key_here
--customboundaryContent-Disposition: form-data; name="instructions"Content-Type: application/json
{ "parts": [ { "file": "document" } ], "actions": [ { "type": "applyInstantJson", "file": "annotations.json" } ]}--customboundaryContent-Disposition: form-data; name="document"; filename="document.pdf"Content-Type: application/pdf
(document data)--customboundaryContent-Disposition: form-data; name="annotations.json"; filename="annotations.json"Content-Type: application/json
(annotations.json data)--customboundary--The Instant JSON format is the native annotation format of the Nutrient API, and it defines an extensive number of annotation types and properties for your documents. Use this format to programmatically generate robust, feature-rich annotations for your documents.
Most common next steps
Use the following:
Get started:
Platform resources:
No input or resulting documents are stored on our infrastructure. All files are deleted as soon as a request finishes. Alternatively, check out our self-hosted product.
All communication between your application and Nutrient is done via HTTPS to ensure your data is encrypted when it’s sent to us.
All payments are handled by Paddle. Nutrient DWS Processor API never has direct access to any of your payment data.
A PDF annotations API lets you add and manage markup — highlights, comments, sticky notes, text boxes, shapes, and more — in PDF documents programmatically over REST. Nutrient DWS Processor API uses the Instant JSON format to apply annotations without manual editing, so you can automate annotation across entire document workflows.
The API supports a wide range of annotation types through the Instant JSON format, including highlights, sticky notes, comments, text boxes, shapes, and ink markup, with control over position, color, and page placement. See the Instant JSON reference for the full list of types and properties.
Yes. The API is REST-based, so it works from PHP as well as JavaScript, Python, Java, and HTTP (curl). Ready-to-use examples and a Postman collection help you send your first annotation request quickly from any of these languages.
Send your document along with Instant JSON annotation instructions to the Processor API, and it applies the annotations and returns the updated PDF. The getting started guide covers API key setup, and the Instant JSON reference documents the import format.
You can start free with Nutrient DWS credits — no credit card required — and test before scaling. See the Processor API pricing page for current credit details.
Create an account to get your DWS Processor API key and start making API calls.