Документация API

NoiseCut API — интеграция проверки заявок

Сервис принимает данные заявки, проверяет подпись, анализирует контактные данные, текст и краткосрочный контекст, а затем возвращает категорию и причины для маршрутизации в CRM. Гибридный анализ объединяет эвристики, поведенческий слой и подключённую текстовую ML-модель, обученную на более чем 10 000 реальных заявок с ручной разметкой.

Что делает Отсекает спам, выделяет другой регион и помогает менеджерам не тратить время на мусорные лиды.
Как работает POST-запрос + HMAC-подпись + проверка подписки + анализ содержимого заявки.
Что возвращает Итоговую категорию, список причин и нормализованные данные для интерфейса и CRM.

1. Endpoint

Все заявки отправляются на один endpoint методом POST.

POST https://noisecut.ru/netcat/modules/noisecut/ingest.php

2. Формат запроса

Сервис принимает JSON и обычный form-data / x-www-form-urlencoded. Рекомендуемый формат — JSON.

Параметр Тип Обязательный Описание
sitestringДаДомен сайта клиента. Должен совпадать с данными, для которых выдан ключ.
namestringНетИмя клиента или ФИО.
phonestringНетТелефон клиента в любом удобном формате.
textstringНетКомментарий, текст заявки, данные квиза или анкеты.
timestampintДаUnix timestamp. Входит в подпись запроса.
signaturestringДаHMAC SHA256 подпись.
IDintНетУстаревшее диагностическое поле v1. Владелец и подписка определяются сервером по ключу сайта.
signature_versionintДля новых интеграцийПередавайте 2. Значение 1 оставлено для совместимости.
visitor_ipstringДля v2IP, сохранённый в данных заявки. Не REMOTE_ADDR отложенного обработчика.
user_agentstringНетНе используется в рекомендуемой интеграции; передавайте пустую строку.
form_idstringДля v2Стабильный ID формы, до 100 символов.
penaltyintНетДополнительный штраф, если нужен внешний автоматический флаг.
Минимально обязательны site, timestamp и signature. Новые интеграции должны использовать v2 и передавать IP, сохранённый вместе с заявкой. Не оставляйте тестовый ID владельца: статистика может попасть в чужой кабинет. В актуальном API владелец определяется сервером по ключу сайта, а поле ID для новых интеграций не требуется.

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);
Любое отличие в нормализации — например лишний пробел, другой timestamp, пропущенный text или другой домен в поле site — приведёт к ошибке Invalid signature.

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 или менеджеру
    }
}
Не используйте $_SERVER['REMOTE_ADDR'] в отложенном действии. Передавайте IP, который был записан в объект заявки в момент отправки формы.

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": "оператор и регион"
}

Зачем это нужно

phoneНормализованный номер для хранения, поиска и аналитики.
nameОчищенное имя без мусора.
textТекст в стабильном виде после базовой нормализации.
phone_infoОператор и регион, определённые по номеру телефона.

9. Ошибки

Если что-то не так с запросом, API вернёт ошибку и соответствующий HTTP-код.

HTTP Ошибка Когда возникает
400Missing required fieldsНе переданы обязательные поля.
400Invalid visitor IPВ запросе v2 нет корректного сохранённого IP заявки.
403Invalid signatureПодпись не совпала.
403Subscription expiredПодписка пользователя истекла.
403Invalid source domainOrigin/Referer не совпадает с доменом сайта.
404Site owner not foundУ записи сайта нет действующего владельца.
503Behavior analysis temporarily unavailableИсторию нельзя безопасно рассчитать или заблокировать; запрос следует повторить.
404Site not foundДля указанного сайта не найден ключ.
405Method not allowedИспользован не POST-запрос.

10. Безопасность

В API уже встроены базовые проверки, которые защищают endpoint от случайных и злонамеренных вызовов.

HMAC-подпись

Исключает подмену данных, если секретный ключ хранится только на стороне клиента и сервера.

Проверка домена

Сверяется домен источника запроса через Origin или Referer.

Проверка подписки

Запрос обрабатывается только для активного пользователя с действующей подпиской.

11. Рекомендации по интеграции

Ниже — практические рекомендации, чтобы интеграция получилась предсказуемой и стабильной.

Передавайте text всегда.Даже короткий комментарий улучшает качество анализа и подписи.
Считайте подпись один раз.Тот же timestamp, который вошёл в подпись, должен уйти и в запрос.
Используйте JSON.Так проще отлаживать и логировать запросы целиком.
Не меняйте site на лету.Домен в подписи должен совпадать с реальным сайтом клиента.
Сохраняйте публичный результат API.Используйте result_code и отображаемые причины для маршрутизации и аналитики. Не привязывайте интеграцию к внутренним баллам.
Не передавайте User-Agent.В рекомендуемой интеграции поле остаётся пустым; сохранённый IP и form_id дают необходимый технический контекст.
Структурированные заявки не нужно штрафовать.Если текст похож на анкету и содержит email, API пометит это отдельными reason-кодами без лишнего штрафа.
Типовой сценарий: хорошие заявки показывать менеджеру сразу, другой регион — помечать как нецелевой, подозрительные — отправлять на ручную проверку, спам — скрывать или складывать отдельно.

12. Частые вопросы

Нужно ли передавать email отдельно?

Нет. Если email есть внутри текста заявки, API это увидит и пометит reason-кодом text_contains_email.

Что делать с заявками из другого региона?

Обычно это не спам, а нецелевой лид. Их можно не удалять, а просто снижать в приоритете.

Можно ли передавать квиз или анкету целиком?

Да. Структурированный текст вида «Поле: значение» поддерживается и не должен считаться спамом сам по себе.

Что, если подпись не совпадает?

Проверьте, что клиент и сервер одинаково нормализуют name, phone и text, и используют один и тот же timestamp.