Назад на Главную страницу

Руководство по API Редакто

Практическое руководство по размещенной тестовой среде API для внешних интеграторов. Точные схемы, enum-значения и примеры ответов зафиксированы в Swagger и OpenAPI JSON.

Тестовая среда предназначена только для синтетических тестовых данных. Не отправляйте реальные персональные данные, реальные документы, реальные JWT, реальные словари восстановления или боевые данные запроса.

Получение API ключа

API ключ тестовой среды выдается через блок «Тестовая среда API для интеграторов» на Главной странице. Форма запрашивает email, подтверждение синтетических тестовых данных и подтверждение политики обработки персональных данных. После проверки кода из письма исходный API ключ показывается один раз.

Ключ используется только на домене тестовой среды API, а не на основном домене лендинга. Если ключ потерян, получите новый ключ через тот же сценарий выдачи.

Базовый URL

Все рабочие запросы тестовой среды отправляются на отдельный сервис:

export REDACTO_API_BASE='https://sandbox-api.redactoapp.ru'
export REDACTO_SANDBOX_API_KEY='rdx_sbx_<keyId>_<secret>'

REDACTO_API_BASE хранит адрес API, а REDACTO_SANDBOX_API_KEY хранит API ключ, который вы получили на Главной странице. Эти переменные действуют только в текущем окне терминала; в новом окне их нужно задать повторно.

Схемы и полный список endpoint-ов доступны в Swagger. JSON-источник спецификации: openapi/redacto-sandbox.v1.openapi.json.

Подготовка терминала

Перед выполнением примеров задайте переменные и проверьте утилиты для удобного вывода. jq форматирует JSON, а unzip показывает содержимое ZIP-ответа файлового endpoint-а.

export REDACTO_API_BASE='https://sandbox-api.redactoapp.ru'
export REDACTO_SANDBOX_API_KEY='rdx_sbx_<keyId>_<secret>'

jq --version
unzip -v | head -n 1

Если jq не установлен, API все равно работает, но JSON будет выводиться одной длинной строкой. В примерах ниже вариант с | jq нужен только для удобного просмотра ответа.

Авторизация

Рабочие endpoint-ы используют схему OpenAPI SandboxBearer. Передавайте API ключ как Bearer token в заголовке Authorization.

