Введение

Partner API Performance Hub позволяет внешним партнерским платформам беспрепятственно интегрироваться с основными модулями Performance Hub. API поддерживает компьютерное зрение, аналитику, регистрацию доступа участников и аналитику объектов.

Формат запросов

API принимает тела запросов в кодировке JSON и возвращает ответы в кодировке JSON.

Ограничение частоты запросов

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

  • 5 запросов в секунду на конечную точку
  • Рекомендуется: не более 1000 элементов в одном пакетном запросе для оптимальной производительности
  • Не более 10MB — размер полезной нагрузки

Ограничения частоты запросов можно изменить: ваш менеджер партнерской учетной записи Performance Hub настраивает их индивидуально. Если вашей интеграции нужна более высокая пропускная способность для запуска, миграций, загрузки исторических данных для отчетов или объектов с большим объемом данных, сообщите об этом во время подключения или до планового окна изменений.

Базовый URL-адрес

https://partner-api.performancehub.co/partner/v1/

Аутентификация

Для доступа к Partner API требуется аутентификация с помощью секретных ключей API. Создавайте ключи и управляйте ими в Partner Console.

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

Обращайтесь с ключами API бережно — они предоставляют полный доступ к вашей учетной записи! Никогда не размещайте эти ключи в общедоступных репозиториях, клиентских приложениях или в любом другом месте, где они могут быть скомпрометированы.

Аутентифицируйте запросы с помощью HTTP Basic Auth, передавая ключ API в качестве имени пользователя. Пароль оставьте пустым.

API принимает только защищенные подключения HTTPS. Запросы по обычному HTTP отклоняются, как и любые запросы без надлежащих учетных данных аутентификации.

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

curl https://partner-api.performancehub.co/partner/v1/organisations \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:
# The colon prevents curl from asking for a password.

Проверка секретного ключа

curl https://partner-api.performancehub.co/partner/v1/auth/ping \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:
# Returns { "message": "You are successfully authorised as <PartnerName>" }

Контрольный список перед запуском

Используйте этот контрольный список перед включением партнерской интеграции для рабочих объектов.

Настройка Partner Console

  • Профиль партнера заполнен полностью.
  • URL-адрес логотипа, сайт, категория и описание указаны верно.
  • Настроен способ связи данных: Direct Link или Linking Identifier.
  • Связь с объектами проверена как минимум на одном реальном объекте.
  • Используется правильный тип ключа:
    • Dryrun для тестирования записи без изменения данных.
    • Read-only для безопасного получения данных.
    • Live только тогда, когда вы готовы изменять рабочие данные.

Аутентификация и управление ключами

  • Секретные ключи хранятся только на стороне сервера.
  • Ключи не встроены в клиентские приложения, мобильные приложения, общедоступные репозитории или запросы в службу поддержки.
  • Ротация и отзыв ключей протестированы.
  • Ваша команда знает, какой ключ используется в каждой среде.

Проверка данных

  • Для каждой вызываемой конечной точки указаны обязательные поля.
  • Идентификаторы объектов соответствуют настроенному способу связи.
  • Идентификаторы из вашей системы стабильны и не меняются между синхронизациями.
  • Крупные импорты разбиты на пакеты в пределах документированных ограничений.
  • Элементы пакетов с ошибками можно определить и отправить повторно.

Тестирование конечных точек

Перед запуском протестируйте все конечные точки, от которых зависит ваша интеграция:

  • Организации и объекты успешно считываются.
  • Участники сохраняются и обновляются.
  • Планы членства, зоны доступа и часы доступа синхронизируются правильно.
  • Посещения принимаются и могут быть сопоставлены с записями в вашей системе.
  • Снимки отчетов используют ожидаемый отчетный период и показатели.
  • Процессы Door/Gate Controller, где это применимо, протестированы на реальном оборудовании.

Готовность Access Time Windows

Если интеграция передает Access Time Windows:

  • Примеры абсолютных и еженедельных окон проходят контрольный список сертификации поставщика данных.
  • Значения эпохи передаются как целые числа секунд Unix без кавычек; точные границы [from, to) протестированы.
  • Проверены значения UTC по умолчанию, пользовательские часовые пояса IANA интеграции и соответствующие переходы на летнее время.
  • Один надежный монотонный поток ревизий по участнику и источнику координирует инкрементные обновления, сверку и повторные попытки.
  • Операторы понимают поведение при опущенном значении, полной замене, идемпотентном повторе, конфликте, устаревших данных и явном [].
  • Для каждого scope_key, включая default, есть утвержденное сопоставление в Performance Hub; проверено, что неизвестные ключи приводят к отказу в доступе.
  • Настроены ожидаемая частота обновления интеграции, максимальная давность исходных данных, поведение при устаревшем источнике и оповещения.
  • Доказано, что ошибка получения данных из вышестоящего источника не приводит к отправке пустого или неполного снимка.
  • Сходимость потоков по этапам, отмена или отзыв доступа и границы начала и окончания для физических дверей соответствуют согласованным целевым показателям.
  • Обычные правила и постоянные разрешения проверены как резервные варианты, и окна не могут обойти отключение пользователя, blockAllAccess, режим обслуживания или геозонирование.

Готовность контроля доступа

Для интеграций контроля доступа:

  • Ваша система принимает решение о доступе до вызова Performance Hub.
  • Интеграция обрабатывает device_offline, maintenance_mode_active и unlock_confirmation_timeout.
  • Операторы понимают, что тайм-аут означает, что разблокировка не подтверждена.
  • В ваших журналах сохраняются возвращаемые event_id и command_id.
  • У персонала объекта есть ручной резервный процесс.

Обработка ошибок и повторные попытки

  • Ответы 400, 401, 403, 404, 409 и 422 передаются операторам или службе поддержки, а не повторяются вслепую.
  • Для ответов 429, 500, 502, 503 и 504 используется логика ограниченных повторных попыток с задержкой.
  • Повторяющиеся ошибки вызывают оповещение в вашей системе.
  • Интеграция никогда не отбрасывает записи с ошибками без уведомления.

Наблюдаемость

  • Ваши журналы содержат конечную точку, метку времени, идентификатор объекта, идентификатор исходной записи, результат запроса и тело ответа.
  • Ваша служба поддержки может выполнять поиск по идентификатору участника, идентификатору объекта, идентификатору посещения или идентификатору события разблокировки.
  • У вас есть способ повторить или сверить неудачные синхронизации.

Запуск в рабочей среде

  • Performance Hub подтвердил ваш доступ к рабочей среде.
  • Как минимум один рабочий объект включил вашу интеграцию.
  • Ваш рабочий ключ активен.
  • Ваши операционные и технические контакты актуальны.
  • Ваш процесс поддержки задокументирован для клиентов.

После выполнения этих проверок ваша настроенная интеграция появится в каталоге партнеров Performance Hub внутри основной платформы Performance Hub.

Рекомендации

Следуйте этим подходам, чтобы партнерские интеграции оставались предсказуемыми, наблюдаемыми и безопасными для объектов.

Единообразно идентифицируйте объекты

Выберите способ связи, настроенный для вашей партнерской учетной записи, и используйте его единообразно:

  • Direct Link — используйте facility_id Performance Hub, возвращаемый конечной точкой объектов.
  • Linking Identifier — используйте собственный идентификатор площадки, например идентификатор филиала, код площадки или номер магазина.

Не отправляйте оба идентификатора в одном запросе. Performance Hub обрабатывает запросы с помощью способа связи, настроенного для вашей партнерской учетной записи.

Инструкции по настройке см. в разделе Способы связи партнера.

Тщательно формируйте пакетные операции записи

Partner API принимает тела запросов в формате JSON и, где это указано в документации, рассчитан на пакетные процессы синхронизации. Ограничивайте размер пакетов и обеспечивайте возможность их повторной отправки.

Рекомендации по умолчанию:

  • Для оптимальной производительности используйте не более 1000 элементов в одном пакетном запросе.
  • Размер полезной нагрузки не должен превышать 10MB.
  • Не превышайте 5 запросов в секунду на конечную точку.

Ограничения частоты запросов можно изменить: ваш менеджер партнерской учетной записи Performance Hub настраивает их индивидуально. Если вы ожидаете импорт больших объемов, всплеск трафика при запуске или загрузку исторических данных для отчетов, согласуйте необходимую пропускную способность до начала окна изменений.

Если нужно синхронизировать большой набор данных, разделите его на детерминированные части и регистрируйте идентификатор каждой части на своей стороне. Так будет проще разобраться в неудачных повторных попытках.

Безопасно повторяйте попытки

Для временных ошибок, таких как 429, 500, 502, 503 и 504, используйте экспоненциальную задержку.

Избегайте частых циклов повторных попыток. Для начала подойдет такая схема:

  1. Повторите попытку через 1 секунду.
  2. Повторите попытку через 2 секунды.
  3. Повторите попытку через 4 секунды.
  4. Если операция по-прежнему завершается ошибкой, остановитесь и отправьте оповещение.

При ошибках проверки, таких как 400 или 422, исправьте запрос, прежде чем повторять попытку.

Используйте идемпотентность там, где она поддерживается

Конечная точка разблокировки контроллера Door/Gate Controller поддерживает необязательный параметр idempotency_key. При повторном использовании того же ключа для того же партнера, объекта и двери возвращается существующий результат, если он доступен.

Используйте стабильный ключ для выполняемого действия, например идентификатор посещения или идентификатор события доступа из вашей системы.

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

Поддерживайте чистоту исходных данных

