Endpoints
Complete reference for all mail-catcher API endpoints.
All endpoints are served from your API base URL (printed during deployment). Protected endpoints require a Bearer token.
Public endpoints
GET /health
Health check. No authentication required.
Response 200 OK
{
"status": "ok",
"timestamp": 1710000000000
}GET /version
Returns the API version. No authentication required.
Response 200 OK
{
"version": "0.1.0",
"apiVersions": ["v1"]
}GET /openapi.json
Returns the OpenAPI specification. No authentication required.
GET /docs
Interactive API documentation powered by Scalar. No authentication required.
Email endpoints
All email endpoints require authentication and are prefixed with /v1.
GET /v1/emails
List emails for a specific inbox. Returns emails sorted newest first.
Query parameters
| Parameter | Required | Default | Description |
|---|---|---|---|
inbox | yes | - | Inbox name (local part of the email address, before @). Valid characters: a-z 0-9 . _ - |
limit | no | 50 | Results per page (1–100) |
cursor | no | - | Pagination cursor from a previous response |
wait | no | false | "true" to enable long-polling |
timeout | no | 28 | Max wait time in seconds for long-poll (1–28) |
sender | no | - | Filter by sender (substring match) |
subject | no | - | Filter by subject (substring match) |
receivedAfter | no | - | Timestamp or ISO date |
receivedBefore | no | - | Timestamp or ISO date |
hasAttachments | no | - | "true" or "false" |
Response 200 OK
{
"emails": [
{
"messageId": "abc123@mail.example.com",
"inbox": "test",
"sender": "sender@example.com",
"recipient": "test@receive.yourdomain.com",
"subject": "Verify your account",
"body": "Click the link to verify...",
"htmlBody": "<p>Click the link to verify...</p>",
"attachments": [
{
"filename": "invoice.pdf",
"contentType": "application/pdf",
"size": 24680,
"url": "/v1/emails/abc123@mail.example.com/attachments/invoice.pdf"
}
],
"receivedAt": 1710000000000,
"rawUrl": "/v1/emails/abc123@mail.example.com/raw"
}
],
"nextCursor": "2024-03-10T00:00:00.000Z#abc123",
"hasMore": true
}Response fields
| Field | Type | Description |
|---|---|---|
emails | array | List of email objects |
emails[].messageId | string | Unique email identifier (from Message-ID header) |
emails[].inbox | string | Inbox name (lowercase) |
emails[].sender | string | Sender email address |
emails[].recipient | string | Recipient email address |
emails[].subject | string | Email subject line |
emails[].body | string | Plain text body |
emails[].htmlBody | string | HTML body |
emails[].attachments | array | Attachment metadata |
emails[].receivedAt | number | Unix timestamp in milliseconds |
emails[].rawUrl | string | Relative URL to the raw .eml file |
nextCursor | string | undefined | Cursor for the next page |
hasMore | boolean | Whether more results exist |
Long-polling
When wait=true, the API polls DynamoDB with exponential backoff (starting at 500ms, doubling to max 10s) until emails arrive or the timeout is reached. If no emails arrive, the response contains an empty emails array.
curl -H "Authorization: Bearer $TOKEN" \
"$API_URL/v1/emails?inbox=test&wait=true&timeout=15"Pagination
Pass nextCursor from the previous response as cursor:
curl -H "Authorization: Bearer $TOKEN" \
"$API_URL/v1/emails?inbox=test&limit=10&cursor=2024-03-10T00:00:00.000Z%23abc123"GET /v1/emails/:messageId
Retrieve a single email by its message ID.
Response 200 OK, same email object shape as the list endpoint.
Errors
| Status | Error Code |
|---|---|
401 | UNAUTHORIZED |
404 | NOT_FOUND |
DELETE /v1/emails/:messageId
Delete a single email and all its attachments.
Response 200 OK
{
"deleted": true,
"messageId": "abc123@mail.example.com"
}This removes the DynamoDB record, the raw .eml from S3, and all attachment files from S3.
Errors
| Status | Error Code |
|---|---|
401 | UNAUTHORIZED |
404 | NOT_FOUND |
DELETE /v1/emails
Bulk delete all emails in an inbox.
Query parameters
| Parameter | Required | Description |
|---|---|---|
inbox | yes | Inbox name to clear |
Response 200 OK
{
"deleted": 42
}Deletes are batched in groups of 25 with exponential backoff for reliability.
Errors
| Status | Error Code |
|---|---|
400 | MISSING_INBOX |
400 | INVALID_INBOX |
401 | UNAUTHORIZED |
GET /v1/emails/:messageId/raw
Download the raw .eml file.
Response 302 Found, redirects to a pre-signed S3 URL valid for 15 minutes.
curl -L -H "Authorization: Bearer $TOKEN" \
"$API_URL/v1/emails/abc123@mail.example.com/raw" -o email.emlErrors
| Status | Error Code |
|---|---|
401 | UNAUTHORIZED |
404 | NOT_FOUND |
GET /v1/emails/:messageId/attachments/:filename
Download a specific attachment.
Response 302 Found, redirects to a pre-signed S3 URL valid for 15 minutes.
Errors
| Status | Error Code |
|---|---|
401 | UNAUTHORIZED |
404 | NOT_FOUND |