PDF form filling API
Use the PDF form filling API to populate existing PDF form fields with data. The /build endpoint handles form filling. Add the source PDF as a parts item, and apply an Instant JSON file that contains formFieldValues.
For signup, pricing, and task-level examples, refer to the PDF form filling API task page.
Fill form fields with Instant JSON
The following example fills fields in forms.pdf with form_filling.json and writes the output to result.pdf:
curl -X POST https://api.nutrient.io/build \ -H "Authorization: Bearer your_api_key_here" \ -o result.pdf \ --fail \ -F document=@form.pdf \ -F form_filling.json=@form_filling.json \ -F instructions='{ "parts": [ { "file": "document" } ], "actions": [ { "type": "applyInstantJson", "file": "form_filling.json" } ] }'curl -X POST https://api.nutrient.io/build ^ -H "Authorization: Bearer your_api_key_here" ^ -o result.pdf ^ --fail ^ -F document=@form.pdf ^ -F form_filling.json=@form_filling.json ^ -F instructions="{\"parts\": [{\"file\": \"document\"}], \"actions\": [{\"type\": \"applyInstantJson\", \"file\": \"form_filling.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", "form.pdf", RequestBody.create( MediaType.parse("application/pdf"), new File("form.pdf") ) ) .addFormDataPart( "form_filling.json", "form_filling.json", RequestBody.create( MediaType.parse("application/json"), new File("form_filling.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", "form_filling.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", "form.pdf") .AddFile("form_filling.json", "form_filling.json") .AddParameter("instructions", new JsonObject { ["parts"] = new JsonArray { new JsonObject { ["file"] = "document" } }, ["actions"] = new JsonArray { new JsonObject { ["type"] = "applyInstantJson", ["file"] = "form_filling.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: "form_filling.json" } ]}))formData.append('document', fs.createReadStream('form.pdf'))formData.append('form_filling.json', fs.createReadStream('form_filling.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('form.pdf', 'rb'), 'form_filling.json': open('form_filling.json', 'rb') }, data = { 'instructions': json.dumps({ 'parts': [ { 'file': 'document' } ], 'actions': [ { 'type': 'applyInstantJson', 'file': 'form_filling.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": "form_filling.json" } ] }', 'document' => new CURLFILE('form.pdf'), 'form_filling.json' => new CURLFILE('form_filling.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": "form_filling.json" } ]}--customboundaryContent-Disposition: form-data; name="document"; filename="form.pdf"Content-Type: application/pdf
(document data)--customboundaryContent-Disposition: form-data; name="form_filling.json"; filename="form_filling.json"Content-Type: application/json
(form_filling.json data)--customboundary--Create the form filling JSON
The Instant JSON file must include a formFieldValues array. Each item identifies a form field by its field name and provides the value to set.
Use this Instant JSON structure to fill text fields:
{ "formFieldValues": [ { "name": "First Name", "type": "pspdfkit/form-field-value", "v": 1, "value": "John" }, { "name": "Last Name", "type": "pspdfkit/form-field-value", "v": 1, "value": "Appleseed" }, { "name": "Email", "type": "pspdfkit/form-field-value", "v": 1, "value": "john.appleseed@example.com" } ], "format": "https://pspdfkit.com/instant-json/v1"}The field name must match the form field name in the PDF and not only the visible label next to the field.
Fill checkboxes, radio buttons, and choice fields
For checkboxes, radio buttons, list boxes, and combo boxes, use the field’s export value. Depending on the field type, the value can be a string or an array of strings.
Use this Instant JSON structure to fill choice-based fields:
{ "formFieldValues": [ { "name": "Newsletter", "type": "pspdfkit/form-field-value", "v": 1, "value": "Choice1" }, { "name": "Knowledge Level", "type": "pspdfkit/form-field-value", "v": 1, "value": ["Beginner"] }, { "name": "Select Days", "type": "pspdfkit/form-field-value", "v": 1, "value": ["Wednesday"] } ], "format": "https://pspdfkit.com/instant-json/v1"}For checkboxes and radio buttons, the PDF form field defines the on-state value. Common values include Yes, On, Checked, or a custom export value. Use the exact value defined in the PDF.
Fill a form from URLs
For remotely hosted source files, send a JSON request and pass URLs for both the PDF and the Instant JSON file. Use this instructions object:
{ "parts": [ { "file": { "url": "https://example.com/forms.pdf" } } ], "actions": [ { "type": "applyInstantJson", "file": { "url": "https://example.com/form_filling.json" } } ]}Shell
Run this request to fill a form from URLs:
curl -X POST https://api.nutrient.io/build \ -H "Authorization: Bearer $NUTRIENT_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "parts": [ { "file": { "url": "https://example.com/forms.pdf" } } ], "actions": [ { "type": "applyInstantJson", "file": { "url": "https://example.com/form_filling.json" } } ] }' \ -o result.pdfAdd a visual signature appearance
You can use Instant JSON to add an image annotation over a signature field, such as a drawn signature image. This creates a visual signature appearance in the document.
Use this Instant JSON structure to add a visual signature appearance:
{ "annotations": [ { "type": "pspdfkit/image", "v": 2, "pageIndex": 0, "bbox": [72, 700, 200, 48], "contentType": "image/png", "imageAttachmentId": "signature-image", "isSignature": true } ], "attachments": { "signature-image": { "binary": "<base64-encoded-png>", "contentType": "image/png" } }, "format": "https://pspdfkit.com/instant-json/v1"}A visual signature appearance differs from a cryptographic digital signature. To cryptographically sign a PDF, use the Processor API digital signature endpoint. For digital signing workflows, refer to the PDF digital signature API guide.
Flatten filled forms
If the filled form should no longer be editable, add a flatten action after applyInstantJson. Actions run in the order specified in the actions array.
Use this instructions object to fill and flatten a form:
{ "parts": [ { "file": "document" } ], "actions": [ { "type": "applyInstantJson", "file": "form_filling.json" }, { "type": "flatten" } ]}Flattening turns annotations and form appearances into regular page content. Use it only when the output no longer needs to remain editable.
Fill password-protected forms
If the source PDF is password-protected, include the password on the part. Use this instructions object:
{ "parts": [ { "file": "protected_form", "password": "document-password" } ], "actions": [ { "type": "applyInstantJson", "file": "form_filling.json" } ]}Nutrient DWS Processor API uses the password only to open the source document for processing. To set a password on the output PDF, configure output.user_password, output.owner_password, and output.user_permissions.
Combine form filling with other actions
The /build endpoint can fill forms and then apply additional actions. For example, you can fill a form, flatten it, and then add a watermark.
Use this instructions object to combine form filling with other actions:
{ "parts": [ { "file": "document" } ], "actions": [ { "type": "applyInstantJson", "file": "form_filling.json" }, { "type": "flatten" }, { "type": "watermark", "text": "COMPLETED", "width": "50%", "height": "20%", "opacity": 0.3, "rotation": 45 } ]}For workflows that include cryptographic signing, fill the form and optionally flatten it before signing the final PDF.
Reference
A PDF form filling request uses the Build API applyInstantJson action with an Instant JSON file that contains formFieldValues:
type FormFieldValue = { name: string, type: "pspdfkit/form-field-value", v: 1, value: string | string[],};
type InstantJsonFormFilling = { formFieldValues: FormFieldValue[], annotations?: object[], attachments?: Record<string, object>, format: "https://pspdfkit.com/instant-json/v1",};
type ApplyInstantJsonAction = { type: "applyInstantJson",
// Multipart field name, or a remote URL object pointing to Instant JSON. file: string | { url: string },};
type FilePart = { // Multipart field name, or a remote URL object. file: string | { url: string },
// Optional password for encrypted input PDFs. password?: string,};
type BuildInstructions = { parts: FilePart[], actions: ApplyInstantJsonAction[], output?: { type?: "pdf", },};Related API reference operations
- Refer to the build document endpoint API reference for applying Instant JSON, filling form fields, flattening the output, and applying follow-up actions in a single request.
Related guides
- Refer to the PDF flatten API guide.
- Refer to the PDF digital signature API guide.
- Refer to the PDF merge API guide.
- Refer to the PDF split API guide.
- Refer to the PDF watermark API guide.
- Refer to the PDF security API guide.
- Refer to the tools and APIs guide.