> ## Documentation Index
> Fetch the complete documentation index at: https://docs2.speech.palatine.ru/llms.txt
> Use this file to discover all available pages before exploring further.

# Фильтр мата для текста

Эндпоинт `POST /api/v1/profanity/filter` маскирует нецензурную и грубую лексику в
готовом тексте — той же маской, что опция `profanity_filter` при транскрипции (см.
[Анализ звонка](/documentation/quick_start/call_analytics)). Подходит для чатов,
комментариев, расшифровок из других источников.

<Tip>
  Эндпоинт **бесплатный** — запросы не тарифицируются и баланс не расходуют.
</Tip>

<Note>
  Все запросы требуют авторизации через токен в заголовке: `Authorization: Bearer <ваш_токен>`
</Note>

## Запрос

Тело — JSON. Передайте **либо** `text`, **либо** `texts`:

| Поле | Значение |
| - | - |
| `text` | Строка |
| `texts` | Массив строк, от 1 до 100. Ответ — в том же порядке |
| `level` | `soft` — только нецензурная брань (мат) и её производные; `hard` (по умолчанию) — мат **и** грубая, оскорбительная лексика. Без учёта регистра |
| `mask` | `partial` (по умолчанию) — сохранить первую и последнюю букву: `Х****Х`; `full` — заменить все буквы: `******`. Без учёта регистра |
| `positions` | `true` — вернуть позиции замаскированных слов (`hits`); по умолчанию `false` |

* Всего в запросе — не больше **100 000 символов** (сумма по всем текстам).
* Неизвестные поля не допускаются (`422`) — опечатка в имени параметра не превратится
  молча в значение по умолчанию.
* Эвфемизмы и смягчённые формы («блин», «хрен» и т. п.) не маскируются ни на одном уровне.
* Пунктуация, пробелы, регистр оставленных букв и длина текста сохраняются. Маска
  **необратима**; присланный текст сервис не сохраняет.

## Пример запроса

В примерах `Х****Х` — условное обозначение нецензурного слова: подставьте свой текст.

<Tabs>
  <Tab title="cURL">
    ```bash theme={null}
    curl -X POST "https://api.palatine.ru/api/v1/profanity/filter" \
      -H "Authorization: Bearer <YOUR_TOKEN>" \
      -H "Content-Type: application/json" \
      -d '{"text": "Ну что за Х****Х, опять не работает!", "positions": true}'
    ```
  </Tab>

  <Tab title="Python">
    ```python theme={null}
    import requests

    resp = requests.post(
        "https://api.palatine.ru/api/v1/profanity/filter",
        headers={"Authorization": "Bearer <YOUR_TOKEN>"},
        json={
            "texts": ["Всё отлично", "Ну что за Х****Х, опять не работает!"],
            "positions": True,
        },
    )
    resp.raise_for_status()
    result = resp.json()
    ```
  </Tab>
</Tabs>

## Формат ответа

Запрос с `text`:

```json theme={null}
{
  "text": "Ну что за Х****Х, опять не работает!",
  "count": 1,
  "hits": [{ "start": 10, "end": 16 }]
}
```

Запрос с `texts`:

```json theme={null}
{
  "texts": ["Всё отлично", "Ну что за Х****Х, опять не работает!"],
  "counts": [0, 1],
  "count": 1,
  "hits": [[], [{ "start": 10, "end": 16 }]]
}
```

| Поле | Значение |
| - | - |
| `text` / `texts` | Маскированный текст (или тексты в порядке запроса) |
| `count` | Число замаскированных слов — всего |
| `counts` | Число замаскированных слов в каждом тексте (только для `texts`) |
| `hits` | Только при `positions=true`: список позиций для `text`, список списков (по тексту) для `texts` |

### Позиции (`hits`)

Каждая позиция — полуинтервал `[start, end)`: `start` — первый символ слова, `end` —
символ сразу после него. Маска не меняет длину слова, поэтому позиции верны и для
исходного, и для маскированного текста.

<Warning>
  Позиции считаются в **символах Unicode (кодовых точках)**: `ё` — один символ, эмодзи —
  тоже один. В JavaScript `String.length` и индексы строки считают в UTF-16, где эмодзи
  занимает два символа, — если в тексте могут быть эмодзи, индексируйте через
  `Array.from(text)`:

  ```javascript theme={null}
  const chars = Array.from(text);
  const word = chars.slice(hit.start, hit.end).join("");
  ```

  В Python индексы строки совпадают с позициями напрямую: `text[hit["start"]:hit["end"]]`.
</Warning>

## Ограничения частоты

У эндпоинта есть ограничения на частоту и число одновременных запросов. При превышении
сервис отвечает `429` с заголовком `Retry-After` — через сколько секунд повторить запрос.
Отказ из-за объёма текста, недоступности функции или занятости сервиса лимит частоты не
расходует.

## Ошибки

| Код | Когда |
| - | - |
| `401` | Неверный токен авторизации |
| `403` без поля `code` | Нет заголовка `Authorization: Bearer <токен>` |
| `403` с `"code": "feature_disabled"` | Функция не подключена для вашего аккаунта. Чтобы подключить — обратитесь в поддержку |
| `413` | Сумма символов во всех текстах больше 100 000 — разбейте текст на несколько запросов |
| `422` | Некорректное тело: нет ни `text`, ни `texts` или указаны оба; больше 100 текстов; один текст длиннее 100 000 символов; неверное значение `level` / `mask`; неизвестное поле |
| `429` | Превышен лимит частоты или сервис занят — повторите через `Retry-After` секунд |

```json theme={null}
{ "detail": "...", "code": "feature_disabled" }
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.