По возможности отправляйте стабильные нормализованные значения:

  • Используйте согласованные идентификаторы участников, планов, объектов и посещений из исходной системы.
  • Используйте метки времени ISO 8601 для дат и времени.
  • По возможности отправляйте номера телефонов в международном формате.
  • Передавайте валюты в полях, указанных в документации для каждой конечной точки.
  • Не перегружайте поля свободного текста данными, которые должны находиться в структурированных полях.

Предусмотрите инкрементную и полную синхронизацию

Большинству партнерских интеграций нужны оба варианта:

  • Инкрементная синхронизация для ежедневных изменений.
  • Полная сверочная синхронизация для исправления пропущенных событий, импорта исторических данных или расхождения данных.

Ваша интеграция должна уметь повторно отправлять текущее состояние участника, плана членства или снимка отчета, не завися от успешного выполнения предыдущего запроса.

Безопасно публикуйте Access Time Windows

Рассматривайте значение access_time_windows каждого участника как полный снимок с независимой нумерацией ревизий:

  • Согласуйте единый монотонно возрастающий поток access_time_windows_revision между обработчиками инкрементной и сверочной синхронизации.
  • Повторяйте неподтвержденную или временно неудачную доставку с той же ревизией и той же нормализованной полезной нагрузкой.
  • Не указывайте access_time_windows, если не обновляете это значение.
  • Отправляйте [] только после того, как успешное получение данных из основного источника подтвердит, что окон не осталось. Никогда не превращайте тайм-аут вышестоящей системы, неполный результат или ошибку разбора в отзыв доступа.
  • Сохраняйте external_id и scope_key стабильными и сертифицируйте каждое сопоставление областей перед запуском в рабочей среде.
  • Отслеживайте давность исходных данных в соответствии с политикой актуальности, согласованной для этой интеграции.

Сведения о полных снимках, часовых поясах, переходе на летнее время, отмене и тестовых векторах см. в официальном руководстве для поставщиков данных Access Time Windows.

Относитесь к контролю доступа как к критически важной для безопасности функции

Для разблокировки контроллеров Door/Gate Controller:

  • Ваша система должна решить, разрешен ли человеку вход, до вызова Performance Hub.
  • Performance Hub возвращает 200 только после того, как контроллер на площадке подтвердит, что реле физически разблокировано.
  • Обычно подтверждение приходит за 3-5 секунд.
  • Тайм-аут означает явную неудачу разблокировки, а не успешное выполнение в фоновом режиме.
  • Повторяйте попытки только в соответствии с собственными правилами доступа и безопасности.

Всегда регистрируйте значения event_id и command_id, возвращаемые конечной точкой разблокировки.

Отслеживайте работу интеграции

Во время разработки и запуска используйте журналы запросов в Partner Console. В рабочей среде также ведите собственные журналы со следующими данными:

  • Время запроса.
  • Конечная точка.
  • Идентификатор исходной записи.
  • Идентификатор объекта.
  • Код состояния HTTP.
  • Тело ответа Performance Hub или сообщение об ошибке.

Эти поля значительно ускоряют поддержку и сверку, когда клиент спрашивает, что произошло.

Организации

Представляет бизнес-структуру верхнего уровня, которая управляет одним или несколькими объектами, интегрированными с платформой Performance Hub.

Конечные точки

GET /partner/v1/organisations - List all organisations

Объект Organisation

Атрибуты

  • org_id string обязательный

    Уникальный идентификатор организации.

  • name string обязательный

    Название организации.

Объект Organisation

{
  "org_id": "00000000-0000-0000-0000-000000000050",
  "name": "Harbourside Group"
}

Список всех организаций

Возвращает список организаций, доступных вашей партнерской учетной записи.

Возвращаемое значение

Возвращает объект JSON со свойством data, содержащим массив объектов Organisation.

Запрос

curl https://partner-api.performancehub.co/partner/v1/organisations \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:

Ответ

{
  "data": [
    {
      "org_id": "00000000-0000-0000-0000-000000000050",
      "name": "Harbourside Group"
    },
    {
      "org_id": "6ba7b811-9dad-11d1-80b4-00c04fd430c8",
      "name": "Wellness Studios Network"
    }
  ]
}

Объекты

Представляет физическую площадку, например офис, магазин, площадку для мероприятий, кампус, клинику или спортзал, где участники могут пользоваться услугами.

Конечные точки

GET /partner/v1/facilities - List all facilities

Объект Facility

Атрибуты

  • facility_id string обязательный

    Уникальный идентификатор объекта.

  • org_id string обязательный

    Уникальный идентификатор родительской организации.

  • name string обязательный

    Название объекта.

  • brand string необязательный

    Название бренда, используемое объектом.

  • website_url string необязательный

    URL-адрес сайта объекта.

  • place_data object необязательный

    Данные о местоположении из Google Places API: страна, форматированный адрес, Google Place ID, регион и город.

  • social_links object необязательный

    Ссылки объекта на социальные сети.

  • timezone string необязательный

    Идентификатор часового пояса IANA (например, "Australia/Sydney", "America/New_York").

Объект Facility

{
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "org_id": "00000000-0000-0000-0000-000000000050",
  "name": "Harbourside Central",
  "brand": "Harbourside",
  "website_url": "https://example.com/central",
  "social_links": {
    "instagram": {
      "handle": "@harbourside.central"
    },
    "facebook": {
      "handle": "HarboursideCentral"
    }
  },
  "place_data": {
    "country": {
      "iso_code": "AU",
      "full_name": "Australia"
    },
    "formatted_address": "123 Main Street, Suite 100, Sydney NSW 2000, Australia",
    "google_place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
    "province": {
      "abbreviation": "NSW",
      "full_name": "New South Wales"
    },
    "city": {
      "short_name": "Sydney",
      "full_name": "Sydney"
    }
  },
  "timezone": "Australia/Sydney"
}

Список всех объектов

Возвращает список объектов, доступных вашей партнерской учетной записи.

Возвращаемое значение

Возвращает объект JSON со свойством data, содержащим массив объектов Facility.

Запрос

curl https://partner-api.performancehub.co/partner/v1/facilities \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:

Ответ

{
  "data": [
    {
      "facility_id": "550e8400-e29b-41d4-a716-446655440000",
      "org_id": "00000000-0000-0000-0000-000000000050",
      "name": "Harbourside Central",
      "brand": "Harbourside",
      "website_url": "https://example.com/central",
      "place_data": {
        "country": {
          "iso_code": "AU",
          "full_name": "Australia"
        },
        "formatted_address": "123 Main Street, Sydney NSW 2000, Australia",
        "google_place_id": "ChIJN1t_tDeuEmsRUsoyG83frY4",
        "province": {
          "abbreviation": "NSW",
          "full_name": "New South Wales"
        },
        "city": {
          "short_name": "Sydney",
          "full_name": "Sydney"
        }
      },
      "timezone": "Australia/Sydney"
    }
  ]
}

Планы членства

Определяет предложение организации или объекта, доступное для покупки, включая услуги, права, расписание и цены.

Конечные точки

POST /partner/v1/membership-plans - Save a membership plan

Объект Membership Plan

Атрибуты

  • membership_plan_id string обязательный

    Уникальный идентификатор плана членства.

  • facility_id string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Уникальный идентификатор объекта в Performance Hub.

  • linking_identifier string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Уникальное значение идентификатора каждой площадки, используемое партнером (например, "Branch ID", "Location Code", "Store Number"). Подробнее

  • name string обязательный

    Удобочитаемое название плана (например, "Office tenant – business hours", "Student – term access", "Hotel guest", "10 Class Pack").

  • billing_cycle string необязательный

    Периодичность выставления счетов. Одно из значений: weekly, fortnightly, monthly, annually или one_time.

  • price integer необязательный

    Базовая стоимость в наименьшей денежной единице (центы для USD/AUD).

  • currency string необязательный

    Код валюты ISO 4217 (например, "AUD", "USD").

  • description string необязательный

    Необязательное маркетинговое или внутреннее описание.

  • active_members integer необязательный

    Количество активных участников, использующих этот план членства

  • is_recurring boolean необязательный

    Продлевается ли план автоматически.

  • is_trial boolean необязательный

    Является ли предложение пробным.

  • visible_to_public boolean необязательный

    Доступен ли план для самостоятельной покупки.

  • duration_days integer необязательный

    Количество дней действия плана членства.

  • access_zones array необязательный

    Массив зон доступа, входящих в план членства. Для каждой зоны можно задать собственные часы доступа. Подробнее см. в разделе Зоны доступа.

  • class_limit integer необязательный

    Максимальное разрешенное количество занятий (null — без ограничений).

Объект Membership Plan

В этом примере используется facility_id. Для интеграции со связующим идентификатором отправьте вместо него "linking_identifier": "branch_downtown".

{
  "membership_plan_id": "plan_99999",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "name": "Office tenant – business hours",
  "description": "Weekday access to the level 3 tenancy and the end-of-trip facilities",
  "billing_cycle": "monthly",
  "price": 8900,
  "currency": "AUD",
  "duration_days": 30,
  "is_recurring": true,
  "is_trial": false,
  "visible_to_public": false,
  "active_members": 245,
  "access_zones": [
    {
      "name": "Level 3 Tenancy",
      "description": "Lift lobby, offices and meeting rooms on level 3",
      "access_hours": {
        "mon": [["07:00", "19:00"]],
        "tue": [["07:00", "19:00"]],
        "wed": [["07:00", "19:00"]],
        "thu": [["07:00", "19:00"]],
        "fri": [["07:00", "19:00"]]
      }
    },
    {
      "name": "End-of-trip Facilities",
      "description": "Bike storage, lockers and showers",
      "access_hours": {
        "mon": [["06:00", "20:00"]],
        "tue": [["06:00", "20:00"]],
        "wed": [["06:00", "20:00"]],
        "thu": [["06:00", "20:00"]],
        "fri": [["06:00", "20:00"]]
      }
    }
  ],
  "class_limit": null
}

