Tài liệu
Mailera API
Quản lý hộp thư Microsoft (Outlook, Hotmail, Microsoft 365) từ A đến Z qua REST: thêm hộp thư, kiểm tra còn hoạt động, đọc thư, lấy OTP, gửi thư, kéo khỏi Spam và nhận webhook.
Giới thiệu
Mọi endpoint nằm dưới một địa chỉ gốc, nhận và trả về JSON.
- 1Tạo tài khoản và workspace riêng (miễn phí).
- 2Vào Cài đặt → API key, tạo key và chọn quyền.
- 3Gửi key qua header X-API-Key trong mọi lượt gọi.
Thành công trả về trường data; lỗi trả về trường error gồm code và message.
Tạo workspace miễn phíhttps://mailera.app/api/public/v1# 200{ "data": [ ... ], "next_cursor": "..." }# 4xx / 5xx{ "error": { "code": "not_found", "message": "..." } }Xác thực
Gửi API key trong header X-API-Key. Key bắt đầu bằng mh_live_ và chỉ hiện một lần khi tạo; nếu làm mất, hãy tạo key mới và thu hồi key cũ.
Header Authorization dạng Bearer với cùng key cũng được chấp nhận.
Key có thể giới hạn theo danh sách IP; gọi từ IP khác sẽ nhận lỗi 403.
curl https://mailera.app/api/public/v1/mailboxes \ -H "X-API-Key: mh_live_..."Quyền của key
Mỗi key mang một hoặc nhiều quyền. Gọi endpoint mà key không có quyền sẽ nhận lỗi 403 forbidden.
| Quyền | Cho phép |
|---|---|
read | Đọc hộp thư, thư, OTP và vị trí Inbox/Spam |
move | Kéo khỏi Spam và di chuyển thư |
import | Thêm hộp thư |
sync | Yêu cầu đồng bộ ngay |
send | Gửi, trả lời và chuyển tiếp thư |
manage | Tạm dừng, bật lại và xoá hộp thư |
webhooks | Quản lý webhook |
Mã lỗi
Lỗi luôn có code ổn định và message tiếng Anh. Hãy xử lý theo code, không theo nội dung message.
| HTTP | Mã | Ý nghĩa |
|---|---|---|
| 401 | unauthorized | Thiếu, sai, hết hạn hoặc đã thu hồi API key |
| 403 | forbidden | Key không có quyền cần thiết hoặc IP không nằm trong danh sách cho phép |
| 404 | not_found | Hộp thư hoặc thư không tồn tại, hoặc không thuộc workspace của key |
| 409 | mailbox_unavailable | Hộp thư cần kết nối lại, đang tạm dừng hoặc chỉ dùng IMAP (chưa hỗ trợ) |
| 422 | validation_error | Dữ liệu gửi lên sai định dạng |
| 429 | rate_limited | Vượt 300 lượt/phút cho mỗi key — chờ theo header Retry-After |
| 503 | upstream_error | Microsoft đang lỗi hoặc giới hạn tốc độ — thử lại sau |
| 500 | internal_error | Lỗi hệ thống |
Giới hạn và phân trang
Mỗi key được 300 lượt mỗi phút. Vượt giới hạn trả về 429 kèm header Retry-After.
Danh sách trả về next_cursor; gửi lại giá trị đó qua tham số cursor để lấy trang tiếp theo. Khi hết dữ liệu, next_cursor là null.
Tham số limit đặt số dòng mỗi trang.
curl "https://mailera.app/api/public/v1/mailboxes?limit=50&cursor=NEXT_CURSOR" \ -H "X-API-Key: mh_live_..."Hộp thư
Thêm, kiểm tra, đồng bộ, tạm dừng và xoá hộp thư.
- GET
/mailboxesDanh sách hộp thư
- Quyền:
read- Query:
- status, q, cursor, limit
- POST
/mailboxes/importNhập hộp thư hàng loạt (email:password:refresh_token:client_id, hoặc dấu |)
- Quyền:
import- Body:
- lines, text, group_id, duplicate_mode
- GET
/mailboxes/importTiến độ lần nhập và kết quả từng dòng
- Quyền:
import- Query:
- job_id
- GET
/mailboxes/{id}Chi tiết hộp thư và bộ đếm thư mục
- Quyền:
read
- PATCH
/mailboxes/{id}Tạm dừng hoặc bật lại hộp thư
- Quyền:
manage- Body:
- action (bắt buộc)
- DELETE
/mailboxes/{id}Xoá hộp thư
- Quyền:
manage
- GET
/mailboxes/{id}/statusKiểm tra trực tiếp với Microsoft xem hộp thư còn hoạt động
- Quyền:
read
- POST
/mailboxes/{id}/syncĐồng bộ ngay
- Quyền:
sync- Body:
- wait
curl -X POST https://mailera.app/api/public/v1/mailboxes/import \ -H "X-API-Key: mh_live_xxx" -H "content-type: application/json" \ -d '{"lines":["user@hotmail.com:pass:M.C5_refresh...:9e5f94bc-..."]}'# → { "data": { "job_id": "..." } }curl "https://mailera.app/api/public/v1/mailboxes/import?job_id=JOB_ID" -H "X-API-Key: mh_live_xxx"Thư
Đọc, tìm kiếm, lấy OTP và gửi thư.
- GET
/mailboxes/{id}/messagesDanh sách thư theo thư mục
- Quyền:
read- Query:
- folder, unread, cursor, limit
- GET
/mailboxes/{id}/messages/{msgId}Nội dung một thư
- Quyền:
read
- GET
/mailboxes/{id}/otpLấy mã OTP mới nhất
- Quyền:
read- Query:
- from, subject, since_minutes
- POST
/mailboxes/{id}/sendGửi, trả lời hoặc chuyển tiếp thư
- Quyền:
send- Body:
- to, cc, bcc, subject, html, text, importance, reply_to_message_id, mode, attachments
- GET
/messages/searchTìm thư trên mọi hộp thư
- Quyền:
read- Query:
- q, folder, limit
curl -X POST https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/send \ -H "X-API-Key: mh_live_xxx" -H "content-type: application/json" \ -d '{"to":["customer@example.com"],"subject":"Hello","text":"Message body"}'Spam
Kiểm tra vị trí Inbox/Spam và kéo thư khỏi Spam.
- POST
/mailboxes/{id}/messages/{msgId}/moveChuyển thư (ví dụ từ Spam về Inbox)
- Quyền:
move- Body:
- destination (bắt buộc)
- POST
/mailboxes/{id}/unspamKéo toàn bộ hoặc theo người gửi khỏi Spam
- Quyền:
move- Body:
- filter
- GET
/mailboxes/{id}/placementThư vào Inbox hay Spam
- Quyền:
read- Query:
- from, subject, since_minutes
curl "https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/placement?from=me@example.com" -H "X-API-Key: mh_live_xxx"curl -X POST https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/unspam -H "X-API-Key: mh_live_xxx" \ -H "content-type: application/json" -d '{"filter":{"type":"sender","value":"me@example.com"}}'Webhook
Đăng ký URL nhận sự kiện.
Với mỗi sự kiện, Mailera gửi POST JSON tới URL của bạn. Nếu endpoint trả lỗi hoặc không phản hồi, Mailera tự gửi lại với khoảng chờ tăng dần.
| Sự kiện | Khi nào |
|---|---|
message.received | Có thư mới vào Inbox |
message.junk | Có thư mới rơi vào Spam |
mailbox.disconnected | Hộp thư mất kết nối (token bị thu hồi, đổi mật khẩu…) |
Để xác minh, tính HMAC-SHA256 của chuỗi timestamp, dấu chấm và body bằng secret của webhook, rồi so sánh với header chữ ký.
Header đi kèm: X-MailHub-Event X-MailHub-Delivery X-MailHub-Timestamp X-MailHub-Signature
- GET
/webhooksDanh sách webhook
- Quyền:
webhooks
- POST
/webhooksTạo webhook (secret ký chỉ trả về một lần)
- Quyền:
webhooks- Body:
- url (bắt buộc), events, group_id
- PATCH
/webhooks/{id}Bật/tắt, đổi sự kiện hoặc URL của webhook
- Quyền:
webhooks
- DELETE
/webhooks/{id}Xoá webhook
- Quyền:
webhooks
import crypto from "node:crypto";// X-MailHub-Signature: sha256=<hex> X-MailHub-Timestamp: <unix seconds>const expected = "sha256=" + crypto.createHmac("sha256", SECRET) .update(timestamp + "." + rawBody).digest("hex");const ok = expected.length === signature.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));Ví dụ
Thay MAILBOX_ID và key bằng giá trị của bạn.
curl -X POST https://mailera.app/api/public/v1/mailboxes/import \ -H "X-API-Key: mh_live_xxx" -H "content-type: application/json" \ -d '{"lines":["user@hotmail.com:pass:M.C5_refresh...:9e5f94bc-..."]}'# → { "data": { "job_id": "..." } }curl "https://mailera.app/api/public/v1/mailboxes/import?job_id=JOB_ID" -H "X-API-Key: mh_live_xxx"curl https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/status -H "X-API-Key: mh_live_xxx"curl "https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/otp?from=noreply@service.com&since_minutes=15" \ -H "X-API-Key: mh_live_xxx"# → { "data": { "code": "482913", "folder": "inbox", ... } } or { "data": { "code": null } }curl -X POST https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/send \ -H "X-API-Key: mh_live_xxx" -H "content-type: application/json" \ -d '{"to":["customer@example.com"],"subject":"Hello","text":"Message body"}'curl "https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/placement?from=me@example.com" -H "X-API-Key: mh_live_xxx"curl -X POST https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/unspam -H "X-API-Key: mh_live_xxx" \ -H "content-type: application/json" -d '{"filter":{"type":"sender","value":"me@example.com"}}'const res = await fetch("https://mailera.app/api/public/v1/mailboxes?limit=50", { headers: { "X-API-Key": process.env.MAILERA_API_KEY },});const { data, next_cursor } = await res.json();import os, requestsr = requests.get( "https://mailera.app/api/public/v1/mailboxes/MAILBOX_ID/messages", params={"folder": "inbox", "limit": 20}, headers={"X-API-Key": os.environ["MAILERA_API_KEY"]},)print(r.json()["data"])import crypto from "node:crypto";// X-MailHub-Signature: sha256=<hex> X-MailHub-Timestamp: <unix seconds>const expected = "sha256=" + crypto.createHmac("sha256", SECRET) .update(timestamp + "." + rawBody).digest("hex");const ok = expected.length === signature.length && crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
