Overview
The Mergram REST API lets you trigger PDF merges and email campaigns programmatically. All endpoints use JSON for request and response bodies.
- Base URL —
https://mergram.com/api/v1(or your self-hosted domain) - Content type —
application/json - Authentication — API keys via
Authorization: Bearer <key>header
Try the API interactively
Use the API Playground to test endpoints with your API key directly in the browser. It provides a full interactive interface for building and testing requests.
Authentication
All API requests require an API key. Include it in the Authorization header:
GET /api/v1/templates HTTP/1.1
Host: mergram.com
Authorization: Bearer mg_abc123...
Content-Type: application/json
Keep your API keys secret
Never expose them in client-side code or public repositories. Use environment variables or secrets management. If a key is compromised, revoke it immediately in Developer → API Keys.
Endpoints
List Templates
GET /api/v1/templates?search=&limit=50&offset=0
Returns a paginated list of your team’s templates.
Query parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
search | string | — | Filter by template name |
limit | number | 50 | Results per page (max 200) |
offset | number | 0 | Skip results for pagination |
Get Template
GET /api/v1/templates/:id
Returns template metadata including column headers and required fields. Canvas data and form mapping are not included in the API response — use the visual editor to view or edit template layout.
Create Merge Job
POST /api/v1/merge
Request body:
{
"templateId": "abc123-def456",
"data": [
{ "Name": "Alice Chen", "InvoiceNumber": "INV-001", "Amount": "$2,700.00" },
{ "Name": "Bob Martinez", "InvoiceNumber": "INV-002", "Amount": "$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 (max 10,000 rows). Keys must match the spreadsheet column headers used to create the template |
outputConfig | No | Output settings: combinePdf (boolean), filenameTemplate (string with [[Column]] placeholders), passwordTemplate (string for per-PDF encryption) |
Prepare your template 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.
Response (201 Created):
{
"jobId": "abc123-def456-789",
"status": "pending",
"total": 2,
"message": "Merge job enqueued. 2 rows will be processed."
}
Create Email Job
POST /api/v1/email
Request body:
{
"templateId": "abc123-def456",
"data": [
{ "Name": "Alice Chen", "Email": "alice@acme.com", "InvoiceNumber": "INV-001" },
{ "Name": "Bob Martinez", "Email": "bob@globex.com", "InvoiceNumber": "INV-002" }
],
"email": {
"toColumn": "Email",
"subjectTemplate": "Your Invoice [[InvoiceNumber]]",
"bodyTemplate": "<p>Dear [[Name]],</p><p>Please find your invoice attached.</p>"
},
"outputConfig": {
"filenameTemplate": "Invoice_[[InvoiceNumber]]"
}
}
| Parameter | Required | Description |
|---|---|---|
templateId | Yes | ID of the saved template |
data | Yes | Array of row objects (max 10,000 rows). Must include the column referenced by toColumn |
email | Yes | Email configuration object |
email.toColumn | Yes | Column name containing recipient email addresses |
email.subjectTemplate | Yes | Email subject with [[Column]] placeholders |
email.bodyTemplate | Yes | HTML email body with [[Column]] placeholders |
email.fromName | No | Override the sender display name (otherwise uses SMTP settings) |
email.fromEmail | No | Override the sender email address (otherwise uses SMTP settings) |
email.attachmentFilenameTemplate | No | Filename template for the PDF attachment with [[Column]] placeholders |
Response (201 Created):
{
"jobId": "abc123-def456-789",
"status": "pending",
"total": 2,
"message": "Email job enqueued. 2 emails will be processed."
}
Get Job Status
GET /api/v1/jobs/:id
Returns the current status, progress, and any error details for a job.
Response:
{
"id": "abc123-def456-789",
"type": "pdf_merge",
"status": "running",
"total": 150,
"completed": 75,
"failed": 0,
"createdAt": "2025-01-28T10:30:00Z"
}
Get Job Output
GET /api/v1/jobs/:id/output
Returns a list of generated files with download URLs. Only available when status is completed.
Response:
{
"files": [
{
"filename": "Invoice_INV-001.pdf",
"downloadUrl": "https://mergram.com/api/v1/files/...",
"size": 245678
}
]
}
Download URL expiry
Signed download URLs expire after 1 hour by default. Download your files promptly after the job completes.
Job Lifecycle
- Submit —
POST /api/v1/mergeorPOST /api/v1/emailreturns ajobId - Poll —
GET /api/v1/jobs/:idto check status (pending,running,completed,failed) - Download —
GET /api/v1/jobs/:id/outputto get result file URLs
Polling
Jobs are processed asynchronously. Poll the status endpoint at intervals (every 2–5 seconds is recommended) until the status is completed or failed. There are no webhook callbacks — polling is the only way to check job status.
Error Handling
| Status | Meaning |
|---|---|
| 400 | Bad request — invalid parameters or missing fields |
| 401 | Unauthorized — invalid or missing API key |
| 402 | Payment required — insufficient credits |
| 403 | Forbidden — API key lacks required scope |
| 404 | Not found — template or job doesn’t exist |
| 500 | Internal error — try again or contact support |
Best Practices
- Use environment variables — Store API keys in environment variables, never in source code
- Implement retry logic — Retry failed requests with exponential backoff (start with 2 seconds)
- Poll efficiently — Check job status every 2–5 seconds, not more frequently
- Validate before submitting — Verify template IDs exist before creating jobs
- Monitor credit usage — Check your credit balance periodically to avoid 402 errors mid-workflow
Limitations
- No template creation via API — Templates must be created in the visual editor
- No file upload via API — PDF templates and spreadsheets must be uploaded through the web interface
- Polling only — No webhook callbacks for job completion notifications
- Rate limited — Standard rate limits apply (100 total requests per minute, 20 write operations per minute)
- Inline data limit — API requests accept up to 10,000 rows of inline data per job. For larger datasets, use the web interface which supports up to 100,000 rows