Factorizer/Cluster ERP WikiCluster ERP Türkçe
Home / API reference

API

Mail API (mail)

HTTP endpoints of the mail module under /api/v1/mail: 28 routes with permissions, schemas, status codes, and error codes.

The mail module serves mail domains, OAuth app configurations per provider, connected mail accounts (OAuth and IMAP), and messages with sync, send, drafts, attachments, read state, trash, and threads. All 28 endpoints sit under /api/v1/mail. For business meaning see the Mail module page.

Group facts

Item Value Source
Base path /api/v1/mail src/cluster_erp/core/module_base.py:37-38, src/cluster_erp/modules/mail/module.py:42
Routers 4 router objects in 4 files; listed in the section Endpoint summary src/cluster_erp/modules/mail/module.py:34
Endpoints 28, counted from the route decorators and add_api_route calls of the routers that register_routes mounts src/cluster_erp/modules/mail/accounts/routes.py, src/cluster_erp/modules/mail/domains/routes.py, src/cluster_erp/modules/mail/messages/routes.py ...
Authentication Bearer header or session cookie, resolved by get_current_user; see Authentication and headers src/cluster_erp/modules/auth/guards.py:85-167
Permission guard 28 of 28 routes declare require_permission src/cluster_erp/modules/auth/guards.py:205-240
App entitlement gate require_app("mail") on every mounted router src/cluster_erp/modules/mail/module.py:42
Error format JSON body {"error": {...}}; see Errors src/cluster_erp/server/error_handler.py:33-46

Endpoint summary

One row per sub-module folder. The router prefix is added to the base path.

Sub-module Routers Endpoints Router source
domains router (/domains) 5 src/cluster_erp/modules/mail/domains/routes.py:21
providers router (/oauth-apps) 3 src/cluster_erp/modules/mail/providers/routes.py:27
accounts router (/accounts) 7 src/cluster_erp/modules/mail/accounts/routes.py:30
messages router (/messages) 13 src/cluster_erp/modules/mail/messages/routes.py:33

Mail domains endpoints

Mail domain records.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/mail/domains/ list_domains mail_domain.read none search, limit, offset MailDomainListResponse 200 (default) src/cluster_erp/modules/mail/domains/routes.py:24
GET /api/v1/mail/domains/{domain_id} get_domain mail_domain.read none none MailDomainRead 200 (default) src/cluster_erp/modules/mail/domains/routes.py:43
POST /api/v1/mail/domains/ create_domain mail_domain.create MailDomainCreate none MailDomainRead 201 src/cluster_erp/modules/mail/domains/routes.py:55
PUT /api/v1/mail/domains/{domain_id} update_domain mail_domain.update MailDomainUpdate none MailDomainRead 200 (default) src/cluster_erp/modules/mail/domains/routes.py:65
DELETE /api/v1/mail/domains/{domain_id} delete_domain mail_domain.delete none none none 204 src/cluster_erp/modules/mail/domains/routes.py:78

OAuth app configurations endpoints

Provider OAuth app configurations: list, upsert, and remove.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/mail/oauth-apps/ list_provider_configs mail_provider.read none none MailProviderListResponse 200 (default) src/cluster_erp/modules/mail/providers/routes.py:30
PUT /api/v1/mail/oauth-apps/{provider} upsert_provider_config mail_provider.update MailProviderUpsert none MailProviderRead 200 (default) src/cluster_erp/modules/mail/providers/routes.py:44
DELETE /api/v1/mail/oauth-apps/{provider} delete_provider_config mail_provider.delete none none none 204 src/cluster_erp/modules/mail/providers/routes.py:57

Mail accounts endpoints

Connected accounts, available providers, OAuth start and callback, IMAP connect, and disconnect.