Зоны доступа

Зоны доступа определяют конкретные области объекта, к которым план членства предоставляет доступ. Для каждой зоны можно задать собственные часы доступа, что позволяет устанавливать разные временные ограничения для разных областей.

Структура

Каждая зона доступа включает:

  • name string обязательный

    Название зоны (например, "Level 3 Tenancy", "Library", "Guest Floors", "Main Gym Floor").

  • description string необязательный

    Описание того, что входит в эту зону.

  • access_hours object необязательный

    Часы доступа для этой зоны. Формат временных диапазонов см. в разделе Часы доступа.

Пример

Офисное здание со спортзалом для арендаторов: доступ к арендуемым помещениям в рабочее время, а к спортзалу — с раннего утра до позднего вечера.

{
  "access_zones": [
    {
      "name": "Level 3 Tenancy",
      "description": "Lift lobby, offices and meeting rooms on level 3",
      "access_hours": {
        "mon": [["07:00", "19:00"]],
        "tue": [["07:00", "19:00"]],
        "wed": [["07:00", "19:00"]],
        "thu": [["07:00", "19:00"]],
        "fri": [["07:00", "19:00"]]
      }
    },
    {
      "name": "Tenant Gym",
      "description": "Ground-floor gym and change rooms for building tenants",
      "access_hours": {
        "mon": [["05:00", "22:00"]],
        "tue": [["05:00", "22:00"]],
        "wed": [["05:00", "22:00"]],
        "thu": [["05:00", "22:00"]],
        "fri": [["05:00", "22:00"]],
        "sat": [["07:00", "18:00"]],
        "sun": [["07:00", "18:00"]]
      }
    }
  ]
}

Часы доступа

Часы доступа определяют, когда участники могут получить доступ к определенной зоне в каждый день недели. Часы доступа задаются для каждой зоны доступа, что позволяет устанавливать разные временные ограничения для разных областей объекта.

Структура

{
  "mon": [["start_time", "end_time"]],
  "tue": [["start_time", "end_time"]],
  "wed": [["start_time", "end_time"]],
  "thu": [["start_time", "end_time"]],
  "fri": [["start_time", "end_time"]],
  "sat": [["start_time", "end_time"]],
  "sun": [["start_time", "end_time"]]
}

Каждый день представлен массивом временных диапазонов в формате HH:MM (24-часовой формат). Пустой массив [] означает отсутствие доступа в этот день. Пропущенные дни обрабатываются так же, как пустой массив.

Примеры использования

Арендатор офиса — рабочие часы: доступ в рабочее время только по будним дням.

{
  "access_hours": {
    "mon": [["07:00", "19:00"]],
    "tue": [["07:00", "19:00"]],
    "wed": [["07:00", "19:00"]],
    "thu": [["07:00", "19:00"]],
    "fri": [["07:00", "19:00"]]
  }
}

Студент — доступ на время семестра: библиотека кампуса, открытая по будним дням с перерывом в середине дня, а также по субботам утром.

{
  "access_hours": {
    "mon": [["08:00", "12:30"], ["13:30", "21:00"]],
    "tue": [["08:00", "12:30"], ["13:30", "21:00"]],
    "wed": [["08:00", "12:30"], ["13:30", "21:00"]],
    "thu": [["08:00", "12:30"], ["13:30", "21:00"]],
    "fri": [["08:00", "12:30"], ["13:30", "17:00"]],
    "sat": [["09:00", "13:00"]]
  }
}

Спортзал — ранние пташки: доступ только в утренние часы по будним дням.

{
  "access_hours": {
    "mon": [["04:00", "12:00"]],
    "tue": [["04:00", "12:00"]],
    "wed": [["04:00", "12:00"]],
    "thu": [["04:00", "12:00"]],
    "fri": [["04:00", "12:00"]]
  }
}

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

{
  "access_hours": {
    "mon": [["00:00", "23:59"]],
    "tue": [["00:00", "23:59"]],
    "wed": [["00:00", "23:59"]],
    "thu": [["00:00", "23:59"]],
    "fri": [["00:00", "23:59"]],
    "sat": [["00:00", "23:59"]],
    "sun": [["00:00", "23:59"]]
  }
}

Пример для отдельных зон

План для гостей отеля с круглосуточным доступом к гостевым этажам и сокращенными часами работы бассейна:

{
  "access_zones": [
    {
      "name": "Guest Floors",
      "description": "Lifts and corridors on the guest room levels",
      "access_hours": {
        "mon": [["00:00", "23:59"]],
        "tue": [["00:00", "23:59"]],
        "wed": [["00:00", "23:59"]],
        "thu": [["00:00", "23:59"]],
        "fri": [["00:00", "23:59"]],
        "sat": [["00:00", "23:59"]],
        "sun": [["00:00", "23:59"]]
      }
    },
    {
      "name": "Swimming Pool",
      "description": "Access to the swimming pool and change rooms",
      "access_hours": {
        "mon": [["06:00", "20:00"]],
        "tue": [["06:00", "20:00"]],
        "wed": [["06:00", "20:00"]],
        "thu": [["06:00", "20:00"]],
        "fri": [["06:00", "20:00"]],
        "sat": [["08:00", "18:00"]],
        "sun": [["08:00", "18:00"]]
      }
    }
  ]
}

Сохранение плана членства

Создает или обновляет записи планов членства. API определяет, создавать или обновлять запись, на основе membership_plan_id.

Параметры

  • membership_plans array обязательный

    Массив объектов Membership Plan для сохранения. Рекомендуемый максимум для оптимальной производительности — 1000 элементов на запрос. API автоматически разбивает элементы на пакеты для обработки. Каждый элемент должен содержать либо facility_id (обязателен, если не используется linking_identifier), либо linking_identifier (обязателен, если не используется facility_id).

Возвращаемое значение

Возвращает простое сообщение, подтверждающее операцию синхронизации.

Запрос

В этом примере используется facility_id. Для интеграции со связующим идентификатором отправьте вместо него "linking_identifier": "branch_downtown".

curl -X POST https://partner-api.performancehub.co/partner/v1/membership-plans \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "membership_plans": [
      {
        "membership_plan_id": "plan_99999",
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        "name": "Student – term access",
        "description": "Library and student hub access for one teaching term",
        "billing_cycle": "one_time",
        "price": 4500,
        "currency": "AUD",
        "duration_days": 84,
        "is_recurring": false,
        "is_trial": false,
        "visible_to_public": true,
        "active_members": 245,
        "access_zones": [
          {
            "name": "Library",
            "description": "Reading rooms, study spaces and bookable rooms",
            "access_hours": {
              "mon": [["08:00", "21:00"]],
              "tue": [["08:00", "21:00"]],
              "wed": [["08:00", "21:00"]],
              "thu": [["08:00", "21:00"]],
              "fri": [["08:00", "17:00"]],
              "sat": [["09:00", "13:00"]]
            }
          },
          {
            "name": "Student Hub",
            "description": "Common room, kitchen and lockers",
            "access_hours": {
              "mon": [["07:00", "22:00"]],
              "tue": [["07:00", "22:00"]],
              "wed": [["07:00", "22:00"]],
              "thu": [["07:00", "22:00"]],
              "fri": [["07:00", "22:00"]]
            }
          }
        ],
        "class_limit": null
      }
    ]
  }'

Ответ

Возвращает сообщение об успешном выполнении с метаданными операции синхронизации.

{
  "message": "Membership plan sync successful.",
  "metadata": {
    "success": 98,
    "skipped": 2,
    "skipped_items": [
      {
        "membership_plan_id": "plan_456",
        "facility_id": null,
        "reason": "Missing facility_id"
      }
    ]
  }
}

Поля метаданных:

  • success — количество успешно обработанных планов членства
  • skipped — количество пропущенных планов (если есть)
  • skipped_items — массив пропущенных планов с указанием причин (если есть)
  • dry-run — логический флаг при использовании ключа типа dryrun (если применимо)

Участники

Представляет отдельного клиента объекта. Это может быть лид, потенциальный клиент, постоянный клиент, участник с истекшим членством или заблокированный пользователь.

Операции upsert для участников также могут передавать полный снимок access_time_windows с ревизией, содержащий абсолютный и еженедельный повторяющийся доступ. Прежде чем формировать эти поля, ознакомьтесь с разделом Access Time Windows. Они являются дополнительными разрешениями и не заменяют обычные правила объекта или постоянные разрешения.

Конечные точки

POST /partner/v1/members - Save a member

Объект Member

