App Activity API v1
Emperor забирает зарегистрированных пользователей и дневную активность из приложений по общему контракту. Источник (приложение) сохраняется, повторная синхронизация обновляет данные. Один человек из нескольких приложений не создаёт дубль Person.
Страница для команд, которые реализуют контракт. Машиночитаемая спецификация OpenAPI 3.1: спецификация App Activity API.
v1 — черновик, может меняться до финализации. После финализации несовместимые изменения выходят как /v2.
Ресурсы
Приложение отдаёт три GET-ресурса под /v1 относительно URL App Activity API:
/v1/manifest— версия контракта (1), название приложения, IANA часовой пояс агрегации дней и каталог ключей активности с подписями./v1/users— пользователи. Запрос:updatedSince,cursor,limit./v1/activity— дневные агрегаты: одна строка на пользователя, день и ключ из каталога. Те же параметры запроса, что у users.
Если contractVersion не 1, Emperor отклоняет подключение с явной ошибкой.
Курсоры и перезапись активности
updatedSince — datetime ISO-8601 со смещением или Z. Нужно отдать записи с updatedAt больше или равным этому значению. Без параметра — полная выгрузка. cursor — непрозрачная строка из nextCursor предыдущей страницы. limit по умолчанию 100, максимум 100.
Ответ списка: { "data": [...], "nextCursor": null | string }. nextCursor равен null на последней странице.
Поздняя строка активности для той же корзины (externalUserId, day, metricKey) перезаписывает сохранённый счётчик. Приложение отдаёт дневные итоги, а не сырые события.
Email или телефон
У каждой записи должен быть email, phone (E.164, например +79991234567) или оба. Запись без того и другого контракт отклоняет. В статистике синхронизации она учитывается как отклонённая, Person не создаётся.
Как Emperor склеивает контакты
Человек в CRM — Person. Email и телефон — контакты. Идентичность в приложении живёт на отдельной связке: один человек — несколько приложений.
- Email нормализуется (trim и нижний регистр). Телефон хранится в E.164.
- Уже связанная идентичность (
LINKED) обновляет срез и активность. Имя Person не перезаписывается. - Отклонённая идентичность не сопоставляется.
- Новая идентичность без совпадений по email или телефону создаёт Person и контакты email / телефон.
- Любое совпадение с существующим Person, включая конфликт email/телефона или второе приложение с тем же email, уходит в
PENDING_REVIEW. Второго Person нет, автослияния нет.
Проверка совпадений
Откройте CRM → Совпадения из приложений. Очередь — совпадения, ожидающие проверки. В строке видны срез профиля из приложения, email и телефон, кандидаты Person и причина (совпадение email, телефона, обоих или конфликт email/телефона).
Сравните входящие данные с контактами и приложениями каждого кандидата и выберите одно действие:
- Привязать к выбранному кандидату. Недостающие email и телефон дописываются как контакты. Идентичность становится
LINKED. Второй Person не создаётся, имя Person не меняется. - Создать нового Person — так же, как при синхронизации без совпадений. Идентичность становится
LINKED. - Отбросить. Идентичность становится
DISCARDED. Следующая синхронизация не вернёт её в очередь. Emperor сохраняет, кто и когда решил.
Чек-лист подключения
- В production публиковать
/v1/manifest,/v1/usersи/v1/activityтолько по HTTPS. - Выдать Bearer-токен с высокой энтропией на связку проект–приложение, только чтение App Activity API. Не использовать общий ключ сервиса.
- Сравнивать токен за постоянное время. Запрос без валидного Bearer —
401в RFC 7807application/problem+json. Не различать «токена нет» и «токен неверен». - Принимать
User-Agent: Emperor-AppProvider/1.0иX-Request-Id(UUID). Тот же id возвращать в problem-документе при ошибке. - При
429отдаватьRetry-After. - Ротация: в окне ротации принимать текущий и предыдущий токен, затем отозвать старый.
Подключение приложения в Emperor
В Development-проекте откройте Приложения (быстрое действие или настройки проекта). Привяжите существующую публикацию с соединением App Activity API или создайте новую публикацию (имя, UID, домен, сервер, URL API активности приложения, токен). Токен только на запись: дальше UI показывает отпечаток.
На экранах редактирования и просмотра публикации блок Активность приложения хранит этот URL и токен. Просмотр показывает URL целиком (не «Настроен») и отпечаток токена.
Проверить вызывает GET {baseUrl}/v1/manifest. Синхронизировать в строке или Синхронизировать все выгружает users, затем activity в том же HTTP-запросе (не дольше пяти минут). Отвязка снимает связку с проектом и курсоры; публикация остаётся.
Emperor хранит соединение, курсоры синхронизации и журнал запусков. Синхронизация сразу сопоставляет идентичности: без совпадения создаётся Person; любое совпадение уходит в очередь проверки.
На карточке Person блок Приложения показывает связанные идентичности, даты регистрации и последнего визита и активность за выбранный период и метрику. В списке контактов CRM можно отфильтровать людей с связанной идентичностью выбранного приложения.
Ограничения
- Запрос синхронизации дольше пяти минут останавливается.
- Если синхронизация зависла и отвечает HTTP
409, в строке Приложения кнопка Снять блокировку завершает запуск какFAILEDбез сдвига курсоров. После этого снова Синхронизировать. - Активность пользователя, отклонённого из‑за отсутствия email и телефона, не вернётся после исправления профиля, пока у этой строки активности не изменится
updatedAt. Полная повторная выгрузка — отвязать и привязать приложение снова.
Безопасность и аудит-лог приложения
v1 — HTTPS и Bearer-токен на связку проект–приложение.
Рекомендуется на каждый запрос App Activity API писать время, исходящий IP, X-Request-Id, User-Agent, ресурс (manifest / users / activity), updatedSince, HTTP-статус и число отданных записей. Не писать токен, заголовок Authorization, email, телефон и тела ответов.
Также: отдельный токен только для этого API; rate limit; алерты на пачку 401, чужой User-Agent, неожиданный IP, резкий рост объёма. IP allowlist не требовать: исходящие адреса Emperor не сводятся к одному фиксированному IP.