Messages API

Send, receive, list, search, and delete emails. All endpoints require a Bearer token in the Authorization header.

Base URL: https://mails-worker.genedai.workers.dev

Send Email

POST/v1/send

Request Body

FieldTypeRequiredDescription
fromstringYesSender email address (must belong to your mailbox)
tostring[]YesRecipient email addresses (max 50)
subjectstringYesEmail subject (max 998 characters)
textstringNoPlain text body (max 500KB)
htmlstringNoHTML body (max 1MB)
reply_tostringNoReply-To address
headersRecord<string, string>NoCustom email headers
ccstring[]NoCC recipients
bccstring[]NoBCC recipients
in_reply_tostringNoMessage ID to reply to (for threading)
attachmentsobject[]NoFile attachments (see below)

Attachment Object

FieldTypeRequiredDescription
filenamestringYesFile name
contentstringYesBase64-encoded file content
content_typestringNoMIME type (e.g. application/pdf)
content_idstringNoContent-ID for inline images

Example

curl -X POST https://mails-worker.genedai.workers.dev/v1/send \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "from": "[email protected]",
    "to": ["[email protected]"],
    "subject": "Your report is ready",
    "text": "Hi, your weekly report is attached.",
    "attachments": [
      {
        "filename": "report.pdf",
        "content": "JVBERi0xLjQK...",
        "content_type": "application/pdf"
      }
    ]
  }'

Response

{
  "id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "provider_id": "re_abc123",
  "thread_id": "thr_def456"
}

List Emails (Inbox)

GET/v1/inbox

Query Parameters

ParamTypeDefaultDescription
limitinteger20Number of emails to return (max 100)
offsetinteger0Pagination offset
directionstringFilter by inbound or outbound
querystringSearch query string
labelstringFilter by label: newsletter, notification, code, personal
modestringkeywordSearch mode: keyword, semantic, or hybrid

Example

# List latest 20 emails
curl https://mails-worker.genedai.workers.dev/v1/inbox \
  -H "Authorization: Bearer YOUR_API_KEY"

# Search for verification codes
curl "https://mails-worker.genedai.workers.dev/v1/inbox?query=verification&label=code&limit=5" \
  -H "Authorization: Bearer YOUR_API_KEY"

# List outbound emails with pagination
curl "https://mails-worker.genedai.workers.dev/v1/inbox?direction=outbound&limit=50&offset=100" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "emails": [
    {
      "id": "msg_abc123",
      "mailbox": "[email protected]",
      "from_address": "[email protected]",
      "from_name": "Sender Name",
      "subject": "Welcome to our service",
      "code": null,
      "direction": "inbound",
      "status": "received",
      "received_at": "2026-04-01T12:00:00Z",
      "has_attachments": false,
      "attachment_count": 0
    }
  ],
  "search_mode": "keyword"
}

Get Single Email

GET/v1/email?id=xxx

Returns the full email including body content and attachments metadata.

Example

curl "https://mails-worker.genedai.workers.dev/v1/email?id=msg_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

Returns the email object directly (not wrapped in an "email" key):

{
  "id": "msg_abc123",
  "mailbox": "[email protected]",
  "from_address": "[email protected]",
  "from_name": "Sender Name",
  "to_address": "[email protected]",
  "subject": "Welcome to our service",
  "body_text": "Thank you for signing up. Your account is ready.",
  "body_html": "<p>Thank you for signing up.</p>",
  "code": null,
  "direction": "inbound",
  "status": "received",
  "headers": {},
  "metadata": {},
  "message_id": "<[email protected]>",
  "thread_id": "thr_def456",
  "in_reply_to": null,
  "references": null,
  "has_attachments": true,
  "attachment_count": 1,
  "labels": ["notification"],
  "attachments": [
    {
      "id": "att_xyz789",
      "filename": "welcome.pdf",
      "content_type": "application/pdf",
      "size_bytes": 24576,
      "downloadable": true
    }
  ],
  "received_at": "2026-04-01T12:00:00Z"
}

Delete Email

DELETE/v1/email?id=xxx

Permanently deletes an email. This cascade deletes all associated attachments and R2 storage objects.

Example

curl -X DELETE "https://mails-worker.genedai.workers.dev/v1/email?id=msg_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "deleted": true
}

Wait for Code

GET/v1/code

Long-polls until a verification code arrives in the mailbox. Supports extraction of 4-8 character verification codes in English, Chinese, Japanese, and Korean.

Query Parameters

ParamTypeDefaultDescription
timeoutinteger30Max seconds to wait (max 55)
sincestringISO 8601 timestamp. Only consider emails after this time.

Example

# Wait up to 60 seconds for a verification code
curl "https://mails-worker.genedai.workers.dev/v1/code?timeout=60" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Only look at emails after a specific time
curl "https://mails-worker.genedai.workers.dev/v1/code?timeout=60&since=2026-04-01T12:00:00Z" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response (code found)

{
  "id": "msg_abc123",
  "code": "847291",
  "from": "[email protected]",
  "subject": "Your verification code",
  "received_at": "2026-04-01T12:05:00Z"
}

Response (timeout)

Returns HTTP 200 with code set to null:

{
  "code": null
}

Semantic Search

GET/v1/search?q=xxx

Alias for /v1/inbox with mode=hybrid. Combines Workers AI text embeddings with FTS5 full-text search using Reciprocal Rank Fusion (RRF) for best results.

Example

# Search for emails about invoice payments
curl "https://mails-worker.genedai.workers.dev/v1/search?q=invoice+payment+due" \
  -H "Authorization: Bearer YOUR_API_KEY"

# Equivalent to:
curl "https://mails-worker.genedai.workers.dev/v1/inbox?query=invoice+payment+due&mode=hybrid" \
  -H "Authorization: Bearer YOUR_API_KEY"

Response

{
  "emails": [
    {
      "id": "msg_def456",
      "mailbox": "[email protected]",
      "from_address": "[email protected]",
      "from_name": "Billing",
      "subject": "Invoice #1042 - Payment Due March 31",
      "code": null,
      "direction": "inbound",
      "status": "received",
      "received_at": "2026-03-28T09:15:00Z",
      "has_attachments": false,
      "attachment_count": 0
    }
  ],
  "search_mode": "hybrid"
}

Message Statuses

Every email has a status field that tracks its lifecycle. Inbound emails are always received. Outbound email statuses are updated in real-time via Resend webhooks.

StatusDirectionDescription
receivedInboundEmail was received and stored
sentOutboundEmail accepted by Resend for delivery
deliveredOutboundEmail delivered to recipient's mail server
queuedOutboundDelivery is temporarily delayed (queued for retry)
bouncedOutboundDelivery failed permanently (bad address, etc.)
complainedOutboundRecipient marked the email as spam
failedOutboundSending failed (API error, rate limit, etc.)

Limits

ConstraintLimit
Subject length998 characters
Text body size500KB
HTML body size1MB
Recipients per email50
Inbox list limit100 per request
Code wait timeout55 seconds
Verification code length4-8 characters

Rate Limits

Each mailbox has a daily send limit of 100 emails per day (default). When exceeded, POST /v1/send returns a 429 status. Self-hosted deployments can configure this via the DAILY_SEND_LIMIT environment variable.

Suppression List

Bounced and complained recipients are automatically added to a suppression list. Attempting to send to a suppressed address returns 400 with:

{
  "error": "Recipient is suppressed: [email protected] (bounce)"
}