NoiseCut API — интеграция проверки заявок
Сервис принимает данные заявки, проверяет подпись, анализирует контактные данные, текст и краткосрочный контекст, а затем возвращает категорию и причины для маршрутизации в CRM. Гибридный анализ объединяет эвристики, поведенческий слой и подключённую текстовую ML-модель, обученную на более чем 10 000 реальных заявок с ручной разметкой.
1. Endpoint
Все заявки отправляются на один endpoint методом POST.
POST https://noisecut.ru/netcat/modules/noisecut/ingest.php
2. Формат запроса
Сервис принимает JSON и обычный form-data / x-www-form-urlencoded. Рекомендуемый формат — JSON.
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
| site | string | Да | Домен сайта клиента. Должен совпадать с данными, для которых выдан ключ. |
| name | string | Нет | Имя клиента или ФИО. |
| phone | string | Нет | Телефон клиента в любом удобном формате. |
| text | string | Нет | Комментарий, текст заявки, данные квиза или анкеты. |
| timestamp | int | Да | Unix timestamp. Входит в подпись запроса. |
| signature | string | Да | HMAC SHA256 подпись. |
| ID | int | Нет | Устаревшее диагностическое поле v1. Владелец и подписка определяются сервером по ключу сайта. |
| signature_version | int | Для новых интеграций | Передавайте 2. Значение 1 оставлено для совместимости. |
| visitor_ip | string | Для v2 | IP, сохранённый в данных заявки. Не REMOTE_ADDR отложенного обработчика. |
| user_agent | string | Нет | Не используется в рекомендуемой интеграции; передавайте пустую строку. |
| form_id | string | Для v2 | Стабильный ID формы, до 100 символов. |
| penalty | int | Нет | Дополнительный штраф, если нужен внешний автоматический флаг. |
3. Подпись запроса
Подпись защищает заявку от подмены. Сервер и клиент должны формировать строку для подписи абсолютно одинаково.
Нормализация
$name_norm = trim(mb_strtolower($name, 'UTF-8'));
$phone_norm = preg_replace('/\D+/', '', $phone);
$text_norm = trim(mb_strtolower($text, 'UTF-8'));
Строка для подписи
$data_string = $site . '|' . $timestamp . '|' . $name_norm . '|' . $phone_norm . '|' . $text_norm;
Для v2 добавьте в точном порядке:
$data_string .= '|' . $visitor_ip . '||' . $form_id; // пустой сегмент user_agent обязателен
Генерация подписи
$signature = hash_hmac('sha256', $data_string, $secret);
4. Пример на PHP
Функция использует подпись v2, сохранённый IP заявки и стабильный form_id. Она не содержит внутренних порогов NoiseCut и принимает решение по публичному result_code.
<?php
function checkSpam($name, $phone, $text, $formId, $savedIp)
{
$endpoint = 'https://noisecut.ru/netcat/modules/noisecut/ingest.php';
$site = 'YOUR_SITE_HOST';
$secret = 'YOUR_SITE_SECRET';
$savedIp = trim((string)$savedIp);
if (!filter_var($savedIp, FILTER_VALIDATE_IP)) {
error_log('NoiseCut: saved request IP is missing');
return true; // не теряем заявку при ошибке интеграции
}
$timestamp = time();
$nameNorm = trim(mb_strtolower($name, 'UTF-8'));
$phoneNorm = preg_replace('/\D+/', '', $phone);
$textNorm = trim(mb_strtolower($text, 'UTF-8'));
$dataString = $site . '|' . $timestamp . '|' . $nameNorm . '|' . $phoneNorm . '|' . $textNorm;
$dataString .= '|' . $savedIp . '||' . $formId; // user_agent намеренно пуст
$payload = array(
'site' => $site,
'name' => $name,
'phone' => $phone,
'text' => $text,
'timestamp' => $timestamp,
'signature' => hash_hmac('sha256', $dataString, $secret),
'signature_version' => 2,
'visitor_ip' => $savedIp,
'user_agent' => '',
'form_id' => $formId
);
$json = json_encode($payload, JSON_UNESCAPED_UNICODE);
$ch = curl_init($endpoint);
curl_setopt_array($ch, array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => $json,
CURLOPT_HTTPHEADER => array('Content-Type: application/json'),
CURLOPT_TIMEOUT => 10,
CURLOPT_SSL_VERIFYPEER => true,
CURLOPT_SSL_VERIFYHOST => 2
));
$response = curl_exec($ch);
$httpCode = (int)curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
$result = json_decode((string)$response, true);
if ($httpCode !== 200 || !is_array($result) || isset($result['error'])) {
error_log('NoiseCut: API request failed');
return true;
}
$resultCode = isset($result['analysis']['result_code'])
? (string)$result['analysis']['result_code']
: '';
return $resultCode !== 'spam';
}
5. Вызов после добавления объекта Netcat
IP нужно сохранить в поле заявки при её создании. В обработчике после добавления объекта используйте $f_IP или поле MessageXXX.IP, но не REMOTE_ADDR: в отложенном обработчике это может быть адрес воркера.
<?php
// Действие после добавления объекта компонента заявки.
$savedIp = trim((string)$f_IP); // поле IP текущего MessageXXX
$formId = 'callback-form';
if (!filter_var($savedIp, FILTER_VALIDATE_IP)) {
error_log('NoiseCut: saved request IP is missing');
} else {
$sendToCrm = checkSpam($f_Name, $f_Phone, $f_Text, $formId, $savedIp);
if ($sendToCrm) {
// штатная отправка заявки в CRM или менеджеру
}
}6. Ответ API
Если заявка обработана, API возвращает статус ok, исходные данные запроса и блок анализа.
{
"status": "ok",
"site": "example.ru",
"site_id": 123,
"user_id": 456,
"request": {
"name": "Имя клиента",
"phone": "номер из формы",
"text": "текст обращения",
"timestamp": "1710000000"
},
"analysis": {
"result_code": "other_region",
"result_label": "Другой регион",
"css_class": "good-other",
"reasons": [
{
"code": "phone_other_region",
"text": "Номер относится к другому региону"
}
],
"normalized": {
"phone": "нормализованный номер",
"name": "имя клиента",
"text": "текст обращения",
"phone_info": "оператор и регион"
}
}
}
8. Нормализованные данные
В блоке normalized API возвращает очищенные и приведённые к стабильному формату данные.
Что входит
{
"phone": "нормализованный номер",
"name": "имя клиента",
"text": "текст обращения",
"phone_info": "оператор и регион"
}
Зачем это нужно
9. Ошибки
Если что-то не так с запросом, API вернёт ошибку и соответствующий HTTP-код.
| HTTP | Ошибка | Когда возникает |
|---|---|---|
| 400 | Missing required fields | Не переданы обязательные поля. |
| 400 | Invalid visitor IP | В запросе v2 нет корректного сохранённого IP заявки. |
| 403 | Invalid signature | Подпись не совпала. |
| 403 | Subscription expired | Подписка пользователя истекла. |
| 403 | Invalid source domain | Origin/Referer не совпадает с доменом сайта. |
| 404 | Site owner not found | У записи сайта нет действующего владельца. |
| 503 | Behavior analysis temporarily unavailable | Историю нельзя безопасно рассчитать или заблокировать; запрос следует повторить. |
| 404 | Site not found | Для указанного сайта не найден ключ. |
| 405 | Method not allowed | Использован не POST-запрос. |
10. Безопасность
В API уже встроены базовые проверки, которые защищают endpoint от случайных и злонамеренных вызовов.
HMAC-подпись
Исключает подмену данных, если секретный ключ хранится только на стороне клиента и сервера.
Проверка домена
Сверяется домен источника запроса через Origin или Referer.
Проверка подписки
Запрос обрабатывается только для активного пользователя с действующей подпиской.
11. Рекомендации по интеграции
Ниже — практические рекомендации, чтобы интеграция получилась предсказуемой и стабильной.
12. Частые вопросы
Нужно ли передавать email отдельно?
Нет. Если email есть внутри текста заявки, API это увидит и пометит reason-кодом text_contains_email.
Что делать с заявками из другого региона?
Обычно это не спам, а нецелевой лид. Их можно не удалять, а просто снижать в приоритете.
Можно ли передавать квиз или анкету целиком?
Да. Структурированный текст вида «Поле: значение» поддерживается и не должен считаться спамом сам по себе.
Что, если подпись не совпадает?
Проверьте, что клиент и сервер одинаково нормализуют name, phone и text, и используют один и тот же timestamp.