Skip to main content
POST
/
transformations
Watermark PDF
curl --request POST \
  --url https://api.gonitro.dev/transformations \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: multipart/form-data' \
  --form method=watermark \
  --form 'params={
  "boundingBox": [
    210,
    10,
    290,
    60
  ],
  "opacity": 0.75,
  "rotation": 15,
  "pageIndices": [
    0,
    1
  ],
  "rotateWithPage": false,
  "centerOnPage": false,
  "contentDepth": "below_existing",
  "fitToPageWidth": false,
  "fitToPageHeight": false
}' \
  --form 'files[0]=@SampleFile1.pdf' \
  --form 'files[1]=@SampleFile2.pdf' \
  --form files.items.0='@example-file'
{
  "file": {
    "URL": "<string>",
    "contentType": "application/json",
    "metadata": {
      "fileSizeBytes": 123,
      "pageCount": 123
    }
  }
}
The Watermark method of the Transformations endpoint lets you overlay an image onto specific pages of a PDF document. You provide the PDF file and a watermark image as separate file uploads, along with parameters that control placement, sizing, and appearance:
  • boundingBox (required): The position and size of the watermark area as [x0, y0, x1, y1] in PDF points. See the bounding box guide for details on how coordinates work in the Nitro API.
  • opacity: Controls the transparency of the watermark, from 0.0 (fully transparent) to 1.0 (fully opaque). Defaults to 1.0.
  • rotation: The rotation angle in degrees to apply to the watermark image. Defaults to 0.
  • pageIndices: An array of zero-based page indices where the watermark should be applied. If omitted, the watermark is applied to all pages.
Page indices must be non-negative integers. Negative values will cause a validation error. Out-of-range indices (beyond the document’s page count) are ignored — the watermark is applied only to pages that exist.
  • flip: Optionally mirror the watermark image. Accepted values: horizontal, vertical, or both.
  • rotateWithPage: When set to true, the watermark rotates along with the page if the page itself has a rotation applied. Defaults to false.
  • centerOnPage: When set to true, the watermark is centered on the page. Defaults to false. Also accepts center_on_page.
boundingBox is required when using centerOnPage.
  • contentDepth: Controls whether the watermark renders above or below the existing page content. Accepted values: above_existing or below_existing. Defaults to below_existing. Also accepts content_depth.
The contentDepth values use underscores: above_existing and below_existing. Some upstream specs incorrectly list these with hyphens — using hyphens will not work.
  • fitToPageWidth: When set to true, scales the watermark image to fit the full page width. Defaults to false. Also accepts fit_to_page_width.
When fitToPageWidth is true and fitToPageHeight is false, boundingBox must be provided for vertical positioning.
  • fitToPageHeight: When set to true, scales the watermark image to fit the full page height. Defaults to false. Also accepts fit_to_page_height.
When fitToPageHeight is true and fitToPageWidth is false, boundingBox must be provided for horizontal positioning.

Supported Image Formats

The watermark image can be provided in the following formats:
  • PNG (recommended)
  • JPEG
  • TIFF
  • GIF
  • SVG
WebP images are not supported and will result in an error. Make sure the actual file format matches the expected type — a WebP file renamed to .png will be rejected.

Example

Original PDF

Watermarked PDF

File Upload

Unlike most transformation methods that accept a single file field, the Watermark method requires two files uploaded via the files parameter:
  • files[0]: The source PDF document
  • files[1]: The watermark image
curl --request POST \
  --url https://api.gonitro.dev/transformations \
  --header 'Authorization: Bearer <token>' \
  --header 'Accept: application/json' \
  --form method=watermark \
  --form 'params={"boundingBox": [210, 10, 290, 60], "opacity": 0.75, "rotation": 15, "pageIndices": [0, 1]}' \
  --form 'files[0]=@document.pdf;type=application/pdf' \
  --form 'files[1]=@watermark.png;type=image/png'

Output File Format

The endpoint can return output either as JSON or as a binary file. The format depends on the Accept header (details below), which defaults to application/json.

Processing

When requesting JSON, you can run the operation synchronously or asynchronously. This is determined by the Prefer header (details below).
  • In sync mode, the response includes a URL pointing to the processed file.
  • In async mode, the request creates a Job, and the response contains the Job ID and status so you can track progress.
Binary (octet-stream) responses are only available for synchronous operations.

