The TrackPost REST API allows you to send emails, manage templates, and track analytics from any programming language.
Table of Contents
Base URL
https://api.trackpost.de/v1
Authentication
All API requests require authentication using your API key in the Authorization header.
Header Format
Authorization: Bearer {your_api_key}
Example
curl https://api.trackpost.de/v1/emails \
-H "Authorization: Bearer tp_live_your_api_key"
Warning
Security Warning: Never expose your API keys in client-side code, public repositories, or browser applications. Use environment variables or secret management systems.
API Key Types
| Type | Prefix | Purpose | Rate Limits |
|---|---|---|---|
| Test | tp_test_ | Development and testing | Same as live |
| Live | tp_live_ | Production emails | Based on your plan |
Response Format
All responses are returned as JSON.
Success Response
{
"success": true,
"data": {
// Response data here
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Error Response
{
"success": false,
"error": {
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded. Please retry after 60 seconds.",
"status": 429
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Rate Limiting
API requests are rate-limited based on your plan:
| Plan | Requests/Minute | Monthly Emails |
|---|---|---|
| Free | 60 | 1,000 |
| Indie | 120 | 10,000 |
| Startup | 300 | 50,000 |
| Growth | 600 | 250,000 |
| Enterprise | 1,200 | Custom |
Rate Limit Headers
Every response includes rate limit information:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705323000
Handling Rate Limits
When you hit the rate limit, you’ll receive a 429 status code. Implement exponential backoff:
// Example retry logic
async function sendWithRetry(emailData, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await sendEmail(emailData);
} catch (error) {
if (error.status === 429) {
const delay = Math.pow(2, i) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
continue;
}
throw error;
}
}
throw new Error('Max retries exceeded');
}
Emails
Send Email
Send a new email to one or more recipients.
Endpoint: POST /emails
Request Body:
{
"to": "[email protected]",
"from": "[email protected]",
"subject": "Welcome!",
"html": "<h1>Welcome!</h1>",
"text": "Welcome!",
"cc": ["[email protected]"],
"bcc": ["[email protected]"],
"reply_to": "[email protected]",
"attachments": [
{
"filename": "document.pdf",
"content": "base64_encoded_content",
"contentType": "application/pdf"
}
],
"template_id": "welcome_email",
"variables": {
"user_name": "John Doe"
},
"tags": ["onboarding", "welcome"],
"track_opens": true,
"track_clicks": true,
"scheduled_at": "2025-01-20T10:00:00Z"
}
Parameters:
| Field | Type | Required | Description |
|---|---|---|---|
to | string | array | Yes | Recipient email(s) |
from | string | Yes | Sender email address |
subject | string | Conditional* | Email subject |
html | string | Conditional* | HTML content |
text | string | No | Plain text content |
cc | string | array | No | CC recipients |
bcc | string | array | No | BCC recipients |
reply_to | string | No | Reply-to address |
attachments | array | No | File attachments |
template_id | string | Conditional* | Template ID to use |
variables | object | No | Template variables |
tags | array | No | Tags for analytics |
track_opens | boolean | No | Enable open tracking (default: true) |
track_clicks | boolean | No | Enable click tracking (default: true) |
scheduled_at | string | No | ISO 8601 datetime for scheduled send |
* Either html or template_id is required. If using template_id, subject can come from the template.
Response:
{
"success": true,
"data": {
"id": "msg_abc123def456",
"to": "[email protected]",
"from": "[email protected]",
"subject": "Welcome!",
"status": "sent",
"created_at": "2025-01-15T10:30:00Z",
"scheduled_at": null,
"tags": ["onboarding", "welcome"]
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Example:
curl -X POST https://api.trackpost.de/v1/emails \
-H "Authorization: Bearer tp_live_your_key" \
-H "Content-Type: application/json" \
-d '{
"to": "[email protected]",
"from": "[email protected]",
"subject": "Welcome!",
"html": "<h1>Welcome!</h1>"
}'
List Emails
Retrieve a list of emails with optional filtering.
Endpoint: GET /emails
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
limit | integer | Number of results (1-100, default: 20) |
offset | integer | Pagination offset |
status | string | Filter by status: sent, delivered, bounced, complained |
from_date | string | Filter by date (ISO 8601) |
to_date | string | Filter by date (ISO 8601) |
to | string | Filter by recipient email |
from | string | Filter by sender email |
tags | string | Comma-separated list of tags |
Response:
{
"success": true,
"data": {
"emails": [
{
"id": "msg_abc123",
"to": "[email protected]",
"from": "[email protected]",
"subject": "Welcome!",
"status": "delivered",
"created_at": "2025-01-15T10:30:00Z",
"delivered_at": "2025-01-15T10:30:02Z"
}
],
"pagination": {
"total": 150,
"limit": 20,
"offset": 0,
"has_more": true
}
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Example:
curl "https://api.trackpost.de/v1/emails?limit=10&status=delivered" \
-H "Authorization: Bearer tp_live_your_key"
Get Email
Retrieve details of a specific email.
Endpoint: GET /emails/{id}
Response:
{
"success": true,
"data": {
"id": "msg_abc123",
"to": "[email protected]",
"from": "[email protected]",
"subject": "Welcome!",
"html": "<h1>Welcome!</h1>",
"text": "Welcome!",
"status": "delivered",
"created_at": "2025-01-15T10:30:00Z",
"sent_at": "2025-01-15T10:30:01Z",
"delivered_at": "2025-01-15T10:30:02Z",
"opened_at": "2025-01-15T10:35:00Z",
"opens_count": 2,
"clicks_count": 1,
"tags": ["onboarding"],
"bounce_reason": null,
"template_id": null,
"variables": null
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Cancel Scheduled Email
Cancel an email that hasn’t been sent yet.
Endpoint: DELETE /emails/{id}
Response:
{
"success": true,
"data": {
"id": "msg_abc123",
"status": "cancelled"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Templates
Create Template
Create a new email template.
Endpoint: POST /templates
Request Body:
{
"name": "welcome_email",
"subject": "Welcome to {{company}}, {{user_name}}!",
"html": "<h1>Welcome, {{user_name}}!</h1><p>We're excited to have you at {{company}}.</p>",
"text": "Welcome {{user_name}}! We're excited to have you at {{company}}."
}
Response:
{
"success": true,
"data": {
"id": "tpl_abc123",
"name": "welcome_email",
"subject": "Welcome to {{company}}, {{user_name}}!",
"html": "<h1>Welcome, {{user_name}}!</h1>...",
"text": "Welcome {{user_name}}!...",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-01-15T10:30:00Z"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
List Templates
Endpoint: GET /templates
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
limit | integer | Number of results (1-100, default: 20) |
offset | integer | Pagination offset |
Get Template
Endpoint: GET /templates/{id}
Update Template
Endpoint: PATCH /templates/{id}
Request Body: (all fields optional)
{
"name": "welcome_email_v2",
"subject": "Welcome!",
"html": "<h1>Welcome!</h1>",
"text": "Welcome!"
}
Delete Template
Endpoint: DELETE /templates/{id}
Render Template (Preview)
Render a template with variables to preview the output.
Endpoint: POST /templates/{id}/render
Request Body:
{
"variables": {
"user_name": "Test User",
"company": "Test Company"
}
}
Response:
{
"success": true,
"data": {
"subject": "Welcome to Test Company, Test User!",
"html": "<h1>Welcome, Test User!</h1><p>We're excited to have you at Test Company.</p>",
"text": "Welcome Test User! We're excited to have you at Test Company."
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Domains
List Domains
Endpoint: GET /domains
Response:
{
"success": true,
"data": {
"domains": [
{
"domain": "yourapp.com",
"status": "verified",
"dkim_verified": true,
"spf_verified": true,
"dmarc_verified": true,
"created_at": "2025-01-15T10:30:00Z"
}
]
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Add Domain
Endpoint: POST /domains
Request Body:
{
"domain": "yourapp.com"
}
Response: Includes DNS records to add:
{
"success": true,
"data": {
"domain": "yourapp.com",
"status": "pending",
"dns_records": [
{
"type": "TXT",
"name": "_amazonses.yourapp.com",
"value": "token_abc123",
"purpose": "verification"
},
{
"type": "TXT",
"name": "yourapp.com",
"value": "v=spf1 include:amazonses.com ~all",
"purpose": "spf"
},
{
"type": "TXT",
"name": "selector1._domainkey.yourapp.com",
"value": "DKIM_key_1",
"purpose": "dkim"
}
]
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Verify Domain
Endpoint: POST /domains/{domain}/verify
Get Domain
Endpoint: GET /domains/{domain}
Delete Domain
Endpoint: DELETE /domains/{domain}
API Keys
List API Keys
Endpoint: GET /api-keys
Create API Key
Endpoint: POST /api-keys
Request Body:
{
"name": "Production API Key",
"environment": "live",
"rate_limit": 60
}
Response:
{
"success": true,
"data": {
"id": "key_abc123",
"name": "Production API Key",
"key": "tp_live_abc123def456", // Only shown once!
"environment": "live",
"rate_limit": 60,
"created_at": "2025-01-15T10:30:00Z"
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Revoke API Key
Endpoint: DELETE /api-keys/{id}
Webhooks
List Webhooks
Endpoint: GET /webhooks
Create Webhook
Endpoint: POST /webhooks
Request Body:
{
"url": "https://yourapp.com/webhooks/trackpost",
"events": ["email.delivered", "email.bounced", "email.opened"],
"secret": "your_webhook_secret" // optional, for signature verification
}
Update Webhook
Endpoint: PATCH /webhooks/{id}
Delete Webhook
Endpoint: DELETE /webhooks/{id}
Analytics
Get Email Stats
Endpoint: GET /analytics/emails
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
from_date | string | Start date (ISO 8601) |
to_date | string | End date (ISO 8601) |
group_by | string | Group by: day, week, month |
Response:
{
"success": true,
"data": {
"total": {
"sent": 1000,
"delivered": 980,
"bounced": 15,
"complained": 5,
"opened": 450,
"clicked": 120
},
"by_date": [
{
"date": "2025-01-15",
"sent": 100,
"delivered": 98,
"bounced": 2
}
]
},
"meta": {
"request_id": "req_abc123",
"timestamp": "2025-01-15T10:30:00Z"
}
}
Error Codes
HTTP Status Codes
| Code | Meaning | Description |
|---|---|---|
| 200 | OK | Request successful |
| 201 | Created | Resource created successfully |
| 204 | No Content | Request successful, no body |
| 400 | Bad Request | Invalid request parameters |
| 401 | Unauthorized | Invalid or missing API key |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 409 | Conflict | Resource conflict (e.g., duplicate) |
| 422 | Unprocessable | Validation error |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Server Error | Internal server error |
Error Codes
| Code | Description |
|---|---|
authentication_error | API key is invalid or expired |
authorization_error | Insufficient permissions |
validation_error | Request validation failed |
not_found | Resource doesn’t exist |
rate_limit_exceeded | Rate limit reached |
domain_not_verified | Sending domain not verified |
template_not_found | Template ID doesn’t exist |
invalid_variables | Template variables missing or invalid |
aws_error | AWS SES error |
internal_error | Server error |
SDKs and Libraries
While you can use the REST API directly, we recommend our official SDKs:
- Node.js SDK
- Python SDK (Coming Q1 2026)
- Go SDK (Coming Q2 2026)
Next Steps
- CLI Tool - Command-line interface
- Node.js SDK - TypeScript/JavaScript SDK
- Webhooks - Event handling
- Templates - Email templating