API и интеграция с CRM

Полный цикл без ручной работы: ваша система сама выпускает код на съёмку, узнаёт о снятом материале и программно проверяет подлинность файла. Подходит для CRM, систем учёта заявок, 1С и no-code-платформ.

Доступ Сценарий Коды на съёмку Проверка файла Вебхуки Рецепты для CRM Расписание Ошибки

Доступ: один ключ на всё

API-ключ создаётся в личном кабинете, раздел «Интеграции и API» — самостоятельно, без обращения в поддержку. Ключ показывается один раз в момент создания; если потеряли — отзовите его там же и создайте новый.

Ключ передаётся в заголовке X-Api-Key в каждом запросе. Один и тот же ключ работает для всех операций ниже.

БазаЧто там
https://api.trustvisor.ruКоды на съёмку, статусы, вебхуки — всё под /v1/business/…
https://portal.trustvisor.ruПроверка файлов — /v1/verify

Типовой сценарий (страховая, СТО, логистика — любой)

1. В CRM создаётся заявка → CRM вызывает наш API и получает код на съёмку, привязанный к номеру заявки.
2. Код уходит исполнителю (СМС, мессенджер — как вы обычно общаетесь).
3. Исполнитель вводит код в приложении TrustVisor и снимает.
4. В момент съёмки мы шлём вебхук на ваш адрес (или CRM опрашивает статус кода) → заявка двигается по воронке сама.
5. Полученный файл CRM отправляет на проверку — вердикт о подлинности возвращается за секунды и сам записывается в журнал панели.

Коды на съёмку

Выпустить код

POST https://api.trustvisor.ru/v1/business/case-codes

curl -X POST https://api.trustvisor.ru/v1/business/case-codes \
  -H "X-Api-Key: ваш_ключ" \
  -H "Content-Type: application/json" \
  -d '{"case_id": "ОСАГО-4712", "max_videos": 2, "max_photos": 10}'

Поля запроса (обязателен только case_id — ваш номер заявки/сделки, до 64 символов):

ПолеОписание
case_idНомер вашей заявки — по нему код виден в панели и в вебхуках
object_nameОбъект — адрес, номер точки или склада, до 120 символов. Виден в панели, в отчёте, акте, реестре и исполнителю на странице съёмки по ссылке
template_idШаблон отчёта компании (см. ниже): поля, которых нет в запросе, — пункты, срок, требования к съёмке, объект — берутся из него
assign_toПостоянный ключ сотрудника вашей компании (TV-…). Код становится его заданием: сотрудник видит заявку в приложении в «Заданиях» и снимает без ввода кода. В ответе — assigned_to; ключ другой компании — 404, недействующий — 422
due_at или due_in_hoursСрок сдачи: момент в ISO 8601 (с поясом — приводится к UTC; без пояса — считается UTC) или «через N часов», от 1 до 720. Не раньше чем через 5 минут и не дальше 30 дней. Не сдано к сроку — заявка помечается «просрочено» и приходит вебхук overdue
max_videos, max_photosЛимиты съёмки. Не передали — подставляется потолок 10 видео / 30 фото; значение выше потолка молча уменьшается до него, «без лимита» не бывает
quality, ratioТребования к съёмке (качество, соотношение сторон)
gps_modeТребование геометки
require_onlinetrue — съёмка только при живой связи с сервером
max_duration_secondsМаксимальная длительность видео

Ответ: {"key": "TV-XXXX-XXXX", "case_id": "…", "object_name": "…", "due_at": "…", "expires_at": "…", …}. Код живёт 24 часа до первого ввода в приложение; дальше срок отсчитывается от активации. Если задан срок сдачи, код действует до него — но не меньше 24 часов от выдачи и от первого ввода.

Узнать статус

GET https://api.trustvisor.ru/v1/business/case-codes/TV-XXXX-XXXX — один код, или без ключа в пути — все коды разом.

{
  "key": "TV-XXXX-XXXX",
  "case_id": "ОСАГО-4712",
  "state": "in_use",      // unused | in_use | expired
  "captured": true,        // съёмка состоялась
  "received": false,       // вы отметили файл полученным
  "object_name": "Склад №5",
  "due_at": "2026-10-03T12:00:00",  // UTC; null — срока нет
  "due_state": null,     // после срока: on_time | overdue
  "overdue": false,       // к сроку не снято, чек-лист не закрыт или висело «доснять»
  "videos_used": 1, "max_videos": 2, …
}

Отметить, что файл дошёл до вас: POST /v1/business/case-codes/TV-XXXX-XXXX/mark-received.

