Skip to content

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.

https://relaypost.dev/api/v1

All endpoints are prefixed with /api/v1. Requests and responses use JSON.

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"
}
}
MethodEndpointDescription
POST/api/v1/emails/sendSend an email
GET/api/v1/emailsList emails
GET/api/v1/emails/:idGet email by ID
MethodEndpointDescription
POST/api/v1/domainsAdd a domain
GET/api/v1/domainsList domains
GET/api/v1/domains/:id/verifyVerify domain DNS
MethodEndpointDescription
GET/api/v1/suppressionsList suppressions
POST/api/v1/suppressionsAdd suppression
DELETE/api/v1/suppressions/:idRemove suppression
MethodEndpointDescription
GET/api/v1/templatesList templates
POST/api/v1/templatesCreate template
PUT/api/v1/templates/:idUpdate template
DELETE/api/v1/templates/:idDelete template

Send JSON in the request body with Content-Type: application/json. All field names use snake_case.

Terminal window
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>"
}'

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"
}
}

List endpoints return a pagination object alongside the data:

{
"data": [ ... ],
"pagination": {
"page": 1,
"limit": 20,
"total_count": 150,
"total_pages": 8
}
}

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.

Each API key is rate-limited to 60 requests per 60-second sliding window. Every response includes rate limit headers:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests remaining in the current window
Retry-AfterSeconds 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."
}
}