Moperator Documentation
Moperator is email infrastructure for AI agents. It provides a REST API, MCP server, and webhooks to let your AI assistants send and receive email.
Base URL: https://api.moperator.work
Quickstart
- 1. Sign up at app.moperator.work
- 2. Get your API key from the dashboard (format:
mop_xxx_yyy) - 3. Your email address is
yourname@moperator.work - 4. Query emails using the REST API or connect via MCP
Authentication
All API requests require a Bearer token in the Authorization header:
Authorization: Bearer mop_yourtenantid_yoursecret
Your API key is available in the dashboard after signing up.
List Emails
GET /api/v1/emails
Retrieve a list of emails with optional filtering.
Query Parameters
| Parameter | Type | Description |
|---|---|---|
labels |
string | Filter by label (comma-separated for multiple) |
status |
string | unread or read |
limit |
number | Max emails to return (default: 20) |
offset |
number | Pagination offset |
Example Request
curl "https://api.moperator.work/api/v1/emails?status=unread&labels=finance" \
-H "Authorization: Bearer mop_yourkey"
Response
{
"emails": [
{
"id": "1704067200000-abc123",
"email": {
"from": "billing@example.com",
"to": "yourbot@moperator.work",
"subject": "Invoice #1234",
"textBody": "Please find attached...",
"receivedAt": "2024-01-01T00:00:00.000Z"
},
"labels": ["finance", "important"],
"status": "unread",
"processedAt": "2024-01-01T00:00:01.000Z"
}
],
"total": 1,
"unreadCount": 1
}
Get Email
GET /api/v1/emails/:id
Retrieve a single email by ID.
Query Parameters
markRead |
boolean | Set to true to automatically mark as read |
Example
# Get email without marking as read
curl "https://api.moperator.work/api/v1/emails/1704067200000-abc123" \
-H "Authorization: Bearer mop_yourkey"
# Get email and mark as read
curl "https://api.moperator.work/api/v1/emails/1704067200000-abc123?markRead=true" \
-H "Authorization: Bearer mop_yourkey"
Update Email Status
PATCH /api/v1/emails/:id
Update the read/unread status of an email.
Request Body
{
"status": "read" // or "unread"
}
Example
curl -X PATCH "https://api.moperator.work/api/v1/emails/1704067200000-abc123" \
-H "Authorization: Bearer mop_yourkey" \
-H "Content-Type: application/json" \
-d '{"status": "read"}'
Search Emails
GET /api/v1/emails/search
Search emails by sender, subject, or labels.
Query Parameters
from |
string | Filter by sender (partial match) |
subject |
string | Filter by subject (partial match) |
labels |
string | Filter by labels |
Example
curl "https://api.moperator.work/api/v1/emails/search?from=stripe&subject=invoice" \
-H "Authorization: Bearer mop_yourkey"
Labels
Labels are used by Claude to automatically classify incoming emails. Define labels with descriptions to help Claude understand what each label means.
List Labels
curl "https://api.moperator.work/api/v1/labels" \
-H "Authorization: Bearer mop_yourkey"
Create Label
curl -X POST "https://api.moperator.work/api/v1/labels" \
-H "Authorization: Bearer mop_yourkey" \
-H "Content-Type: application/json" \
-d '{
"id": "finance",
"name": "Finance",
"description": "Invoices, receipts, bank statements, payment confirmations"
}'
Claude Desktop (MCP)
Connect Moperator to Claude Desktop using the Model Context Protocol (MCP).
Configuration
Add to your claude_desktop_config.json:
{
"mcpServers": {
"moperator": {
"command": "npx",
"args": [
"-y", "mcp-remote",
"https://api.moperator.work/mcp",
"--header", "Authorization: Bearer mop_yourkey"
]
}
}
}
Available Tools
list_emails- List emails with optional filtersget_email- Get a specific email by IDsearch_emails- Search emails by sender/subjectmark_as_read- Mark an email as read
Example Prompts
- "Check my email"
- "Do I have any unread emails?"
- "Show me emails labeled finance"
- "Search for emails from Stripe"
ChatGPT (OpenAPI)
Connect Moperator to ChatGPT using OpenAPI Actions.
Setup
- 1. Go to ChatGPT → Create a GPT → Configure → Actions
- 2. Click "Import from URL"
- 3. Enter:
https://api.moperator.work/openapi.json - 4. Set authentication to "API Key" with header
Authorization - 5. Enter your API key as
Bearer mop_yourkey
Webhooks
Receive real-time notifications when emails arrive. Configure webhooks in the dashboard to get POST requests to your endpoint.
Webhook Payload
{
"email": {
"from": "sender@example.com",
"to": "yourbot@moperator.work",
"subject": "Hello",
"textBody": "Email content...",
"receivedAt": "2024-01-01T00:00:00.000Z"
},
"labels": ["important"],
"matchedLabel": "important",
"timestamp": "2024-01-01T00:00:01.000Z",
"signature": "sha256=..."
}
Verifying Signatures
Webhooks include an HMAC-SHA256 signature for verification:
import hmac
import hashlib
def verify_webhook(payload: bytes, signature: str, secret: str) -> bool:
expected = hmac.new(
secret.encode(),
payload,
hashlib.sha256
).hexdigest()
return hmac.compare_digest(f"sha256={expected}", signature)
Python Example
import requests
API_KEY = "mop_yourkey"
BASE_URL = "https://api.moperator.work"
headers = {"Authorization": f"Bearer {API_KEY}"}
# List unread emails
response = requests.get(
f"{BASE_URL}/api/v1/emails",
headers=headers,
params={"status": "unread"}
)
emails = response.json()
print(f"You have {emails['unreadCount']} unread emails")
for email in emails['emails']:
print(f"- {email['email']['subject']} from {email['email']['from']}")
# Get and mark as read
if emails['emails']:
email_id = emails['emails'][0]['id']
detail = requests.get(
f"{BASE_URL}/api/v1/emails/{email_id}",
headers=headers,
params={"markRead": "true"}
).json()
print(f"\nRead: {detail['email']['textBody'][:200]}...")
JavaScript / Node.js Example
const API_KEY = 'mop_yourkey';
const BASE_URL = 'https://api.moperator.work';
const headers = {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
};
// List unread emails
async function getUnreadEmails() {
const response = await fetch(
`${BASE_URL}/api/v1/emails?status=unread`,
{ headers }
);
const data = await response.json();
console.log(`You have ${data.unreadCount} unread emails`);
for (const email of data.emails) {
console.log(`- ${email.email.subject} from ${email.email.from}`);
}
return data.emails;
}
// Mark email as read
async function markAsRead(emailId) {
await fetch(`${BASE_URL}/api/v1/emails/${emailId}`, {
method: 'PATCH',
headers,
body: JSON.stringify({ status: 'read' })
});
}
getUnreadEmails();