API Overview
The RelayPost REST API lives at /api/v1/* and gives you standard HTTP endpoints for sending emails, managing domains, templates, and suppression lists.
Base URL
Section titled “Base URL”https://relaypost.dev/api/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 |
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://relaypost.dev/api/v1/emails/send \ -H "Content-Type: application/json" \ -H "Authorization: Bearer YOUR_API_KEY" \ -d '{ "from": { "email": "[email protected]", "name": "Your App" }, "to": [{ "email": "[email protected]" }], "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”Each API key is rate-limited to 60 requests per 60-second sliding 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." }}