Атрибуты

  • member_id string обязательный

    Уникальный идентификатор участника.

  • facility_id string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Уникальный идентификатор объекта в Performance Hub.

  • linking_identifier string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Уникальное значение идентификатора каждой площадки, используемое партнером (например, "Branch ID", "Location Code", "Store Number"). Подробнее

  • first_name string обязательный

    Имя участника.

  • last_name string обязательный

    Фамилия участника.

  • email string необязательный

    Адрес электронной почты.

  • mobile_phone string необязательный

    Номер мобильного телефона в формате E.123 (например, "+1 415 555 2671").

  • address object необязательный

    Объект физического адреса со следующими свойствами:

    • address_line_1 (string) — основная строка адреса
    • address_line_2 (string, optional) — дополнительная строка адреса
    • city (string) — название города
    • state (string) — код штата или региона
    • postal_code (string) — почтовый индекс
    • country (string) — код страны ISO 3166-1 alpha-2 (например, "AU", "US")
    • country_name (string, optional) — полное название страны
  • date_of_birth string необязательный

    Дата рождения в формате YYYY-MM-DD.

  • gender string необязательный

    Одно из значений: male, female, non_binary, prefer_not_to_say или unknown.

  • type string необязательный

    Тип участника (например, staff, member, prospect).

  • tags array необязательный

    Короткие вспомогательные строки или тексты для категоризации и идентификации определенных участников (например, ["vip", "personal-training", "student"]).

  • membership_status string необязательный

    Текущий статус членства (например, active, expired, on_hold).

  • membership_plans array необязательный

    Массив планов членства, связанных с участником.

  • profile_picture string необязательный

    Фотография профиля в кодировке Base64 (необязательно).

  • created string необязательный

    Метка времени ISO 8601 создания участника.

  • updated string необязательный

    Метка времени ISO 8601 последнего обновления участника.

  • access_time_windows array необязательный

    Полный снимок абсолютных и (или) еженедельных повторяющихся Access Time Windows, принадлежащий источнику. Не указывайте поле, чтобы оставить снимок без изменений; отправьте пустой массив с более новой ревизией, чтобы отозвать его. Сведения о формах, проверке, сопоставлении областей и семантике замены см. в разделе Access Time Windows.

  • access_time_windows_revision integer обязателен вместе с access_time_windows

    Монотонно возрастающее неотрицательное целое число, безопасное для JSON, для потока этого участника и источника. Обязательно, если указано access_time_windows.

Объект Member

{
  "member_id": "member_11111",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  // "linking_identifier": "branch_downtown",  // If using linking identifier
  "first_name": "John",
  "last_name": "Smith",
  "email": "john.smith@example.com",
  "mobile_phone": "+61 412 345 678",
  "date_of_birth": "1985-06-15",
  "gender": "male",
  "type": "member",
  "tags": ["vip", "personal-training"],
  "profile_picture": "/9j/4AAQSkZJRgABAQAAAQ...",
  "membership_status": "current",
  "created": "2024-01-15T10:30:00Z",
  "updated": "2024-01-20T14:45:00Z",
  "access_time_windows_revision": 1842,
  "access_time_windows": [
    {
      "external_id": "access-4b1782",
      "kind": "absolute",
      "from": 1792053000,
      "to": 1792058400,
      "timezone": "Australia/Perth",
      "scope_key": "after_hours_entry",
      "label": "Temporary site access"
    }
  ],
  "address": {
    "address_line_1": "456 Bourke Street",
    "address_line_2": "Apt 12",
    "city": "Melbourne",
    "state": "VIC",
    "postal_code": "3000",
    "country": "AU",
    "country_name": "Australia"
  },
  "membership_plans": [
    {
      "membership_plan_id": "plan_99999",
      "name": "Unlimited Monthly",
      "start_date": "2024-01-01T00:00:00Z",
      "status": "current",
      "is_current": true,
      "end_date": null
    }
  ]
}

Временные окна доступа

Access Time Windows позволяют участнику на стороне партнера получать временный или повторяющийся доступ, предоставленный внешней системой. Эта страница — официальное руководство для поставщиков данных по полям access_time_windows и access_time_windows_revision.

Access Time Windows — это дополнительные разрешения, которые только предоставляют доступ. Активное окно может разрешить доступ, но неактивное, истекшее, устаревшее или несопоставленное окно не запрещает доступ, который уже разрешен обычным правилом или постоянным разрешением. Отключение пользователя, явная блокировка двери, режим обслуживания, геозонирование, ограничения частоты и доступность контроллера по-прежнему действуют.

Реализации для конкретных вышестоящих систем представляют собой отдельные адаптеры. Они должны преобразовывать исходные данные в этот независимый от поставщика контракт, не меняя значения полей.

Поля снимка участника

  • access_time_windows array необязательный

    Полный снимок Access Time Windows для этого участника и источника партнера. Снимок может сочетать окна absolute и weekly. Не указывайте поле, чтобы оставить сохраненный снимок без изменений; отправьте [], чтобы отозвать все окна, принадлежащие этому источнику.

  • access_time_windows_revision integer обязателен вместе с access_time_windows

    Монотонно возрастающее неотрицательное целое число, безопасное для JSON, для потока ревизий этого участника и источника. Обязательно, если указано access_time_windows, и не должно превышать 9007199254740991.

Каждый снимок может содержать не более 50 окон. Поля external_id, scope_key и label принимают не более 120 символов. Абсолютное окно может охватывать не более 90 дней. Для одного дня недели допускается не более восьми непересекающихся блоков. Недопустимые данные отклоняются, а не обрезаются или угадываются.

Формы окон

Абсолютное окно задает один точный интервал:

Полный смешанный запрос

Этот запрос заменяет предыдущий снимок участника, принадлежащий источнику, одним абсолютным и одним еженедельным окном:

Правила времени и границ

from, to, active_from и active_until — целые числа JSON в секундах Unix, обозначающие моменты времени UTC:

  • Отправляйте целое число JSON без кавычек. Числовые строки, числа с плавающей запятой, строки RFC 3339 и миллисекунды Unix отклоняются.
  • Каждый интервал полуоткрытый: [from, to). Доступ может начаться точно в момент from; в момент to он уже не активен.
  • from должно быть меньше to. Если указаны обе границы еженедельного окна, active_from должно быть меньше active_until.
  • Не вычисляйте значения эпохи из местной даты и времени без часового пояса. Сначала преобразуйте исходное время в момент UTC, затем разделите миллисекунды Unix на 1000 и убедитесь, что результат — целое число.

Часовые пояса и летнее время

timezone должен быть допустимым часовым поясом IANA, например UTC, Australia/Perth или America/New_York. Если он не указан, по умолчанию используется UTC.

  • Абсолютные окна: from и to уже обозначают точные моменты UTC. timezone служит только метаданными для отображения и аудита; его изменение никогда не сдвигает ни один из этих моментов.
  • Еженедельные окна: timezone определяет местное время и правила перехода на летнее время, используемые для оценки access_hours. Не преобразуйте еженедельные блоки в UTC заранее.
  • При переводе часов вперед местное время, которое пропускается в этом часовом поясе, не наступает.
  • При переводе часов назад еженедельному блоку соответствуют оба реальных момента с повторяющимся местным временем.
  • active_from и active_until остаются моментами UTC, даже если еженедельное окно использует часовой пояс, отличный от UTC.

access_hours использует ключи в нижнем регистре от sun до sat. Каждое значение — массив пар [start, end] в 24-часовом формате HH:mm с ведущими нулями. Блоки должны быть непустыми, упорядоченными и непересекающимися. end не включается в интервал. Блок не может переходить через полночь; разделите ночной исходный интервал на поздний блок в первый день и ранний блок на следующий день.

Стабильные идентификаторы и сопоставление областей

external_id должен оставаться неизменным в течение всего срока существования логического окна и быть уникальным в пределах снимка участника. Сохраняйте его неизменным при изменении времени или меток, чтобы операторы и записи аудита могли сопоставлять ревизии. Не используйте его повторно для несвязанного окна.

scope_key — ваша стабильная логическая цель доступа. По умолчанию используется default. Администратор объекта сопоставляет каждый разрешенный ключ с целями Performance Hub: весь объект, дверь или Область доступа:

Полные снимки и ревизии

Рассматривайте эти два поля как отдельный раздел с независимым управлением версиями внутри операции upsert для участника:

Входные данные Результат
access_time_windows не указано Существующий снимок остается без изменений; ревизия не требуется
Указано с более новой ревизией Весь сохраненный снимок для этого участника и источника заменяется
Та же ревизия и та же нормализованная полезная нагрузка Идемпотентный повтор; снимок не меняется
Та же ревизия и другая нормализованная полезная нагрузка Конфликт; после сверки назначьте новую ревизию
Более старая ревизия Устаревший снимок пропускается; он не может перезаписать более новое состояние
access_time_windows: [] с более новой ревизией Явно отзывает все окна, принадлежащие источнику

Снимок является полным, а не исправлением. Если ревизия 1842 содержит окна A и B, то ревизия 1843, содержащая только B, удаляет A.

Поддерживайте один согласованный поток ревизий для каждой пары партнер — участник во всех обработчиках веб-перехватчиков, опросе, повторной отправке и полной сверке. Предпочтительно использовать надежную последовательность базы данных. Значение в миллисекундах Unix можно использовать в качестве ревизии, только если все записывающие процессы согласованы и гарантируют строгий порядок и уникальность; это значение ревизии, а не поле эпохи.

Сохраняйте точный запрос и ревизию, пока не станет известен ответ API. После тайм-аута или временной ошибки повторите отправку того же нормализованного снимка с той же ревизией. Не назначайте новую ревизию только потому, что доставка неизвестна.

Отмена, истечение срока и сбои вышестоящих систем

  • Отмена одного окна: успешно получите состояние из основного источника, удалите это окно и отправьте оставшийся полный снимок с более новой ревизией.
  • Отмена всех окон: отправьте access_time_windows: [] с более новой ревизией.
  • Истечение срока абсолютного окна: оно перестает предоставлять доступ в момент to; отправьте последующую сверку без истекшей записи, чтобы снимки оставались чистыми.
  • Завершение еженедельного окна: удалите его в более новом снимке или используйте active_until, если в источнике известен момент окончания.
  • Получение данных из источника не удалось или неполно: не отправляйте [] и не публикуйте неполный снимок. Отправьте оповещение и повторите получение данных. Превращение сбоя вышестоящей системы в пустой снимок — это непреднамеренный отзыв доступа.
  • Запрос Partner API не прошел проверку: исправьте данные и отправьте более новую ревизию, только если нормализованный снимок изменился. Временные ошибки повторяйте с исходной ревизией.

