API Overview
The RelayPost API is a REST API for sending transactional and campaign emails programmatically. It provides endpoints for email, domains, templates, and suppression lists with API key authentication and rate limiting.
The API lives at /api/v1/* and gives you standard HTTP endpoints for all email operations.
Base URL
Section titled “Base URL”https://api.relaypost.dev/v1All endpoints are prefixed with /api/v1. Requests and responses use JSON.
Authentication
Section titled “Authentication”Include your API key in the Authorization header as a Bearer token:
Authorization: Bearer rp_live_aBcDeFgHiJkLmNoPqRsT...API keys are scoped to an organization. Every resource you create or query is automatically scoped to the organization that owns the key. You can create and manage API keys from the RelayPost dashboard.
A request without a valid key returns 401:
{ "error": { "code": "AUTH_INVALID", "message": "Invalid or revoked API key" }}Available endpoints
Section titled “Available endpoints”Emails
Section titled “Emails”| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/emails/send | Send an email |
| GET | /api/v1/emails | List emails |
| GET | /api/v1/emails/:id | Get email by ID |
Domains
Section titled “Domains”| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/domains | Add a domain |
| GET | /api/v1/domains | List domains |
| GET | /api/v1/domains/:id/verify | Verify domain DNS |
Suppressions
Section titled “Suppressions”| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/suppressions | List suppressions |
| POST | /api/v1/suppressions | Add suppression |
| DELETE | /api/v1/suppressions/:id | Remove suppression |
Templates
Section titled “Templates”| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/templates | List templates |
| POST | /api/v1/templates | Create template |
| PUT | /api/v1/templates/:id | Update template |
| DELETE | /api/v1/templates/:id | Delete template |
Email Validation
Section titled “Email Validation”| Method | Endpoint | Description |
|---|---|---|
| POST | /api/v1/emails/validate | Validate a single email |
| POST | /api/v1/emails/validate/batch | Validate up to 100 emails |
Settings
Section titled “Settings”| Method | Endpoint | Description |
|---|---|---|
| GET | /api/v1/settings/auto-validation | Get auto-validation threshold |
| PUT | /api/v1/settings/auto-validation | Update auto-validation threshold |
Request format
Section titled “Request format”Send JSON in the request body with Content-Type: application/json. All field names use snake_case.
curl -X POST https://api.relaypost.dev/v1/emails/send \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "from": { "email": "hello@yourdomain.com", "name": "Your App" }, "to": [{ "email": "user@example.com" }], "subject": "Hello", "html": "<p>Hello from RelayPost!</p>" }'Response format
Section titled “Response format”Success
Section titled “Success”Successful responses wrap the result in a data field:
{ "data": { "message_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890", "status": "queued", "queued_at": "2025-01-15T10:30:00.000Z" }}Paginated lists
Section titled “Paginated lists”List endpoints return a pagination object alongside the data:
{ "data": [ ... ], "pagination": { "page": 1, "limit": 20, "total_count": 150, "total_pages": 8 }}Errors
Section titled “Errors”Error responses use a consistent format with a machine-readable code and a human-readable message:
{ "error": { "code": "VALIDATION_ERROR", "message": "Request validation failed", "details": [ { "field": "to", "message": "At least one recipient is required" } ] }}See Error Codes for the full list.
Rate limiting
Section titled “Rate limiting”API request rate limits are derived from your organization’s hourly email sending limit. The per-minute request cap equals your hourly limit divided by 60 (rounded up). For example, the default hourly limit of 1,000 allows 17 API requests per 60-second window. Every response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the window |
X-RateLimit-Remaining | Requests remaining in the current window |
Retry-After | Seconds to wait before retrying (only on 429 responses) |
When you exceed the limit, the API returns 429:
{ "error": { "code": "RATE_LIMITED", "message": "Rate limit exceeded. Try again later." }}