Zmail Docs
operator + agent reference for zmail.zergai.com
source: docs/api-reference.md

API Reference

Zmail exposes three API surfaces:

  • API key APIs for server-to-server calls
  • Session APIs under /app/api/* for product app and CLI
  • Scoped service-token APIs under /v1/transactional/*

1. API Key APIs

Auth header:

  • Authorization: Bearer <ZMAIL_API_KEY>
  • Optional tenant scoping: X-Tenant-ID: <tenant_id>

Health

  • GET /health

Mailboxes

  • GET /mailboxes
  • POST /mailboxes?address=<email>&description=<text>
  • GET /mailboxes/{address}
  • DELETE /mailboxes/{address}

Messages

  • GET /inbox?mailbox=&folder=inbox&limit=50&offset=0
  • GET /messages/{message_id}?mark_read=true
  • POST /messages/{message_id}/read?read=true
  • POST /messages/{message_id}/move?folder=archive
  • DELETE /messages/{message_id}

Sending

  • POST /send
  • Body: from_mailbox, to, subject, body, optional html

Stats and Spam

  • GET /stats
  • POST /messages/{message_id}/spam
  • POST /messages/{message_id}/not-spam

2. Session APIs (/app/api/*)

Auth header:

  • X-Zmail-Session: <session_token>

Session and Workspace

  • POST /app/api/login
  • POST /app/api/logout
  • GET /app/api/session
  • POST /app/api/workspaces/select

Mailboxes

  • GET /app/api/mailboxes
  • POST /app/api/mailboxes

Sending Domains and Service Tokens

These routes require an owner/admin session in the active workspace.

  • GET /app/api/sending-domains
  • POST /app/api/sending-domains
  • POST /app/api/sending-domains/{domain_id}/verify
  • GET /app/api/service-tokens
  • POST /app/api/service-tokens
  • POST /app/api/service-tokens/{token_id}/rotate
  • DELETE /app/api/service-tokens/{token_id}

Domain creation returns the DNS verification token once. Service-token creation

and rotation return plaintext credentials once; list responses never contain

them. Only message:send is currently supported.

Messages

  • GET /app/api/messages
  • GET /app/api/messages/{message_id}
  • POST /app/api/messages/{message_id}/read
  • POST /app/api/messages/{message_id}/move
  • POST /app/api/messages/{message_id}/labels
  • GET /app/api/messages/{message_id}/thread
  • GET /app/api/messages/{message_id}/attachments
  • GET /app/api/messages/{message_id}/attachments/{attachment_id}

Threads

  • GET /app/api/threads
  • GET /app/api/threads/{thread_id}
  • POST /app/api/threads/{thread_id}/labels

Drafts

  • GET /app/api/drafts
  • POST /app/api/drafts
  • GET /app/api/drafts/{draft_id}
  • PATCH /app/api/drafts/{draft_id}
  • DELETE /app/api/drafts/{draft_id}
  • POST /app/api/drafts/{draft_id}/send

Lists

  • GET /app/api/lists/{direction}/{list_type}
  • POST /app/api/lists/{direction}/{list_type}
  • GET /app/api/lists/{direction}/{list_type}/{entry:path}
  • DELETE /app/api/lists/{direction}/{list_type}/{entry:path}

Outbound and Sent

  • POST /app/api/send
  • GET /app/api/sent

Webhooks

  • GET /app/api/webhooks
  • POST /app/api/webhooks
  • GET /app/api/webhooks/{webhook_id}
  • PATCH /app/api/webhooks/{webhook_id}
  • DELETE /app/api/webhooks/{webhook_id}
  • GET /app/api/webhooks/{webhook_id}/deliveries
  • POST /app/api/webhooks/{webhook_id}/test

3. Transactional Service API

Auth and idempotency headers:

  • Authorization: Bearer <scoped_service_token>
  • Idempotency-Key: <stable caller request ID>

Create a message:

  • POST /v1/transactional/messages
  • Body: from_mailbox, to, subject, body, optional html, from_name, reply_to
  • Returns 202 with stable message_id and status: queued

The token is bound to one workspace, verified sending domain, mailbox, and

message:send scope. The same key and canonical payload replay the original

202; reusing a key for different content returns 409. Tracking pixels are

disabled for this API.

Status lookup:

  • GET /v1/transactional/messages/{message_id}
  • GET /v1/transactional/messages?idempotency_key=<key>

Statuses are queued, processing, accepted, failed, and unknown.

accepted means the SMTP peer accepted responsibility; it is not proof of

final inbox delivery. unknown is terminal and prevents an ambiguous SMTP

retry from duplicating authentication mail.

Response Conventions

  • Success responses use object payloads and include ok/success where appropriate.
  • Errors return JSON with error or detail and HTTP status code.

cURL Examples


# API-key mailbox list
curl -sS https://zerg-mail.com/mailboxes \
  -H "Authorization: Bearer $ZMAIL_API_KEY" \
  -H "X-Tenant-ID: 1"

# Session login
curl -sS https://zerg-mail.com/app/api/login \
  -H "content-type: application/json" \
  -d '{"email":"you@example.com","password":"***"}'

# Create webhook in active workspace
curl -sS https://zerg-mail.com/app/api/webhooks \
  -H "content-type: application/json" \
  -H "X-Zmail-Session: $SESSION" \
  -d '{"url":"https://example.com/webhooks/zmail","event_types":["message.received"]}'

# Queue transactional auth mail
curl -sS https://zerg-mail.com/v1/transactional/messages \
  -H "Authorization: Bearer $ZMAIL_SERVICE_TOKEN" \
  -H "Idempotency-Key: core-auth-email:$OUTBOX_ID" \
  -H "content-type: application/json" \
  -d '{"from_mailbox":"auth@example.com","to":"user@example.net","subject":"Verify","body":"Code: 123456"}'