Актуальность источника настраивается для каждой интеграции на основе обещанной частоты доставки и сверки. Перед активацией согласуйте максимальную давность исходных данных, последствия ее превышения, пороги оповещений и возможность для операторов подтвердить, что они полагаются только на собственные границы каждого окна. Устаревшее окно источника никогда не становится запрещающим правилом; обычные правила и постоянные разрешения остаются резервными вариантами.

Алгоритм для поставщика данных

Используйте этот не зависящий от языка программирования процесс для каждого обновления участника:

Контрольный список сертификации

Выполните эти проверки на тестовом объекте с окончательным сопоставлением scope_key:

  • Абсолютное окно без часового пояса принимается и оценивается в UTC.
  • Абсолютное окно с пользовательским часовым поясом IANA сохраняет те же моменты from/to.
  • Еженедельное окно с пользовательским часовым поясом IANA следует местному времени при переводе часов вперед и назад.
  • Смешанный снимок с абсолютными и еженедельными окнами полностью заменяет предыдущий снимок.
  • Доступ начинается точно в момент from и прекращается точно в момент to; окончание еженедельных блоков также не включается.
  • Изменение времени для того же external_id с более новой ревизией вступает в силу.
  • Если access_time_windows не указано, другие поля участника изменяются без изменения окон.
  • Повторная отправка той же ревизии и полезной нагрузки идемпотентна.
  • Та же ревизия с другой полезной нагрузкой возвращает конфликт и не меняет снимок.
  • Более старая ревизия, пришедшая не по порядку, помечается как устаревшая и не может откатить состояние.
  • Более новое значение [] отзывает окна, принадлежащие источнику; при сбое получения данных из вышестоящего источника ничего не отправляется.
  • Неизвестный или несопоставленный scope_key приводит к отказу в доступе и создает предупреждение, видимое оператору.
  • Оповещения о давности источника и настроенная политика для устаревшего источника срабатывают на согласованном пороге.
  • Пути веб-перехватчика и полной сверки приводят к одному и тому же снимку и порядку ревизий.
  • Доставка потока достигает Door & Gate Access в пределах согласованного целевого времени.
  • Активное окно может разрешить доступ к сопоставленной физической двери, но не может обойти отключение пользователя, blockAllAccess, режим обслуживания или геозонирование.
  • До окна, вне его и после него обычные правила и постоянные разрешения по-прежнему допускают пользователей, которые иным образом соответствуют требованиям.

Связанные рекомендации

{
  "external_id": "access-4b1782",
  "kind": "absolute",
  "from": 1792053000,
  "to": 1792058400,
  "timezone": "Australia/Perth",
  "scope_key": "after_hours_entry",
  "label": "Temporary site access"
}

Обязательные поля: external_id, kind, from и to. Поля timezone, scope_key и label необязательны.

Еженедельное окно задает повторяющиеся интервалы по местному времени, при необходимости ограниченные моментами времени UTC:

{
  "external_id": "weekly-early-access",
  "kind": "weekly",
  "timezone": "America/New_York",
  "access_hours": {
    "sun": [],
    "mon": [["06:00", "08:30"]],
    "tue": [["06:00", "08:30"]],
    "wed": [["06:00", "08:30"]],
    "thu": [["06:00", "08:30"]],
    "fri": [["06:00", "08:30"]],
    "sat": []
  },
  "active_from": 1790812800,
  "active_until": 1796083200,
  "scope_key": "main_entry",
  "label": "Weekday early access"
}

Обязательные поля: external_id, kind и access_hours. Поля timezone, active_from, active_until, scope_key и label необязательны.

curl -X POST https://partner-api.performancehub.co/partner/v1/members \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "members": [
      {
        "member_id": "member_11111",
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        "first_name": "John",
        "last_name": "Smith",
        "access_time_windows_revision": 1842,
        "access_time_windows": [
          {
            "external_id": "access-4b1782",
            "kind": "absolute",
            "from": 1792053000,
            "to": 1792058400,
            "timezone": "Australia/Perth",
            "scope_key": "after_hours_entry",
            "label": "Temporary site access"
          },
          {
            "external_id": "weekly-early-access",
            "kind": "weekly",
            "timezone": "America/New_York",
            "access_hours": {
              "sun": [],
              "mon": [["06:00", "08:30"]],
              "tue": [["06:00", "08:30"]],
              "wed": [["06:00", "08:30"]],
              "thu": [["06:00", "08:30"]],
              "fri": [["06:00", "08:30"]],
              "sat": []
            },
            "active_from": 1790812800,
            "active_until": 1796083200,
            "scope_key": "main_entry",
            "label": "Weekday early access"
          }
        ]
      }
    ]
  }'

Используйте либо facility_id, либо linking_identifier в соответствии с настроенным способом связи. Не отправляйте оба.

Преобразование в эпоху

2026-10-15T08:30:00Z преобразуется в 1792053000:

UTC instant                 Unix milliseconds   Unix seconds sent
2026-10-15T08:30:00Z        1792053000000        1792053000

Преобразование, не зависящее от языка программирования:

instant = parse_source_timestamp_with_explicit_zone(source_timestamp)
milliseconds = instant.to_unix_milliseconds()
assert milliseconds modulo 1000 equals 0
seconds = milliseconds / 1000
assert seconds is a JSON-safe nonnegative integer

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

Partner scope_key           Performance Hub mapping
default                     Facility's configured default target
main_entry                  Access Scope "Main entrances"
after_hours_entry           Doors approved for after-hours entry

Партнеры не передают в окне идентификаторы объектов, дверей или областей доступа Performance Hub. Неизвестный, отключенный или несопоставленный scope_key приводит к отказу в доступе для этого окна; он не расширяет доступ. Согласуйте и протестируйте сопоставления до запуска.

function publish_member(member_key):
    source_result = fetch_authoritative_access_state(member_key)

    if source_result.failed or source_result.incomplete:
        record_failure(member_key)
        schedule_retry(member_key)
        return without sending access_time_windows

    windows = []
    for source_window in source_result.current_windows:
        if source_window.is_absolute:
            windows.append({
                external_id: stable_window_id(source_window),
                kind: "absolute",
                from: to_integer_unix_seconds(source_window.start_instant),
                to: to_integer_unix_seconds(source_window.end_instant),
                timezone: source_window.display_timezone or "UTC",
                scope_key: stable_scope_key(source_window) or "default",
                label: safe_label(source_window)
            })
        else:
            windows.append({
                external_id: stable_window_id(source_window),
                kind: "weekly",
                timezone: valid_iana_zone(source_window.timezone) or "UTC",
                access_hours: split_validate_and_sort_weekly_blocks(source_window),
                active_from: optional_integer_unix_seconds(source_window.active_start),
                active_until: optional_integer_unix_seconds(source_window.active_end),
                scope_key: stable_scope_key(source_window) or "default",
                label: safe_label(source_window)
            })

    normalized_snapshot = validate_sort_and_deduplicate(windows)
    revision = next_durable_member_revision(member_key)
    request = member_upsert_with(normalized_snapshot, revision)
    persist_for_retry(member_key, request)

    response = post_request(request)
    if response.is_transient_or_unknown:
        retry_exact_request_with_same_revision(request)
    else if response.is_revision_conflict:
        reconcile_with_latest_committed_source_state(member_key)
    else if response.is_stale_skip:
        stop_replaying_this_revision_and_reconcile(member_key)

Минимальные тестовые векторы

[
  {
    "name": "absolute-half-open",
    "window": {
      "external_id": "tv-absolute",
      "kind": "absolute",
      "from": 1792053000,
      "to": 1792058400
    },
    "expect": {
      "1792052999": "inactive",
      "1792053000": "active",
      "1792058399": "active",
      "1792058400": "inactive"
    }
  },
  {
    "name": "weekly-dst",
    "window": {
      "external_id": "tv-weekly-dst",
      "kind": "weekly",
      "timezone": "America/New_York",
      "access_hours": {
        "sun": [["01:00", "03:30"]],
        "mon": [],
        "tue": [],
        "wed": [],
        "thu": [],
        "fri": [],
        "sat": []
      }
    },
    "expect": "Evaluate local wall time: skipped times do not occur; both repeated 01:30 instants qualify."
  }
]

Также отправьте отрицательные векторы для миллисекунд Unix, числовых строк, чисел с плавающей запятой, недопустимых часовых поясов IANA, from >= to, повторяющихся external_id, пересекающихся блоков, ночных блоков, более восьми блоков в день, более 50 окон и несопоставленных ключей областей.

Сохранение участника

Создает или обновляет записи участников. API определяет, создавать или обновлять запись, на основе member_id.

Параметры

  • members array обязательный

    Массив объектов Member для сохранения. Рекомендуемый максимум для оптимальной производительности — 1000 элементов на запрос. API автоматически разбивает элементы на пакеты для обработки. Каждый элемент должен содержать либо facility_id (обязателен, если не используется linking_identifier), либо linking_identifier (обязателен, если не используется facility_id).

    Если участник содержит access_time_windows, он также должен содержать access_time_windows_revision. Массив представляет собой полный снимок источника, а не исправление. Не указывайте его, чтобы сохранить существующий снимок, или отправьте [] с более новой ревизией, чтобы отозвать все окна, принадлежащие источнику. Перед включением этого поля прочитайте руководство по Access Time Windows.

Возвращаемое значение

Возвращает простое сообщение, подтверждающее операцию синхронизации.

Поля профиля участника обрабатываются как обычные операции upsert, даже если снимок окон зарегистрирован как идемпотентный повтор или пропуск устаревших данных. Конфликтующий снимок (та же ревизия, другая полезная нагрузка) нельзя повторно отправить без изменений; выполните сверку состояния источника и отправьте более новую ревизию.

