How to Add Attachments to PDF Files with Java
In this tutorial, we'll walk through how to add attachments to PDF files with Java using the Add to PDF API Tool. The code supplies the source PDF and attachment as separate multipart parts, then receives a new PDF resource that contains both. You'll see how the request is assembled and how to work with the response returned when you add attachments to PDF files.
Why Add Attachments to PDF Files with Java?
A claims platform may need to keep an XML decision record or original evidence beside the readable PDF. Embedding the source as an attachment keeps the related material together without changing the visible pages.
The Java request sends the PDF as file and the supporting document as file_to_attach. Both are multipart file parts, so callers should preserve meaningful filenames and media types.
Java Code Example
import io.github.cdimascio.dotenv.Dotenv;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
import org.json.JSONObject;
public class PDFWithAddedAttachment {
// By default, we use the US-based API service. This is the primary endpoint for global use.
private static final String API_URL = "https://api.pdfrest.com";
// For GDPR compliance and enhanced performance for European users, you can switch to the EU-based
// service by commenting out the URL above and uncommenting the URL below.
// For more information visit https://pdfrest.com/pricing#how-do-eu-gdpr-api-calls-work
// private static final String API_URL = "https://eu-api.pdfrest.com";
// Specify the path to your file here, or as the first argument when running the program.
private static final String DEFAULT_FILE_PATH = "/path/to/file.pdf";
// Specify the path to your file attachment here, or as the second argument when running the
// program.
private static final String DEFAULT_ATTACHMENT_PATH = "/path/to/file.xml";
// Specify your API key here, or in the environment variable PDFREST_API_KEY.
// You can also put the environment variable in a .env file.
private static final String DEFAULT_API_KEY = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
public static void main(String[] args) {
File inputFile, attachmentFile;
if (args.length > 1) {
inputFile = new File(args[0]);
attachmentFile = new File(args[1]);
} else {
inputFile = new File(DEFAULT_FILE_PATH);
attachmentFile = new File(DEFAULT_ATTACHMENT_PATH);
}
final Dotenv dotenv = Dotenv.configure().ignoreIfMalformed().ignoreIfMissing().load();
final RequestBody inputFileRequestBody =
RequestBody.create(inputFile, MediaType.parse("application/pdf"));
final RequestBody attachmentFileRequestBody =
RequestBody.create(attachmentFile, MediaType.parse("application/xml"));
RequestBody requestBody =
new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", inputFile.getName(), inputFileRequestBody)
.addFormDataPart("file_to_attach", attachmentFile.getName(), attachmentFileRequestBody)
.build();
Request request =
new Request.Builder()
.header("Api-Key", dotenv.get("PDFREST_API_KEY", DEFAULT_API_KEY))
.url(API_URL + "/pdf-with-added-attachment")
.post(requestBody)
.build();
try {
OkHttpClient client =
new OkHttpClient().newBuilder().readTimeout(60, TimeUnit.SECONDS).build();
Response response = client.newCall(request).execute();
System.out.println("Result code " + response.code());
if (response.body() != null) {
System.out.println(prettyJson(response.body().string()));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static String prettyJson(String json) {
// https://stackoverflow.com/a/9583835/11996393
return new JSONObject(json).toString(4);
}
}
Source: Java sample on GitHub.
Breaking Down the Code
Load the Java HTTP and JSON dependencies
import io.github.cdimascio.dotenv.Dotenv; import java.io.File; import java.io.IOException; import java.util.concurrent.TimeUnit; import okhttp3.MediaType; import okhttp3.MultipartBody; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.RequestBody; import okhttp3.Response; import org.json.JSONObject;
The import block uses OkHttp for transport, dotenv for loading PDFREST_API_KEY, and org.json for structured request or response data.
Choose the input and load credentials
// service by commenting out the URL above and uncommenting the URL below.
// For more information visit https://pdfrest.com/pricing#how-do-eu-gdpr-api-calls-work
// private static final String API_URL = "https://eu-api.pdfrest.com";
// Specify the path to your file here, or as the first argument when running the program.
private static final String DEFAULT_FILE_PATH = "/path/to/file.pdf";
// Specify the path to your file attachment here, or as the second argument when running the
// program.
private static final String DEFAULT_ATTACHMENT_PATH = "/path/to/file.xml";
// Specify your API key here, or in the environment variable PDFREST_API_KEY.
// You can also put the environment variable in a .env file.
private static final String DEFAULT_API_KEY = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
public static void main(String[] args) {
File inputFile, attachmentFile;
if (args.length > 1) {
inputFile = new File(args[0]);
attachmentFile = new File(args[1]);
} else {
inputFile = new File(DEFAULT_FILE_PATH);
Two default paths identify the PDF and its attachment, and two command-line arguments can replace them at runtime; dotenv supplies the API key independently of both files.
Build the multipart request body
final RequestBody attachmentFileRequestBody =
RequestBody.create(attachmentFile, MediaType.parse("application/xml"));
RequestBody requestBody =
new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("file", inputFile.getName(), inputFileRequestBody)
.addFormDataPart("file_to_attach", attachmentFile.getName(), attachmentFileRequestBody)
.build();
Request request =
new Request.Builder()
.header("Api-Key", dotenv.get("PDFREST_API_KEY", DEFAULT_API_KEY))
.url(API_URL + "/pdf-with-added-attachment")
.post(requestBody)
.build();
try {
OkHttpClient client =
new OkHttpClient().newBuilder().readTimeout(60, TimeUnit.SECONDS).build();
The Java request sends the PDF as file and the supporting document as file_to_attach. Both are multipart file parts, so callers should preserve meaningful filenames and media types. This payload builder leaves boundary construction to OkHttp so the header remains synchronized with the serialized content.
Send the request to pdfRest
.build();
Request request =
new Request.Builder()
.header("Api-Key", dotenv.get("PDFREST_API_KEY", DEFAULT_API_KEY))
.url(API_URL + "/pdf-with-added-attachment")
.post(requestBody)
.build();
try {
OkHttpClient client =
new OkHttpClient().newBuilder().readTimeout(60, TimeUnit.SECONDS).build();
Response response = client.newCall(request).execute();
The outbound call posts the multipart content to pdfRest and keeps deployment-region changes independent of the rest of the Java code.
Read the API response
try {
OkHttpClient client =
new OkHttpClient().newBuilder().readTimeout(60, TimeUnit.SECONDS).build();
Response response = client.newCall(request).execute();
System.out.println("Result code " + response.code());
if (response.body() != null) {
System.out.println(prettyJson(response.body().string()));
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
private static String prettyJson(String json) {
// https://stackoverflow.com/a/9583835/11996393
return new JSONObject(json).toString(4);
The returned-data block prints the HTTP status and JSON body so generated resource IDs or API error details are visible.
Beyond the Tutorial
In this tutorial, we walked through how to add attachments to PDF files with Java. With that foundation, you can use this pattern for invoice XML, audit evidence, source documents, or machine-readable records that must travel with a human-readable PDF.
As you adapt this example for production, preserve meaningful attachment filenames and media types so recipients can identify embedded material. Test the output in the PDF viewers your users rely on, and delete temporary source and output resources when the package no longer needs to remain available.
To continue exploring the Add Attachments to PDF operation, visit API Lab. For complete request fields, defaults, and limitations, refer to the Add to PDF API Tool documentation.
Note: The Add Attachments to PDF example above uses multipart form data; when a prior API call returned the input ID, use the JSON payload example as a guide.