One normalized email surface spans Gmail, Microsoft 365, and custom IMAP/SMTP. Actions are gated by connection capabilities, so an SMTP-only mailbox can send but not read.
Connect a mailbox
Gmail and Microsoft 365 connect over OAuth. Custom mailboxes connect with direct IMAP/SMTP credentials, stored encrypted at rest — no OAuth app required. Check capabilities before acting: an IMAP+SMTP mailbox reads and sends, an SMTP-only mailbox sends only.
Create a mailbox connection by posting credentials. The connection activates immediately and returns its id.
curl -X POST https://api.hora.to/v1/connections \
-H "Authorization: Bearer $HORATO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"provider": "imap",
"credentials": {
"user": "agent@acme.com",
"password": "app-specific-password",
"imap": { "host": "imap.acme.com", "port": 993, "secure": true },
"smtp": { "host": "smtp.acme.com", "port": 465, "secure": true }
}
}'curl https://api.hora.to/v1/email/capabilities/conn_123 \
-H "Authorization: Bearer $HORATO_API_KEY"Read, search, and organize
List and read messages and threads from the canonical store, or pull live from the provider. Search with `q`, list folders and labels, mark read/unread, move labels, and download attachments.
Set `live=true` to bypass the cache and fetch straight from the provider (it also refreshes the local copy).
curl "https://api.hora.to/v1/email/messages?connection_id=conn_123&q=invoice&limit=25" \
-H "Authorization: Bearer $HORATO_API_KEY"curl -X PATCH https://api.hora.to/v1/email/messages/msg_123 \
-H "Authorization: Bearer $HORATO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connection_id":"conn_123","is_read":true,"add_labels":["Processed"]}'Send, reply, and schedule
Send immediately, reply on a thread, or defer delivery. Add a `send_at` timestamp to schedule a send; scheduled messages run through a retrying dispatcher and can be listed or cancelled before they go out.
Reference a template by id or slug to send templated mail with merge variables.
curl -X POST https://api.hora.to/v1/email/send \
-H "Authorization: Bearer $HORATO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connection_id":"conn_123","to":[{"email":"client@example.com"}],"subject":"Hello","body_text":"Hi there"}'curl -X POST https://api.hora.to/v1/email/send \
-H "Authorization: Bearer $HORATO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connection_id":"conn_123","to":[{"email":"client@example.com"}],"subject":"Reminder","body_text":"See you tomorrow","send_at":"2026-06-11T09:00:00Z"}'Provider-native drafts
Drafts are real provider drafts. On Gmail and Microsoft 365 a draft is created in the account's own Drafts folder, so it is visible in the native client and is sent as the provider's stored copy. Custom IMAP/SMTP mailboxes fall back to a Horato-managed draft.
Create, update, send, and delete follow the same lifecycle. Updating replaces the draft's content; sending delivers it and marks it sent.
curl -X POST https://api.hora.to/v1/email/drafts \
-H "Authorization: Bearer $HORATO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connection_id":"conn_123","to":[{"email":"client@example.com"}],"subject":"Proposal","body_text":"Draft body"}'
curl -X POST https://api.hora.to/v1/email/drafts/draft_123/send \
-H "Authorization: Bearer $HORATO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"connection_id":"conn_123"}'Dynamic templates
Store reusable subject/body templates with `{{ variable }}` merge fields (dot-paths like `{{ invitee.name }}` are supported). Rendering is substitution-only — no logic or code execution — so a stored template can never run arbitrary code. Preview a render with sample variables before sending.
curl -X POST https://api.hora.to/v1/email/templates \
-H "Authorization: Bearer $HORATO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"slug":"welcome","name":"Welcome","subject":"Welcome, {{ name }}","body_text":"Thanks for joining, {{ name }}."}'
curl -X POST https://api.hora.to/v1/email/templates/tmpl_123/preview \
-H "Authorization: Bearer $HORATO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"variables":{"name":"Dana"}}'AI message processing
Turn raw mail into structured signal. Summarize a thread, classify intent, extract fields, or clean quoted replies and signatures into plain text. These run on Horato-managed models and return structured JSON.
AI endpoints require an AI key to be configured for the deployment; when it is not, they return a clear error rather than failing silently.
- `POST /v1/email/ai/summarize`: concise thread or message summary.
- `POST /v1/email/ai/classify`: label intent/category.
- `POST /v1/email/ai/extract`: pull structured fields from a message.
- `POST /v1/email/ai/clean`: strip quotes and signatures to core text.