Запрос

curl -X POST https://partner-api.performancehub.co/partner/v1/members \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "members": [
      {
        "member_id": "member_11111",
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        // "linking_identifier": "branch_downtown",  // If using linking identifier
        "first_name": "John",
        "last_name": "Smith",
        "email": "john.smith@example.com",
        "mobile_phone": "+61 412 345 678",
        "date_of_birth": "1985-06-15",
        "gender": "male",
        "type": "member",
        "tags": ["vip", "personal-training"],
        "profile_picture": "/9j/4AAQSkZJRgABAQAAAQ...",
        "membership_status": "current",
        "created": "2024-01-15T10:30:00Z",
        "updated": "2024-01-20T14:45:00Z",
        "access_time_windows_revision": 1842,
        "access_time_windows": [
          {
            "external_id": "access-4b1782",
            "kind": "absolute",
            "from": 1792053000,
            "to": 1792058400,
            "timezone": "Australia/Perth",
            "scope_key": "after_hours_entry",
            "label": "Temporary site access"
          }
        ],
        "address": {
          "address_line_1": "456 Bourke Street",
          "address_line_2": "Apt 12",
          "city": "Melbourne",
          "state": "VIC",
          "postal_code": "3000",
          "country": "AU",
          "country_name": "Australia"
        },
        "membership_plans": [
          {
            "membership_plan_id": "plan_99999",
            "name": "Unlimited Monthly",
            "start_date": "2024-01-01T00:00:00Z",
            "status": "current",
            "is_current": true,
            "end_date": null
          }
        ]
      }
    ]
  }'

Ответ

Возвращает сообщение об успешном выполнении с метаданными операции синхронизации.

{
  "message": "Member sync successful.",
  "metadata": {
    "success": 245,
    "skipped": 5,
    "skipped_items": [
      {
        "member_id": "member_123",
        "facility_id": null,
        "reason": "Facility integration is disabled in facility-partner-config"
      }
    ]
  }
}

Поля метаданных:

  • success — количество успешно обработанных участников
  • skipped — количество пропущенных участников (если есть)
  • skipped_items — массив пропущенных участников с указанием причин (если есть)
  • dry-run — логический флаг при использовании ключа типа dryrun (если применимо)

Посещения

Представляет запись о присутствии человека на объекте, занятии или мероприятии. Используется для учета посещаемости, аналитики использования и повышения точности визуального распознавания.

Конечные точки

POST /partner/v1/check-ins - Save check-ins

Объект Check-In

Атрибуты

  • check_in_id string необязательный

    Уникальный идентификатор посещения. Необязательный параметр: если он не указан, он автоматически формируется из пары member_id и timestamp.

  • member_id string обязательный

    Уникальный идентификатор участника.

  • facility_id string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Уникальный идентификатор объекта в Performance Hub.

  • linking_identifier string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Уникальное значение идентификатора каждой площадки, используемое партнером (например, "Branch ID", "Location Code", "Store Number"). Подробнее

  • check_in_type string необязательный

    Тип визита. Одно из значений: member, class, staff, guest или trial.

  • source string необязательный

    Способ регистрации посещения. Распространенные значения: manual, tag, rfid, kiosk, app. Также могут использоваться дополнительные значения, например door_reader или booking.

  • class_id string необязательный

    Необязательный параметр. Указывается, если посещение связано с бронированием или посещением занятия.

  • timestamp string обязательный

    Метка времени посещения в формате ISO 8601.

Объект Check-In

{
  // "check_in_id": "checkin_abc123",  // Optional - auto-generated from member_id + timestamp if not provided
  "member_id": "mem_12345",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  // "linking_identifier": "branch_downtown",  // If using linking identifier
  "check_in_type": "member",
  "source": "rfid",
  "timestamp": "2025-01-20T08:45:30Z"
}

Сохранение посещений

Создает записи о посещениях. API автоматически удаляет дубликаты по участнику, объекту и метке времени.

Параметры

  • check_ins array обязательный

    Массив объектов Check-In для сохранения. Рекомендуемый максимум для оптимальной производительности — 1000 элементов на запрос. API автоматически разбивает элементы на пакеты для обработки. Каждый элемент должен содержать либо facility_id (обязателен, если не используется linking_identifier), либо linking_identifier (обязателен, если не используется facility_id).

Возвращаемое значение

Возвращает простое сообщение, подтверждающее операцию синхронизации.

Запрос

curl -X POST https://partner-api.performancehub.co/partner/v1/check-ins \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "check_ins": [
      {
        // "check_in_id": "checkin_abc123",  // Optional - auto-generated from member_id + timestamp if not provided
        "member_id": "mem_12345",
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        // "linking_identifier": "branch_downtown",  // If using linking identifier
        "check_in_type": "member",
        "source": "rfid",
        "timestamp": "2025-01-20T08:45:30Z"
      }
    ]
  }'

Ответ

Возвращает сообщение об успешном выполнении с метаданными операции синхронизации.

{
  "message": "Check-in sync successful.",
  "metadata": {
    "success": 523,
    "skipped": 3,
    "skipped_items": [
      {
        "member_id": "member_789",
        "facility_id": null,
        "reason": "No matching facility_id for the linking_identifier"
      }
    ]
  }
}

Поля метаданных:

  • success — количество успешно обработанных посещений
  • skipped — количество пропущенных посещений (если есть)
  • skipped_items — массив пропущенных посещений с указанием причин (если есть)
  • dry-run — логический флаг при использовании ключа типа dryrun (если применимо)

Контроль доступа

Partner API может активировать оборудование Door/Gate Controller в Performance Hub на объектах, где включена ваша интеграция.

Используйте этот API, когда ваша система управления участниками уже решила, что человеку разрешен вход. Performance Hub не проверяет статус членства, часы доступа, правила зон дверей, признаки мошенничества или логику приостановки. Ваша система по-прежнему принимает эти решения.

Запрос на разблокировку синхронный. Performance Hub в реальном времени отправляет команду контроллеру на площадке и возвращает 200 только после того, как устройство подтвердит, что реле физически разблокировано. Обычно подтверждение приходит за 3-5 секунд. Если подтверждение не получено в течение времени ожидания, API возвращает явную ошибку.

Вы также можете записать попытку доступа или отказ, не дошедшие до контроллера. Такой вызов не разблокирует дверь, а записывает событие в журналы доступа Door & Gate Access.

Конечные точки

GET /partner/v1/access-control/doors - List available Door/Gate Controllers
GET /partner/v1/access-control/doors/{door_id} - Get Door/Gate Controller status
POST /partner/v1/access-control/doors/{door_id}/unlock - Unlock a Door/Gate Controller
POST /partner/v1/access-control/doors/{door_id}/access-events - Record an access attempt or denial

Объект Door/Gate Controller

Атрибуты

  • door_id string обязательный

    Уникальный идентификатор контроллера Door/Gate Controller. Сохраните его в своей системе после обнаружения и используйте при вызове конечной точки разблокировки.

  • facility_id string обязательный

    Идентификатор объекта в Performance Hub.

  • linking_identifier string необязательный

    Идентификатор объекта на стороне партнера, если ваша интеграция использует связующие идентификаторы. Подробнее

  • name string обязательный

    Удобочитаемое имя устройства, заданное в Performance Hub.

  • zone string необязательный

    Зона или расположение двери, например Entrance.

  • status string обязательный

    online или offline.

  • relay_state string необязательный

    Последнее известное состояние реле, например locked или unlocked.

  • maintenance_mode string обязательный

    Текущий режим обслуживания. Одно из значений: off, force-open или force-closed.

  • hold_time_seconds integer обязательный

    Время удержания разблокировки по умолчанию, настроенное для двери.

  • last_seen string необязательный

    Метка времени ISO последнего обновления метаданных устройства.

Объект Door/Gate Controller

{
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "linking_identifier": "branch_downtown",
  "name": "Front Door",
  "zone": "Entrance",
  "status": "online",
  "online": true,
  "relay_state": "locked",
  "maintenance_mode": "off",
  "hold_time_seconds": 10,
  "last_seen": "2026-05-01T04:30:00.000Z"
}

Список контроллеров Door/Gate Controller

Возвращает контроллеры Door/Gate Controller, доступные вашей интеграции.

Если не указан ни facility_id, ни linking_identifier, API возвращает контроллеры Door/Gate Controller на всех объектах, связанных с вашей партнерской учетной записью.

Recommended: Include a facility identifier whenever possible. Requests without `facility_id` or `linking_identifier` may take longer to load for partners with hundreds or thousands of Door/Gate Controllers.

Параметры

  • facility_id string необязательный одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Идентификатор объекта в Performance Hub. Используйте его для интеграций с прямой связью.

  • linking_identifier string необязательный одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Ваш собственный идентификатор объекта или площадки. Используйте его, если ваша интеграция настроена на связующие идентификаторы.

Возвращаемое значение

Возвращает массив объектов Door/Gate Controller.

Запрос

curl -X GET "https://partner-api.performancehub.co/partner/v1/access-control/doors?facility_id=550e8400-e29b-41d4-a716-446655440000" \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:

Ответ

{
  "data": [
    {
      "door_id": "00000000000000000000000000000007",
      "facility_id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Front Door",
      "zone": "Entrance",
      "status": "online",
      "relay_state": "locked",
      "maintenance_mode": "off",
      "hold_time_seconds": 10,
      "last_seen": "2026-05-01T04:30:00.000Z"
    }
  ]
}

Получение состояния контроллера Door/Gate Controller

Возвращает последнее известное состояние и основную конфигурацию одного контроллера Door/Gate Controller.