Проверка файла

POST https://portal.trustvisor.ru/v1/verify — multipart/form-data, файл в поле package.

curl -X POST https://portal.trustvisor.ru/v1/verify \
  -H "X-Api-Key: ваш_ключ" \
  -F "package=@REC_20260622_0702.trustvisor"

Код 200 и JSON — если проверка вообще состоялась (в том числе если файл оказался поддельным — это тоже успешный результат проверки, не ошибка запроса). Каждая проверка автоматически попадает в журнал «Проверки» вашей панели.

TRUSTED_CAPTURE — файл подлинный, устройство аппаратно подтверждено. Наивысший уровень доверия.
UNVERIFIED_DEVICE — подпись и содержимое верны, но устройство не прошло аппаратную проверку (эмулятор или очень старый телефон). Файл не изменён, но происхождение с конкретной камеры не доказано.
TIME_UNCONFIRMED — подпись, содержимое и устройство подтверждены, но не подтверждён момент съёмки: истёк срок подтверждения от сервера (телефон был без связи дольше срока, заданного в панели: «Ключи сотрудников» → «Съёмка без связи», по умолчанию 12 часов), либо часы телефона разошлись с сервером или со спутниковым временем. Не выносится, если приложение записало привязку к серверному времени (см. поле momentSource): тогда момент известен точно при любой длительности без связи. Уровень доверия как у UNVERIFIED_DEVICE; письмо на почту — по тому же переключателю.
Момент съёмки в ответе. moment — момент съёмки в миллисекундах UTC; momentSource — откуда он: anchor (привязка к серверному времени: приложение считает момент от последней связи по счётчику загрузки телефона, часы телефона не участвуют), token (часы телефона в границах серверного подтверждения) или device (только часы телефона). offlineHours — сколько часов телефон был без связи до съёмки (по привязке). deviceClockShiftMin — на сколько минут часы телефона расходились с сервером в момент съёмки (перевод часов виден здесь, на вердикт не влияет). locationMock — во время съёмки работало приложение подмены местоположения; его данные отброшены, координат в файле нет. checks.locationNet — второе мнение о месте (приложение 1.4): координаты по сотовой сети и Wi-Fi против спутниковых; расхождение больше суммы точностей и двух километров — признак подмены сигнала, вердикт UNVERIFIED_DEVICE с причиной location; без покрытия или без спутникового фикса — skip. checks.gnssPortrait — портрет спутникового сигнала (приложение 1.4): спутников в фиксе, созвездия, сила сигнала и её разброс, диапазоны, уровень усиления; сочетание двух и более признаков передатчика (одно созвездие при шести и более спутниках, разброс сигнала меньше 1,5 дБ, ровный и очень сильный сигнал) — причина location, вердикт UNVERIFIED_DEVICE; один признак — только пометка в отчёте. Файлы приложения до версии 1.4 привязки не несут: momentSource у них token или device.
TAMPERED — файл повреждён, изменён после съёмки или подпись не сходится. Доверять нельзя.

Загруженный файл не хранится на сервере дольше самой проверки. Бесплатный браузерный верификатор на trustvisor.ru остаётся доступен без ключа — он работает целиком в браузере и в журнал панели не пишет.

Вебхуки: события в вашу систему

Вместо опроса статусов мы сами отправим POST-запрос на ваш адрес. Вебхук создаётся в панели («Интеграции и API»). По API его создать нельзя: это настройка компании, ей нужен вход в кабинет — API-ключ её не открывает (ответ 403 api_key_not_allowed_here).

Ответ содержит secret — ключ подписи, показывается один раз.

СобытиеКогда приходитТело (JSON)
capturedПервая завершённая съёмка по кейс-коду{"event":"captured","at":"…","key":"TV-…","case_id":"…"}
verifiedПроверка пакета записана в журнал (из панели, по API, при загрузке по коду или при съёмке по ссылке; source: dashboard, api, upload, web-link){"event":"verified","at":"…","verdict":"TAMPERED","file_name":"…","source":"api"}
acceptedСнимок принят в кабинете (при хранении фото для приёмки){"event":"accepted","at":"…","media_id":42,"key":"TV-…","case_id":"…","checklist_index":1,"checklist_item":"…","reason":null,"verdict":"TRUSTED_CAPTURE"}
reworkСнимок отправлен на доснятие; в reason — что доснять словами сотрудника. Пересъёмка пункта закрывает «доснять» сама{"event":"rework","at":"…","media_id":42,"key":"TV-…","case_id":"…","checklist_index":1,"checklist_item":"…","reason":"Номер не читается","verdict":"TRUSTED_CAPTURE"}
overdueЗаявка не сдана к сроку due_at: к сроку не было съёмки, чек-лист не закрыт или висело «доснять». Один раз на код, в течение 15 минут после срока{"event":"overdue","at":"…","key":"TV-…","case_id":"…","object_name":"…","due_at":"…","captured":false,"checklist_total":3,"checklist_done":1}
schedule_pausedРасписание заданий встало на паузу: ключ сотрудника не действует или шаблон удалён. Задания по нему больше не выпускаются, пока расписание не включат снова{"event":"schedule_paused","at":"…","schedule_id":7,"template_id":3,"template_name":"Уборка офиса","assign_to":"TV-…","assignee":"Иванов","reason":"assignee_inactive","reason_text":"ключ сотрудника не действует"}
testТолько по кнопке «Тест» в панели; в список events его не включают — сервер такое значение отбрасывает{"event":"test","at":"…"}

