How to Flatten Annotations in PDF Files with Java

Flatten PDF annotations into page content with Java.
Share this page

Learn how to flatten annotations in PDF files with Java and the Flatten Annotations API Tool. The request creates a new PDF whose annotation appearances are incorporated into ordinary page content while preserving their visible appearance for controlled distribution. We'll move from input and authentication setup through the request and returned data involved when you flatten annotations in PDF files.

Why Flatten Annotations in PDF Files with Java?

After a review cycle, comments, stamps, and markup may need to remain visible without staying independently editable. Flattening incorporates their appearances into the page content.

The Java request sends the reviewed PDF to /flattened-annotations-pdf. The operation produces a new PDF, so the original annotated version can be retained separately when needed.

Java Code Example

import io.github.cdimascio.dotenv.Dotenv;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
import okhttp3.*;
import org.json.JSONObject;

public class FlattenedAnnotationsPDF {

  // 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 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;
    if (args.length > 0) {
      inputFile = new File(args[0]);
    } else {
      inputFile = new File(DEFAULT_FILE_PATH);
    }

    final Dotenv dotenv = Dotenv.configure().ignoreIfMalformed().ignoreIfMissing().load();

    final RequestBody inputFileRequestBody =
        RequestBody.create(inputFile, MediaType.parse("application/pdf"));
    RequestBody requestBody =
        new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("file", inputFile.getName(), inputFileRequestBody)
            .addFormDataPart("output", "flattened")
            .build();
    Request request =
        new Request.Builder()
            .header("Api-Key", dotenv.get("PDFREST_API_KEY", DEFAULT_API_KEY))
            .url(API_URL + "/flattened-annotations-pdf")
            .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.*;
import org.json.JSONObject;

The Java setup combines OkHttp networking with dotenv configuration and org.json processing.

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 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;
    if (args.length > 0) {
      inputFile = new File(args[0]);
    } else {
      inputFile = new File(DEFAULT_FILE_PATH);
    }

    final Dotenv dotenv = Dotenv.configure().ignoreIfMalformed().ignoreIfMissing().load();

    final RequestBody inputFileRequestBody =

The input setup separates file selection from authentication so either value can change without rewriting the request.

Build the multipart request body

final RequestBody inputFileRequestBody =
        RequestBody.create(inputFile, MediaType.parse("application/pdf"));
    RequestBody requestBody =
        new MultipartBody.Builder()
            .setType(MultipartBody.FORM)
            .addFormDataPart("file", inputFile.getName(), inputFileRequestBody)
            .addFormDataPart("output", "flattened")
            .build();
    Request request =
        new Request.Builder()
            .header("Api-Key", dotenv.get("PDFREST_API_KEY", DEFAULT_API_KEY))
            .url(API_URL + "/flattened-annotations-pdf")
            .post(requestBody)
            .build();
    try {
      OkHttpClient client =
          new OkHttpClient().newBuilder().readTimeout(60, TimeUnit.SECONDS).build();

The Java request sends the reviewed PDF to /flattened-annotations-pdf. The operation produces a new PDF, so the original annotated version can be retained separately when needed. The OkHttp body uses the form multipart type required for combining uploaded content with operation parameters.

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 + "/flattened-annotations-pdf")
            .post(requestBody)
            .build();
    try {
      OkHttpClient client =
          new OkHttpClient().newBuilder().readTimeout(60, TimeUnit.SECONDS).build();

This POST request adds the API key header, selects the operation URL, and attaches the prepared body; changing the base constant switches between US and EU service hosts.

Read the API response

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);

This result handling shows the raw outcome for learning purposes; production code can retain output IDs and branch on reported errors.

Beyond the Tutorial

Together, we stepped through the Java request needed to flatten annotations in PDF files. With that foundation, you can flatten annotations before final distribution, printing, archival conversion, or workflows that cannot preserve interactive markup.

As you build this into a larger workflow, keep in mind that flattening is intentionally irreversible in the generated output: comments and marks remain visible but are no longer separate editable annotations. Preserve the reviewed source when audit history matters, and verify that all required annotation appearances are visible before final distribution.

Try the Flatten Annotations in PDF operation with representative files in API Lab. Review the Flatten Annotations API Tool documentation for supported values and production considerations.

Note: The Flatten Annotations in PDF example above uses multipart form data; for the resource-ID form of this operation, compare the multipart call with the JSON payload example.

Generate a self-service API Key now!
Create your FREE API Key to start processing PDFs in seconds, only possible with pdfRest.