Lightweight document protection — includes watermarks and metadata establishing clear chain of custody.
Storage tip: Each funder receives a unique PDF, so files can accumulate quickly. We recommend deleting watermarked files immediately after confirming successful delivery to the funder by adding a basic file deletion command to your existing workflow.
The API uses asynchronous processing to handle large volumes without timeouts. Choose whichever delivery method fits your workflow:
webhook_url → Get job_id instantlyBoth options return the same watermarked files. Webhooks eliminate the need to poll, making them ideal for high-volume or event-driven workflows.
Requires Bearer token. Returns the watermarked ZIP file directly. All downloads are logged for audit purposes.
Authorization: Bearer aqua-api-watermark-77204041104282
This API key is universal and can be used immediately for testing.
| Parameter | Type | Description |
|---|---|---|
user_email |
String | Your Aquamark account email Use [email protected] for testing with Aquamark branding |
funder |
String or Array | Funder name(s) Max 15 per request |
files |
Array of Objects | Array of file objects, each containing:name (required): Filename with .pdf extensionurl or data (required): Public URL or base64-encoded PDFCan mix URL and base64 files in the same request |
webhook_url |
String (optional) | HTTPS URL to receive job results If provided, we POST the result to this URL on completion or failure. |
Max file size: 50MB per file
name: The filename (e.g., "bank-statement-jan.pdf")url: Public URL to the PDF file, ORdata: Base64-encoded PDF dataNote: Examples use cURL for clarity. Translate to your preferred language (Python, JavaScript, Java, etc.). Standard HTTP requests—nothing custom.
curl -X POST https://aquamark-broker-funder.onrender.com/watermark-broker-funder \
-H "Authorization: Bearer aqua-api-watermark-77204041104282" \
-H "Content-Type: application/json" \
-d '{
"user_email": "[email protected]",
"funder": ["Forward Financing", "OnDeck Capital", "Kapitus"],
"files": [
{
"name": "bank-statement-jan.pdf",
"url": "https://your-portal.com/submissions/jan.pdf"
},
{
"name": "bank-statement-feb.pdf",
"data": "JVBERi0xLjcKJeLjz9MK..."
},
{
"name": "credit-application.pdf",
"data": "JVBERi0xLjcKJeLjz9MK..."
}
]
}'
Note: You can mix files with url and files with data (base64) in the same request. The data field should contain the complete base64-encoded PDF. Convert your PDF files to base64 using any standard library before sending.
{
"job_id": "abc-123-def-456",
"status": "processing",
"file_count": 3,
"webhook_url": null,
"message": "Job created successfully. Poll /job-status/{job_id} for updates."
}
Use the job_id from Step 2 to check status every 10 seconds:
curl https://aquamark-broker-funder.onrender.com/job-status/abc-123-def-456
While processing:
{
"job_id": "abc-123-def-456",
"status": "processing",
"progress": "Processing 2 of 3 files",
"created_at": "2025-01-06T10:00:00Z"
}
When complete:
{
"job_id": "abc-123-def-456",
"status": "complete",
"download_url": "https://...broker-job-results/abc-123-def-456.zip?token=eyJhbG...",
"download_expires_at": "2026-02-24T19:45:22.418Z",
"authenticated_download_url": "https://aquamark-broker-funder.onrender.com/download/abc-123-def-456",
"message": "Ready for download. Signed link expires in 10 minutes. For logged/authenticated downloads, use the authenticated_download_url with your Bearer token.",
"created_at": "2026-01-06T10:00:00Z",
"completed_at": "2026-01-06T10:01:30Z"
}
On error:
{
"job_id": "abc-123-def-456",
"status": "error",
"error_message": "Job timed out after 10 minutes",
"created_at": "2025-01-06T10:00:00Z",
"completed_at": "2025-01-06T10:10:00Z"
}
Two download methods are available:
Option A: Signed URL (direct)
Use the download_url from Step 3. No auth required, but the link expires in 10 minutes.
curl "https://...broker-job-results/abc-123-def-456.zip?token=eyJhbG..." --output watermarked.zip
Option B: Authenticated download
Use the authenticated_download_url with your Bearer token. Every download is logged with IP, timestamp, and file size.
curl -H "Authorization: Bearer aqua-api-watermark-77204041104282" \
https://aquamark-broker-funder.onrender.com/download/abc-123-def-456 \
--output watermarked.zip
Instead of polling, add a webhook_url to your request and we'll POST the results directly to your server when the job finishes.
curl -X POST https://aquamark-broker-funder.onrender.com/watermark-broker-funder \
-H "Authorization: Bearer aqua-api-watermark-77204041104282" \
-H "Content-Type: application/json" \
-d '{
"user_email": "[email protected]",
"funder": ["Forward Financing", "OnDeck Capital", "Kapitus"],
"files": [
{
"name": "bank-statement-jan.pdf",
"url": "https://your-portal.com/submissions/jan.pdf"
}
],
"webhook_url": "https://your-server.com/aquamark-webhook"
}'
{
"job_id": "abc-123-def-456",
"status": "processing",
"file_count": 1,
"webhook_url": "https://your-server.com/aquamark-webhook",
"message": "Job created successfully. You will receive a webhook when processing completes."
}
When processing completes, we POST to your webhook_url:
On success:
POST https://your-server.com/aquamark-webhook
Headers:
Content-Type: application/json
X-Aquamark-Event: job.completed
X-Aquamark-Signature: 2ed0b90b005db9ef29a048f28a1e8acf...
X-Aquamark-Delivery: 7860e1bc-0b42-48e5-ad95-587c04c0efbe
User-Agent: Aquamark-Webhooks/1.0
Body:
{
"event": "job.completed",
"job_id": "abc-123-def-456",
"status": "complete",
"download_url": "https://...broker-job-results/abc-123-def-456.zip?token=eyJhbG...",
"download_expires_at": "2026-02-24T19:45:22.418Z",
"authenticated_download_url": "https://aquamark-broker-funder.onrender.com/download/abc-123-def-456",
"file_count": 3,
"failure_count": 0,
"elapsed_ms": 2283,
"completed_at": "2026-02-18T23:32:33.679Z"
}
On error:
{
"event": "job.failed",
"job_id": "abc-123-def-456",
"status": "error",
"error_message": "All files/funders failed to process",
"completed_at": "2026-02-18T23:35:00.000Z"
}
Two download options are available:
Option A: Signed URL (direct)
Use the download_url from the webhook payload. No auth required, but the link expires in 10 minutes.
curl "https://...broker-job-results/abc-123-def-456.zip?token=eyJhbG..." --output watermarked.zip
Option B: Authenticated download
Use the authenticated_download_url with your Bearer token. Every download is logged.
curl -H "Authorization: Bearer aqua-api-watermark-77204041104282" \
https://aquamark-broker-funder.onrender.com/download/abc-123-def-456 \
--output watermarked.zip
Each webhook includes an X-Aquamark-Signature header — an HMAC-SHA256 hash of the request body signed with your API key. Verify it to confirm the webhook came from Aquamark:
// Node.js example
const crypto = require('crypto');
function verifyWebhook(requestBody, signatureHeader, apiKey) {
const expected = crypto
.createHmac('sha256', apiKey)
.update(requestBody)
.digest('hex');
return expected === signatureHeader;
}
/job-status/:job_id as a backup, even when using webhooks.
watermarked.zip/
├── bank-statement-jan-forward-financing.pdf
├── bank-statement-jan-ondeck-capital.pdf
├── bank-statement-jan-kapitus.pdf
├── bank-statement-feb-forward-financing.pdf
├── bank-statement-feb-ondeck-capital.pdf
├── bank-statement-feb-kapitus.pdf
├── credit-application-forward-financing.pdf
├── credit-application-ondeck-capital.pdf
└── credit-application-kapitus.pdf
Each file is watermarked with your broker logo and the funder's name.
complete or error/download/:job_id) are deleted immediately after downloadPOST /job-complete/:job_id or are auto-deleted after 30 minutescurl -X POST https://aquamark-broker-funder.onrender.com/watermark-broker-funder \
-H "Authorization: Bearer aqua-api-watermark-77204041104282" \
-H "Content-Type: application/json" \
-d '{
"user_email": "[email protected]",
"funder": ["Forward Financing", "OnDeck Capital"],
"files": [
{
"name": "statement.pdf",
"url": "https://example.com/statement.pdf"
}
]
}'
curl -X POST https://aquamark-broker-funder.onrender.com/watermark-broker-funder \
-H "Authorization: Bearer aqua-api-watermark-77204041104282" \
-H "Content-Type: application/json" \
-d '{
"user_email": "[email protected]",
"funder": ["Forward Financing", "OnDeck Capital"],
"files": [
{
"name": "statement.pdf",
"data": "JVBERi0xLjcKJeLjz9MK..."
}
]
}'
curl -X POST https://aquamark-broker-funder.onrender.com/watermark-broker-funder \
-H "Authorization: Bearer aqua-api-watermark-77204041104282" \
-H "Content-Type: application/json" \
-d '{
"user_email": "[email protected]",
"funder": ["Forward Financing", "OnDeck Capital"],
"files": [
{
"name": "statement.pdf",
"url": "https://example.com/statement.pdf"
}
],
"webhook_url": "https://your-server.com/aquamark-webhook"
}'
| Code | Meaning | Example Response |
|---|---|---|
| 400 | Bad request | Missing 'files' array. Provide array of file objects with 'name' and either 'data' (base64) or 'url' |
| 401 | Invalid API key | Invalid API key |
| 402 | Account not authorized | Requires the Leak Detection plan |
| 404 | Job not found | Job not found |
| 410 | File expired or already downloaded | File has already been downloaded and removed, or has expired |
| 413 | File too large | File 'statement.pdf' exceeds 50MB limit |
| 429 | Rate limit exceeded | Too many requests. Please wait 15 minutes and try again. |
| 500 | Server error | Internal server error |
The examples above use test credentials with Aquamark branding. To deploy with your own branding:
[email protected] with your Aquamark account email in the user_email parameterQuestions? Email [email protected]