Подпись и повторы

Каждый запрос несёт заголовки X-TrustVisor-Event, X-TrustVisor-Delivery (номер доставки) и X-TrustVisor-Signature: sha256=<hex> — HMAC-SHA256 сырого тела запроса вашим секретом. Проверка на Python:

import hashlib, hmac
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
ok = hmac.compare_digest(expected, request.headers["X-TrustVisor-Signature"])

Ответьте любым кодом 2xx за 6 секунд. Не успели/упали — повторим до 6 раз с нарастающими интервалами (1 мин → 5 мин → 30 мин → 2 ч → 6 ч). Обрабатывайте события идемпотентно: при повторе X-TrustVisor-Delivery тот же.

Ограничения: до 5 вебхуков на компанию; адрес — только внешний https/http (локальные и внутренние адреса не принимаются).

Рецепты для CRM

Битрикс24

Без разработки: роботы Битрикс24 умеют слать исходящие вебхуки, но не умеют добавлять свой заголовок X-Api-Key — поэтому прямой вызов нашего API из робота не собрать. Рабочие пути:

amoCRM

Salesbot / digital pipeline умеют шаг «отправить вебхук» — тоже без своих заголовков, поэтому схема та же: связка через no-code-платформу или свой мини-обработчик, который держит ключ и ходит в наш API.

1С

Из 1С наш API вызывается штатно, без посредников:

Соединение = Новый HTTPСоединение("api.trustvisor.ru",,,,, Новый ЗащищённоеСоединениеOpenSSL);
Запрос = Новый HTTPЗапрос("/v1/business/case-codes");
Запрос.Заголовки.Вставить("X-Api-Key", Ключ);
Запрос.Заголовки.Вставить("Content-Type", "application/json");
Запрос.УстановитьТелоИзСтроки("{""case_id"": ""ЗАКАЗ-1042""}");
Ответ = Соединение.ОтправитьДляОбработки(Запрос);

Albato, ApiX-Drive, n8n, Make

Любая платформа связок с шагом «HTTP-запрос с заголовками» подключается за вечер: шаг 1 — триггер вашей CRM, шаг 2 — POST к нам с X-Api-Key, шаг 3 — записать key из ответа в поле сделки. Входящие вебхуки от нас эти платформы принимают штатным триггером «Webhook».

Свой сайт или внутренняя система

Просто HTTP: выпуск кода — один POST, проверка файла — один POST, события — вебхук. Примеры на curl и JavaScript выше подходят без изменений.

Шаблоны отчётов

Шаблон — запись компании: название, пункты чек-листа, срок «через N часов», качество, формат, GPS, лимиты, объект по умолчанию. Его видят все менеджеры компании в кабинете и ваша CRM по API.

ЗапросЧто делает
GET /v1/business/templatesСписок шаблонов компании
POST /v1/business/templatesСоздать: {"name": "Уборка офиса", "checklist": ["Общий вид", "Пол"], "due_in_hours": 24, "quality": "FHD", "object_name": "…"}; до 100 шаблонов
PUT /v1/business/templates/{id}Заменить поля шаблона
DELETE /v1/business/templates/{id}Убрать в архив — уже выпущенные по нему коды не меняются
PUT /v1/business/keys/{key}/labelИмя ключа сотрудника: {"label": "Иванов, бригада 2"} — видно в кабинете, архиве, реестре и акте

Выпуск по шаблону — POST /v1/business/case-codes с template_id; задание сотруднику — тот же запрос с assign_to. В архиве и списке кодов у такого кода — assigned_to, в архиве можно отобрать заявки одного исполнителя (?assignee=TV-…).

Задания по расписанию

