Концепції, цінність і типові сценарії
Концепції, цінність і типові сценарії
Preparing Ring content
Preparing Ring content
Preparing Ring content
Всі маршрути /api/admin/email/* потребують аутентифікованої сесії platform admin (роль admin або superadmin).
Інтерфейс перегляду знаходиться за адресою /admin/crm/* (CrmAdminShell). API залишаються /api/admin/email/* — див. Email AI-CRM.
/api/cron/* та /api/webhooks/email/inbound використовують CRON_SECRET або WEBHOOK_EMAIL_SECRET — не user session. Якщо секрет відсутній — запит відхиляється.
Відправка чернеток використовує EmailSenderService + канальний SMTP (CRM_CHANNEL_*). Для авторизаційних OTP використовується lib/mailer.ts / SMTP_*. Не плутайте це в технічній документації.
GET /api/admin/email/channelsТільки для читання: статус каналів CRM (без паролей). Використовується для фільтрації inbox за каналами в UI.
Відповідь:
{
"channels": [
{
"id": "primary",
"name": "Primary",
"flow": "standard",
"mailbox": "INBOX",
"imapHost": "mail.ringdom.org",
"imapUser": "info@ringdom.org",
"smtpHost": "mail.ringdom.org",
"smtpUser": "info@ringdom.org",
"hasImapPassword": true,
"hasSmtpPassword": true
}
],
"validation": { "ok": true, "errors": [] }
}Реалізація: loadCrmChannels() + validateCrmChannels() з features/email-crm/pipeline/imap/config.ts.
GET /api/admin/email/threadsСписок email-тредів.
| Query | Тип | Опис |
|---|---|---|
status | string | Фільтр: new, ongoing, waiting, resolved або всі |
sourceChannel | string | Фільтрація за id чи назвою каналу (для мультискринькової підтримки) |
Відповідь: { threads: EmailThreadRecord[] }
PATCH /api/admin/email/threadsОновлення статусу треду.
Body: { "id": "<threadId>", "status": "resolved" }
GET /api/admin/email/threads/[id]Детальна інформація про тред: повідомлення, чернетки, відкриті задачі.
Відповідь: { thread, messages, drafts, tasks }
GET /api/admin/email/draftsЧернетки до відправки (status: pending), найновіші першими.
POST /api/admin/email/drafts/[id]/approveЗатвердити чернетку до відправки (відмітка reviewer — user із сесії).
POST /api/admin/email/drafts/[id]/rejectBody: { "reason": "текстове пояснення (необов'язково)" }
POST /api/admin/email/drafts/[id]/sendВідправити затверджену чернетку через CRM SMTP-канал (EmailSenderService).
Body (опціонально): { "toEmail": "...", "subject": "..." } — за замовчуванням з треду.
Відповідь: { "success": true, "messageId": "<smtp-message-id>" }
Email зберігається у email_messages + статус треду змінюється на waiting.
GET /api/admin/email/contacts| Query | Опис |
|---|---|
email, name, company, type | Параметри для пошуку |
POST /api/admin/email/contactsBody: { "email": "обовʼязково", "name?", "company?", "type?" }
GET /api/admin/email/tasks| Query | Опис |
|---|---|
status | open, in_progress, overdue, completed і т.д. |
POST /api/admin/email/tasksBody: { "threadId", "title", "taskType", ... } — приклад див. у TaskCreateInput (task-service.ts).
POST /api/admin/email/tasks/[id]/completeBody: { "completionNotes?": "text" }
GET /api/admin/email/analytics| Query | Значення |
|---|---|
range | 7d (за замовчуванням), 30d, 90d |
Відповідь: розподіл намірів/емоцій, costStats з email_api_usage, dailyStats, підсумки по чернетках/задачах.
POST або GET /api/cron/email-processorAuth: Authorization: Bearer $CRON_SECRET (обовʼязково)
Body або query action:
| Action | Опис |
|---|---|
poll (default) | pollInboundBatch() — забрати UNSEEN по каналах, обробити, закрити зʼєднання |
status | Статистика процесора + IMAP (getEmailProcessor() для цієї дії) |
stop | Зупинити IDLE listener |
start | Старт IDLE (потрібен EMAIL_PROCESSOR_ALLOW_HTTP_START=true) |
mark-overdue-tasks | Виклик EmailTaskService.processOverdueTasks() |
Екземпляри процесора створюються окремо для кожної дії (не long-running-сервіс).
Приклад:
GET /api/cron/email-analyticsПовертає 7-денний знімок дашборду (як admin analytics). Тільки cron-авторизація.
GET/POST /api/cron/cleanup-email-tokens — видаляє прострочені email_login_tokens. Той самий pattern з CRON_SECRET. Документація — Ring Mailer; не відноситься до Email CRM напряму.
POST /api/webhooks/email/inboundAuth: Authorization: Bearer $WEBHOOK_EMAIL_SECRET або HMAC-SHA256 hex у X-Email-Webhook-Signature по raw body.
Body (JSON):
Викликає EmailProcessor.ingestEvent() з uid: 0 (без позначки IMAP як прочитаного).
Передумова: налаштування операторів, секрети каналів, різниця Auth та CRM SMTP.
Деталі реалізації: EmailProcessor та jsonb-collection persist.
Workflow: локальний poll + відправка чернетки (smoke test).
Див. також: cron очистки токенів авторизації, SMTP_* plane.
Всі маршрути /api/admin/email/* потребують аутентифікованої сесії platform admin (роль admin або superadmin).
Інтерфейс перегляду знаходиться за адресою /admin/crm/* (CrmAdminShell). API залишаються /api/admin/email/* — див. Email AI-CRM.
/api/cron/* та /api/webhooks/email/inbound використовують CRON_SECRET або WEBHOOK_EMAIL_SECRET — не user session. Якщо секрет відсутній — запит відхиляється.
Відправка чернеток використовує EmailSenderService + канальний SMTP (CRM_CHANNEL_*). Для авторизаційних OTP використовується lib/mailer.ts / SMTP_*. Не плутайте це в технічній документації.
GET /api/admin/email/channelsТільки для читання: статус каналів CRM (без паролей). Використовується для фільтрації inbox за каналами в UI.
Відповідь:
{
"channels": [
{
"id": "primary",
"name": "Primary",
"flow": "standard",
"mailbox": "INBOX",
"imapHost": "mail.ringdom.org",
"imapUser": "info@ringdom.org",
"smtpHost": "mail.ringdom.org",
"smtpUser": "info@ringdom.org",
"hasImapPassword": true,
"hasSmtpPassword": true
}
],
"validation": { "ok": true, "errors": [] }
}Реалізація: loadCrmChannels() + validateCrmChannels() з features/email-crm/pipeline/imap/config.ts.
GET /api/admin/email/threadsСписок email-тредів.
| Query | Тип | Опис |
|---|---|---|
status | string | Фільтр: new, ongoing, waiting, resolved або всі |
sourceChannel | string | Фільтрація за id чи назвою каналу (для мультискринькової підтримки) |
Відповідь: { threads: EmailThreadRecord[] }
PATCH /api/admin/email/threadsОновлення статусу треду.
Body: { "id": "<threadId>", "status": "resolved" }
GET /api/admin/email/threads/[id]Детальна інформація про тред: повідомлення, чернетки, відкриті задачі.
Відповідь: { thread, messages, drafts, tasks }
GET /api/admin/email/draftsЧернетки до відправки (status: pending), найновіші першими.
POST /api/admin/email/drafts/[id]/approveЗатвердити чернетку до відправки (відмітка reviewer — user із сесії).
POST /api/admin/email/drafts/[id]/rejectBody: { "reason": "текстове пояснення (необов'язково)" }
POST /api/admin/email/drafts/[id]/sendВідправити затверджену чернетку через CRM SMTP-канал (EmailSenderService).
Body (опціонально): { "toEmail": "...", "subject": "..." } — за замовчуванням з треду.
Відповідь: { "success": true, "messageId": "<smtp-message-id>" }
Email зберігається у email_messages + статус треду змінюється на waiting.
GET /api/admin/email/contacts| Query | Опис |
|---|---|
email, name, company, type | Параметри для пошуку |
POST /api/admin/email/contactsBody: { "email": "обовʼязково", "name?", "company?", "type?" }
GET /api/admin/email/tasks| Query | Опис |
|---|---|
status | open, in_progress, overdue, completed і т.д. |
POST /api/admin/email/tasksBody: { "threadId", "title", "taskType", ... } — приклад див. у TaskCreateInput (task-service.ts).
POST /api/admin/email/tasks/[id]/completeBody: { "completionNotes?": "text" }
GET /api/admin/email/analytics| Query | Значення |
|---|---|
range | 7d (за замовчуванням), 30d, 90d |
Відповідь: розподіл намірів/емоцій, costStats з email_api_usage, dailyStats, підсумки по чернетках/задачах.
POST або GET /api/cron/email-processorAuth: Authorization: Bearer $CRON_SECRET (обовʼязково)
Body або query action:
| Action | Опис |
|---|---|
poll (default) | pollInboundBatch() — забрати UNSEEN по каналах, обробити, закрити зʼєднання |
status | Статистика процесора + IMAP (getEmailProcessor() для цієї дії) |
stop | Зупинити IDLE listener |
start | Старт IDLE (потрібен EMAIL_PROCESSOR_ALLOW_HTTP_START=true) |
mark-overdue-tasks | Виклик EmailTaskService.processOverdueTasks() |
Екземпляри процесора створюються окремо для кожної дії (не long-running-сервіс).
Приклад:
GET /api/cron/email-analyticsПовертає 7-денний знімок дашборду (як admin analytics). Тільки cron-авторизація.
GET/POST /api/cron/cleanup-email-tokens — видаляє прострочені email_login_tokens. Той самий pattern з CRON_SECRET. Документація — Ring Mailer; не відноситься до Email CRM напряму.
POST /api/webhooks/email/inboundAuth: Authorization: Bearer $WEBHOOK_EMAIL_SECRET або HMAC-SHA256 hex у X-Email-Webhook-Signature по raw body.
Body (JSON):
Викликає EmailProcessor.ingestEvent() з uid: 0 (без позначки IMAP як прочитаного).
Передумова: налаштування операторів, секрети каналів, різниця Auth та CRM SMTP.
Деталі реалізації: EmailProcessor та jsonb-collection persist.
Workflow: локальний poll + відправка чернетки (smoke test).
Див. також: cron очистки токенів авторизації, SMTP_* plane.
Всі маршрути /api/admin/email/* потребують аутентифікованої сесії platform admin (роль admin або superadmin).
Інтерфейс перегляду знаходиться за адресою /admin/crm/* (CrmAdminShell). API залишаються /api/admin/email/* — див. Email AI-CRM.
/api/cron/* та /api/webhooks/email/inbound використовують CRON_SECRET або WEBHOOK_EMAIL_SECRET — не user session. Якщо секрет відсутній — запит відхиляється.
Відправка чернеток використовує EmailSenderService + канальний SMTP (CRM_CHANNEL_*). Для авторизаційних OTP використовується lib/mailer.ts / SMTP_*. Не плутайте це в технічній документації.
GET /api/admin/email/channelsТільки для читання: статус каналів CRM (без паролей). Використовується для фільтрації inbox за каналами в UI.
Відповідь:
{
"channels": [
{
"id": "primary",
"name": "Primary",
"flow": "standard",
"mailbox": "INBOX",
"imapHost": "mail.ringdom.org",
"imapUser": "info@ringdom.org",
"smtpHost": "mail.ringdom.org",
"smtpUser": "info@ringdom.org",
"hasImapPassword": true,
"hasSmtpPassword": true
}
],
"validation": { "ok": true, "errors": [] }
}Реалізація: loadCrmChannels() + validateCrmChannels() з features/email-crm/pipeline/imap/config.ts.
GET /api/admin/email/threadsСписок email-тредів.
| Query | Тип | Опис |
|---|---|---|
status | string | Фільтр: new, ongoing, waiting, resolved або всі |
sourceChannel | string | Фільтрація за id чи назвою каналу (для мультискринькової підтримки) |
Відповідь: { threads: EmailThreadRecord[] }
PATCH /api/admin/email/threadsОновлення статусу треду.
Body: { "id": "<threadId>", "status": "resolved" }
GET /api/admin/email/threads/[id]Детальна інформація про тред: повідомлення, чернетки, відкриті задачі.
Відповідь: { thread, messages, drafts, tasks }
GET /api/admin/email/draftsЧернетки до відправки (status: pending), найновіші першими.
POST /api/admin/email/drafts/[id]/approveЗатвердити чернетку до відправки (відмітка reviewer — user із сесії).
POST /api/admin/email/drafts/[id]/rejectBody: { "reason": "текстове пояснення (необов'язково)" }
POST /api/admin/email/drafts/[id]/sendВідправити затверджену чернетку через CRM SMTP-канал (EmailSenderService).
Body (опціонально): { "toEmail": "...", "subject": "..." } — за замовчуванням з треду.
Відповідь: { "success": true, "messageId": "<smtp-message-id>" }
Email зберігається у email_messages + статус треду змінюється на waiting.
GET /api/admin/email/contacts| Query | Опис |
|---|---|
email, name, company, type | Параметри для пошуку |
POST /api/admin/email/contactsBody: { "email": "обовʼязково", "name?", "company?", "type?" }
GET /api/admin/email/tasks| Query | Опис |
|---|---|
status | open, in_progress, overdue, completed і т.д. |
POST /api/admin/email/tasksBody: { "threadId", "title", "taskType", ... } — приклад див. у TaskCreateInput (task-service.ts).
POST /api/admin/email/tasks/[id]/completeBody: { "completionNotes?": "text" }
GET /api/admin/email/analytics| Query | Значення |
|---|---|
range | 7d (за замовчуванням), 30d, 90d |
Відповідь: розподіл намірів/емоцій, costStats з email_api_usage, dailyStats, підсумки по чернетках/задачах.
POST або GET /api/cron/email-processorAuth: Authorization: Bearer $CRON_SECRET (обовʼязково)
Body або query action:
| Action | Опис |
|---|---|
poll (default) | pollInboundBatch() — забрати UNSEEN по каналах, обробити, закрити зʼєднання |
status | Статистика процесора + IMAP (getEmailProcessor() для цієї дії) |
stop | Зупинити IDLE listener |
start | Старт IDLE (потрібен EMAIL_PROCESSOR_ALLOW_HTTP_START=true) |
mark-overdue-tasks | Виклик EmailTaskService.processOverdueTasks() |
Екземпляри процесора створюються окремо для кожної дії (не long-running-сервіс).
Приклад:
GET /api/cron/email-analyticsПовертає 7-денний знімок дашборду (як admin analytics). Тільки cron-авторизація.
GET/POST /api/cron/cleanup-email-tokens — видаляє прострочені email_login_tokens. Той самий pattern з CRON_SECRET. Документація — Ring Mailer; не відноситься до Email CRM напряму.
POST /api/webhooks/email/inboundAuth: Authorization: Bearer $WEBHOOK_EMAIL_SECRET або HMAC-SHA256 hex у X-Email-Webhook-Signature по raw body.
Body (JSON):
Викликає EmailProcessor.ingestEvent() з uid: 0 (без позначки IMAP як прочитаного).
Передумова: налаштування операторів, секрети каналів, різниця Auth та CRM SMTP.
Деталі реалізації: EmailProcessor та jsonb-collection persist.
Workflow: локальний poll + відправка чернетки (smoke test).
Див. також: cron очистки токенів авторизації, SMTP_* plane.
Див. також: адмінський shell замовлень CRM.
curl -X POST "$BASE_URL/api/cron/email-processor" \
-H "Authorization: Bearer $CRON_SECRET" \
-H "Content-Type: application/json" \
-d '{"action":"poll"}'
{
"messageId": "<rfc5322-message-id>",
"from": "sender@example.com",
"fromName": "НЕОБОВ’ЯЗКОВО",
"to": "info@example.com",
"subject": "Тема листа",
"bodyText": "Текст листа",
"bodyHtml": "<div>опційно</div>",
"date": "2026-06-10T12:00:00.000Z",
"inReplyTo": "<parent-message-id>",
"references": ["<ref1>", "<ref2>"]
}Див. також: адмінський shell замовлень CRM.
curl -X POST "$BASE_URL/api/cron/email-processor" \
-H "Authorization: Bearer $CRON_SECRET" \
-H "Content-Type: application/json" \
-d '{"action":"poll"}'
{
"messageId": "<rfc5322-message-id>",
"from": "sender@example.com",
"fromName": "НЕОБОВ’ЯЗКОВО",
"to": "info@example.com",
"subject": "Тема листа",
"bodyText": "Текст листа",
"bodyHtml": "<div>опційно</div>",
"date": "2026-06-10T12:00:00.000Z",
"inReplyTo": "<parent-message-id>",
"references": ["<ref1>", "<ref2>"]
}Див. також: адмінський shell замовлень CRM.
curl -X POST "$BASE_URL/api/cron/email-processor" \
-H "Authorization: Bearer $CRON_SECRET" \
-H "Content-Type: application/json" \
-d '{"action":"poll"}'
{
"messageId": "<rfc5322-message-id>",
"from": "sender@example.com",
"fromName": "НЕОБОВ’ЯЗКОВО",
"to": "info@example.com",
"subject": "Тема листа",
"bodyText": "Текст листа",
"bodyHtml": "<div>опційно</div>",
"date": "2026-06-10T12:00:00.000Z",
"inReplyTo": "<parent-message-id>",
"references": ["<ref1>", "<ref2>"]
}