Укажите идентификатор объекта, чтобы Performance Hub мог убедиться, что дверь принадлежит объекту, к которому у вашей интеграции есть доступ.

Параметры

  • door_id string обязательный

    Идентификатор контроллера Door/Gate Controller, возвращаемый конечной точкой получения списка.

  • facility_id string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Идентификатор объекта в Performance Hub. Обязателен для интеграций с прямой связью.

  • linking_identifier string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Идентификатор объекта на стороне партнера. Обязателен для интеграций со связующим идентификатором.

Возвращаемое значение

Возвращает объект Door/Gate Controller.

Запрос

curl -X GET "https://partner-api.performancehub.co/partner/v1/access-control/doors/00000000000000000000000000000007?facility_id=550e8400-e29b-41d4-a716-446655440000" \
  -u sk_live_YOUR_PARTNER_SECRET_KEY:

Ответ

{
  "data": {
    "door_id": "00000000000000000000000000000007",
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Front Door",
    "zone": "Entrance",
    "status": "online",
    "relay_state": "locked",
    "maintenance_mode": "off",
    "hold_time_seconds": 10,
    "last_seen": "2026-05-01T04:30:00.000Z"
  }
}

Разблокировка контроллера Door/Gate Controller

Отправляет команду разблокировки контроллеру Door/Gate Controller и ожидает подтверждения от физического реле о том, что разблокировка выполнена.

Перед вызовом этой конечной точки ваша система должна решить, есть ли у человека право доступа. Performance Hub проверяет только ключ партнера, доступ к объекту, принадлежность двери и состояние устройства.

Параметры

  • door_id string обязательный

    Идентификатор контроллера Door/Gate Controller, возвращаемый конечной точкой получения списка.

  • facility_id string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Идентификатор объекта в Performance Hub. Обязателен для интеграций с прямой связью.

  • linking_identifier string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Идентификатор объекта на стороне партнера. Обязателен для интеграций со связующим идентификатором.

  • member_id string обязательный

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

  • first_name string обязательный

    Имя человека, открывающего дверь.

  • last_name string обязательный

    Фамилия человека, открывающего дверь.

  • full_name string необязательный

    Необязательный параметр. Если он не указан, Performance Hub объединяет first_name и last_name.

  • check_in_id string необязательный

    Необязательный идентификатор посещения из вашей системы для сопоставления.

  • idempotency_key string необязательный

    Необязательный ключ защиты от повторов. При повторном использовании того же ключа для того же партнера, объекта и двери возвращается существующий результат, если он доступен.

Возвращаемое значение

Возвращает 200 только в том случае, если устройство подтверждает, что реле физически разблокировано. Дверь использует время удержания, настроенное в разделе «Управление устройствами» Performance Hub; партнеры не могут переопределять время срабатывания реле в отдельном запросе. Обычно подтверждение приходит за 3-5 секунд. Рассматривайте истечение документированного времени ожидания как явную неудачу разблокировки и повторяйте попытку только в соответствии с собственными правилами безопасности.

Типичные ошибки:

  • 403 integration_not_enabled — ваша интеграция не включена для объекта.
  • 409 maintenance_mode_active — персонал объекта включил для двери режим обслуживания.
  • 503 device_offline — контроллер Door/Gate Controller не в сети или его данные устарели.
  • 504 unlock_confirmation_timeout — команда отправлена, но соответствующее подтверждение не получено до истечения времени ожидания.

Запрос

curl -X POST https://partner-api.performancehub.co/partner/v1/access-control/doors/00000000000000000000000000000007/unlock \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "member_id": "mem_12345",
    "first_name": "Jane",
    "last_name": "S.",
    "full_name": "Jane S.",
    "source": "door_reader",
    "idempotency_key": "unlock_20260501_0001"
  }'

Ответ

{
  "status": "unlocked",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "event_id": "00000000-0000-0000-0000-000000000045",
  "command_id": "00000000-0000-0000-0000-000000000049",
  "hold_time_seconds": 10,
  "confirmed_at": "2026-05-01T04:30:00.000Z"
}

Ответ с ошибкой

{
  "status": "failed",
  "reason": "device_offline",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "event_id": "00000000-0000-0000-0000-000000000045"
}

Запись попытки доступа или отказа

Записывает попытку доступа или отказ, решение о котором ваша система уже приняла. Обращения к контроллеру Door/Gate Controller не происходит, и дверь не разблокируется.

Используйте этот вызов, когда ваша система отказывает во входе или когда попытка должна отобразиться в журналах доступа Door & Gate Access без разблокировки. Performance Hub не проверяет статус членства, часы доступа или другие правила доступа.

Событие отказа отображается в журналах доступа Door & Gate Access с результатом Denied, именем вашего партнера, дверью, идентификатором участника (если вы его передали) и кодом причины в удобочитаемом виде. Например, membership_expired отображается как "Membership Expired". Значения reason_display_text и user_email сохраняются вместе с событием.

Параметры

  • door_id string обязательный

    Идентификатор контроллера Door/Gate Controller, возвращаемый конечной точкой получения списка.

  • facility_id string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Идентификатор объекта в Performance Hub. Обязателен для интеграций с прямой связью.

  • linking_identifier string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Идентификатор объекта на стороне партнера. Обязателен для интеграций со связующим идентификатором.

  • outcome string обязательный

    denied или attempted.

  • reason string необязательный

    Код причины в нижнем регистре в формате snake_case, до 64 символов. Обязателен, если outcome имеет значение denied. Пример: membership_expired.

  • reason_display_text string необязательный

    Удобочитаемая причина, до 256 символов. Пример: Membership expired on 2026-04-01.

  • member_id string необязательный

    Идентификатор участника на стороне партнера. Не указывайте его, если учетные данные не соответствуют ни одному участнику, например при использовании неизвестной карты.

  • user_email string необязательный

    Адрес электронной почты человека, пытавшегося получить доступ.

  • timestamp string необязательный

    Время попытки в формате ISO 8601 с часовым поясом. Пример: 2026-05-18T10:15:30Z. По умолчанию используется время получения запроса. Значение не должно опережать текущее время более чем на 5 минут или быть старше 30 дней.

  • idempotency_key string необязательный

    Ключ защиты от повторов, до 128 символов. При повторном использовании того же ключа для того же партнера, объекта и двери возвращается исходный результат.

Возвращаемое значение

Возвращает 201, если событие записано. Повторная отправка с тем же idempotency_key возвращает 200 со значением idempotent, равным true, и не создает новое событие.

Ключ dry-run возвращает 200 со значением dry_run, равным true. Ничего не записывается.

Типичные ошибки:

  • 400 — тело запроса недопустимо, для отказа не указан reason, время вне допустимого диапазона или facility_id / linking_identifier не соответствует связанному объекту.
  • 403 — ключ предназначен только для чтения.
  • 403 integration_not_enabled — ваша интеграция не включена для объекта. Причина указана в message.
  • 404 — контроллер Door/Gate Controller не найден для связанного объекта.

Запрос

curl -X POST https://partner-api.performancehub.co/partner/v1/access-control/doors/00000000000000000000000000000007/access-events \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "facility_id": "550e8400-e29b-41d4-a716-446655440000",
    "outcome": "denied",
    "reason": "membership_expired",
    "reason_display_text": "Membership expired on 2026-04-01",
    "member_id": "mem_12345",
    "user_email": "member@example.com",
    "timestamp": "2026-05-18T10:15:30Z",
    "idempotency_key": "evt_abc12345"
  }'

Ответ

{
  "status": "recorded",
  "event_id": "00000000-0000-0000-0000-000000000045",
  "outcome": "denied",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-05-18T10:15:30.000Z"
}

Идемпотентный повтор

{
  "status": "recorded",
  "event_id": "00000000-0000-0000-0000-000000000045",
  "outcome": "denied",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "timestamp": "2026-05-18T10:15:30.000Z",
  "idempotent": true
}

Отчеты объекта

Запись на определенный момент времени, содержащая ключевые операционные и финансовые показатели объекта за определенный период.

Конечные точки

POST /partner/v1/report-snapshots - Save report snapshots

Объект Report Snapshot

Атрибуты

  • facility_id string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Уникальный идентификатор объекта в Performance Hub.

  • linking_identifier string одно из двухУкажите тип идентификатора объекта, настроенный для вашей интеграции: facility_id для интеграций с прямой связью или linking_identifier для интеграций со связующим идентификатором. Не отправляйте оба; API использует тип идентификатора, настроенный для вашей партнерской учетной записи, и игнорирует другой. Подробнее

    Уникальное значение идентификатора каждой площадки, используемое партнером (например, "Branch ID", "Location Code", "Store Number"). Подробнее

  • start_date string обязательный

    Дата начала периода снимка в формате YYYY-MM-DD.

  • end_date string обязательный

    Дата окончания периода снимка в формате YYYY-MM-DD.

  • metrics object обязательный

    Объект показателей с данными об участниках и выручке за период.

Объект Report Snapshot

{
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  // "linking_identifier": "branch_downtown",  // If using linking identifier
  "start_date": "2025-01-01",
  "end_date": "2025-01-31",
  "metrics": {
    "members": {
      "active": 1200,
      "new": 45,
      "cancelled": 12
    },
    "revenue": {
      "total_payments": 289000.00,
      "total_payments_count": 1200,
      "currency": "AUD"
    }
  }
}

Сохранение снимков отчетов

Передает операционные и финансовые показатели объекта за определенный период.

Параметры

  • snapshots array обязательный

    Массив объектов Report Snapshot для сохранения. Не более 25 элементов на запрос. Каждый элемент должен содержать либо facility_id (обязателен, если не используется linking_identifier), либо linking_identifier (обязателен, если не используется facility_id).