Расписание выпускает задание по шаблону сотруднику само — в выбранные дни недели и время по местному часу. Одно задание на день; пропущенные дни не догоняются. Номер заявки — имя шаблона и дата («Уборка офиса · 01.10.2026»), у кода — schedule_id. Ключ сотрудника не действует или шаблон удалён — расписание встаёт на паузу, приходит вебхук schedule_paused и письмо.

ЗапросЧто делает
GET /v1/business/schedulesСписок расписаний: у каждого next_run (UTC) и next_run_local (по поясу расписания), last_issued_on, last_key, на паузе — paused_reason. Там же tz_choices — допустимые пояса
POST /v1/business/schedulesСоздать: {"template_id": 3, "assign_to": "TV-…", "weekdays": [1,2,3,4,5], "time": "08:00", "tz": "Europe/Moscow", "object_name": "…", "starts_on": "2026-10-01", "ends_on": null}. weekdays — 1 (пн) … 7 (вс); пояса — от Europe/Kaliningrad до Asia/Kamchatka; до 200 расписаний
PUT /v1/business/schedules/{id}Заменить поля; "active": false — пауза, true — включить (только с действующим ключом сотрудника и живым шаблоном)
DELETE /v1/business/schedules/{id}Убрать в архив — уже выпущенные задания не меняются

Что ещё есть в API

Точки, которых раньше не было в этой документации. Хост у проверки файла — тот же, что у /v1/verify (портал), у остального — api.trustvisor.ru.

ТочкаЧто делаетДоступ
POST /v1/verify-by-code?code=TV-…Проверка файла по коду заявки — без API-ключа и без входа. Файл в поле package, multipart. Удобно отдать исполнителю или подрядчику: страница /upload.html на портале делает то же самое из браузерасам код заявки
GET /v1/business/case-codes/{key}/reportОтчёт по заявке: состояние кода, съёмки, проверки. При хранении фото для приёмки — ещё media (снимки заявки: вердикт, время, пункт чек-листа, решение review_status и причина review_reason, пометки dup_case_id — этот же снимок уже сдавался в другой заявке, other_case_id — снят для другой заявки, before_issue — снят раньше, чем выдан код) и rework (пункты «доснять» с причинами). Самих снимков, координат и устройства по API-ключу нет — только в кабинетеAPI-ключ
Акт по заявке (PDF), реестр за период (Excel)Акт — компания, заявка, объект, сроки, по пунктам — решения и их история, превью, время и место съёмки, отпечатки для сверки в открытом реестре. Реестр — лист «Заявки» и лист «Снимки» за выбранный период. Время — по МосквеТолько в кабинете
checklist в теле выпуска кодаСписок пунктов, которые исполнитель отмечает в приложении по ходу съёмки; отметки видны в панели и в отчёте—
GET /v1/business/delivery, GET /v1/business/uploadsНастройки доставки и список присланных файлов. Режима доставки два: none — файл остаётся на телефоне, и transit — файл проверяется у нас и тут же уходит в Яндекс.Диск компании, в папку /TrustVisor. Отдельно — хранение фото для приёмки: компания включает его в кабинете на 7, 30 или 90 дней. Фото и кадры-превью видео видны в кабинете в течение срока; решения по снимкам приходят вебхуками accepted («принято») и rework («доснять», с причиной). Видео мы не храним. В ответе — вердикт, отпечаток и путь на вашем Диске, самого файла нет. Поле transit_format задаёт, что именно туда кладётся: package — пакет .trustvisor, media — обычный MP4, PNG или JPEG с подписью внутри (открывается любым плеером и проходит проверку), both — оба файла рядом. Менять настройки — только из кабинетаAPI-ключ — чтение

Ошибки

КодЗначение
401Не передан X-Api-Key, либо ключ неверный/отозван
400Запрос не удалось разобрать; для вебхуков — недопустимый адрес или превышен лимит 5 вебхуков
402/403 client_plan_requiredКоды на съёмку доступны только на тарифе Business
403 api_key_not_allowed_hereОперации нужен вход в личный кабинет — API-ключ её не открывает: покупка ключей, настройка доставки, удаление застрявшего файла, создание и удаление вебхуков, история платежей
404Код или вебхук не найден (или принадлежит другой компании)
413Файл слишком большой
422Файл отклонён как подозрительный до полной проверки
429Превышен лимит запросов: выпуск кодов — 30/мин; все точки портала, включая проверку файла, — 20 запросов/мин с одного адреса

Нужна помощь с интеграцией — напишите на info@trustvisor.ru, поможем собрать связку под вашу систему.