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
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
from | string | Yes | Sender email address (must belong to your mailbox) |
to | string[] | Yes | Recipient email addresses (max 50) |
subject | string | Yes | Email subject (max 998 characters) |
text | string | No | Plain text body (max 500KB) |
html | string | No | HTML body (max 1MB) |
reply_to | string | No | Reply-To address |
headers | Record<string, string> | No | Custom email headers |
cc | string[] | No | CC recipients |
bcc | string[] | No | BCC recipients |
in_reply_to | string | No | Message ID to reply to (for threading) |
attachments | object[] | No | File attachments (see below) |
Attachment Object
| Field | Type | Required | Description |
|---|---|---|---|
filename | string | Yes | File name |
content | string | Yes | Base64-encoded file content |
content_type | string | No | MIME type (e.g. application/pdf) |
content_id | string | No | Content-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)
Query Parameters
| Param | Type | Default | Description |
|---|---|---|---|
limit | integer | 20 | Number of emails to return (max 100) |
offset | integer | 0 | Pagination offset |
direction | string | — | Filter by inbound or outbound |
query | string | — | Search query string |
label | string | — | Filter by label: newsletter, notification, code, personal |
mode | string | keyword | Search 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
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
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
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
| Param | Type | Default | Description |
|---|---|---|---|
timeout | integer | 30 | Max seconds to wait (max 55) |
since | string | — | ISO 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
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.
| Status | Direction | Description |
|---|---|---|
received | Inbound | Email was received and stored |
sent | Outbound | Email accepted by Resend for delivery |
delivered | Outbound | Email delivered to recipient's mail server |
queued | Outbound | Delivery is temporarily delayed (queued for retry) |
bounced | Outbound | Delivery failed permanently (bad address, etc.) |
complained | Outbound | Recipient marked the email as spam |
failed | Outbound | Sending failed (API error, rate limit, etc.) |
Limits
| Constraint | Limit |
|---|---|
| Subject length | 998 characters |
| Text body size | 500KB |
| HTML body size | 1MB |
| Recipients per email | 50 |
| Inbox list limit | 100 per request |
| Code wait timeout | 55 seconds |
| Verification code length | 4-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)"
}