API reference
Complete REST API for managing aliases, emails, domains, webhooks, and more.
Authentication
Authenticated user-resource endpoints accept an API key passed as a Bearer token in the Authorization header. Dashboard requests may use the signed-in session cookie; public configuration and signed webhook routes document their own authentication.
Authorization: Bearer YOUR_API_KEY
Generate API keys from Settings → Developers in the dashboard. Plus includes 1 key; Max includes up to 10.
REST responses follow { data: T } on success or { error: string } on failure. The SimpleLogin compatibility endpoint intentionally uses its provider-specific top-level shape.
Addresses
Create, list, update, and delete email aliases.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/addresses | List all addresses (filter by domainId) |
| POST | /api/addresses | Create a new address |
| GET | /api/addresses/:id | Get address details |
| PATCH | /api/addresses/:id | Update note, expiration, enabled, or category |
| DELETE | /api/addresses/:id | Delete an address |
| POST | /api/addresses/generate | Generate a random address using naming preferences |
| GET | /api/addresses/:id/stats | Get address statistics and top senders |
Example: Create address
curl -X POST https://mailservr.app/api/addresses \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "notifications", "domainId": 1, "note": "GitHub alerts"}'
// Response (201):
{
"data": {
"id": 42,
"name": "notifications",
"enabled": true,
"note": "GitHub alerts",
"expiresAt": null,
"domain": { "id": 1, "name": "priv.sh", "receiveOnly": false }
}
}Example: Generate random address
curl -X POST https://mailservr.app/api/addresses/generate \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domainId": 1}'
// Response (201):
{
"data": {
"id": 43,
"name": "sarah.mitchell42",
"enabled": true,
"domain": { "id": 1, "name": "priv.sh", "receiveOnly": false }
}
}Address Categories
Organize addresses into color-coded categories.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/address-categories | List all categories |
| POST | /api/address-categories | Create a category |
| PATCH | /api/address-categories/:id | Update category name or color |
| DELETE | /api/address-categories/:id | Delete a category |
Example: Create category
curl -X POST https://mailservr.app/api/address-categories \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "Work", "color": "#3B82F6"}'
// Response (201):
{
"data": {
"id": 5,
"name": "Work",
"color": "#3B82F6",
"sortOrder": 0
}
}Emails
Read, compose, reply, and manage email threads.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/emails | List threads (paginated, searchable, filterable) |
| POST | /api/emails/compose | Compose now or queue a future email with scheduledAt |
| GET | /api/emails/:threadId | Get thread with all messages |
| PATCH | /api/emails/:threadId | Update read, starred, archived, or trash state |
| DELETE | /api/emails/:threadId | Move to trash or permanently delete |
| POST | /api/emails/:threadId/reply | Reply, reply-all, or forward |
| GET | /api/emails/scheduled | List scheduled delivery records |
| DELETE | /api/emails/scheduled/:id | Cancel a pending message or permanently remove a canceled/failed record |
| PATCH | /api/emails/batch | Batch update read/starred state (up to 100) |
| GET | /api/emails/html/:emailId | Get rendered HTML of an email |
| GET | /api/emails/raw/:emailId | Get raw email data |
| POST | /api/emails/empty-trash | Permanently delete all trashed emails |
Example: List threads
curl "https://mailservr.app/api/emails?folder=inbox&limit=10&search=deploy" \
-H "Authorization: Bearer YOUR_API_KEY"
// Response:
{
"data": {
"items": [
{
"id": 87,
"subject": "Deployment successful",
"messageCount": 1,
"isRead": false,
"isStarred": false,
"lastMessageAt": "2026-02-13T10:30:00Z",
"emails": [
{
"id": 150,
"snippet": "Your app was deployed to...",
"fromAddress": "[email protected]",
"fromName": "Build system"
}
]
}
],
"pagination": { "page": 1, "limit": 10, "total": 1, "totalPages": 1 }
}
}Example: Compose email
Send a unique `Idempotency-Key` header and reuse it only when retrying the exact same compose, reply, or scheduling request. A key reused with different content returns 409.
curl -X POST https://mailservr.app/api/emails/compose \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 8449af57-b9cf-4d5b-a12e-6b605e58e6bf" \
-d '{
"addressId": 42,
"to": "[email protected]",
"subject": "Hello from mailservr",
"textBody": "Hello from mailservr."
}'
// Response (201):
{
"data": {
"id": 88,
"subject": "Hello from mailservr",
"emails": [{ "id": 150, "fromAddress": "[email protected]", "deliveryStatus": "SENT" }]
}
}Schedule delivery
Add a future ISO-8601 `scheduledAt` value to compose or reply. Delivery rechecks the current plan and sending limits, and pending messages can be canceled through the scheduled endpoint.
curl -X POST https://mailservr.app/api/emails/compose \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: e8a9a9f0-97b2-4c7e-a672-9108dcf58acb" \
-d '{
"addressId": 42,
"to": "[email protected]",
"subject": "A note for tomorrow",
"textBody": "See you then.",
"scheduledAt": "2026-08-01T09:00:00.000Z"
}'Query parameters for GET /api/emails
Free accounts receive their visible 7-day history only; retained older messages are restored automatically after an upgrade.
| Parameter | Type | Description |
|---|---|---|
| page | number | Page number (default: 1) |
| limit | number | Items per page (default: 20, max: 100) |
| folder | string | "inbox", "trash", or "archived" |
| addressId | number | Filter by address |
| search | string | Search subjects, senders, and message text |
| isStarred | boolean | Filter starred threads |
| isRead | boolean | Filter read/unread |
| dateFrom | string | ISO date lower bound |
| dateTo | string | ISO date upper bound |
| sortBy | string | "date" or "subject" |
| sortOrder | string | "asc" or "desc" |
Domains
List available domains. Domain creation is admin-restricted; address counts on shared domains are scoped to the current user unless the caller is an administrator.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/domains | List domains (filter by isPrivate) |
| GET | /api/domains/:id | Get domain details and address count |
Example: List domains
curl https://mailservr.app/api/domains \
-H "Authorization: Bearer YOUR_API_KEY"
// Response:
{
"data": [
{
"id": 1,
"name": "priv.sh",
"status": "ACTIVE",
"isPrivate": false,
"receiveOnly": false,
"_count": { "addresses": 12 }
}
]
}Blocked Senders
Block specific senders from delivering to your addresses.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/blocked-senders | List blocked senders (filter by addressId) |
| POST | /api/blocked-senders | Block a sender for an address |
| DELETE | /api/blocked-senders/:id | Unblock a sender |
Example: Block a sender
curl -X POST https://mailservr.app/api/blocked-senders \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"addressId": 42, "senderEmail": "[email protected]"}'
// Response (201):
{
"data": {
"id": 7,
"addressId": 42,
"senderEmail": "[email protected]",
"createdAt": "2026-02-13T10:30:00Z"
}
}API Keys
Manage API keys for programmatic access.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/api-keys | List API keys (key prefix only) |
| POST | /api/api-keys | Create a new API key |
| DELETE | /api/api-keys/:id | Revoke an API key |
Example: Create API key
curl -X POST https://mailservr.app/api/api-keys \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name": "CI/CD Pipeline", "expiresAt": "2027-01-01T00:00:00Z"}'
// Response (201):
{
"data": {
"id": 3,
"name": "CI/CD Pipeline",
"keyPrefix": "a3f95c10",
"expiresAt": "2027-01-01T00:00:00Z",
"key": "a3f95c10d42e7b8f4e38ce758ea3d907f946b5991768bf47c314f4892b107f65"
}
}The full key value is only returned once at creation time. Store it securely.
Webhooks
Manage outbound webhook endpoints. Available on the Max plan. See the webhook documentation for event payloads and signature verification.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/webhooks | List webhook endpoints with recent deliveries |
| POST | /api/webhooks | Create a webhook endpoint |
| PATCH | /api/webhooks/:id | Update events or toggle enabled |
| DELETE | /api/webhooks/:id | Delete a webhook endpoint |
| GET | /api/webhooks/:id/deliveries | View delivery history |
Example: Create webhook
curl -X POST https://mailservr.app/api/webhooks \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://example.com/webhook",
"format": "STANDARD",
"events": ["EMAIL_RECEIVED", "THREAD_CREATED"]
}'
// Response (201):
{
"data": {
"id": 2,
"url": "https://example.com/webhook",
"format": "STANDARD",
"events": ["EMAIL_RECEIVED", "THREAD_CREATED"],
"enabled": true,
"secret": "4f7df09bca4e5d2d4580a62690eb928bd9521426c04cc9d96edaa79fdbe3af21"
}
}The secret is only returned once for STANDARD endpoints. Set format to DISCORD for a direct Discord incoming webhook URL; Discord endpoints return no secret and receive embed payloads.
Push Notifications
Subscribe to browser push notifications for new emails.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/push/vapid | Get the VAPID public key |
| POST | /api/push/subscribe | Register a push subscription |
| GET | /api/push/subscribe | List active subscriptions |
| DELETE | /api/push/subscribe | Remove a push subscription |
Example: Subscribe
curl -X POST https://mailservr.app/api/push/subscribe \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"endpoint": "https://fcm.googleapis.com/fcm/send/...",
"keys": {
"p256dh": "BNcRd...",
"auth": "tBHI..."
}
}'
// Response:
{ "data": { "id": 12 } }Attachments
Download email attachments via presigned URLs.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/attachments/:id | Get a presigned download URL |
Example
curl https://mailservr.app/api/attachments/15 \
-H "Authorization: Bearer YOUR_API_KEY"
// Response:
{
"data": {
"url": "https://storage.example.com/...",
"expiresAt": "2026-07-17T10:15:00.000Z",
"filename": "report.pdf",
"contentType": "application/pdf"
}
}Preferences
Manage user preferences for default domain and alias generation format.
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/preferences | Get current preferences |
| PATCH | /api/preferences | Update preferences |
Example: Update preferences
curl -X PATCH https://mailservr.app/api/preferences \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"defaultDomainId": 1, "emailFormat": "FIRST_DOT_LAST", "includeNumbers": true}'
// Response:
{
"data": {
"defaultDomainId": 1,
"emailFormat": "FIRST_DOT_LAST",
"includeNumbers": true,
"defaultDomain": { "id": 1, "name": "priv.sh" }
}
}Email format options
| Format | Example |
|---|---|
| RANDOM | x7k9m2p4 |
| FIRST_NAME | sarah |
| FIRST_LAST | sarahmitchell |
| FIRST_DOT_LAST | sarah.mitchell |
| FIRST_INITIAL_LAST | smitchell |
| RANDOM_WORD | autumn |
| RANDOM_LETTERS | qwxztp |
Password Manager Aliases
Endpoints matching the SimpleLogin and Addy.io request formats used by Bitwarden's custom-server provider modes. See the password manager setup guide for configuration instructions.
| Method | Endpoint | Description |
|---|---|---|
| POST | /api/alias/random/new | Generate alias (SimpleLogin-compatible format) |
| POST | /api/v1/aliases | Generate alias (Addy.io-compatible format) |
Example: SimpleLogin
curl -X POST "https://mailservr.app/api/alias/random/new?hostname=github.com" \
-H "Authentication: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"note": "Generated for github.com"}'
// Response (201):
{ "alias": "[email protected]" }Example: Addy.io
curl -X POST https://mailservr.app/api/v1/aliases \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domain": "priv.sh", "description": "Generated for github.com"}'
// Response (201):
{ "data": { "email": "[email protected]" } }