Возвращаемое значение

Возвращает простое сообщение, подтверждающее операцию синхронизации.

Запрос

curl -X POST https://partner-api.performancehub.co/partner/v1/report-snapshots \
  -u sk_live_YOUR_PARTNER_SECRET_KEY: \
  -H "Content-Type: application/json" \
  -d '{
    "snapshots": [
      {
        "facility_id": "550e8400-e29b-41d4-a716-446655440000",
        // "linking_identifier": "branch_downtown",  // If using linking identifier
        "start_date": "2025-01-01",
        "end_date": "2025-01-31",
        "metrics": {
          "members": {
            "active": 1200,
            "new": 45,
            "cancelled": 12
          },
          "revenue": {
            "total_payments": 289000.00,
            "currency": "AUD"
          }
        }
      }
    ]
  }'

Ответ

{
  "message": "Report snapshot sync successful."
}

Ошибки

Partner API использует стандартные коды состояния HTTP и тела ответов в формате JSON, чтобы объяснить причину неудачного запроса.

Структура ответа с ошибкой

Большинство ошибок API возвращают тело JSON с сообщением и, если доступно, структурированными подробностями.

Коды состояния

Ошибки Access Time Windows

Проверка окон завершается ошибкой до того, как недопустимый снимок будет записан. Распространенные причины, при которых повторная попытка не поможет:

  • Отсутствует access_time_windows_revision, хотя указан access_time_windows.
  • Строковые значения, значения с плавающей запятой или значения эпохи, вероятно указанные в миллисекундах.
  • Недопустимый часовой пояс IANA, перевернутый интервал, повторяющийся external_id, пересекающиеся еженедельные блоки или неразделенный ночной блок.
  • Значение, выходящее за документированные ограничения по количеству, длине или продолжительности.

Повторная ревизия с другим нормализованным содержимым приводит к ошибке 409 Conflict. Выполните сверку с последним состоянием основного источника и назначьте более новую ревизию; не повторяйте попытки с конфликтующей парой. Более старая ревизия регистрируется как устаревший пропущенный снимок и не может перезаписать более новое состояние. Неизвестный или несопоставленный scope_key приводит к отказу в авторизации и должен рассматриваться как оповещение о проблеме конфигурации.

Если при доставке истекло время ожидания или получена временная ошибка 5xx, повторите отправку точно того же нормализованного снимка с той же ревизией. Если не удалось получить данные из вышестоящего источника, полностью опустите поле окон; никогда не подставляйте пустой массив.

Рекомендации по повторным попыткам

Повторяйте следующие запросы с ограниченной экспоненциальной задержкой:

  • 429
  • 500
  • 502
  • 503
  • 504

Не повторяйте вслепую следующие запросы:

  • 400
  • 401
  • 403
  • 404
  • 409
  • 422

В контексте контроля доступа всегда рассматривайте тайм-аут и ответы о том, что устройство не в сети, как неудачную разблокировку, если ваши собственные правила доступа и процессы безопасности не предписывают иное.

Сведения для службы поддержки

При обращении в службу поддержки укажите:

  • Конечную точку и метод HTTP.
  • Время и часовой пояс.
  • Идентификатор ключа партнера (не сам секретный ключ).
  • Использованный идентификатор объекта.
  • Идентификатор исходной записи в вашей системе.
  • Состояние и тело ответа.
  • event_id или command_id, если доступны.
{
  "success": false,
  "message": "Request body.members[0].member_id is required"
}

Некоторые предметные конечные точки возвращают явное состояние и причину. Например, ошибки контроля доступа содержат такие поля, как reason, door_id, facility_id и event_id.

{
  "status": "failed",
  "reason": "device_offline",
  "door_id": "00000000000000000000000000000007",
  "facility_id": "550e8400-e29b-41d4-a716-446655440000",
  "event_id": "00000000-0000-0000-0000-000000000045"
}

400 Bad Request

Запрос сформирован неправильно или в нем отсутствуют обязательные поля. Исправьте запрос, прежде чем повторять попытку.

401 Unauthorized

Ошибка аутентификации. Убедитесь, что вы используете HTTP Basic Auth с секретным ключом API в качестве имени пользователя и пустым паролем.

403 Forbidden

Ключ действителен, но операция не разрешена. Распространенные причины: использование ключа только для чтения для операции записи или попытка доступа к объекту, для которого ваша интеграция не включена.

404 Not Found

Запрошенный ресурс не найден или недоступен вашей интеграции.

409 Conflict

Запрос конфликтует с текущим состоянием ресурса. В контексте контроля доступа это может означать, что контроллер Door/Gate Controller находится в режиме обслуживания.

422 Unprocessable Entity

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

429 Too Many Requests

Интеграция превысила документированное ограничение частоты запросов. Повторите попытку с экспоненциальной задержкой.

500 Internal Server Error

Performance Hub не удалось выполнить запрос из-за внутренней ошибки. Повторите попытку с задержкой. Если проблема не исчезнет, обратитесь в службу поддержки, указав конечную точку, метку времени и тело ответа.

503 Service Unavailable

Зависимая служба или устройство недоступны. При разблокировке контроллера Door/Gate Controller это может означать, что контроллер не в сети.

504 Gateway Timeout

Истекло время ожидания операции. При разблокировке контроллера Door/Gate Controller это означает, что разблокировка не была подтверждена до истечения времени ожидания.

Управление версиями

Версия Partner API указывается в URL-адресе. Текущая версия:

Политика изменений

По возможности Performance Hub стремится вносить дополняющие изменения с сохранением обратной совместимости.

Примеры изменений с обратной совместимостью:

  • Добавление нового необязательного поля в запрос.
  • Добавление нового поля в ответ.
  • Добавление новой конечной точки.
  • Добавление нового значения перечисления, если клиенты должны обрабатывать неизвестные значения.
  • Улучшение сообщений проверки без изменения контракта кодов состояния.

access_time_windows и access_time_windows_revision — дополнительные поля запроса Member. У существующих клиентов, которые их не указывают, сохраненный снимок Access Time Windows остается без изменений. Это правило опускания сохраняет совместимость с частичными операциями upsert; опускание поля не равнозначно отправке пустого массива.

Примеры изменений, нарушающих совместимость:

  • Удаление или переименование поля.
  • Изменение типа поля.
  • Превращение необязательного поля запроса в обязательное.
  • Удаление конечной точки.
  • Изменение значения существующего кода состояния или предметного reason.

Вывод из использования

Если требуется изменение, нарушающее совместимость, Performance Hub по возможности не будет изменять существующую версию на месте. Вместо этого мы представим новую версию или путь миграции и сообщим об изменении затронутым партнерам.

Уведомления о выводе из использования могут включать:

  • Запись в журнале изменений.
  • Прямое информирование партнеров.
  • Примечания в Partner Console.
  • Рекомендации по миграции в документации.

Рекомендации для клиентов

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

  • Игнорируйте поля ответа, которые вы не используете.
  • Рассматривайте неизвестные значения перечислений как неподдерживаемые, а не завершайте работу аварийно.
  • Избегайте строгих проверок на точное совпадение ответов.
  • Регистрируйте нераспознанные значения, чтобы обновлять интеграцию осознанно.

Для разделов Member с ревизиями, таких как Access Time Windows, сохраняйте отправленную ревизию и нормализованную полезную нагрузку, пока не станет известен результат. Повторное использование ревизии для измененного содержимого приводит к конфликту, а повторная отправка того же содержимого идемпотентна. См. раздел Access Time Windows.

Спецификации OpenAPI

Используйте опубликованные спецификации OpenAPI для создания клиентов, проверки запросов и отслеживания изменений структуры API со временем.

См. раздел Спецификации OpenAPI.

https://partner-api.performancehub.co/partner/v1/

Журнал изменений

В этом журнале изменений фиксируются значимые изменения Partner API и Partner Console, влияющие на работу интеграций.

2026-09-09

2026-05-06

2026-05-01

Категории изменений

В будущих записях используются следующие категории:

  • Добавлено — новая конечная точка, поле, руководство или возможность.
  • Изменено — изменение поведения или документации без прекращения поддержки.
  • Устарело — функция остается доступной, но для нее запланирован путь миграции.
  • Удалено — функция или конечная точка удалена.
  • Исправлено — исправление ошибки или уточнение документации.
  • Безопасность — изменение аутентификации, авторизации, обработки данных или управления ключами.

Добавлено

  • Добавлены независимые от поставщика снимки access_time_windows участника со смешанными абсолютными и еженедельными повторяющимися окнами.
  • Добавлены упорядочение по access_time_windows_revision, идемпотентный повтор, обработка конфликтов, пропуск устаревших данных и семантика явного отзыва.
  • Добавлены рекомендации по часовым поясам IANA, летнему времени, логическому сопоставлению scope_key, актуальности исходных данных, реализации на стороне поставщика данных и сертификации.

Добавлено

  • Добавлена документация партнерской программы: типы партнеров, подключение, рекомендации, готовность к запуску, ошибки, управление версиями и поддержка.
  • Добавлена отдельная форма запроса «Стать партнером» для потенциальных технических и коммерческих партнеров.
  • Добавлена документация о том, как одобренные партнерские интеграции отображаются в каталоге партнеров Performance Hub на основной платформе Performance Hub.

Добавлено

  • Добавлена документация по контролю доступа через Door/Gate Controller, включая операции получения списка, состояния и разблокировки.
  • Добавлена документация по синхронной разблокировке: API возвращает успешный результат только после того, как контроллер на площадке подтвердит, что реле физически разблокировано.
  • Добавлена документация по поддержке необязательного параметра idempotency_key в запросах на разблокировку Door/Gate Controller.