Skip to main content

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.

MethodEndpointDescription
GET/api/addressesList all addresses (filter by domainId)
POST/api/addressesCreate a new address
GET/api/addresses/:idGet address details
PATCH/api/addresses/:idUpdate note, expiration, enabled, or category
DELETE/api/addresses/:idDelete an address
POST/api/addresses/generateGenerate a random address using naming preferences
GET/api/addresses/:id/statsGet 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.

MethodEndpointDescription
GET/api/address-categoriesList all categories
POST/api/address-categoriesCreate a category
PATCH/api/address-categories/:idUpdate category name or color
DELETE/api/address-categories/:idDelete 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.

MethodEndpointDescription
GET/api/emailsList threads (paginated, searchable, filterable)
POST/api/emails/composeCompose now or queue a future email with scheduledAt
GET/api/emails/:threadIdGet thread with all messages
PATCH/api/emails/:threadIdUpdate read, starred, archived, or trash state
DELETE/api/emails/:threadIdMove to trash or permanently delete
POST/api/emails/:threadId/replyReply, reply-all, or forward
GET/api/emails/scheduledList scheduled delivery records
DELETE/api/emails/scheduled/:idCancel a pending message or permanently remove a canceled/failed record
PATCH/api/emails/batchBatch update read/starred state (up to 100)
GET/api/emails/html/:emailIdGet rendered HTML of an email
GET/api/emails/raw/:emailIdGet raw email data
POST/api/emails/empty-trashPermanently 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.

ParameterTypeDescription
pagenumberPage number (default: 1)
limitnumberItems per page (default: 20, max: 100)
folderstring"inbox", "trash", or "archived"
addressIdnumberFilter by address
searchstringSearch subjects, senders, and message text
isStarredbooleanFilter starred threads
isReadbooleanFilter read/unread
dateFromstringISO date lower bound
dateTostringISO date upper bound
sortBystring"date" or "subject"
sortOrderstring"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.

MethodEndpointDescription
GET/api/domainsList domains (filter by isPrivate)
GET/api/domains/:idGet 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.

MethodEndpointDescription
GET/api/blocked-sendersList blocked senders (filter by addressId)
POST/api/blocked-sendersBlock a sender for an address
DELETE/api/blocked-senders/:idUnblock 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.

MethodEndpointDescription
GET/api/api-keysList API keys (key prefix only)
POST/api/api-keysCreate a new API key
DELETE/api/api-keys/:idRevoke 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.

MethodEndpointDescription
GET/api/webhooksList webhook endpoints with recent deliveries
POST/api/webhooksCreate a webhook endpoint
PATCH/api/webhooks/:idUpdate events or toggle enabled
DELETE/api/webhooks/:idDelete a webhook endpoint
GET/api/webhooks/:id/deliveriesView 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.

MethodEndpointDescription
GET/api/push/vapidGet the VAPID public key
POST/api/push/subscribeRegister a push subscription
GET/api/push/subscribeList active subscriptions
DELETE/api/push/subscribeRemove 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.

MethodEndpointDescription
GET/api/attachments/:idGet 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.

MethodEndpointDescription
GET/api/preferencesGet current preferences
PATCH/api/preferencesUpdate 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

FormatExample
RANDOMx7k9m2p4
FIRST_NAMEsarah
FIRST_LASTsarahmitchell
FIRST_DOT_LASTsarah.mitchell
FIRST_INITIAL_LASTsmitchell
RANDOM_WORDautumn
RANDOM_LETTERSqwxztp

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.

MethodEndpointDescription
POST/api/alias/random/newGenerate alias (SimpleLogin-compatible format)
POST/api/v1/aliasesGenerate 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]" } }

Related