Method Path Handler Permission Request Query Response Status Source
GET /api/v1/mail/accounts/ list_accounts mail_account.read none none MailAccountListResponse 200 (default) src/cluster_erp/modules/mail/accounts/routes.py:33
GET /api/v1/mail/accounts/providers get_providers mail_account.read none none ProviderInfo 200 (default) src/cluster_erp/modules/mail/accounts/routes.py:47
POST /api/v1/mail/accounts/oauth/{provider}/start oauth_start mail_account.connect none none OAuthStartResponse 200 (default) src/cluster_erp/modules/mail/accounts/routes.py:66
POST /api/v1/mail/accounts/oauth/callback oauth_callback mail_account.connect OAuthCallbackRequest none MailAccountRead 200 (default) src/cluster_erp/modules/mail/accounts/routes.py:99
POST /api/v1/mail/accounts/imap connect_imap mail_account.connect ImapConnectRequest none MailAccountRead 200 (default) src/cluster_erp/modules/mail/accounts/routes.py:166
GET /api/v1/mail/accounts/{account_id} get_account mail_account.read none none MailAccountRead 200 (default) src/cluster_erp/modules/mail/accounts/routes.py:185
DELETE /api/v1/mail/accounts/{account_id} disconnect_account mail_account.delete none none none 204 src/cluster_erp/modules/mail/accounts/routes.py:197

Messages endpoints

Sync, send, drafts, attachments, read state, trash, threads, list, and read.

Method Path Handler Permission Request Query Response Status Source
POST /api/v1/mail/messages/sync sync_messages mail_message.sync none account_id MailSyncResponse 200 (default) src/cluster_erp/modules/mail/messages/routes.py:43
POST /api/v1/mail/messages/send send_message mail_message.send MailSendRequest none MailMessageSummary 200 (default) src/cluster_erp/modules/mail/messages/routes.py:57
POST /api/v1/mail/messages/drafts save_draft mail_message.create MailDraftRequest none MailMessageSummary 200 (default) src/cluster_erp/modules/mail/messages/routes.py:84
POST /api/v1/mail/messages/drafts/{draft_id}/discard discard_draft mail_message.delete none none none 204 src/cluster_erp/modules/mail/messages/routes.py:105
GET /api/v1/mail/messages/{message_id}/attachments list_attachments mail_message.read none none list[MailAttachmentRead] 200 (default) src/cluster_erp/modules/mail/messages/routes.py:119
POST /api/v1/mail/messages/{draft_id}/attachments upload_attachment mail_message.update multipart file none MailAttachmentRead 201 src/cluster_erp/modules/mail/messages/routes.py:130
POST /api/v1/mail/messages/{draft_id}/attachments/{attachment_id}/remove remove_attachment mail_message.update none none none 204 src/cluster_erp/modules/mail/messages/routes.py:151
GET /api/v1/mail/messages/{message_id}/attachments/{attachment_id}/content download_attachment mail_message.read none none Response 200 (default) src/cluster_erp/modules/mail/messages/routes.py:162
POST /api/v1/mail/messages/{message_id}/read set_read_state mail_message.update MailReadState none none 204 src/cluster_erp/modules/mail/messages/routes.py:185
POST /api/v1/mail/messages/{message_id}/trash trash_message mail_message.update none none none 204 src/cluster_erp/modules/mail/messages/routes.py:197
GET /api/v1/mail/messages/{message_id}/thread message_thread mail_message.read none none list[MailMessageSummary] 200 (default) src/cluster_erp/modules/mail/messages/routes.py:208
GET /api/v1/mail/messages/ list_messages mail_message.read none folder, account_id, search, limit, offset MailMessageListResponse 200 (default) src/cluster_erp/modules/mail/messages/routes.py:220
GET /api/v1/mail/messages/{message_id} get_message mail_message.read none none MailMessageDetail 200 (default) src/cluster_erp/modules/mail/messages/routes.py:243

Error codes

The table lists the error codes that code under src/cluster_erp/modules/mail/ raises, found by a syntax-tree scan for AppError(...), the factories in src/cluster_erp/core/errors.py (not_found, conflict, protected, permission_denied, privilege_escalation, check_version), and HTTPException(...). A status of 400 is the AppError default (src/cluster_erp/core/errors.py:23). Guard errors (401, 403), the entitlement codes, and validation errors (422) apply to every route and are listed on Errors.

Code HTTP status Raised in First site
RESOURCE_NOT_FOUND 404 accounts, domains, messages, providers src/cluster_erp/modules/mail/accounts/routes.py:193
VALIDATION_ERROR 400, 404, 500, 502 accounts, messages, providers src/cluster_erp/modules/mail/accounts/routes.py:77

Events emitted

The table lists the contract classes that code under src/cluster_erp/modules/mail/ passes directly to EventBus.emit, found by a syntax-tree scan. Events built in a variable first are not counted. The contracts are described in Contracts reference.

None found by the scan.


Verified against commit 92f8051 on 2026-11-13.

Verified against commit 92f8051 · 2026-11-13