Automating PDF Generation with the REST API
Manual merge operations work well for occasional use, but production workflows often need programmatic access — generating invoices from your CRM, producing reports on a schedule, or integrating document generation into your application. The Mergram REST API lets you trigger PDF merges, monitor progress, and download results from any backend system.
Prerequisites
To use the REST API, you need:
- A Mergram account with API access
- A saved template created in the editor (you’ll need its ID)
- An API key generated from your account settings
- Your merge data as a JSON array of objects
API keys vs. session authentication
The REST API uses API key authentication (Bearer token), not browser session cookies. This is designed for server-to-server communication where no browser is involved. API keys are independent of user sessions and don’t expire unless revoked.
Authentication
All API requests require an API key sent as a Bearer token in the Authorization header:
Authorization: Bearer mg_your_api_key_here
Creating an API Key
- Navigate to Developer → API Keys in the Mergram dashboard
- Click Generate New Key
- Give it a descriptive name (e.g., “Production CRM Integration”)
- Copy the key immediately — it is shown only once
- Store it securely (environment variable, secrets manager)
API keys are team-scoped — they inherit the permissions of the team they belong to. Revoke a key at any time from the same settings page.
API Endpoints
The base URL for all API v1 endpoints is:
https://mergram.com/api/v1
Core Endpoints
| Method | Endpoint | Description |
|---|---|---|
POST | /merge | Submit a new merge job |
POST | /email | Submit a new email send job |
GET | /jobs/:id | Check job status and progress |
GET | /jobs/:id/output | Get download URLs for completed files |
GET | /templates | List available templates |
GET | /templates/:id | Get template details |
Submit a Merge Job
Send a POST request to /api/v1/merge with the following body:
{
"templateId": "abc123-def456",
"data": [
{ "InvoiceNumber": "INV-001", "ClientName": "Acme Corp", "Total": "$2,700.00" },
{ "InvoiceNumber": "INV-002", "ClientName": "Globex Inc", "Total": "$5,400.00" }
],
"outputConfig": {
"combinePdf": false,
"filenameTemplate": "Invoice_[[InvoiceNumber]]"
}
}
| Parameter | Required | Description |
|---|---|---|
templateId | Yes | ID of the saved template |
data | Yes | Array of row objects. Keys must match the spreadsheet column headers used to create the template |
outputConfig | No | Output settings: combinePdf (boolean), filenameTemplate (string with merge fields), passwordTemplate (string for per-PDF encryption) |
Response (201 Created):
{
"jobId": "abc123-def456-789",
"status": "pending",
"total": 2,
"message": "Merge job enqueued. 2 rows will be processed."
}
Prepare your template with a spreadsheet first
Before using the API, create and save your template in the Mergram editor with a spreadsheet attached. The API uses the column headers from that spreadsheet to map your inline data. The template must have a PDF file and a configured data source.
Check Job Status
Poll GET /api/v1/jobs/:id to track progress:
curl -H "Authorization: Bearer mg_your_api_key" \
https://mergram.com/api/v1/jobs/abc123-def456-789
Response:
{
"id": "abc123-def456-789",
"type": "pdf_merge",
"status": "completed",
"total": 2,
"progress": 2,
"progressMessage": "Completed",
"output": {
"files": [
{
"filename": "Invoice_INV-001.pdf",
"downloadUrl": "https://mergram.com/api/v1/files/...",
"size": 245678
},
{
"filename": "Invoice_INV-002.pdf",
"downloadUrl": "https://mergram.com/api/v1/files/...",
"size": 251024
}
]
},
"items": [
{ "id": "...", "itemIndex": 0, "status": "completed", "processedAt": "..." },
{ "id": "...", "itemIndex": 1, "status": "completed", "processedAt": "..." }
],
"createdAt": "2025-01-28T10:30:00Z",
"completedAt": "2025-01-28T10:30:45Z"
}
Job Status Values
| Status | Meaning |
|---|---|
pending | Job is queued, waiting for a worker |
running | Job is actively processing |
completed | All rows processed successfully |
failed | Job encountered an unrecoverable error |
paused | Job was manually paused |
cancelled | Job was cancelled |
Download Results
Fetch download URLs for all generated files:
# Get download URLs for all output files
curl -H "Authorization: Bearer mg_your_api_key" \
https://mergram.com/api/v1/jobs/abc123-def456-789/output
# Download a specific file using the signed URL from the response
curl -o Invoice_INV-001.pdf \
"https://mergram.com/api/v1/files/..."
The /output endpoint returns { files: [{ filename, downloadUrl, size }] } with signed URLs for each generated PDF.
Complete End-to-End Example
Here is a full workflow using curl:
# Step 1: Submit merge job
JOB_RESPONSE=$(curl -s -X POST \
-H "Authorization: Bearer mg_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"templateId": "abc123-def456",
"data": [
{ "InvoiceNumber": "INV-001", "ClientName": "Acme Corp", "Total": "$2,700.00" },
{ "InvoiceNumber": "INV-002", "ClientName": "Globex Inc", "Total": "$5,400.00" }
],
"outputConfig": {
"combinePdf": false,
"filenameTemplate": "Invoice_[[InvoiceNumber]]"
}
}' \
https://mergram.com/api/v1/merge)
# Step 2: Extract job ID
JOB_ID=$(echo $JOB_RESPONSE | jq -r '.jobId')
echo "Job submitted: $JOB_ID"
# Step 3: Poll for completion (every 5 seconds)
while true; do
STATUS=$(curl -s -H "Authorization: Bearer mg_your_api_key" \
https://mergram.com/api/v1/jobs/$JOB_ID | jq -r '.status')
echo "Status: $STATUS"
if [ "$STATUS" = "completed" ] || [ "$STATUS" = "failed" ]; then
break
fi
sleep 5
done
# Step 4: Get download URLs
curl -s -H "Authorization: Bearer mg_your_api_key" \
https://mergram.com/api/v1/jobs/$JOB_ID/output | jq '.files[]'
echo "Done. Download files using the URLs above."
Integration with Automation Platforms
Zapier Integration
Configure a custom webhook action in Zapier:
- Trigger: Any Zapier trigger (new CRM deal, form submission, scheduled time)
- Action: Webhooks by Zapier → Custom Request
- Method:
POST - URL:
https://mergram.com/api/v1/merge - Headers:
Authorization: Bearer mg_your_api_key - Payload: JSON body with
templateIdanddataarray
- Method:
- Follow-up action: Use the response
jobIdto poll status
Make.com Integration
Use the HTTP module in Make.com:
- Add an HTTP module
- Set method to
POST - URL:
https://mergram.com/api/v1/merge - Add header:
Authorization=Bearer mg_your_api_key - Body type:
application/json - Map your scenario data to the request fields
Async processing model
The API processes merge jobs asynchronously. Your request returns immediately with a job ID, and the actual PDF generation happens in the background. This design handles large datasets (thousands of rows) without timeout issues. Poll the status endpoint until the job completes.
Error Handling
| HTTP Status | Meaning | Action |
|---|---|---|
201 | Job created successfully | Poll for status |
400 | Invalid request body or data format | Check parameters and retry |
401 | Missing or invalid API key | Verify your API key |
402 | Insufficient credits | Purchase credits or check your balance |
404 | Template not found | Check the template ID |
429 | Rate limit exceeded | Wait and retry with backoff |
500 | Server error | Retry after a short delay |
{
"error": "Template not found"
}
Best Practices for API Integration
- Store API keys in environment variables — Never hardcode keys in source code. Use a secrets manager or
.envfile (not committed to git) - Implement exponential backoff — If polling returns
running, increase the interval between checks (5s, 10s, 20s, etc.) - Handle partial failures gracefully — A completed job may have some failed rows. Check the
failedcount in the progress object - Cache template IDs — List templates once and cache the IDs rather than querying on every request
- Use webhooks for large jobs — For jobs processing thousands of rows, consider using automation platform webhooks instead of polling
- Validate data before submitting — Ensure your
dataarray keys match the template’s column headers exactly and that all rows have the expected fields
Common Issues and Troubleshooting
401 Unauthorized errors: Verify the API key is correct and hasn’t been revoked. Check that the header format is exactly Authorization: Bearer mg_your_key (note the space after “Bearer”).
Job stuck in “pending” status: This may indicate all workers are busy. Large jobs may queue briefly during peak usage. Continue polling — the job will start when a worker becomes available.
Data validation errors: Ensure your data array keys exactly match the column headers used when the template was created. Column matching is case-sensitive. Check for extra whitespace or typos in key names.
Template ID not found: The template must be saved and belong to the same team as the API key. Create the template in the editor first, then retrieve its ID from the templates list endpoint.
Get Started
Generate an API key in Developer → API Keys, create a template in the editor, and submit your first merge job via curl or your preferred HTTP client. The API documentation in the playground provides an interactive reference for all endpoints.