Templates
Templates let you define reusable email layouts with placeholder variables. Store your HTML once, then send personalized emails by passing different data each time.
Create a template
Section titled “Create a template”POST /api/v1/templates
curl -X POST https://relaypost.dev/api/v1/templates \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "name": "Order Confirmation", "subject": "Your order #{{orderNumber}}", "html": "<h1>Thanks, {{customerName}}!</h1><p>Your order #{{orderNumber}} totaling {{total}} has been confirmed.</p>", "text": "Thanks, {{customerName}}! Your order #{{orderNumber}} totaling {{total}} has been confirmed." }'const response = await fetch("https://relaypost.dev/api/v1/templates", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer YOUR_API_KEY", }, body: JSON.stringify({ name: "Order Confirmation", subject: "Your order #{{orderNumber}}", html: "<h1>Thanks, {{customerName}}!</h1><p>Your order #{{orderNumber}} totaling {{total}} has been confirmed.</p>", text: "Thanks, {{customerName}}! Your order #{{orderNumber}} totaling {{total}} has been confirmed.", }),});
const result = await response.json();console.log(result.data.id);import requests
response = requests.post( "https://relaypost.dev/api/v1/templates", headers={ "Content-Type": "application/json", "Authorization": "Bearer YOUR_API_KEY", }, json={ "name": "Order Confirmation", "subject": "Your order #{{orderNumber}}", "html": "<h1>Thanks, {{customerName}}!</h1><p>Your order #{{orderNumber}} totaling {{total}} has been confirmed.</p>", "text": "Thanks, {{customerName}}! Your order #{{orderNumber}} totaling {{total}} has been confirmed.", },)
result = response.json()print(result["data"]["id"])Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | Template name |
subject | string | Yes | Subject line (supports {{variables}}) |
html | string | No | HTML body (supports {{variables}}) |
text | string | No | Plain text body (supports {{variables}}) |
Response (201)
Section titled “Response (201)”{ "data": { "id": "tmpl_abc123", "name": "Order Confirmation", "subject": "Your order #{{orderNumber}}", "html_body": "<h1>Thanks, {{customerName}}!</h1><p>Your order #{{orderNumber}} totaling {{total}} has been confirmed.</p>", "text_body": "Thanks, {{customerName}}! Your order #{{orderNumber}} totaling {{total}} has been confirmed.", "variables": null, "is_active": true, "created_at": "2025-01-15T10:30:00.000Z", "updated_at": "2025-01-15T10:30:00.000Z" }}Send with a template
Section titled “Send with a template”Reference the template by ID and pass the variable values using POST /api/v1/emails/send:
curl -X POST https://relaypost.dev/api/v1/emails/send \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "from": { "email": "[email protected]" }, "to": [{ "email": "[email protected]" }], "subject": "Your order #1234", "template_id": "tmpl_abc123", "template_data": { "customerName": "Jane", "orderNumber": "1234", "total": "$49.99" } }'const response = await fetch("https://relaypost.dev/api/v1/emails/send", { method: "POST", headers: { "Content-Type": "application/json", "Authorization": "Bearer YOUR_API_KEY", }, body: JSON.stringify({ subject: "Your order #1234", template_id: "tmpl_abc123", template_data: { customerName: "Jane", orderNumber: "1234", total: "$49.99", }, }),});
const result = await response.json();console.log(result.data.message_id);import requests
response = requests.post( "https://relaypost.dev/api/v1/emails/send", headers={ "Content-Type": "application/json", "Authorization": "Bearer YOUR_API_KEY", }, json={ "subject": "Your order #1234", "template_id": "tmpl_abc123", "template_data": { "customerName": "Jane", "orderNumber": "1234", "total": "$49.99", }, },)
result = response.json()print(result["data"]["message_id"])List templates
Section titled “List templates”GET /api/v1/templates
curl "https://relaypost.dev/api/v1/templates?page=1&limit=20" \ -H "Authorization: Bearer YOUR_API_KEY"const response = await fetch( "https://relaypost.dev/api/v1/templates?page=1&limit=20", { headers: { "Authorization": "Bearer YOUR_API_KEY" }, });
const result = await response.json();console.log(result.data);import requests
response = requests.get( "https://relaypost.dev/api/v1/templates", headers={"Authorization": "Bearer YOUR_API_KEY"}, params={"page": 1, "limit": 20},)
result = response.json()print(result["data"])Query parameters
Section titled “Query parameters”| Parameter | Type | Default | Description |
|---|---|---|---|
page | integer | 1 | Page number |
limit | integer | 20 | Results per page (max 100) |
Response (200)
Section titled “Response (200)”{ "data": [ { "id": "tmpl_abc123", "name": "Order Confirmation", "subject": "Your order #{{orderNumber}}", "html_body": "...", "text_body": "...", "variables": null, "is_active": true, "created_at": "2025-01-15T10:30:00.000Z", "updated_at": "2025-01-15T10:30:00.000Z" } ], "pagination": { "page": 1, "limit": 20, "total_count": 5, "total_pages": 1 }}Update a template
Section titled “Update a template”PUT /api/v1/templates/:id
Only include the fields you want to change — everything else stays the same.
curl -X PUT https://relaypost.dev/api/v1/templates/tmpl_abc123 \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "html": "<h1>Updated layout</h1><p>Hello {{customerName}}</p>" }'const response = await fetch( "https://relaypost.dev/api/v1/templates/tmpl_abc123", { method: "PUT", headers: { "Content-Type": "application/json", "Authorization": "Bearer YOUR_API_KEY", }, body: JSON.stringify({ html: "<h1>Updated layout</h1><p>Hello {{customerName}}</p>", }), });
const result = await response.json();console.log(result.data.updated_at);import requests
response = requests.put( "https://relaypost.dev/api/v1/templates/tmpl_abc123", headers={ "Content-Type": "application/json", "Authorization": "Bearer YOUR_API_KEY", }, json={ "html": "<h1>Updated layout</h1><p>Hello {{customerName}}</p>", },)
result = response.json()print(result["data"]["updated_at"])Request body
Section titled “Request body”| Field | Type | Required | Description |
|---|---|---|---|
name | string | No | Updated template name |
subject | string | No | Updated subject line |
html | string | No | Updated HTML body |
text | string | No | Updated plain text body |
At least one field must be provided.
Response (200)
Section titled “Response (200)”{ "data": { "id": "tmpl_abc123", "name": "Order Confirmation", "subject": "Your order #{{orderNumber}}", "html_body": "<h1>Updated layout</h1><p>Hello {{customerName}}</p>", "text_body": "Thanks, {{customerName}}! Your order #{{orderNumber}} totaling {{total}} has been confirmed.", "variables": null, "is_active": true, "created_at": "2025-01-15T10:30:00.000Z", "updated_at": "2025-01-15T11:00:00.000Z" }}Errors
Section titled “Errors”| Status | Code | Description |
|---|---|---|
| 400 | VALIDATION_ERROR | No update fields provided or invalid values |
| 404 | NOT_FOUND | Template not found or belongs to another organization |
Delete a template
Section titled “Delete a template”DELETE /api/v1/templates/:id
curl -X DELETE https://relaypost.dev/api/v1/templates/tmpl_abc123 \ -H "Authorization: Bearer YOUR_API_KEY"const response = await fetch( "https://relaypost.dev/api/v1/templates/tmpl_abc123", { method: "DELETE", headers: { "Authorization": "Bearer YOUR_API_KEY" }, });
const result = await response.json();console.log(result.data);import requests
response = requests.delete( "https://relaypost.dev/api/v1/templates/tmpl_abc123", headers={"Authorization": "Bearer YOUR_API_KEY"},)
result = response.json()print(result["data"])Response (200)
Section titled “Response (200)”{ "data": { "id": "tmpl_abc123", "deleted": true }}Errors
Section titled “Errors”| Status | Code | Description |
|---|---|---|
| 404 | NOT_FOUND | Template not found or belongs to another organization |