# Персональные письма клиентам из CRM через API

> Письмо каждому клиенту по его истории: после заявки на демо, перед концом пробного периода, к продлению, тем, кто ушёл. Жалобы и возвраты код отправляет менеджеру, остальное уходит само. Ключ Polza.ai, оплата в рублях.

- 1 000 писем — от 57,84 ₽, оценка по ценам каталога
- Факты из CRM в каждом письме
- Жалобы — менеджеру
- Тема до 60 символов

## Письмо клиенту · Ольга, Складка → Константин

**Складка теперь с Ozon**

> Константин, добрый день.
> Появилась интеграция с Ozon — помню, вы ждали её, когда работали со Складкой.
> Остальные условия прежние: тариф «Старт» за 990 ₽ в месяц или «Бизнес» за 2 490 ₽, если нужно несколько складов. Пробный период — 14 дней. Можем встретиться на демо, чтобы я показала, как обмен с Ozon выглядит на ваших данных.
> Если это по-прежнему актуально, напишите — включу пробный доступ.
> Ольга, Складка

Реальное письмо из теста, сервис и клиент вымышленные. [Как тестировали](#test)

## Задача

В CRM каждый день появляются поводы написать: заявка без ответа, пробный период на исходе, клиент перестал заходить. Шаблонная рассылка с «Уважаемый клиент» не учитывает, что клиент уже сделал, а написать вручную каждому менеджер не успевает.

Через API строка CRM превращается в письмо с фактами именно этого клиента: сколько складов завёл, какую интеграцию подключил, почему ушёл. Модель пишет, код решает, что можно отправить без человека.

## Для кого

Для тех, у кого клиентов больше, чем писем, которые успевают написать менеджеры.

- **SaaS и онлайн-сервисы.** Пробный период, онбординг, продление, возврат ушедших. Поводы приходят из событий в продукте. Письмо в день события, а не раз в месяц.
- **Отделы продаж B2B.** Письмо после заявки или звонка с фактами из карточки сделки: что спросил клиент, сколько у него точек. Менеджер правит, а не пишет с нуля.
- **Сервисные компании.** Напоминание о плановом обслуживании, продление договора, письмо после закрытой заявки. Тон и факты одинаковые у всех менеджеров.
- **Клиентский сервис.** Ответ после решённой жалобы. Черновик пишет модель, отправляет человек. Извинения без обещаний, которых нет.

## Как письмо уходит клиенту

Четыре шага. Главный — второй: острые поводы код отделяет до модели.

- **Шаг 1. Выгрузка из CRM.** Клиенты с поводом для письма: заявка, конец пробного периода, продление, уход, жалоба. (клиент, повод, факты)
- **Шаг 2. Маршрут кодом.** Жалобы, возвраты и конфликты код помечает до модели. Решение не зависит от того, что модель «подумает». (жалоб, возврат, груб → менеджеру)
- **Шаг 3. Письмо.** Обычные поводы пишет DeepSeek V4 Pro, острые — Claude Sonnet 5. Ответ — тема и текст в JSON. (25 автоматически · 5 на проверку)
- **Шаг 4. Отправка.** Готовые письма уходят из CRM или сервиса рассылок от имени менеджера, черновики ждут в очереди. ("send": true / false)

Отправка — через вашу CRM или сервис рассылок: amoCRM, Битрикс24 и любую CRM с API. Скрипт отдаёт тему, текст и флаг `send`, а письмо уходит тем же путём, что и сейчас.

## Как это выглядит

Реальные письма из теста: во входящих у клиента, открытое письмо и очередь менеджера с острыми поводами.

### Входящие клиента

> Ольга · Складка — Складка теперь с Ozon
> Константин, добрый день.
>
> Игорь · Складка — Пробный период завершается через 3 дня
> Ксения, добрый день.
>
> Ольга · Складка — Подписка «Складки» заканчивается через 14 дней
> Сергей, добрый день.
>
> Ольга · Складка — Демо «Складки» для студии «Глина»
> Марина, здравствуйте.

Тема и первая строка решают, откроют ли письмо

### Письмо клиенту · Игорь, Складка → Ксения

**Пробный период завершается через 3 дня**

> Ксения, добрый день.
> Ваш пробный период в Складке закончится через три дня. Вы завели один склад и добавили 85 товаров, подключили Ozon — по статистике, вы заходили в сервис каждый день.
> Чтобы учёт не прерывался, вы можете перейти на платный тариф. Для одного склада по вашим задачам подойдёт «Старт» за 990 ₽ в месяц.
> До 31 октября действует акция: при оплате за год два месяца идут в подарок.
> Выберите тариф в приложении.
> Игорь, Складка

Конец пробного периода: факты из CRM и тариф

### Очередь менеджера

**5 черновиков ждут проверки**

> 25 писем из 30 ушли автоматически
>
> Оксана · ИП Миронова, бижутерия — жалоба в поддержку решена
> Мария · магазин чая «Пиала» — жалоба в поддержку не решена
> Евгений · ООО «Профкрепёж» — жалоба в поддержку решена
> Андрей · ООО «Канцмир» — жалоба в поддержку решена
> Филипп · ООО «Агро-Семена» — жалоба в поддержку решена

проверить

Острые поводы код отправляет человеку

## Сколько стоят 1 000 писем

Замер — фактический расход по полю `cost_rub` на 8 одинаковых трудных записях CRM, пересчитанный на 1 000. Рассуждение отключено. Стоимость «сейчас» Polza.ai оценивает по текущим ценам [каталога](https://polza.ai/models).

| Модель | 1 000 писем, замер 6 октября | Письмо | Остановила острые | 1 000 писем, оценка сейчас |
| --- | --- | --- | --- | --- |
| [GPT-5 Mini](https://polza.ai/models/openai/gpt-5-mini.md) | 72 ₽ | 5,2 с | 3 из 3 | 57,84 ₽ |
| [Gemini 2.5 Flash](https://polza.ai/models/google/gemini-2.5-flash.md) | 82 ₽ | 3,5 с | 1 из 3 | 71,48 ₽ |
| [DeepSeek V4 Pro](https://polza.ai/models/deepseek/deepseek-v4-pro.md) | 16 ₽ | 7,1 с | 2 из 3 | 204 ₽ |
| [Grok 4.3](https://polza.ai/models/x-ai/grok-4.3.md) | 164 ₽ | 2,6 с | 3 из 3 | 267 ₽ |
| [Claude Sonnet 5](https://polza.ai/models/anthropic/claude-sonnet-5.md) | 709 ₽ | 6,2 с | 3 из 3 | 676 ₽ |

Замер — 6 октября 2026, по ценам того дня.

«Оценка сейчас» — по текущим ценам каталога для объёмов, которые оценила редакция, а не замерил тест: 1 100 токенов на входе (промпт, описание продукта, строка CRM) и 350 на выходе (тема и письмо в JSON) на одно письмо.

**Смешанная схема.** В тесте острых поводов было 5 из 30. Обычные письма пишет DeepSeek V4 Pro, острые — Claude Sonnet 5: по оценке на текущих ценах каталога это 204 ₽ и 676 ₽ за 1 000 писем. Как не переплатить за рассуждение и провайдера — [в сценарии про SEO-тексты](https://polza.ai/use-cases/seo-content#stoimost).

## Готовый скрипт на Python

Читает выгрузку CRM, сам решает по словам в поводе, кому писать с проверкой, выбирает модель и печатает расход. Нужен пакет `openai` и ключ в `POLZA_API_KEY`.

### Вход: crm.csv и offer.txt

Строка на клиента: повод, факты, менеджер. В `offer.txt` — всё, что модель может говорить о продукте.

crm.csv:

```
id,name,company,event,facts,manager
C22,Константин,"ООО «Сантехника Дом»",ушёл 3 месяца назад,"причина: не было интеграции с Ozon — сейчас она есть",Ольга
C29,Мария,"магазин чая «Пиала»",жалоба в поддержку не решена,"ждёт ответа 3 дня по вопросу отчёта о продажах",Игорь
```

offer.txt:

```
Продукт: «Складка» — онлайн-учёт склада для малого
бизнеса.
Тарифы: «Старт» — 990 ₽ в месяц, один склад;
«Бизнес» — 2 490 ₽ в месяц, до пяти складов.
Пробный период — 14 дней, без привязки карты.
Интеграции: 1С, Ozon, Wildberries, МойСклад не
поддерживается.
Акция до 31 октября: при оплате за год — два месяца
в подарок.
Поддержка: чат в приложении, с 9 до 21 по Москве,
без выходных.
Демо: 30 минут по видеосвязи, менеджер показывает на
данных клиента.
```

### Выход: emails.jsonl

Тема, текст и флаг `send`. Реальный ответ из теста, текст сокращён.

emails.jsonl · одна строка:

```
{
  "id": "C22",
  "subject": "Складка теперь с Ozon",
  "send": true,
  "body": "Константин, добрый день. Появилась интеграция с Ozon — помню, вы ждали её, когда работали со Складкой. Остальные условия прежние: тариф «Старт» за 990…"
}
```

Python · write_mail.py:

```
# write_mail.py — персональные письма клиентам по строкам CRM через Polza
import asyncio, csv, json, os
from openai import AsyncOpenAI, APIStatusError

MODEL = "deepseek/deepseek-v4-pro"
PROVIDER = "streamlake/fp8"  # самый дешёвый провайдер модели: top_provider.name в каталоге
CONCURRENCY = 10
# острые поводы решает код, а не модель: такие письма уходят менеджеру на проверку
HOLD_WORDS = ["жалоб", "возврат", "вернуть деньги", "вернула", "груб", "не писать"]
SENSITIVE_MODEL = "anthropic/claude-sonnet-5"  # черновик для менеджера пишет модель аккуратнее

ai = AsyncOpenAI(base_url="https://polza.ai/api/v1", api_key=os.environ["POLZA_API_KEY"])
SYSTEM = open("prompt.txt", encoding="utf-8").read() + "\n\nО продукте:\n" + open("offer.txt", encoding="utf-8").read()

SCHEMA = {
    "name": "client_email",
    "strict": True,
    "schema": {
        "type": "object",
        "properties": {"subject": {"type": "string"}, "body": {"type": "string"},
                       "send": {"type": "boolean"}, "reason": {"type": "string"}},
        "required": ["subject", "body", "send", "reason"],
        "additionalProperties": False,
    },
}

async def write(row, sem, stats):
    hold = any(w in (row["event"] + " " + row["facts"]).lower() for w in HOLD_WORDS)
    model = SENSITIVE_MODEL if hold else MODEL
    extra = {"reasoning": {"effort": "none"}}
    if not hold:
        extra["provider"] = {"only": [PROVIDER], "allow_fallbacks": False}
    prompt = (f"Клиент: {row['name']}, {row['company']}\nПовод: {row['event']}\n"
              f"Факты из CRM: {row['facts']}\nМенеджер: {row['manager']}")
    async with sem:
        for attempt in range(5):
            try:
                r = await ai.chat.completions.create(
                    model=model,
                    messages=[{"role": "system", "content": SYSTEM},
                              {"role": "user", "content": prompt}],
                    response_format={"type": "json_schema", "json_schema": SCHEMA},
                    extra_body=extra,
                )
                break
            except APIStatusError as e:
                if e.status_code in (429, 500, 502, 503) and attempt < 4:
                    await asyncio.sleep(2 ** attempt)
                    continue
                raise
    stats["rub"] += r.usage.model_extra.get("cost_rub", 0)
    mail = json.loads(r.choices[0].message.content)
    if hold:
        mail["send"], mail["reason"] = False, "острый повод: письмо проверяет менеджер"
    return {"id": row["id"], "model": model, **mail}

async def main():
    rows = list(csv.DictReader(open("crm.csv", encoding="utf-8")))
    sem, stats = asyncio.Semaphore(CONCURRENCY), {"rub": 0}
    results = await asyncio.gather(*(write(r, sem, stats) for r in rows), return_exceptions=True)
    ok = 0
    with open("emails.jsonl", "w", encoding="utf-8") as out, open("errors.txt", "w", encoding="utf-8") as err:
        for row, res in zip(rows, results):
            if isinstance(res, Exception):
                err.write(f"{row['id']}\t{res}\n")
            else:
                out.write(json.dumps(res, ensure_ascii=False) + "\n")
                ok += 1
    print(f"Готово {ok} из {len(rows)}, расход {stats['rub']:.2f} ₽")

asyncio.run(main())
```

## Промпт для писем

Промпт держит модель в двух источниках: строка CRM и блок «О продукте». Всё, чего там нет, — функции, сроки, скидки, действия менеджера, — модель писать не должна.

Вторая версия добавила запреты по итогам первого прогона. Модель писала «импорт из Excel есть», «подписка продлится автоматически», «потерь и расхождений нет», а клиенту, жаловавшемуся на грубость, сообщила об исправленной ошибке в учёте.

prompt.txt:

```
Ты пишешь письмо клиенту от имени менеджера сервиса.
Факты о продукте — в блоке «О продукте», факты о
клиенте — в строке CRM.

Письмо:
- тема до 60 символов, без капслока и слов «срочно»,
  «только сегодня», «бесплатно»;
- обращение по имени, на «вы»;
- 3–5 коротких абзацев, до 700 символов вместе;
- первый абзац — о поводе письма и о самом клиенте:
  используй факты из CRM;
- одно предложение-действие: что клиенту сделать
  дальше;
- подпись: имя менеджера и «Складка».

Правила:
- Используй только факты из CRM и блока «О
  продукте». Не придумывай скидки, функции, сроки,
  цифры и обещания.
- Предлагай тариф или акцию, только если это
  помогает клиенту по его фактам.
- Не обещай того, чего продукт не умеет. Если клиент
  ушёл к конкуренту из-за функции, которой нет, не
  утверждай, что она есть.
- Без восклицательных знаков, эмодзи и шаблонных
  фраз «Надеемся на сотрудничество», «Будем рады
  видеть вас снова».
- Если у клиента нерешённая жалоба — не продавай:
  извинись и скажи, что делаешь по его вопросу,
  только по фактам.
- Не утверждай, что функция есть, если её нет в
  блоке «О продукте». Если клиент спрашивал о такой
  функции — предложи обсудить на демо.
- Не пиши, что проблема исправлена, данные
  восстановлены, вопрос передан или менеджер что-то
  сделал, если этого нет в фактах CRM.
- Не описывай, как поведёт себя сервис:
  автопродление, ограничения, блокировки, — если
  этого нет в данных.
- Без восклицательных знаков, даже в приветствии.
  Письмо всегда заканчивается подписью.

Поставь send = false и объясни в reason, если письмо
нельзя отправлять без менеджера: нерешённая жалоба,
любой возврат денег — даже уже сделанный, грубость
сотрудника, конфликт, просьба не писать.

Верни JSON: subject, body, send, reason.
```

## Проверка перед отправкой

Модель хорошо пишет и плохо решает, что можно отправлять. Поэтому решение — за кодом, а текст проверяют правила. Та же маршрутизация работает в [ответах на отзывы](https://polza.ai/use-cases/otvety-na-otzyvy).

- **Острые поводы — кодом.** В промпте мы просили модель саму помечать жалобы и возвраты. DeepSeek остановила 1 из 3 таких писем в первом прогоне и 1 из 3 во втором. Правило по словам в поводе CRM ловит все.
- **Функции только из offer.txt.** Самая частая выдумка — «такая функция есть». Держите в `offer.txt` полный список возможностей и отдельной строкой — чего продукт не умеет.
- **Действия менеджера.** «Я уже передал вопрос», «уточняю статус» — модель обещает от имени человека. Такие фразы стоит искать кодом и отправлять письмо на проверку.
- **Подпись и восклицания.** Подпись менеджера и отсутствие «!» проверяются одной строкой кода. В первом прогоне без подписи ушли бы 2 письма из 30, с восклицанием — 3.
- **Тема до 60 символов.** Длинная тема обрезается во входящих. Модель держит лимит почти всегда, но проверка стоит дёшево.
- **Выборка — человеку.** Первые 30–50 писем каждого повода менеджер читает целиком. Найденные выдумки становятся новыми строками в промпте или в `offer.txt`.

## Через Claude, OpenAI и Grok — или без кода

Скрипт с маршрутизацией соберёт ИИ-агент. Модели — в том же каталоге Polza.ai.

- **Claude Code и Claude Desktop.** Положите выгрузку CRM, `offer.txt` и промпт в папку и отдайте Claude задание ниже. Claude Sonnet 5: 1 000 писем — 676 ₽, оценка по ценам каталога.
- **Codex и ChatGPT Desktop.** То же задание выполняет Codex CLI. Модели GPT подключаются тем же ключом Polza. GPT-5 Mini: 1 000 писем — 57,84 ₽, оценка по ценам каталога.
- **Grok.** Модели xAI в том же API: `MODEL = "x-ai/grok-4.3"` в скрипте. Grok 4.3: 1 000 писем — 267 ₽, оценка по ценам каталога.

### Задание для агента

Подходит для Claude Code, Codex и других агентов из [интеграций](https://polza.ai/integrations).

задание для Claude Code или Codex:

```
В папке лежат crm.csv, offer.txt и prompt.txt.
Напиши и запусти скрипт на Python:
для каждой строки CRM запрос к https://polza.ai/api/v1
через OpenAI SDK, ключ — в переменной POLZA_API_KEY.
Если в поводе или фактах есть «жалоб», «возврат», «груб» —
модель anthropic/claude-sonnet-5 и send = false,
иначе deepseek/deepseek-v4-pro, провайдер streamlake/fp8.
Рассуждение отключено: reasoning: {effort: none}.
Системный промпт — prompt.txt и offer.txt,
ответ — JSON с полями subject, body, send, reason.
Покажи 10 писем и отдельно те, где send = false.
```

### Без кода: n8n и Dify

Событие в CRM — проверка повода — нода OpenAI Chat Model с адресом `https://polza.ai/api/v1` — письмо в CRM или черновик менеджеру в Telegram.

- **n8n.** Пробный период кончается через 3 дня — письмо ушло утром. Нода OpenAI Chat Model с адресом Polza.
- **Dify.** Workflow: маршрут, письмо, проверка, выгрузка. Облако или self-hosted.

## Тест редакции: 30 писем

Вымышленный сервис складского учёта и 30 клиентов с шестью поводами: заявка на демо, конец пробного периода, не заходит месяц, продление, ушёл, жалоба. Среди них ловушки: ушёл к конкуренту из-за функции, которой нет; деньги уже вернули; жалоба не решена. Замер 6 октября 2026: весь тест стоил 13,4 ₽ по ценам того дня.

- Писем: 30
- Время: 42 с
- Расход: 0,48 ₽
- Готовы без правок: 23 из 30

### Три прогона DeepSeek V4 Pro

| Прогон | Расход | Время | Письма с выдумкой | Остановила острые | Готовы без правок |
| --- | --- | --- | --- | --- | --- |
| v1: базовый промпт | 0,42 ₽ | 46 с | 8 | 1 из 3 | 17 из 30 |
| v2: запрет выдумок | 0,48 ₽ | 42 с | 4 | 1 из 3 | 23 из 30 |
| v2 + короткое рассуждение | 2,89 ₽ | 184 с | 1 | 2 из 3 | 25 из 30 |

Выдумки и «готовы без правок» — по вычитке редактора всех 30 писем. Короткое рассуждение убрало почти все выдумки, но стоило 2,89 ₽ вместо 0,48 ₽ и всё равно пропустило одно острое письмо. Расход — по ценам 6 октября 2026.

- **Несуществующая функция.** Клиенту, который спрашивал про импорт из Excel: «Такая функция есть — подготовьте файл по шаблону». В описании продукта импорта нет.
- **Действия, которых не было.** «Передал ваш вопрос коллегам с пометкой "срочно"», «потерь и расхождений нет», «подписка продлится автоматически».
- **Честно про конкурента.** Клиенту, ушедшему в МойСклад, модель прямо написала, что интеграции с ним по-прежнему нет. Так и должно быть.

### Пять моделей на 8 трудных записях

| Модель | 1 000 писем, замер | Остановила острые | Что увидел редактор |
| --- | --- | --- | --- |
| DeepSeek V4 Pro | 16 ₽ | 2 из 3 | Написала «импорт из Excel доступен», после жалобы на грубость предложила акцию. |
| GPT-5 Mini | 72 ₽ | 3 из 3 | Острые письма остановила все. Канцелярский тон: «Обращаюсь по поводу вашего аккаунта». |
| Gemini 2.5 Flash | 82 ₽ | 1 из 3 | Придумала «я уже связался с поддержкой». Из трёх острых писем остановила одно. |
| Grok 4.3 | 164 ₽ | 3 из 3 | Без выдумок, острые остановила. Слишком сухо: письмо после грубости — две строки. |
| Claude Sonnet 5 | 709 ₽ | 3 из 3 | Без выдумок, острые остановила, тон спокойный. |

Трудные записи: вопрос про несуществующую функцию, обновление интерфейса, продление, лимит тарифа, возврат денег, сбой, нерешённая жалоба, грубость поддержки. Промпт v2. Стоимость — замер 6 октября 2026 по ценам того дня, текущая — в [разделе «Стоимость»](#stoimost).

**Вывод.** Обычные поводы — DeepSeek V4 Pro: 23 из 30 писем без правок, по оценке на текущих ценах каталога 1 000 писем — 204 ₽. Острые поводы отделяет код, черновик для менеджера пишет Claude Sonnet 5. Главное, что показал тест: модели нельзя доверять решение «отправлять или нет» — его принимает правило по полям CRM.

## Вопросы

### Можно ли отправлять письма без проверки?

Письма по обычным поводам — после того как менеджер прочитал первые 30–50. Жалобы, возвраты и конфликты — только после человека. В тесте модель сама остановила лишь часть таких писем, поэтому решает код.

### Не придумает ли модель скидку или функцию?

Может, если её нет в данных, — в первом прогоне так и было. Держите в offer.txt полный список того, что можно говорить о продукте, и запрет на всё остальное в промпте.

### Сколько писем в час?

В тесте 30 писем заняли 42 секунды при 10 параллельных запросах — около 2 500 в час.

### С какими CRM это работает?

С amoCRM, Битрикс24 и любой CRM с API или выгрузкой в таблицу: скрипту нужна строка на клиента с поводом и фактами, а письмо уходит из вашей CRM или сервиса рассылок.

### Как сделать письма в стиле компании?

Добавьте в начало промпта две-три строки о тоне и пару писем, которые нравятся менеджерам. Проверьте на 20 клиентах разных поводов.

### Можно ли платить юрлицом?

Да. Polza.ai работает по договору: счёт, УПД и НДС. Расход виден в кабинете по ключам и моделям.

## Ссылки

- Сценарий «SEO-тексты»: https://polza.ai/use-cases/seo-content.md
- Сценарий «Ответы на отзывы»: https://polza.ai/use-cases/otvety-na-otzyvy.md
- Сценарий «Объявления для Авито»: https://polza.ai/use-cases/obyavleniya-avito.md
- Сценарий «Тесты по урокам»: https://polza.ai/use-cases/testy-po-urokam.md
- Сценарий «Протоколы встреч»: https://polza.ai/use-cases/protokoly-vstrech.md
- Документация: https://polza.ai/docs
- Каталог моделей: https://polza.ai/models/llms.txt
- Страница: https://polza.ai/use-cases/pisma-klientam
- Обновлено: 2026-10-14; замер теста — 6 октября 2026
