Accounts
Connect and manage IMAP/SMTP email accounts, share them, and check sender reputation
Email accounts are the connected mailboxes used for inbox sync and as sending identities. Each account stores IMAP/SMTP settings and an encrypted password, and belongs to the authenticated user (accounts can also be shared with other users).
Account endpoints use session authentication (dashboard cookie), not API-key auth. To send programmatically via API key, use POST /api/v1/send. The reputation endpoint is the exception — it accepts a bearer token (see below). Base URL: https://api.misar.io/mail.
List connected accounts
/mail/accountsList all email accounts the user owns or that have been shared with them.
Response fields
successbooleantrue when the request succeeded.
dataarrayAccounts. Each includes id, email, display_name, imap_host, smtp_host, last_sync_at, sync_status, signature, is_default, created_at, user_id, and the booleans isOwned / isShared.
sync_status values: idle (default, no sync in progress), syncing (actively syncing inbox), synced, error (IMAP connection failed — check credentials).
curl https://api.misar.io/mail/accounts \
-H "Cookie: sb-access-token=YOUR_SESSION"{
"success": true,
"data": [
{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "hello@yourdomain.com",
"display_name": "Your Name",
"imap_host": "imap.yourdomain.com",
"smtp_host": "smtp.yourdomain.com",
"last_sync_at": "2026-01-15T10:05:00Z",
"sync_status": "idle",
"signature": null,
"is_default": true,
"created_at": "2026-01-15T10:00:00Z",
"user_id": "user_abc...",
"isOwned": true,
"isShared": false
}
]
}Connect a new account
/mail/accountsConnect a new IMAP/SMTP email account. Request fields are camelCase; host/port fields default to MisarMail's servers when omitted.
Request body
emailstringbodyrequiredThe email address of the account (≤254 chars).
passwordstringbodyrequiredIMAP/SMTP login password or app password (min 8 chars, stored encrypted).
displayNamestringbodyDisplay name for outgoing emails (≤255 chars).
imapHoststringbodydefault: mail.misar.ioIMAP server hostname.
imapPortintegerbodydefault: 993IMAP port.
smtpHoststringbodydefault: mail.misar.ioSMTP server hostname.
smtpPortintegerbodydefault: 587SMTP port.
signaturestringbodyDefault signature appended to outgoing mail (≤5000 chars).
isDefaultbooleanbodydefault: falseMake this the default sending account.
workspaceIdUUIDbodyAssociate the account with a workspace.
Response fields
successbooleantrue when the account was connected.
dataobjectThe created account: id, email, display_name, imap_host, smtp_host, is_default, and created_at.
curl -X POST https://api.misar.io/mail/accounts \
-H "Cookie: sb-access-token=YOUR_SESSION" \
-H "Content-Type: application/json" \
-d '{
"email": "hello@yourdomain.com",
"displayName": "Your Display Name",
"imapHost": "imap.yourdomain.com",
"imapPort": 993,
"smtpHost": "smtp.yourdomain.com",
"smtpPort": 587,
"password": "your-email-password"
}'{
"success": true,
"data": {
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "hello@yourdomain.com",
"display_name": "Your Display Name",
"imap_host": "imap.yourdomain.com",
"smtp_host": "smtp.yourdomain.com",
"is_default": false,
"created_at": "2026-01-15T10:00:00Z"
}
}{ "error": "Email account already exists" }Update an account
/mail/accountsUpdate an account you own. The account id is passed in the body.
Request body
idUUIDbodyrequiredID of the account to update.
displayNamestringbodyNew display name.
signaturestringbodyNew default signature.
isDefaultbooleanbodyMake this the default sending account.
Response fields
successbooleantrue when the update succeeded.
dataobjectThe updated account.
curl -X PATCH https://api.misar.io/mail/accounts \
-H "Cookie: sb-access-token=YOUR_SESSION" \
-H "Content-Type: application/json" \
-d '{ "id": "550e8400-...", "isDefault": true }'Disconnect an account
/mail/accountsDisconnect an account and stop inbox sync. The account id is passed as a query parameter, not a path segment. Already-synced emails are not deleted.
Query parameters
idUUIDqueryrequiredID of the account to disconnect.
Response fields
successbooleantrue when the account was disconnected.
curl -X DELETE "https://api.misar.io/mail/accounts?id=550e8400-e29b-41d4-a716-446655440000" \
-H "Cookie: sb-access-token=YOUR_SESSION"{ "success": true }Status codes
- 200 — OK. List, update, delete, or reputation request succeeded.
- 201 — Created. Account connected.
- 400 — Bad request.
Validation failed(withdetails),Account ID is required, orInvalid account ID format. - 401 — Unauthorized. No active session (or missing bearer token on the reputation endpoint).
- 403 — Forbidden. The account is not yours, or your plan's
email_accountslimit is reached. - 404 — Not found.
Account not found. - 409 — Conflict.
Email account already exists. - 500 — Server error. Retry.
Get sender reputation
/mail/accounts/reputationReturns cached reputation signals for your connected accounts. This endpoint authenticates with a bearer token (Authorization: Bearer <token>), not the session cookie.
Headers
AuthorizationstringheaderrequiredBearer <token>
Response fields
accountsarrayPer-account reputation. Each row includes the account's reputation columns plus a derived severity. reputation_score is categorical — one of high, medium, low, or none — and reputation_suspicious is a boolean flag.
summaryobjectRoll-up counts: total, critical, warning, good, and unknown.
curl https://api.misar.io/mail/accounts/reputation \
-H "Authorization: Bearer YOUR_TOKEN"{
"accounts": [
{
"id": "550e8400-...",
"email": "hello@yourdomain.com",
"reputation_score": "high",
"reputation_suspicious": false,
"severity": "good"
}
],
"summary": { "total": 1, "critical": 0, "warning": 0, "good": 1, "unknown": 0 }
}Trigger a fresh reputation check for one account with POST /mail/accounts/reputation and a body of { "id": "<accountId>" }. It returns that account's refreshed row with its severity. Errors: 400 Missing account id, 404 (not found), 502 (upstream check failed).
Account sharing
Accounts can be shared with other MisarMail users. Sharing uses a permission model — owner, admin, editor, or viewer (default viewer) — issued via invitations that the recipient accepts or declines.
List account invitations
/mail/accounts/:id/invitationsList invitations issued for this account. Account owner only.
Path parameters
idUUIDpathrequiredID of the account.
Response fields
successbooleantrue when the request succeeded.
dataarrayInvitations. Each includes id, invitee_email, invitee_user_id, permission, status, message, expires_at, accepted_at, and created_at.
{
"success": true,
"data": [
{
"id": "inv_abc123",
"invitee_email": "colleague@example.com",
"invitee_user_id": null,
"permission": "viewer",
"status": "pending",
"message": "Join our shared mailbox",
"expires_at": "2026-06-20T10:00:00Z",
"accepted_at": null,
"created_at": "2026-05-20T10:00:00Z"
}
]
}Invite a user to an account
/mail/accounts/:id/invitationsInvite another MisarMail user to access this account. Account owner only. Only owners can grant the owner permission.
Path parameters
idUUIDpathrequiredID of the account.
Request body
emailstringbodyrequiredInvitee's email address.
permissionstringbodydefault: viewerOne of owner, admin, editor, viewer.
curl -X POST https://api.misar.io/mail/accounts/550e8400-.../invitations \
-H "Cookie: sb-access-token=YOUR_SESSION" \
-H "Content-Type: application/json" \
-d '{ "email": "colleague@example.com", "permission": "editor" }'Revoke a pending invitation with DELETE /mail/accounts/:id/invitations (account owner only).
List account shares
/mail/accounts/:id/sharesList active shares (accepted access) for this account. Account owner only.
Path parameters
idUUIDpathrequiredID of the account.
Response fields
successbooleantrue when the request succeeded.
dataobjectownerId, accountEmail, and shares — each share with id, user_id, permission, granted_by, and granted_at.
{
"success": true,
"data": {
"ownerId": "user_owner...",
"accountEmail": "hello@yourdomain.com",
"shares": [
{
"id": "share_01hv...",
"user_id": "user_abc...",
"permission": "editor",
"granted_by": "user_owner...",
"granted_at": "2026-05-21T14:00:00Z"
}
]
}
}Revoke an active share with DELETE /mail/accounts/:id/shares. Add a share directly (owner only) with POST /mail/accounts/:id/shares.
List pending invitations received
/mail/invitations/pendingList all pending invitations the current user has received (across accounts). Powers the dashboard's "You've been invited" banner.
Response fields
successbooleantrue when the request succeeded.
dataarrayReceived invitations. Each includes id, account_id, inviter_id, invitee_email, permission, status, message, token, expires_at, and created_at.
{
"success": true,
"data": [
{
"id": "inv_abc123",
"account_id": "550e8400-...",
"inviter_id": "user_boss...",
"invitee_email": "me@example.com",
"permission": "admin",
"status": "pending",
"message": null,
"token": "tok_...",
"expires_at": "2026-06-20T10:00:00Z",
"created_at": "2026-05-20T10:00:00Z"
}
]
}Accept or decline an invitation
/mail/invitations/declineDecline a pending invitation. To accept instead, POST /mail/invitations/accept with the same body.
Request body
invitation_idUUIDbodyrequiredID of the invitation.
curl -X POST https://api.misar.io/mail/invitations/decline \
-H "Cookie: sb-access-token=YOUR_SESSION" \
-H "Content-Type: application/json" \
-d '{ "invitation_id": "inv_abc123" }'{ "error": "Invitation not found" }Declining fails with 400 if the invitation is no longer pending or was sent to a different email address than the signed-in user.