Authorization: Bearer rdx_sbx_<keyId>_<secret>
Сценарий Требование
/v1/anonymize/* Нужна область доступа redacto.anonymize.
/v1/restore/* Нужна область доступа redacto.restore.
GET /v1/entity-types Авторизация не нужна, квота ключа не расходуется.
/healthz, /readyz Служебные проверки доступны без API ключа.

Лимиты тестовой среды

Ограничение Значение по умолчанию
Срок ключа 3 дня
Запросов в час 10
Запросов всего 50
Максимальное тело запроса 2 MB
Поддерживаемые форматы файлов .txt, .csv, .docx, .xlsx, .pptx

При превышении почасового или общего лимита API возвращает 429 {"error":"quota_exceeded"}. При превышении размера запроса возвращается 413 {"error":"body_too_large"}.

Быстрый старт

Минимальная проверка: сначала убедитесь, что задан базовый URL и API ключ, затем запросите готовность среды выполнения и отправьте синтетический текст на анонимизацию.

Команда для проверки готовности:

export REDACTO_API_BASE='https://sandbox-api.redactoapp.ru'
export REDACTO_SANDBOX_API_KEY='rdx_sbx_<keyId>_<secret>'

curl -fsS "$REDACTO_API_BASE/readyz" | jq

Ответ на команду готовности:

{
  "ok": true
}

Следующая команда отправляет синтетический текст на анонимизацию:

curl -fsS "$REDACTO_API_BASE/v1/anonymize/text" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- <<'JSON' | jq
{
  "text": "Почта synthetic-buyer@example.test",
  "enableNer": false
}
JSON

Ответ на команду анонимизации будет JSON с maskedText, dictionary и кратким report:

{
  "maskedText": "Почта [EMAIL_1]",
  "dictionary": {
    "encrypted": false,
    "mapping": {
      "[EMAIL_1]": "synthetic-buyer@example.test"
    }
  },
  "report": {
    "totalFindings": 1,
    "maskedCount": 1,
    "dictionaryEntries": 1
  }
}

Словарь восстановления содержит исходные значения и должен храниться как чувствительный артефакт.

Текстовая анонимизация и восстановление

Перед выполнением примеров задайте REDACTO_API_BASE и REDACTO_SANDBOX_API_KEY, как показано в разделе подготовки терминала. POST /v1/anonymize/text принимает JSON. Поле text обязательно. Поля enableNer, dictionaryPassword и policy опциональны.

curl -fsS "$REDACTO_API_BASE/v1/anonymize/text" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- <<'JSON' | jq
{
  "text": "Почта synthetic-buyer@example.test\nТелефон +7 (111) 111-11-11",
  "enableNer": false,
  "dictionaryPassword": "",
  "policy": {
    "entityTypes": ["EMAIL", "PHONE"]
  }
}
JSON

Если нужно сохранить полный ответ и отдельно посмотреть замаскированный текст:

curl -fsS "$REDACTO_API_BASE/v1/anonymize/text" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- <<'JSON' > /tmp/redacto-text-response.json
{
  "text": "Почта synthetic-buyer@example.test\nТелефон +7 (111) 111-11-11",
  "enableNer": false,
  "dictionaryPassword": "",
  "policy": {
    "entityTypes": ["EMAIL", "PHONE"]
  }
}
JSON

Команды для просмотра сохраненного ответа:

jq -r '.maskedText' /tmp/redacto-text-response.json
jq '.report' /tmp/redacto-text-response.json

Вывод будет выглядеть так:

Почта [EMAIL_1]
Телефон [PHONE_1]

Краткий отчет из report:

{
  "totalFindings": 2,
  "maskedCount": 2,
  "dictionaryEntries": 2
}

Пример полного успешного JSON-ответа:

{
  "maskedText": "Почта [EMAIL_1]\nТелефон [PHONE_1]",
  "dictionary": {
    "version": 1,
    "generator": "Redacto",
    "sourceFilename": "text.txt",
    "maskedFilename": "text.sanitized.txt",
    "encrypted": false,
    "mapping": {
      "[EMAIL_1]": "synthetic-buyer@example.test",
      "[PHONE_1]": "+7 (111) 111-11-11"
    }
  },
  "report": {
    "totalFindings": 2,
    "maskedCount": 2,
    "dictionaryEntries": 2
  }
}

POST /v1/restore/text восстанавливает текст по словарю из предыдущего ответа.

curl -fsS "$REDACTO_API_BASE/v1/restore/text" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- <<'JSON' | jq -r '.text'
{
  "text": "Почта [EMAIL_1]\nТелефон [PHONE_1]",
  "dictionary": {
    "version": 1,
    "generator": "Redacto",
    "encrypted": false,
    "mapping": {
      "[EMAIL_1]": "synthetic-buyer@example.test",
      "[PHONE_1]": "+7 (111) 111-11-11"
    }
  },
  "dictionaryPassword": ""
}
JSON

Ожидаемый вывод:

Почта synthetic-buyer@example.test
Телефон +7 (111) 111-11-11

Файловый ZIP-сценарий

Перед файловыми примерами задайте REDACTO_API_BASE и REDACTO_SANDBOX_API_KEY. Для просмотра результата нужен unzip. POST /v1/anonymize/file принимает multipart/form-data и возвращает бинарный ZIP. ZIP содержит анонимизированный файл и связанный *.dict.json.

printf 'Почта synthetic-buyer@example.test\nТелефон +7 (111) 111-11-11\n' > /tmp/redacto-synthetic.txt

curl -fsS "$REDACTO_API_BASE/v1/anonymize/file" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -F 'file=@/tmp/redacto-synthetic.txt;type=text/plain' \
  -F 'policy={"entityTypes":["EMAIL","PHONE"]}' \
  -F 'dictionaryPassword=' \
  -o /tmp/redacto-synthetic.sanitized.zip

unzip -l /tmp/redacto-synthetic.sanitized.zip

Вывод unzip -l должен показать два файла:

redacto-synthetic.sanitized.txt
redacto-synthetic.sanitized.dict.json

Чтобы быстро проверить содержимое словаря без вывода всего файла:

unzip -p /tmp/redacto-synthetic.sanitized.zip redacto-synthetic.sanitized.dict.json \
  | jq '.report? // {mappingSize: (.mapping | length)}'

POST /v1/restore/file принимает анонимизированный файл и словарь восстановления. Ответом будет восстановленный бинарный файл с подходящим Content-Type.

unzip -o /tmp/redacto-synthetic.sanitized.zip -d /tmp/redacto-synthetic-result

curl -fsS "$REDACTO_API_BASE/v1/restore/file" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -F 'file=@/tmp/redacto-synthetic-result/redacto-synthetic.sanitized.txt;type=text/plain' \
  -F 'dictionary=@/tmp/redacto-synthetic-result/redacto-synthetic.sanitized.dict.json;type=application/json' \
  -F 'dictionaryPassword=' \
  -o /tmp/redacto-synthetic.restored.txt

Проверка восстановленного текстового файла:

cat /tmp/redacto-synthetic.restored.txt

Ожидаемый вывод:

Почта synthetic-buyer@example.test
Телефон +7 (111) 111-11-11

JSON-режим для сервисных клиентов

Файловые endpoint-ы также принимают JSON с contentBase64. Этот режим удобен для сервисных интеграций и автотестов, но ответ /v1/anonymize/file все равно остается ZIP.

curl -fsS "$REDACTO_API_BASE/v1/anonymize/file" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- \
  -o /tmp/redacto-synthetic.sanitized.zip <<'JSON'
{
  "filename": "redacto-synthetic.txt",
  "contentBase64": "0J/QvtGH0YLQsCBzeW50aGV0aWMtYnV5ZXJAZXhhbXBsZS50ZXN0",
  "dictionaryPassword": "",
  "policy": {
    "entityTypes": ["EMAIL"]
  }
}
JSON

После JSON-запроса проверка такая же, как для multipart: unzip -l /tmp/redacto-synthetic.sanitized.zip.

policy.entityTypes

policy.entityTypes работает как список разрешенных типов для конкретного запроса: API обрабатывает только указанные типы, а остальные типы не ищет. Серверные обязательные типы могут быть добавлены обратно настройкой сервера и не отключаются политикой запроса.

Минимальный фрагмент JSON-политики:

{
  "policy": {
    "entityTypes": ["EMAIL", "PHONE"]
  }
}

Проверить такую политику на синтетическом тексте можно отдельным запросом. В ответе удобно смотреть только maskedText и report.

curl -fsS "$REDACTO_API_BASE/v1/anonymize/text" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- <<'JSON' | jq '{maskedText, report}'
{
  "text": "Почта synthetic-buyer@example.test, телефон +7 (111) 111-11-11, договор № SYN-42",
  "enableNer": false,
  "policy": {
    "entityTypes": ["EMAIL", "PHONE"]
  }
}
JSON

Ожидаемый вывод показывает, что маскируются только email и телефон; номер договора остается открытым, потому что CONTRACTNO не указан в списке разрешенных типов.

{
  "maskedText": "Почта [EMAIL_1], телефон [PHONE_1], договор № SYN-42",
  "report": {
    "totalFindings": 2,
    "maskedCount": 2,
    "dictionaryEntries": 2
  }
}

Чтобы отключить один тип из набора по умолчанию, передайте полный список типов, которые должны остаться включенными. Актуальный enum смотрите в Swagger или получайте через GET /v1/entity-types.

Каталог сущностей

GET /v1/entity-types возвращает каталог допустимых значений для policy.entityTypes, русские и английские названия, группы интерфейса, набор по умолчанию и обязательные серверные типы.

Сущность Название Описание По умолчанию
PERSON ФИО Имена людей, ФИО и персональные подписи. Включена
ORG Организация Названия компаний, учреждений и организаций. Включена
BANK Банк Названия банков и банковских организаций. Включена
ADDRESS Адрес Почтовые адреса, населенные пункты, улицы и адресные строки. Включена
EMAIL Email Адреса электронной почты. Включена
SITE Сайт Сайты, домены и URL-адреса. Включена
IP_ADDRESS IP-адрес IPv4, IPv6 и совместимые IP-адреса. Включена
MAC_ADDRESS MAC-адрес Аппаратные MAC-адреса сетевых устройств. Включена
PHONE Телефон Телефонные номера в российских и международных форматах. Включена
PRICE Цена / сумма Денежные суммы с валютой или сильной ценовой меткой. Включена
NDS Сумма НДС Денежные суммы налога на добавленную стоимость. Включена
DOB Дата рождения Даты рождения в анкетах, паспортах и похожих блоках. Включена
CARD Банковская карта Номера банковских карт. Включена
CRYPTO Bitcoin-кошелек Bitcoin-адреса с проверкой контрольной суммы. Включена
PASSPORT Номер паспорта Номера паспортов РФ и загранпаспортов по явным меткам. Включена
PASSPORT_KZ Номер паспорта Казахстана Номера паспортов Казахстана. Включена
PASSPORT_AUTHORITY Орган выдачи паспорта Орган, выдавший паспорт, в паспортном блоке. Включена
PASSPORT_BIRTH_PLACE Место рождения Место рождения в паспортном блоке. Включена
PASSPORT_CITIZENSHIP Гражданство Гражданство в паспортном блоке. Включена
PASSPORT_ISSUE_DATE Дата выдачи паспорта Дата выдачи паспорта. Включена
PASSPORT_EXPIRY_DATE Срок действия паспорта Дата окончания срока действия паспорта. Включена
PASSPORT_DEPT_CODE Код подразделения паспорта Код подразделения в паспорте РФ. Включена
INN ИНН Идентификационные номера налогоплательщика. Включена
KPP КПП Коды причины постановки на учет. Включена
OKPO ОКПО Коды ОКПО по явной метке. Включена
OKTMO ОКТМО Коды ОКТМО по явной метке. Включена
SNILS СНИЛС Номера страхового свидетельства. Включена
LICENSE_PLATE Госномер ТС Государственные регистрационные номера транспортных средств. Включена
VIN VIN ТС Идентификационные номера транспортных средств. Включена
STS Номер СТС Номера свидетельств о регистрации транспортного средства. Включена
PTS Номер ПТС Номера паспортов транспортного средства. Включена
EPTS Номер ЭПТС Номера электронных паспортов транспортного средства. Включена
CADASTRAL_NUMBER Кадастровый номер Кадастровые номера объектов недвижимости. Включена
EGRN_REGISTRATION_NO Номер регистрации ЕГРН Номера записей о государственной регистрации права. Включена
LEGACY_REALTY_OBJECT_NO Условный / инвентарный номер Условные, инвентарные и ранее присвоенные номера объектов. Включена
POWER_OF_ATTORNEY_NO Номер доверенности Номера доверенностей по явному доверенному контексту. Включена
NOTARY_REGISTER_NO Нотариальный реестровый номер Номера нотариальных реестровых записей. Включена
DRIVER_LICENSE_NO Номер водительского удостоверения Номера водительских удостоверений. Включена
BIRTH_CERTIFICATE_NO Номер свидетельства о рождении Номера свидетельств о рождении. Включена
MCHD Машиночитаемая доверенность GUID машиночитаемой доверенности. Включена
POSTAL_TRACKING_NO Почтовый трек-номер Почтовые трек-номера по явному контексту отправления. Включена
CONTRACTNO Номер договора / контракта Номера договоров и контрактов по сильному договорному контексту. Выключена
OGRN ОГРН / ОГРНИП Основные государственные регистрационные номера организаций и ИП. Включена
RS Расчетный счет Расчетные счета в банковских реквизитах РФ. Включена
LS Лицевой счет Лицевые счета в реквизитах РФ. Включена
KS Корреспондентский счет Корреспондентские счета в банковских реквизитах РФ. Включена
BIK БИК Банковские идентификационные коды РФ. Включена
TREASURY_RS Казначейский счет Казначейские счета по явной метке. Включена
EKS Банковский счет (ЕКС) Единые казначейские счета. Включена
TOFK_BIK БИК ТОФК БИК территориального органа Федерального казначейства. Включена
IIN ИИН Индивидуальные идентификационные номера Казахстана. Включена
BIN БИН Бизнес-идентификационные номера Казахстана. Включена
IIK ИИК Индивидуальные идентификационные коды банковских счетов Казахстана. Включена
IBAN IBAN Международные номера банковских счетов. Включена
ISIN ISIN Международные идентификаторы ценных бумаг. Включена
KZ_BIK БИК банка Казахстана Банковские идентификационные коды Казахстана. Включена
KBE КБе Коды бенефициара в платежных реквизитах Казахстана. Включена
KNP КНП Коды назначения платежа в реквизитах Казахстана. Включена

Чтобы запросить каталог из терминала, сначала задайте базовый URL. Без форматирования API вернет JSON одной строкой; для удобного просмотра используйте jq.

export REDACTO_API_BASE='https://sandbox-api.redactoapp.ru'

curl -fsS "$REDACTO_API_BASE/v1/entity-types" | jq

Если нужен только список кодов и русских названий:

curl -fsS "$REDACTO_API_BASE/v1/entity-types" \
  | jq -r '.entityTypes[] | "\(.type)\t\(.title.ru)"'

Пример сокращенного JSON-ответа каталога:

{
  "schemaVersion": 24,
  "entityTypes": [
    {
      "type": "EMAIL",
      "title": {
        "ru": "Email",
        "en": "Email"
      },
      "defaultEnabled": true,
      "required": false,
      "groups": ["common.contacts"]
    }
  ],
  "defaultEntityTypes": ["PERSON", "ORG", "BANK", "ADDRESS", "EMAIL"],
  "defaultDisabledEntityTypes": ["CONTRACTNO"],
  "requiredEntityTypes": []
}

Словарь восстановления

dictionary и файл *.dict.json содержат карту маркер -> исходное значение. Это чувствительный артефакт того же класса, что исходный текст или файл.

Формат Когда используется
Незашифрованный JSON Режим по умолчанию для тестов и простых интеграционных проверок.
Зашифрованный конверт Если в запросе задан dictionaryPassword. Для восстановления нужно передать тот же пароль.

Для реальных корпоративных процессов используйте защищенное хранилище словарей, не пишите словари в логи и не передавайте их в системы, которым не нужен restore-сценарий.

Если вы сохранили ответ текстовой анонимизации в /tmp/redacto-text-response.json, структуру словаря можно проверить без вывода исходных значений:

jq '.dictionary | {encrypted, sourceFilename, maskedFilename, mappingSize: (.mapping | length)}' \
  /tmp/redacto-text-response.json

Ожидаемый вывод:

{
  "encrypted": false,
  "sourceFilename": "text.txt",
  "maskedFilename": "text.sanitized.txt",
  "mappingSize": 2
}

Коды ошибок

Ошибки возвращаются как JSON с полем error. Для бинарных endpoint-ов это правило применяется к ошибочным ответам. Для диагностических примеров ниже используется curl -sS без -f, чтобы curl не скрыл тело ожидаемой ошибки.

Пример запроса без Bearer token:

curl -sS "$REDACTO_API_BASE/v1/anonymize/text" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- <<'JSON' | jq
{
  "text": "Почта synthetic-buyer@example.test"
}
JSON

Ожидаемый ответ:

{
  "error": "auth_required"
}

Пример неподдерживаемого расширения файла:

curl -sS "$REDACTO_API_BASE/v1/anonymize/file" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- <<'JSON' | jq
{
  "filename": "synthetic.pdf",
  "contentBase64": "U1lOVEhFVElD"
}
JSON

Ожидаемый ответ:

{
  "error": "unsupported_format"
}
HTTP error Когда возникает
400 bad_json, bad_multipart Некорректный JSON или multipart-тело.
400 file_required, restore_payload_required Файловый endpoint вызван без обязательного файла или словаря.
400 restore_password_required Зашифрованный словарь передан без dictionaryPassword.
401 auth_required, auth_rejected Нет Bearer token, ключ поврежден, истек, отозван или не совпал хэш.
403 scope_required, feature_disabled, restore_wrong_password Нет нужной области доступа, фоновые задачи выключены или пароль словаря неверный.
404 not_found, job_not_found Endpoint или фоновая задача не найдены.
409 job_not_ready Результат фоновой задачи еще не готов.
413 body_too_large Тело запроса больше лимита тестовой среды.
415 unsupported_format, unsupported_media_type Неподдерживаемое расширение файла или Content-Type.
429 quota_exceeded Превышен почасовой или общий лимит ключа.
500 server_error Внутренняя ошибка без раскрытия данных запроса.

Фоновые задачи

Маршруты /v1/jobs/* описаны в Swagger для корпоративных сценариев с крупными Office-файлами и коротким временем ожидания HTTP-запроса. В публичной тестовой среде они выключены по умолчанию.

POST /v1/jobs/anonymize-file GET /v1/jobs/{jobId} GET /v1/jobs/{jobId}/result DELETE /v1/jobs/{jobId}

Команда использует те же REDACTO_API_BASE и REDACTO_SANDBOX_API_KEY. Здесь тоже используется curl -sS без -f, потому что ожидаемый результат публичной тестовой среды: ошибка 403 feature_disabled.

curl -sS "$REDACTO_API_BASE/v1/jobs/anonymize-file" \
  -H "authorization: Bearer $REDACTO_SANDBOX_API_KEY" \
  -H 'content-type: application/json; charset=utf-8' \
  --data-binary @- <<'JSON' | jq
{
  "filename": "redacto-synthetic.txt",
  "contentBase64": "0J/QvtGH0YLQsA=="
}
JSON

Ожидаемый ответ публичной тестовой среды:

{
  "error": "feature_disabled"
}

Безопасность интеграции

  • Не логируйте исходный текст, файлы, словари, ZIP-ответы, maskedText, API ключи и Bearer-заголовки.
  • Храните *.dict.json как секрет: словарь содержит исходные значения и позволяет выполнить восстановление.
  • Передавайте запросы только по HTTPS и задавайте время ожидания на стороне клиента для файловых операций.
  • Перед дальнейшей передачей ZIP проверяйте, что словарь сохранен в защищенном хранилище.
  • В тестовую среду отправляйте только синтетические данные и синтетические файлы.

Разбор неполадок

Все команды в руководстве предполагают предварительную настройку переменных из раздела «Подготовка терминала». Если команда возвращает пустой ответ или ошибку терминала, сначала проверьте echo "$REDACTO_API_BASE", echo "$REDACTO_SANDBOX_API_KEY", наличие jq и наличие unzip.

Симптом Проверка
401 auth_required Проверьте, что заголовок выглядит как Authorization: Bearer rdx_sbx_....
401 auth_rejected Ключ мог истечь, быть отозванным или поврежденным при копировании. Получите новый ключ.
403 scope_required У ключа нет области доступа для выбранного endpoint-а. Для тестовой среды стандартный ключ содержит redacto.anonymize и redacto.restore.
415 unsupported_format Проверьте расширение файла. Поддерживаются только .txt, .csv, .docx, .xlsx, .pptx.
Сущность не маскируется Проверьте policy.entityTypes и каталог GET /v1/entity-types. Если передан список разрешенных типов, остальные типы не обрабатываются.
Restore не возвращает исходный файл Используйте словарь из того же ZIP, что и анонимизированный файл, и передайте исходный dictionaryPassword, если словарь зашифрован.

Если нужна точная форма поля или ответа, сверяйтесь со Swagger: он использует тот же OpenAPI JSON, который хранится рядом со страницей.