Custom File Delivery

The endpoint supports custom file-delivery destinations through the optional delivery parameter. You can provide an upload target, such as your own PUT endpoint or a pre-signed S3 URL, and Nitro will upload the resulting file there. This works for both synchronous and asynchronous processing.
  • Sync delivery

    In synchronous calls, the delivery parameter lets you direct Nitro to upload the output file to a custom URL endpoint or a pre-signed URL (e.g S3), by providing an upload url in the uploadResultTo or uploadResultsTo properties.

    Custom endpoint

    If implementing the upload endpoint by yourself, make sure your code or middleware configuration accepts requests without content-type headers.

    S3 delivery

    If you are using S3 to manage delivery uploads, follow this AWS documentation to generate a pre-signed PUT URL.
    If using the AWS provided Python script, omit the Content-Type in Params to get the pre-signed url. For example:
        url = generate_presigned_url(
            s3_client,
            "put_object",
            { 
                "Bucket": args.bucket, 
                "Key": args.key,
                # Content-Type: "application/octet-stream" => Omit!
            },
        1000)
    
  • Async delivery

    In asynchronous flows, you can also provide a custom URL or pre-signed S3 object via uploadResultTo or uploadResultsTo, to upload your file(s) once the Job is done processing.

    Callback

    For asynchronous processing, you can also include a callback URL within the delivery parameter. This callback is a POST endpoint that Nitro will call once the Job is created and running, providing details about the file-processing job. Example of Nitro’s callback request body:
    {
        "jobID": "babe2aa7-9b5d-4eb2-a679-5fc12cf0a490",
        "location": "https://api.gonitro.dev/jobs/babe2aa7-9b5d-4eb2-a679-5fc12cf0a490"
    }
    

Response behavior Matrix

This matrix shows the expected response behavior based on content type, sync/async mode, and custom file-delivery settings.
JSON (application/json)Binary (application/octet-stream)
SynchronousReturns a JSON object with a file(s) URL(s).Returns the processed file directly as binary.
Asynchronous (respond-async)Returns a JSON object with a Job ID and status.Async preference ignored, returns sync binary.
Synchronous deliveryFile delivered to custom endpoint / Bucket, returns success confirmation.N/A
Asynchronous deliveryReturns a JSON object with a Job ID and status. The file(s) will be uploaded to the provided PUT endpoint / S3 Bucket at the end of process. If callback url is provided, Nitro will notify the endpoint with a JOB ID and location.N/A

Limits

The Platform API has the following limits:
  • File size: Maximum of 100 MB per request. This applies to single-file and multi-file requests.
  • Page count: Maximum of 500 pages per individual document. This applies to single-file and multi-file requests. Multiple documents may exceed 500 pages in total.
  • Retention time: Inputs and outputs are deleted approximately 15 minutes after the operation completes.

Request

Authorizations

Authorization
string
header
required

Bearer authentication header of the form Bearer <token>, where <token> is your auth token.

Headers

Accept
enum<string>
default:*/*

Controls response format and behavior. See endpoint description above for detailed response combinations.

  • application/json: Returns JSON response with operation result
  • application/octet-stream: Returns binary file content
  • */*: Defaults to JSON response
Available options:
application/json,
application/octet-stream,
*/*
Prefer
enum<string>

Controls synchronous vs asynchronous operation. See endpoint description above for behavior details.

  • respond-async: Makes request asynchronous, returns job status for polling
  • No value: Synchronous response
Available options:
respond-async

Body

multipart/form-data
method
enum<string>
default:watermark
required

The Transformations' endpoint method: watermark

Available options:
watermark
params
Watermark · object
required

Parameters controlling watermark placement, sizing, and appearance on each PDF page.

files
(file | object)[]
required

The files to process. They can be provided as a binary uploads or as a JSON with remote file references.

Example:
["@SampleFile1.pdf", "@SampleFile2.pdf"]
delivery
object

This endpoint lets you supply your own URL to receive the single-file output. The URL may point to a custom API endpoint or a pre-signed S3 URL.

The HTTP method defaults to PUT, but you can change it based on your implementation needs via the verb parameter. You can also provide custom headers, such as authentication headers or any others required by your endpoint.

Response

Returns either JSON or binary output depending on the Accept header (defaults to JSON). JSON responses include a file URL for synchronous tasks or a job status for asynchronous tasks.

file
object