---
title: "Email AI-CRM API"
description: "Админские почтовые CRM-роуты (каналы + sourceChannel), cron-процессор, заметка про очистку токенов, входящий вебхук"
locale: "ru"
---
# Email AI-CRM API

Все маршруты `/api/admin/email/*` требуют аутентифицированной сессии **platform admin** (роль `admin` или `superadmin`).

Интерфейс обзора: **`/admin/crm/*`** (`CrmAdminShell`). API остаются на `/api/admin/email/*` — см. [Email AI-CRM](/docs/features/email-ai-crm.md).

`/api/cron/*` и `/api/webhooks/email/inbound` используют `CRON_SECRET` или `WEBHOOK_EMAIL_SECRET` — не user session. Без секрета закрываются по умолчанию.

Отправка черновика использует `EmailSenderService` + SMTP канала (`CRM_CHANNEL_*`). Auth OTP использует `lib/mailer.ts` / `SMTP_*`. Не путайте их в операционных процедурах.

## Admin — каналы

### `GET /api/admin/email/channels`

Только для чтения: статус CRM-каналов (без паролей). Используется для фильтрации почтовых ящиков во UI.

**Ответ:**
```json
{
  "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`.

---

## Admin — треды

### `GET /api/admin/email/threads`

Список тредов переписки.

| Query         | Type   | Описание                                                    |
|---------------|--------|-------------------------------------------------------------|
| `status`      | string | Фильтр: `new`, `ongoing`, `waiting`, `resolved` или все    |
| `sourceChannel` | string | Фильтровать по id/name канала (многопочтовый ящик)        |

**Ответ:** `{ threads: EmailThreadRecord[] }`

### `PATCH /api/admin/email/threads`

Обновить статус треда.

**Тело:** `{ "id": "", "status": "resolved" }`

### `GET /api/admin/email/threads/[id]`

Детали треда с сообщениями, черновиками и открытыми задачами.

**Ответ:** `{ thread, messages, drafts, tasks }`

---

## Admin — черновики

### `GET /api/admin/email/drafts`

Ожидающие черновики (`status: pending`), отсортированы по времени (новые выше).

### `POST /api/admin/email/drafts/[id]/approve`

Утвердить черновик к отправке. В reviewer сохраняется id текущего пользователя-сессии.

### `POST /api/admin/email/drafts/[id]/reject`

**Тело:** `{ "reason": "опциональная строка" }`

### `POST /api/admin/email/drafts/[id]/send`

Отправка утверждённого черновика через **CRM SMTP-канал** (`EmailSenderService`).

**Тело (опционально):** `{ "toEmail": "...", "subject": "..." }` — по умолчанию из треда.

**Ответ:** `{ "success": true, "messageId": "" }`

Запись сохраняется в `email_messages`, статус треда обновляется на `waiting`.

---

## Admin — контакты

### `GET /api/admin/email/contacts`

| Query                       | Описание         |
|-----------------------------|------------------|
| `email`, `name`, `company`, `type` | Фильтры поиска |

### `POST /api/admin/email/contacts`

**Тело:** `{ "email": "обяз.", "name?", "company?", "type?" }`

---

## Admin — задачи

### `GET /api/admin/email/tasks`

| Query   | Описание                                      |
|---------|-----------------------------------------------|
| `status`| `open`, `in_progress`, `overdue`, `completed` и др. |

### `POST /api/admin/email/tasks`

**Тело:** `{ "threadId", "title", "taskType", ... }` — см. `TaskCreateInput` из `task-service.ts`.

### `POST /api/admin/email/tasks/[id]/complete`

**Тело:** `{ "completionNotes?": "string" }`

---

## Admin — аналитика

### `GET /api/admin/email/analytics`

| Query   | Значения                   |
|---------|----------------------------|
| `range` | `7d` (по умолч.), `30d`, `90d` |

**Ответ:** распределение intent/sentiment, `costStats` из `email_api_usage`, `dailyStats`, черновики/задачи.

---

## Cron — email processor

### `POST` или `GET` `/api/cron/email-processor`

**Аутентификация:** `Authorization: Bearer $CRON_SECRET` (без секрета — отказ)

**Тело запроса или query-параметр `action`:**

| Action               | Действие                                                          |
|----------------------|-------------------------------------------------------------------|
| `poll` (по умолч.)   | `pollInboundBatch()` — загрузка UNSEEN на каждом канале, обработка, disconnect |
| `status`             | Статус обработчика и IMAP (`getEmailProcessor()`)                |
| `stop`               | Остановить IDLE слушатель                                         |
| `start`              | Запустить IDLE (`EMAIL_PROCESSOR_ALLOW_HTTP_START=true`)          |
| `mark-overdue-tasks` | Запуск `EmailTaskService.processOverdueTasks()`                   |

На каждый action создаётся новый обработчик (Processor), нет постоянно работающего глобального экземпляра.

**Пример:**
```bash
curl -X POST "$BASE_URL/api/cron/email-processor" \
  -H "Authorization: Bearer $CRON_SECRET" \
  -H "Content-Type: application/json" \
  -d '{"action":"poll"}'
```

### `GET /api/cron/email-analytics`

7-дневный срез дашборда (структура — как admin analytics). Только по cron-авторизации.

### Очистка токенов авторизации (смежное)

`GET/POST /api/cron/cleanup-email-tokens` — чистка просроченных `email_login_tokens`. Такой же fail-closed по `CRON_SECRET`. Документировано в [Ring Mailer](/docs/features/ring-mailer.md), не относится к Email CRM напрямую.

---

## Webhook — входящая почта

### `POST /api/webhooks/email/inbound`

**Авторизация:** `Authorization: Bearer $WEBHOOK_EMAIL_SECRET` **или** HMAC-SHA256 hex в `X-Email-Webhook-Signature` по сырому телу.

**Тело запроса (JSON):**
```json
{
  "messageId": "",
  "from": "sender@example.com",
  "fromName": "Опциональное имя",
  "to": "info@example.com",
  "subject": "Тема письма",
  "bodyText": "Текстовое тело",
  "bodyHtml": "опционально",
  "date": "2026-06-10T12:00:00.000Z",
  "inReplyTo": "",
  "references": ["", ""]
}
```
Вызывает `EmailProcessor.ingestEvent()` c `uid: 0` (IMAP-пометка как “прочитано” не ставится).

---

## Связанная документация

  
- [features/email-ai-crm](/docs/features/email-ai-crm.md) — Предпосылки: настройка операторов, секреты каналов, Auth vs CRM SMTP.

  
- [architecture/email-ai-crm](/docs/architecture/email-ai-crm.md) — Детальный разбор: EmailProcessor и persistance через jsonb-collection.

  
- [examples/email-ai-crm](/docs/examples/email-ai-crm.md) — Использование: локальный poll + smoke-тест отправки черновика.

  
- [features/ring-mailer](/docs/features/ring-mailer.md) — См. также: Auth cleanup-email-tokens cron и SMTP_* плоскость.

  
- [features/owner-project-lab](/docs/features/owner-project-lab.md) — См. также: CRM orders desk, использующий тот же admin shell.
