Auto-watermark PDFs in a folder
Stamp Northwind documents with a confidentiality watermark before they're shared.
Published Sep 6, 2025
Northwind shares contracts, proposals and briefs as PDFs, and every one of them should carry a “Confidential” watermark before it leaves the studio. Doing that by hand — open each file, stamp it, re-export — is exactly the dull step that gets skipped under deadline, and an unmarked document going out is a real risk.
Apps Script cannot edit PDF binaries itself, but it can route them through an external watermarking service (PDFMonkey, ILovePDF, or your own endpoint). This script watches a Drive folder, sends every unstamped PDF to that service, saves the watermarked copy back, and trashes the original — so the folder ends up holding only stamped, shareable documents.
What you’ll need
- A Drive folder that collects the PDFs to be stamped, and its folder ID.
- A watermarking HTTP endpoint that accepts a PDF and returns a stamped PDF.
Set its URL in the
PDF_APIconstant. - If that service needs an API key, store it in Script Properties rather than in the code — see Store API keys and secrets securely.
- Edit access to the folder from the account running the script.
The script
// The watermarking endpoint: accepts a PDF, returns a stamped PDF.
const PDF_API = 'https://your-watermark-service.example/stamp';
// Marker added to stamped filenames, so a file is never processed twice.
const STAMPED_TAG = '[stamped]';
// The default watermark text.
const DEFAULT_WATERMARK = 'CONFIDENTIAL — Northwind';
/**
* Sends every unstamped PDF in a folder through the watermarking
* service, saves the stamped copy back, and trashes the original.
*
* @param {string} folderId The Drive folder of PDFs to watermark.
* @param {string} watermarkText The text to stamp onto each PDF.
*/
function watermarkFolder(folderId, watermarkText = DEFAULT_WATERMARK) {
const folder = DriveApp.getFolderById(folderId);
const files = folder.getFiles();
let stampedCount = 0;
// 1. Walk every file in the folder.
while (files.hasNext()) {
const file = files.next();
// 2. Skip anything that is not a PDF.
if (file.getMimeType() !== 'application/pdf') continue;
// 3. Skip PDFs that have already been stamped.
if (file.getName().includes(STAMPED_TAG)) continue;
// 4. Send the PDF's bytes to the watermarking service.
const response = UrlFetchApp.fetch(PDF_API, {
method: 'post',
contentType: 'application/pdf',
payload: file.getBlob().getBytes(),
headers: { 'X-Watermark': watermarkText },
muteHttpExceptions: true,
});
// 5. Bail on this file if the service did not return success.
if (response.getResponseCode() !== 200) {
Logger.log(
'Watermark failed for "' + file.getName() +
'" (HTTP ' + response.getResponseCode() + ') — skipping.'
);
continue;
}
// 6. Name the stamped copy and save it into the same folder.
const baseName = file.getName().replace(/\.pdf$/i, '');
const stamped = response
.getBlob()
.setName(baseName + ' ' + STAMPED_TAG + '.pdf');
folder.createFile(stamped);
// 7. Trash the original so only stamped PDFs remain.
file.setTrashed(true);
stampedCount++;
}
Logger.log('Watermarked ' + stampedCount + ' PDF(s).');
}
/**
* Convenience wrapper: watermarks a fixed folder. Edit the folder ID,
* or call watermarkFolder directly.
*/
function watermarkNorthwindFolder() {
watermarkFolder('1abcFolderId');
}
How it works
watermarkFolderopens the folder by ID and gets an iterator over its files.- It walks each file and skips anything whose MIME type is not
application/pdf— images, Docs and other formats are left alone. - It skips any PDF whose name already contains
[stamped], so the function is safe to re-run and never double-stamps a document. - It reads the PDF’s raw bytes and POSTs them to the
PDF_APIendpoint, passing the watermark text in anX-Watermarkheader. - It checks the HTTP response code. Anything other than
200is logged and the file is skipped, so a service hiccup does not trash an original that was never successfully stamped. - It takes the stamped PDF the service returned, names it with the original
base name plus the
[stamped]tag, and saves it into the same folder. - Only once the stamped copy is safely saved does it trash the original — so the folder ends up holding stamped versions only.
Example run
The watch folder before a run:
| File | |
|---|---|
| Acme proposal.pdf | original, unstamped |
| Beta contract.pdf | original, unstamped |
| logo.png | not a PDF — ignored |
After a run:
| File | |
|---|---|
| Acme proposal [stamped].pdf | watermarked copy |
| Beta contract [stamped].pdf | watermarked copy |
| logo.png | untouched |
The two originals are in the Drive trash; the folder now contains only “Confidential”-stamped, shareable PDFs.
Run it
This is a job you run on demand, before a batch of documents goes out:
- Set
PDF_APIto your watermarking endpoint and put the folder ID intowatermarkNorthwindFolder(or callwatermarkFolderdirectly). - In the Apps Script editor, select the function and click Run.
- Approve the authorisation prompt the first time.
- Check the folder — every PDF should now carry the
[stamped]tag.
To stamp documents automatically as they are added, attach a time-driven
trigger to watermarkNorthwindFolder running every few hours.
Watch out for
- The script trashes the original after stamping. The file is recoverable from
the Drive trash for 30 days, but if you need to keep originals, save the
stamped copy to a different folder and skip the
setTrashedcall. - It depends entirely on the external service. If
PDF_APIis down, slow, or changes its response format, nothing gets stamped — the HTTP check in step 5 stops a failure from destroying originals, but watch the logs. - PDF bytes go to a third-party endpoint. For confidential documents, use a service you trust (or self-host one), and check its data-retention policy before sending real contracts through it.
UrlFetchAppcaps a single request payload at around 50 MB and the whole job must finish inside Apps Script’s 6-minute runtime. A folder of large or numerous PDFs may need processing in smaller batches.- The
[stamped]filename tag is the only thing preventing re-stamping. If someone renames a stamped file, the next run will stamp it again. - The watermark is whatever the external service produces. A service that lays text over the page is not the same as redaction — it does not remove or protect the underlying content.
Related
Build a recurring file-delivery system
Drop a fresh report file into a Northwind client folder weekly — they don't even ask.
Updated Dec 15, 2025
Build a Drive search index in Sheets
Make Northwind's file metadata searchable in a Sheet — like Spotlight for Drive.
Updated Dec 7, 2025
Build a shared-folder onboarding kit
Auto-grant new Northwind hires the folders they need on day one.
Updated Nov 29, 2025
Route saved email attachments to project folders
File Gmail attachments into the right Northwind client folder based on subject keywords.
Updated Nov 25, 2025
Bundle a folder of images into one PDF
Combine Northwind scans into a single deliverable PDF using a generation service.
Updated Nov 17, 2025