Wprowadzenie

Performance Hub Partner API umożliwia zewnętrznym platformom partnerów płynną integrację z podstawowymi modułami Performance Hub. API obsługuje wizję komputerową, analitykę, rejestrowanie dostępu członków i analizy dotyczące obiektów.

Format żądań

API przyjmuje treść żądań zakodowaną w formacie JSON i zwraca odpowiedzi zakodowane w formacie JSON.

Ograniczanie liczby żądań

Aby zapewnić uczciwe korzystanie i stabilność systemu, konta Partner API zaczynają od domyślnych limitów:

  • 5 żądań na sekundę na punkt końcowy
  • Zalecane: maksymalnie 1000 elementów na żądanie zbiorcze w celu zapewnienia optymalnej wydajności
  • Maksymalnie 10MB rozmiaru ładunku

Limity liczby żądań można dostosować — opiekun konta partnera Performance Hub może je skonfigurować indywidualnie. Jeśli Twoja integracja potrzebuje większej przepustowości na potrzeby uruchomienia, migracji, uzupełniania danych raportowych lub obiektów o dużym natężeniu ruchu, zgłoś to podczas wdrażania lub przed planowanym oknem zmian.

Bazowy adres URL

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

Uwierzytelnianie

Dostęp do Partner API wymaga uwierzytelniania za pomocą tajnych kluczy API. Klucze można generować i nimi zarządzać w Partner Console.

Klucze API są Twoimi poświadczeniami dostępu do zasobów partnera. Każdy klucz ma ograniczony dostęp do danych określonej organizacji i w razie potrzeby można go natychmiast dezaktywować.

Obchodź się z kluczami API ostrożnie — zapewniają one pełny dostęp do Twojego konta! Nigdy nie ujawniaj tych kluczy w publicznych repozytoriach, aplikacjach po stronie klienta ani w żadnym miejscu, w którym mogłyby zostać przejęte.

Uwierzytelniaj żądania za pomocą HTTP Basic Auth, przekazując klucz API jako nazwę użytkownika. Pole hasła pozostaw puste.

API akceptuje wyłącznie bezpieczne połączenia HTTPS. Zwykłe żądania HTTP są odrzucane, podobnie jak wszystkie żądania bez prawidłowych poświadczeń uwierzytelniających.

Przykładowe żądanie

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.

Weryfikacja tajnego klucza

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>" }

Lista kontrolna uruchomienia produkcyjnego

Skorzystaj z tej listy kontrolnej przed włączeniem integracji partnera dla obiektów produkcyjnych.

Konfiguracja Partner Console

  • Profil partnera jest kompletny.
  • Adres URL logo, witryna, kategoria i opis są poprawne.
  • Metoda łączenia danych jest skonfigurowana: Direct Link lub Linking Identifier.
  • Łączenie obiektów zostało przetestowane na co najmniej jednym rzeczywistym obiekcie.
  • Używany jest właściwy typ klucza:
    • Dryrun do nieniszczących testów zapisu.
    • Read-only do bezpiecznego pobierania danych.
    • Live tylko wtedy, gdy możesz już wpływać na dane produkcyjne.

Uwierzytelnianie i zarządzanie kluczami

  • Tajne klucze są przechowywane wyłącznie po stronie serwera.
  • Klucze nie są osadzone w aplikacjach po stronie klienta, aplikacjach mobilnych, publicznych repozytoriach ani zgłoszeniach do pomocy technicznej.
  • Rotacja i unieważnianie kluczy zostały przetestowane.
  • Twój zespół wie, który klucz jest używany w którym środowisku.

Walidacja danych

  • Wymagane pola są obecne w każdym wywoływanym punkcie końcowym.
  • Identyfikatory obiektów są zgodne ze skonfigurowaną metodą łączenia.
  • Identyfikatory z Twojego systemu są stabilne i nie zmieniają się między synchronizacjami.
  • Duże importy są dzielone na partie w granicach udokumentowanych limitów.
  • Nieudane elementy partii można zidentyfikować i wysłać ponownie.

Testowanie punktów końcowych

Przed uruchomieniem przetestuj każdy punkt końcowy, od którego zależy Twoja integracja:

  • Można odczytać organizacje i obiekty.
  • Można zapisywać i aktualizować członków.
  • Plany członkostwa, strefy dostępu i godziny dostępu synchronizują się poprawnie.
  • Wejścia są akceptowane i można je powiązać z Twoim systemem.
  • Migawki raportów używają oczekiwanego okresu raportowania i wskaźników.
  • Procesy kontrolerów drzwi/bram zostały przetestowane na rzeczywistym sprzęcie, jeśli dotyczy.

Gotowość Access Time Windows

Jeśli integracja dostarcza Access Time Windows:

  • Przykłady okien bezwzględnych i tygodniowych przechodzą listę kontrolną certyfikacji producenta.
  • Wartości epoki są liczbami całkowitymi sekund Unix bez cudzysłowów; dokładne granice [from, to) zostały przetestowane.
  • Zweryfikowano domyślne ustawienia UTC, niestandardowe strefy czasowe IANA integracji i odpowiednie zmiany czasu letniego.
  • Jeden trwały, monotoniczny strumień wersji członka/źródła koordynuje aktualizacje przyrostowe, uzgadnianie i ponowienia.
  • Operatorzy rozumieją działanie w przypadku pominięcia, pełnego zastąpienia, idempotencji, konfliktu, nieaktualności i jawnego [].
  • Każdy scope_key, w tym default, ma zatwierdzone mapowanie w Performance Hub; przetestowano, że nieznane klucze powodują odmowę dostępu.
  • Skonfigurowano oczekiwaną częstotliwość odświeżania integracji, maksymalny wiek danych źródłowych, zachowanie przy nieaktualnym źródle i alerty.
  • Udowodniono, że błąd pobierania danych ze źródła nie powoduje wysłania pustej ani częściowej migawki.
  • Zbieżność strumienia w środowisku staging, anulowanie/odwołanie oraz granice rozpoczęcia i zakończenia na fizycznych drzwiach spełniają uzgodnione cele.
  • Zweryfikowano zwykłe reguły i stałe uprawnienia jako ścieżki zapasowe, a okna nie mogą obejść wyłączenia użytkownika, blockAllAccess, trybu serwisowego ani geofencingu.

Gotowość kontroli dostępu

W przypadku integracji kontroli dostępu:

  • Twój system podejmuje decyzję o dostępie przed wywołaniem Performance Hub.
  • Integracja obsługuje device_offline, maintenance_mode_active i unlock_confirmation_timeout.
  • Operatorzy rozumieją, że przekroczenie limitu czasu oznacza, że otwarcie nie zostało potwierdzone.
  • Twoje dzienniki zapisują zwracane wartości event_id i command_id.
  • Masz ręczny proces awaryjny dla personelu obiektu.

Obsługa błędów i ponowień

  • Odpowiedzi 400, 401, 403, 404, 409 i 422 są przekazywane operatorom lub zespołom wsparcia, a nie ponawiane bezrefleksyjnie.
  • Odpowiedzi 429, 500, 502, 503 i 504 korzystają z ograniczonej logiki ponowień z wydłużaniem odstępów.
  • Powtarzające się błędy generują alert w Twoim systemie.
  • Integracja nigdy nie pomija po cichu nieudanych rekordów.

Obserwowalność

  • Twoje dzienniki zawierają punkt końcowy, znacznik czasu, identyfikator obiektu, identyfikator rekordu źródłowego, wynik żądania i treść odpowiedzi.
  • Twój zespół wsparcia może wyszukiwać według identyfikatora członka, identyfikatora obiektu, identyfikatora wejścia lub identyfikatora zdarzenia otwarcia.
  • Masz sposób na ponowne odtworzenie lub uzgodnienie nieudanych synchronizacji.

Uruchomienie produkcyjne

  • Performance Hub potwierdził Twój dostęp produkcyjny.
  • Co najmniej jeden obiekt produkcyjny włączył Twoją integrację.
  • Twój klucz produkcyjny jest aktywny.
  • Twoje dane kontaktowe do spraw operacyjnych i technicznych są aktualne.
  • Twój proces wsparcia jest udokumentowany dla klientów.

Po zakończeniu tych kontroli Twoja skonfigurowana integracja pojawi się w katalogu partnerów Performance Hub w ramach podstawowej platformy Performance Hub.

Sprawdzone metody

Stosuj te wzorce, aby integracje partnerów były przewidywalne, łatwe do monitorowania i bezpieczne dla obiektów.

Spójna identyfikacja obiektów

Wybierz metodę łączenia skonfigurowaną dla Twojego konta partnera i stosuj ją konsekwentnie:

  • Direct Link — używaj wartości facility_id Performance Hub zwracanej przez punkt końcowy obiektów.
  • Linking Identifier — używaj własnego identyfikatora lokalizacji, np. identyfikatora oddziału, kodu lokalizacji lub numeru sklepu.

Nie wysyłaj obu identyfikatorów w tym samym żądaniu. Performance Hub rozpoznaje żądania na podstawie metody łączenia skonfigurowanej dla Twojego konta partnera.

Wskazówki dotyczące konfiguracji znajdziesz w sekcji Metody łączenia partnerów.

Ostrożne zapisy zbiorcze

Partner API przyjmuje treść żądań w formacie JSON i tam, gdzie zostało to udokumentowane, jest przeznaczone do procesów synchronizacji opartych na partiach. Partie powinny mieć ograniczony rozmiar i umożliwiać ponawianie.

Domyślne zalecenia:

  • Używaj maksymalnie 1000 elementów na żądanie zbiorcze, aby uzyskać optymalną wydajność.
  • Utrzymuj rozmiar ładunku poniżej 10MB.
  • Nie przekraczaj 5 żądań na sekundę na punkt końcowy.

Limity liczby żądań można dostosować — opiekun konta partnera Performance Hub może je skonfigurować indywidualnie. Jeśli spodziewasz się dużych importów, ruchu podczas uruchomienia lub uzupełniania danych raportowych, uzgodnij wymaganą przepustowość przed oknem zmian.

Jeśli musisz zsynchronizować duży zbiór danych, podziel go na deterministyczne fragmenty i rejestruj po swojej stronie identyfikator każdego fragmentu. Ułatwia to analizę nieudanych ponowień.

Bezpieczne ponawianie

W przypadku przejściowych błędów, takich jak 429, 500, 502, 503 i 504, stosuj wykładnicze wydłużanie odstępów między ponowieniami.

Unikaj ciasnych pętli ponowień. Dobry punkt wyjścia:

  1. Ponów po 1 sekundzie.
  2. Ponów po 2 sekundach.
  3. Ponów po 4 sekundach.
  4. Zatrzymaj się i wygeneruj alert, jeśli operacja nadal kończy się niepowodzeniem.

W przypadku błędów walidacji, takich jak 400 lub 422, popraw żądanie przed ponowieniem.

Korzystanie z idempotencji tam, gdzie jest obsługiwana

Punkt końcowy otwierania kontrolera drzwi/bramy obsługuje opcjonalny idempotency_key. Ponowne użycie tego samego klucza dla tego samego partnera, obiektu i drzwi zwraca istniejący wynik, jeśli jest dostępny.

Używaj stabilnego klucza dla wykonywanej akcji, np. identyfikatora wejścia lub identyfikatora zdarzenia dostępu z Twojego systemu.

Nie zakładaj, że każdy punkt końcowy zapisu obsługuje idempotencję, chyba że zostało to udokumentowane dla danego punktu końcowego.

Dbanie o czystość danych źródłowych

W miarę możliwości wysyłaj stabilne, znormalizowane wartości:

  • Używaj spójnych identyfikatorów członków, planów, obiektów i wejść z systemu źródłowego.
  • Używaj znaczników czasu ISO 8601 dla dat i godzin.
  • Wysyłaj numery telefonów w formacie międzynarodowym, jeśli są dostępne.
  • Wysyłaj waluty w polach udokumentowanych dla poszczególnych punktów końcowych.
  • Nie przeciążaj pól tekstowych danymi, które należą do pól strukturalnych.

Projektowanie pod kątem synchronizacji przyrostowych i pełnych

Większość integracji partnerów potrzebuje obu rodzajów synchronizacji:

  • Synchronizacji przyrostowych do codziennych zmian.
  • Pełnych synchronizacji uzgadniających do korygowania pominiętych zdarzeń, importów historycznych lub rozbieżności danych.

Integracja powinna umożliwiać ponowne wysłanie bieżącego stanu członka, planu członkostwa lub migawki raportu bez uzależnienia od powodzenia wcześniejszego żądania.

Bezpieczne publikowanie Access Time Windows

Traktuj wartość access_time_windows każdego członka jako kompletną migawkę z niezależną numeracją wersji:

  • Koordynuj jeden monotonicznie rosnący strumień access_time_windows_revision dla procesów przyrostowych i uzgadniających.
  • Ponawiaj niepewne lub przejściowo nieudane dostarczenie z tą samą wersją i znormalizowanym ładunkiem.
  • Pomijaj access_time_windows, gdy nie aktualizujesz tej wartości.
  • Wysyłaj [] dopiero wtedy, gdy udane, wiarygodne pobranie danych ze źródła dowodzi, że nie pozostały żadne okna. Nigdy nie zamieniaj przekroczenia limitu czasu u źródła, częściowego wyniku ani błędu parsowania w odwołanie dostępu.
  • Zachowuj stałe wartości external_id i scope_key oraz certyfikuj każde mapowanie zakresu przed wdrożeniem produkcyjnym.
  • Monitoruj wiek danych źródłowych w odniesieniu do zasad aktualności uzgodnionych dla danej integracji.

Kompletne migawki, strefy czasowe, czas letni, anulowanie i wektory testowe opisano w nadrzędnym przewodniku producenta Access Time Windows.

Kontrola dostępu jako funkcja krytyczna dla bezpieczeństwa

W przypadku otwierania kontrolerów drzwi/bram:

  • Przed wywołaniem Performance Hub Twój system musi zdecydować, czy dana osoba może wejść.
  • Performance Hub zwraca 200 dopiero wtedy, gdy kontroler w obiekcie potwierdzi, że przekaźnik fizycznie zwolnił zamek.
  • Większość potwierdzeń następuje w ciągu 3-5 sekund.
  • Przekroczenie limitu czasu oznacza jednoznacznie nieudane otwarcie, a nie sukces w tle.
  • Ponawiaj próby wyłącznie zgodnie z własnymi zasadami dostępu i bezpieczeństwa.

Zawsze rejestruj wartości event_id i command_id zwracane przez punkt końcowy otwierania.

Monitorowanie integracji

Podczas tworzenia i uruchamiania integracji korzystaj z dzienników żądań w Partner Console. W środowisku produkcyjnym prowadź również własne dzienniki zawierające:

  • Znacznik czasu żądania.
  • Punkt końcowy.
  • Identyfikator rekordu źródłowego.
  • Identyfikator obiektu.
  • Kod stanu HTTP.
  • Treść odpowiedzi lub komunikat o błędzie z Performance Hub.

Te pola znacznie przyspieszają wsparcie i uzgadnianie danych, gdy klient pyta, co się stało.

Organizacje

Reprezentuje podmiot gospodarczy najwyższego poziomu, który prowadzi jeden lub więcej obiektów zintegrowanych z platformą Performance Hub.

Punkty końcowe

GET /partner/v1/organisations - List all organisations

Obiekt Organisation

Atrybuty

  • org_id string wymagany

    Unikatowy identyfikator organizacji.

  • name string wymagany

    Nazwa organizacji.

Obiekt Organisation

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

Lista wszystkich organizacji

Zwraca listę organizacji dostępnych dla Twojego konta partnera.

Zwracane wartości

Zwraca obiekt JSON z właściwością data zawierającą tablicę obiektów Organisation.

Żądanie

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

Odpowiedź

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

Obiekty

Reprezentuje fizyczną lokalizację, taką jak biuro, sklep, obiekt rozrywkowy, kampus, przychodnia lub siłownia, w której członkowie mogą korzystać z usług.

Punkty końcowe

GET /partner/v1/facilities - List all facilities

Struktura danych obiektu

Atrybuty

  • facility_id string wymagany

    Unikatowy identyfikator obiektu.

  • org_id string wymagany

    Unikatowy identyfikator organizacji nadrzędnej.

  • name string wymagany

    Nazwa obiektu.

  • brand string opcjonalny

    Nazwa marki używana przez obiekt.

  • website_url string opcjonalny

    Adres URL witryny obiektu.

  • place_data object opcjonalny

    Dane lokalizacji z Google Places API zawierające kraj, sformatowany adres, Google Place ID, województwo/prowincję i miasto.

  • social_links object opcjonalny

    Linki do mediów społecznościowych obiektu.

  • timezone string opcjonalny

    Identyfikator strefy czasowej IANA (np. "Australia/Sydney", "America/New_York").

Struktura danych obiektu

{
  "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"
}

Lista wszystkich obiektów

Zwraca listę obiektów dostępnych dla Twojego konta partnera.

Zwracane wartości

Zwraca obiekt JSON z właściwością data zawierającą tablicę struktur danych obiektów.

Żądanie

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

Odpowiedź

{
  "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"
    }
  ]
}

Plany członkostwa

Określa ofertę organizacji lub obiektu dostępną do zakupu, w tym usługi, uprawnienia, harmonogram i cennik.

Punkty końcowe

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

Obiekt Membership Plan

Atrybuty

  • membership_plan_id string wymagany

    Unikatowy identyfikator planu członkostwa.

  • facility_id string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Unikatowy identyfikator obiektu z Performance Hub.

  • linking_identifier string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Unikatowa wartość identyfikatora, której partner używa dla każdej lokalizacji (np. „Branch ID”, „Location Code”, „Store Number”). Więcej informacji

  • name string wymagany

    Czytelna nazwa planu (np. "Office tenant – business hours", "Student – term access", "Hotel guest", "10 Class Pack").

  • billing_cycle string opcjonalny

    Częstotliwość rozliczeń. Jedna z wartości: weekly, fortnightly, monthly, annually lub one_time.

  • price integer opcjonalny

    Koszt podstawowy w najmniejszej jednostce waluty (centy w przypadku USD/AUD).

  • currency string opcjonalny

    Kod waluty ISO 4217 (np. "AUD", "USD").

  • description string opcjonalny

    Opcjonalny opis marketingowy lub wewnętrzny.

  • active_members integer opcjonalny

    Liczba aktywnych członków korzystających z tego planu członkostwa

  • is_recurring boolean opcjonalny

    Określa, czy plan odnawia się automatycznie.

  • is_trial boolean opcjonalny

    Określa, czy jest to oferta próbna.

  • visible_to_public boolean opcjonalny

    Określa, czy plan jest dostępny do samodzielnego zakupu.

  • duration_days integer opcjonalny

    Liczba dni ważności planu członkostwa.

  • access_zones array opcjonalny

    Tablica stref dostępu objętych planem członkostwa. Każda strefa może definiować własne godziny dostępu. Szczegóły znajdziesz w sekcji Strefy dostępu.

  • class_limit integer opcjonalny

    Maksymalna dozwolona liczba zajęć (null oznacza brak limitu).

Obiekt Membership Plan

W tym przykładzie użyto facility_id. W przypadku integracji z identyfikatorem łączącym wyślij zamiast tego "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
}

Strefy dostępu

Strefy dostępu określają konkretne obszary obiektu, do których plan członkostwa zapewnia dostęp. Każda strefa może mieć własne godziny dostępu, co pozwala stosować różne ograniczenia czasowe dla poszczególnych obszarów.

Struktura

Każda strefa dostępu zawiera:

  • name string wymagany

    Nazwa strefy (np. "Level 3 Tenancy", "Library", "Guest Floors", "Main Gym Floor").

  • description string opcjonalny

    Opis tego, co obejmuje dana strefa.

  • access_hours object opcjonalny

    Godziny dostępu właściwe dla tej strefy. Format przedziałów czasu opisano w sekcji Godziny dostępu.

Przykład

Biurowiec z siłownią dla najemców: dostęp do wynajmowanej powierzchni w godzinach pracy oraz do siłowni od wczesnego rana do późnego wieczora.

{
  "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"]]
      }
    }
  ]
}

Godziny dostępu

Godziny dostępu określają, kiedy członkowie mogą wchodzić do określonej strefy w poszczególnych dniach tygodnia. Godziny dostępu definiuje się dla każdej strefy dostępu, co pozwala stosować różne ograniczenia czasowe dla różnych części obiektu.

Struktura

{
  "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"]]
}

Każdy dzień jest tablicą przedziałów czasu w formacie HH:MM (zegar 24-godzinny). Pusta tablica [] oznacza brak dostępu w danym dniu. Pominięte dni są traktowane tak samo jak pusta tablica.

Przykładowe przypadki użycia

Najemca biura – godziny pracy: dostęp w godzinach pracy wyłącznie w dni powszednie.

{
  "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"]]
  }
}

Student – dostęp w trakcie semestru: biblioteka kampusu otwarta w dni powszednie z przerwą w środku dnia oraz w soboty rano.

{
  "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"]]
  }
}

Siłownia – ranne ptaszki: dostęp tylko rano w dni powszednie.

{
  "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"]]
  }
}

Gość hotelowy – 24/7: dostęp przez całą dobę, najczęstszy przypadek użycia.

{
  "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"]]
  }
}

Przykład dla poszczególnych stref

Plan dla gości hotelowych z całodobowym dostępem do pięter z pokojami gościnnymi i krótszymi godzinami dostępu do basenu:

{
  "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"]]
      }
    }
  ]
}

Zapisywanie planu członkostwa

Tworzy lub aktualizuje rekordy planów członkostwa. API określa, czy utworzyć, czy zaktualizować rekord, na podstawie membership_plan_id.

Parametry

  • membership_plans array wymagany

    Tablica obiektów Membership Plan do zapisania. Zalecane maksimum: 1000 elementów na żądanie w celu zapewnienia optymalnej wydajności. API automatycznie dzieli elementy na partie do przetworzenia. Każdy element musi zawierać facility_id (wymagany, jeśli nie używasz linking_identifier) lub linking_identifier (wymagany, jeśli nie używasz facility_id).

Zwracane wartości

Zwraca prosty komunikat potwierdzający operację synchronizacji.

Żądanie

W tym przykładzie użyto facility_id. W przypadku integracji z identyfikatorem łączącym wyślij zamiast tego "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
      }
    ]
  }'

Odpowiedź

Zwraca komunikat o powodzeniu z metadanymi operacji synchronizacji.

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

Pola metadanych:

  • success — liczba pomyślnie przetworzonych planów członkostwa
  • skipped — liczba pominiętych planów (jeśli występują)
  • skipped_items — tablica pominiętych planów wraz z przyczynami (jeśli występują)
  • dry-run — flaga logiczna ustawiana przy użyciu klucza typu dryrun (jeśli dotyczy)

Członkowie

Reprezentuje pojedynczego klienta obiektu. Może to być lead, potencjalny klient, stały klient, członek z wygasłym członkostwem lub zablokowany użytkownik.

Operacje upsert członków mogą też zawierać kompletną, wersjonowaną migawkę access_time_windows obejmującą dostęp bezwzględny i cykliczny tygodniowy. Przed generowaniem tych pól zapoznaj się z sekcją Access Time Windows. Są to uprawnienia dodatkowe, które nie zastępują zwykłych reguł obiektu ani stałych uprawnień.

Punkty końcowe

POST /partner/v1/members - Save a member

Obiekt Member

Atrybuty

  • member_id string wymagany

    Unikatowy identyfikator członka.

  • facility_id string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Unikatowy identyfikator obiektu z Performance Hub.

  • linking_identifier string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Unikatowa wartość identyfikatora, której partner używa dla każdej lokalizacji (np. „Branch ID”, „Location Code”, „Store Number”). Więcej informacji

  • first_name string wymagany

    Imię członka.

  • last_name string wymagany

    Nazwisko członka.

  • email string opcjonalny

    Adres e-mail.

  • mobile_phone string opcjonalny

    Numer telefonu komórkowego w formacie E.123 (np. "+1 415 555 2671").

  • address object opcjonalny

    Obiekt adresu fizycznego z następującymi właściwościami:

    • address_line_1 (string) — główny adres (ulica i numer)
    • address_line_2 (string, opcjonalny) — dodatkowy wiersz adresu
    • city (string) — nazwa miasta
    • state (string) — kod stanu/województwa/prowincji
    • postal_code (string) — kod pocztowy/ZIP
    • country (string) — kod kraju ISO 3166-1 alpha-2 (np. "AU", "US")
    • country_name (string, opcjonalny) — pełna nazwa kraju
  • date_of_birth string opcjonalny

    Data urodzenia w formacie YYYY-MM-DD.

  • gender string opcjonalny

    Jedna z wartości: male, female, non_binary, prefer_not_to_say lub unknown.

  • type string opcjonalny

    Typ członka (np. staff, member, prospect).

  • tags array opcjonalny

    Krótkie pomocnicze ciągi znaków lub teksty służące do kategoryzowania i identyfikowania określonych członków (np. ["vip", "personal-training", "student"]).

  • membership_status string opcjonalny

    Bieżący stan członkostwa (np. active, expired, on_hold).

  • membership_plans array opcjonalny

    Tablica planów członkostwa powiązanych z członkiem.

  • profile_picture string opcjonalny

    Zdjęcie profilowe zakodowane w Base64 (opcjonalne).

  • created string opcjonalny

    Znacznik czasu ISO 8601 utworzenia członka.

  • updated string opcjonalny

    Znacznik czasu ISO 8601 ostatniej aktualizacji członka.

  • access_time_windows array opcjonalny

    Kompletna, należąca do źródła migawka bezwzględnych i/lub cyklicznych tygodniowych Access Time Windows. Pomiń to pole, aby pozostawić migawkę bez zmian; wyślij pustą tablicę z nowszą wersją, aby ją odwołać. Kształty, walidację, mapowanie zakresów i semantykę zastępowania opisano w sekcji Access Time Windows.

  • access_time_windows_revision integer wymagany z access_time_windows

    Monotonicznie rosnąca, nieujemna liczba całkowita bezpieczna w JSON dla strumienia danego członka/źródła. Wymagana zawsze, gdy obecne jest access_time_windows.

Obiekt 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
    }
  ]
}

Okna czasowe dostępu

Access Time Windows pozwalają przypisać członkowi partnera tymczasowy lub cykliczny dostęp dostarczany przez system zewnętrzny. Ta strona jest nadrzędnym przewodnikiem dla producentów danych access_time_windows i access_time_windows_revision.

Access Time Windows to dodatkowe uprawnienia, które wyłącznie zezwalają na dostęp. Aktywne okno może zezwolić na dostęp, ale okno nieaktywne, wygasłe, nieaktualne lub niezmapowane nie odbiera dostępu, na który już zezwala zwykła reguła lub stałe uprawnienie. Nadal obowiązują wyłączenie użytkownika, jawne zablokowanie drzwi, tryb serwisowy, geofencing, limity liczby żądań i dostępność kontrolera.

Implementacje dla poszczególnych systemów źródłowych są osobnymi adapterami. Muszą one przekształcać dane źródłowe na ten niezależny od dostawcy kontrakt bez zmieniania znaczenia jego pól.

Pola migawki członka

  • access_time_windows array opcjonalny

    Kompletna migawka Access Time Windows dla tego członka i źródła partnera. Migawka może łączyć okna absolute i weekly. Pomiń to pole, aby pozostawić zapisaną migawkę bez zmian; wyślij [], aby odwołać wszystkie okna należące do tego źródła.

  • access_time_windows_revision integer wymagany z access_time_windows

    Monotonicznie rosnąca, nieujemna liczba całkowita bezpieczna w JSON dla strumienia wersji danego członka/źródła. Jest wymagana zawsze, gdy obecne jest access_time_windows, i nie może przekraczać 9007199254740991.

Każda migawka może zawierać maksymalnie 50 okien. Pola external_id, scope_key i label mogą mieć maksymalnie 120 znaków. Okna bezwzględne mogą obejmować maksymalnie 90 dni. Jeden dzień tygodnia może zawierać maksymalnie osiem nienakładających się bloków. Nieprawidłowe dane są odrzucane, a nie obcinane lub zgadywane.

Kształty okien

Okno bezwzględne określa jeden dokładny przedział:

Kompletne żądanie mieszane

To żądanie zastępuje poprzednią migawkę członka należącą do źródła jednym oknem bezwzględnym i jednym tygodniowym:

Reguły dotyczące czasu i granic

from, to, active_from i active_until to liczby całkowite JSON w sekundach Unix, określające momenty UTC:

  • Wysyłaj liczbę całkowitą JSON bez cudzysłowów. Ciągi liczbowe, liczby zmiennoprzecinkowe, ciągi RFC 3339 i milisekundy Unix są odrzucane.
  • Każdy przedział jest prawostronnie otwarty: [from, to). Dostęp może rozpocząć się dokładnie w momencie from; w momencie to już nie jest aktywny.
  • from musi być mniejsze niż to. Gdy obecne są oba ograniczenia okna tygodniowego, active_from musi być mniejsze niż active_until.
  • Nie wyznaczaj wartości epoki na podstawie lokalnej daty/godziny bez strefy czasowej. Najpierw przekształć czas źródłowy na moment UTC, następnie podziel milisekundy Unix przez 1000 i sprawdź, czy wynik jest liczbą całkowitą.

Strefy czasowe i czas letni

timezone musi być prawidłową strefą czasową IANA, np. UTC, Australia/Perth lub America/New_York. Jeśli zostanie pominięta, domyślnie przyjmowana jest wartość UTC.

  • Okna bezwzględne: from i to już określają dokładne momenty UTC. timezone jest wyłącznie metadaną do wyświetlania i audytu; jej zmiana nigdy nie przesuwa żadnego z tych momentów.
  • Okna tygodniowe: timezone określa lokalny czas zegarowy i reguły czasu letniego używane do oceny access_hours. Nie przeliczaj z góry bloków tygodniowych na UTC.
  • Podczas przejścia na czas letni lokalna godzina, którą strefa czasowa pomija, nigdy nie występuje.
  • Podczas powrotu do czasu zimowego oba rzeczywiste momenty o powtórzonej godzinie lokalnej pasują do bloku tygodniowego.
  • active_from i active_until pozostają momentami UTC nawet wtedy, gdy okno tygodniowe używa strefy czasowej innej niż UTC.

access_hours używa kluczy pisanych małymi literami od sun do sat. Każda wartość jest tablicą par [start, end] w 24-godzinnym formacie HH:mm z zerami wiodącymi. Bloki muszą być niepuste, uporządkowane i nienakładające się. end nie jest wliczany. Blok nie może przechodzić przez północ; podziel nocny przedział źródłowy na późny blok pierwszego dnia i wczesny blok następnego dnia.

Stabilne identyfikatory i mapowanie zakresów

external_id musi pozostawać stały przez cały okres istnienia logicznego okna i być unikatowy w obrębie migawki członka. Zachowuj go bez zmian, gdy zmieniają się godziny lub etykiety, aby operatorzy i rekordy audytu mogli powiązać kolejne wersje. Nie używaj go ponownie dla niepowiązanego okna.

scope_key to Twój stabilny logiczny cel dostępu. Domyślnie ma wartość default. Administrator obiektu mapuje każdy dozwolony klucz na cele Performance Hub obejmujące cały obiekt, konkretne drzwi lub Access Scope:

Kompletne migawki i wersje

Traktuj te dwa pola jako osobno wersjonowaną część operacji upsert członka:

Dane wejściowe Wynik
Pominięto access_time_windows Istniejąca migawka pozostaje bez zmian; wersja nie jest wymagana
Obecne z nowszą wersją Cała zapisana migawka dla tego członka/źródła zostaje zastąpiona
Ta sama wersja i ten sam znormalizowany ładunek Idempotentne ponowne odtworzenie; migawka się nie zmienia
Ta sama wersja i inny znormalizowany ładunek Konflikt; po uzgodnieniu danych przydziel nową wersję
Starsza wersja Nieaktualna migawka zostaje pominięta; nie może nadpisać nowszego stanu
access_time_windows: [] z nowszą wersją Jawnie odwołuje wszystkie okna należące do źródła

Migawka jest kompletna, a nie jest poprawką. Jeśli wersja 1842 zawiera okna A i B, to wersja 1843 zawierająca tylko B usuwa A.

Utrzymuj jeden skoordynowany strumień wersji dla każdej pary partner/członek we wszystkich procesach obsługi webhooków, odpytywania, ponownego odtwarzania i pełnego uzgadniania. Zalecana jest trwała sekwencja w bazie danych. Wartości w milisekundach Unix można używać jako wersji tylko wtedy, gdy wszystkie procesy zapisujące są skoordynowane i gwarantują ścisłą kolejność oraz unikatowość; jest to wartość wersji, a nie pole epoki.

Przechowuj dokładne żądanie i wersję do czasu poznania odpowiedzi API. Po przekroczeniu limitu czasu lub błędzie przejściowym ponów tę samą znormalizowaną migawkę z tą samą wersją. Nie przydzielaj nowej wersji tylko dlatego, że dostarczenie jest niepewne.

Anulowanie, wygaśnięcie i błędy źródła

  • Anulowanie jednego okna: pomyślnie pobierz wiarygodny stan ze źródła, usuń to okno i wyślij pozostałą kompletną migawkę z nowszą wersją.
  • Anulowanie wszystkich okien: wyślij access_time_windows: [] z nowszą wersją.
  • Wygaśnięcie okna bezwzględnego: okno przestaje zezwalać na dostęp w momencie to; aby utrzymać porządek w migawkach, wyślij późniejsze uzgodnienie bez wygasłego wpisu.
  • Zakończenie okna tygodniowego: usuń je w nowszej migawce lub użyj active_until, gdy źródło zna moment zakończenia.
  • Pobranie danych ze źródła nie powiodło się lub jest niekompletne: nie wysyłaj [] i nie publikuj częściowej migawki. Wygeneruj alert i ponów pobranie. Zamiana błędu źródła na pustą migawkę oznacza niezamierzone odwołanie dostępu.
  • Żądanie Partner API nie przeszło walidacji: popraw dane i wyślij nowszą wersję tylko wtedy, gdy znormalizowana migawka się zmienia. Błędy przejściowe ponawiaj z pierwotną wersją.

Aktualność danych źródłowych jest konfigurowana dla każdej integracji na podstawie obiecanej częstotliwości dostarczania i uzgadniania. Przed aktywacją uzgodnij maksymalny wiek danych źródłowych, działanie po jego przekroczeniu, progi alertów oraz to, czy operatorzy mogą zaakceptować poleganie wyłącznie na granicach poszczególnych okien. Nieaktualne okno źródłowe nigdy nie staje się regułą odmowy; zwykłe reguły i stałe uprawnienia pozostają ścieżkami zapasowymi.

Algorytm producenta

Stosuj ten niezależny od języka proces przy każdej aktualizacji członka:

Lista kontrolna certyfikacji

Wykonaj te kontrole w obiekcie testowym (stage), używając ostatecznego mapowania scope_key:

  • Okno bezwzględne bez strefy czasowej jest akceptowane i oceniane jako UTC.
  • Okno bezwzględne z niestandardową strefą IANA zachowuje te same momenty from/to.
  • Okno tygodniowe z niestandardową strefą IANA podąża za lokalnym czasem zegarowym podczas przejścia na czas letni i powrotu do czasu zimowego.
  • Mieszana migawka okien bezwzględnych/tygodniowych całkowicie zastępuje poprzednią migawkę.
  • Dostęp rozpoczyna się dokładnie w momencie from i kończy dokładnie w momencie to; końce bloków tygodniowych również nie są wliczane.
  • Zmiana godzin dla tego samego external_id z nowszą wersją zaczyna obowiązywać.
  • Pominięcie access_time_windows zmienia inne pola członka bez zmiany okien.
  • Ponowne odtworzenie tej samej wersji/ładunku jest idempotentne.
  • Ta sama wersja z innym ładunkiem zwraca konflikt i nie zmienia migawki.
  • Starsza wersja dostarczona poza kolejnością jest zgłaszana jako nieaktualna i nie może cofnąć stanu.
  • Nowsze [] odwołuje okna należące do źródła; błąd pobrania danych ze źródła nie powoduje wysłania niczego.
  • Nieznany lub niezmapowany scope_key powoduje odmowę dostępu i tworzy ostrzeżenie widoczne dla operatora.
  • Alerty dotyczące wieku danych źródłowych i skonfigurowane zasady dla nieaktualnego źródła działają przy uzgodnionym progu.
  • Ścieżki webhooków i pełnego uzgadniania prowadzą do tej samej migawki i kolejności wersji.
  • Dostarczanie strumienia dociera do Door & Gate Access w uzgodnionym czasie docelowym.
  • Aktywne okno może zezwolić na otwarcie zmapowanych fizycznych drzwi, ale nie może obejść wyłączenia użytkownika, blockAllAccess, trybu serwisowego ani geofencingu.
  • Przed oknem, poza nim i po nim zwykłe reguły i stałe uprawnienia nadal zezwalają na dostęp użytkownikom, którzy w inny sposób spełniają warunki.

Powiązane wskazówki

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

Wymagane pola to external_id, kind, from i to. Pola timezone, scope_key i label są opcjonalne.

Okno tygodniowe określa cykliczne przedziały czasu lokalnego, opcjonalnie ograniczone momentami 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"
}

Wymagane pola to external_id, kind i access_hours. Pola timezone, active_from, active_until, scope_key i label są opcjonalne.

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"
          }
        ]
      }
    ]
  }'

Używaj facility_id lub linking_identifier zgodnie ze skonfigurowaną metodą łączenia. Nie wysyłaj obu.

Konwersja epoki

2026-10-15T08:30:00Z po konwersji daje 1792053000:

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

Konwersja niezależna od języka:

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

Jeśli źródło ma precyzję poniżej sekundy, przed testami integracyjnymi określ przemyślane zasady zaokrąglania początku i końca. Nigdy nie przekazuj milisekund w nadziei, że API samo rozpozna jednostkę.

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

Partnerzy nie wysyłają w oknie identyfikatorów obiektów, drzwi ani Access Scope z Performance Hub. Nieznany, wyłączony lub niezmapowany scope_key powoduje odmowę dostępu dla danego okna; nie rozszerza dostępu. Uzgodnij i przetestuj mapowania przed uruchomieniem.

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)

Minimalne wektory testowe

[
  {
    "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."
  }
]

Prześlij również wektory negatywne dla milisekund Unix, ciągów liczbowych, liczb zmiennoprzecinkowych, nieprawidłowych stref IANA, from >= to, zduplikowanego external_id, nakładających się bloków, bloków nocnych, więcej niż ośmiu bloków w ciągu dnia, więcej niż 50 okien i niezmapowanych kluczy zakresu.

Zapisywanie członka

Tworzy lub aktualizuje rekordy członków. API określa, czy utworzyć, czy zaktualizować rekord, na podstawie member_id.

Parametry

  • members array wymagany

    Tablica obiektów Member do zapisania. Zalecane maksimum: 1000 elementów na żądanie w celu zapewnienia optymalnej wydajności. API automatycznie dzieli elementy na partie do przetworzenia. Każdy element musi zawierać facility_id (wymagany, jeśli nie używasz linking_identifier) lub linking_identifier (wymagany, jeśli nie używasz facility_id).

    Jeśli członek zawiera access_time_windows, musi również zawierać access_time_windows_revision. Tablica jest kompletną migawką źródła, a nie poprawką. Pomiń ją, aby zachować istniejącą migawkę, lub wyślij [] z nowszą wersją, aby odwołać wszystkie okna należące do źródła. Przed włączeniem tego pola przeczytaj przewodnik po Access Time Windows.

Zwracane wartości

Zwraca prosty komunikat potwierdzający operację synchronizacji.

Pola profilu członka pozostają zwykłymi operacjami upsert nawet wtedy, gdy migawka okien zostanie zgłoszona jako idempotentne ponowne odtworzenie lub pominięcie nieaktualnych danych. Konfliktowej migawki (ta sama wersja, inny ładunek) nie można ponowić bez zmian; uzgodnij stan źródła i wyślij nowszą wersję.

Żądanie

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
          }
        ]
      }
    ]
  }'

Odpowiedź

Zwraca komunikat o powodzeniu z metadanymi operacji synchronizacji.

{
  "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"
      }
    ]
  }
}

Pola metadanych:

  • success — liczba pomyślnie przetworzonych członków
  • skipped — liczba pominiętych członków (jeśli występują)
  • skipped_items — tablica pominiętych członków wraz z przyczynami (jeśli występują)
  • dry-run — flaga logiczna ustawiana przy użyciu klucza typu dryrun (jeśli dotyczy)

Wejścia

Reprezentuje zapis obecności osoby w obiekcie, na zajęciach lub podczas aktywności. Służy do śledzenia obecności, analizy wykorzystania i zwiększania dokładności wykrywania wizualnego.

Punkty końcowe

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

Obiekt Check-In

Atrybuty

  • check_in_id string opcjonalny

    Unikatowy identyfikator wejścia. Opcjonalny — jeśli nie zostanie podany, jest generowany automatycznie na podstawie pary member_id i timestamp.

  • member_id string wymagany

    Unikatowy identyfikator członka.

  • facility_id string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Unikatowy identyfikator obiektu z Performance Hub.

  • linking_identifier string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Unikatowa wartość identyfikatora, której partner używa dla każdej lokalizacji (np. „Branch ID”, „Location Code”, „Store Number”). Więcej informacji

  • check_in_type string opcjonalny

    Typ wizyty. Jedna z wartości: member, class, staff, guest lub trial.

  • source string opcjonalny

    Sposób zarejestrowania wejścia. Typowe wartości to manual, tag, rfid, kiosk, app. Można też używać dodatkowych wartości, takich jak door_reader lub booking.

  • class_id string opcjonalny

    Opcjonalny. Używany, jeśli wejście jest powiązane z rezerwacją zajęć lub obecnością na zajęciach.

  • timestamp string wymagany

    Znacznik czasu wejścia w formacie ISO 8601.

Obiekt 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"
}

Zapisywanie wejść

Tworzy rekordy wejść. API automatycznie usuwa duplikaty na podstawie członka, obiektu i znacznika czasu.

Parametry

  • check_ins array wymagany

    Tablica obiektów Check-In do zapisania. Zalecane maksimum: 1000 elementów na żądanie w celu zapewnienia optymalnej wydajności. API automatycznie dzieli elementy na partie do przetworzenia. Każdy element musi zawierać facility_id (wymagany, jeśli nie używasz linking_identifier) lub linking_identifier (wymagany, jeśli nie używasz facility_id).

Zwracane wartości

Zwraca prosty komunikat potwierdzający operację synchronizacji.

Żądanie

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"
      }
    ]
  }'

Odpowiedź

Zwraca komunikat o powodzeniu z metadanymi operacji synchronizacji.

{
  "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"
      }
    ]
  }
}

Pola metadanych:

  • success — liczba pomyślnie przetworzonych wejść
  • skipped — liczba pominiętych wejść (jeśli występują)
  • skipped_items — tablica pominiętych wejść wraz z przyczynami (jeśli występują)
  • dry-run — flaga logiczna ustawiana przy użyciu klucza typu dryrun (jeśli dotyczy)

Kontrola dostępu

Partner API może uruchamiać sprzęt kontrolerów drzwi/bram Performance Hub w obiektach, w których Twoja integracja jest włączona.

Używaj tego API, gdy Twój system zarządzania członkami już zdecydował, że dana osoba może wejść. Performance Hub nie ocenia stanu członkostwa, godzin dostępu, reguł stref drzwi, kontroli antyfraudowych ani logiki zawieszeń. To Twój system pozostaje decydujący w tych kwestiach.

Żądanie otwarcia jest synchroniczne. Performance Hub wysyła polecenie do kontrolera w obiekcie w czasie rzeczywistym i zwraca 200 dopiero wtedy, gdy urządzenie potwierdzi, że przekaźnik fizycznie zwolnił zamek. Większość potwierdzeń powinna nastąpić w ciągu 3-5 sekund. Jeśli potwierdzenie nie nadejdzie w wyznaczonym czasie, API zwraca jednoznaczny błąd.

Możesz też zarejestrować próbę dostępu lub odmowę, która nigdy nie dotarła do kontrolera. To wywołanie nie otwiera drzwi. Zapisuje zdarzenie w Rejestry dostępu modułu Door & Gate Access.

Punkty końcowe

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

Obiekt kontrolera drzwi/bramy

Atrybuty

  • door_id string wymagany

    Unikatowy identyfikator kontrolera drzwi/bramy. Zapisz go w swoim systemie po wykryciu i używaj podczas wywoływania punktu końcowego otwierania.

  • facility_id string wymagany

    Identyfikator obiektu w Performance Hub.

  • linking_identifier string opcjonalny

    Identyfikator obiektu partnera, gdy Twoja integracja używa identyfikatorów łączących. Więcej informacji

  • name string wymagany

    Czytelna nazwa urządzenia skonfigurowana w Performance Hub.

  • zone string opcjonalny

    Strefa lub lokalizacja drzwi, np. Entrance.

  • status string wymagany

    online lub offline.

  • relay_state string opcjonalny

    Ostatni znany stan przekaźnika, np. locked lub unlocked.

  • maintenance_mode string wymagany

    Bieżący tryb serwisowy. Jedna z wartości: off, force-open lub force-closed.

  • hold_time_seconds integer wymagany

    Domyślny czas otwarcia skonfigurowany dla drzwi.

  • last_seen string opcjonalny

    Znacznik czasu ISO ostatniej aktualizacji metadanych urządzenia.

Obiekt kontrolera drzwi/bramy

{
  "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"
}

Lista kontrolerów drzwi/bram

Zwraca kontrolery drzwi/bram dostępne dla Twojej integracji.

Jeśli nie podano ani facility_id, ani linking_identifier, API zwraca kontrolery drzwi/bram ze wszystkich obiektów połączonych z Twoim kontem partnera.

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.

Parametry

  • facility_id string opcjonalny jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Identyfikator obiektu w Performance Hub. Używaj go w przypadku integracji z bezpośrednim łączeniem.

  • linking_identifier string opcjonalny jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Twój własny identyfikator obiektu/lokalizacji. Używaj go, gdy Twoja integracja jest skonfigurowana do korzystania z identyfikatorów łączących.

Zwracane wartości

Zwraca tablicę obiektów kontrolerów drzwi/bram.

Żądanie

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:

Odpowiedź

{
  "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"
    }
  ]
}

Pobieranie stanu kontrolera drzwi/bramy

Pobiera ostatni znany stan i podstawową konfigurację pojedynczego kontrolera drzwi/bramy.

Podaj identyfikator obiektu, aby Performance Hub mógł sprawdzić, czy drzwi należą do obiektu, do którego Twoja integracja ma dostęp.

Parametry

  • door_id string wymagany

    Identyfikator kontrolera drzwi/bramy zwrócony przez punkt końcowy listy.

  • facility_id string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Identyfikator obiektu w Performance Hub. Wymagany w przypadku integracji z bezpośrednim łączeniem.

  • linking_identifier string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Identyfikator obiektu partnera. Wymagany w przypadku integracji z identyfikatorem łączącym.

Zwracane wartości

Zwraca obiekt kontrolera drzwi/bramy.

Żądanie

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:

Odpowiedź

{
  "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"
  }
}

Otwieranie kontrolera drzwi/bramy

Wysyła polecenie otwarcia do kontrolera drzwi/bramy i czeka, aż fizyczny przekaźnik potwierdzi zwolnienie zamka.

Przed wywołaniem tego punktu końcowego Twój system musi zdecydować, czy dana osoba ma uprawnienia. Performance Hub sprawdza wyłącznie klucz partnera, dostęp do obiektu, przynależność drzwi i stan urządzenia.

Parametry

  • door_id string wymagany

    Identyfikator kontrolera drzwi/bramy zwrócony przez punkt końcowy listy.

  • facility_id string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Identyfikator obiektu w Performance Hub. Wymagany w przypadku integracji z bezpośrednim łączeniem.

  • linking_identifier string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Identyfikator obiektu partnera. Wymagany w przypadku integracji z identyfikatorem łączącym.

  • member_id string wymagany

    Identyfikator członka u partnera. Służy do rejestrowania na potrzeby audytu i późniejszego łączenia danych.

  • first_name string wymagany

    Imię osoby otwierającej drzwi.

  • last_name string wymagany

    Nazwisko osoby otwierającej drzwi.

  • full_name string opcjonalny

    Opcjonalne. Jeśli zostanie pominięte, Performance Hub połączy first_name i last_name.

  • check_in_id string opcjonalny

    Opcjonalny identyfikator wejścia z Twojego systemu, służący do powiązania danych.

  • idempotency_key string opcjonalny

    Opcjonalny klucz chroniący przed ponownym odtworzeniem. Ponowne użycie tego samego klucza dla tego samego partnera, obiektu i drzwi zwraca istniejący wynik, jeśli jest dostępny.

Zwracane wartości

Zwraca 200 tylko wtedy, gdy urządzenie potwierdzi, że przekaźnik fizycznie zwolnił zamek. Drzwi pozostają otwarte przez czas skonfigurowany w module Zarządzanie urządzeniami Performance Hub; partnerzy nie mogą zmieniać czasu działania przekaźnika w poszczególnych żądaniach. Większość potwierdzeń powinna nastąpić w ciągu 3-5 sekund. Traktuj przekroczenie udokumentowanego limitu czasu jako jednoznacznie nieudane otwarcie i ponawiaj próbę wyłącznie zgodnie z własnymi zasadami bezpieczeństwa.

Typowe błędy:

  • 403 integration_not_enabled — Twoja integracja nie jest włączona dla obiektu.
  • 409 maintenance_mode_active — personel obiektu włączył tryb serwisowy dla drzwi.
  • 503 device_offline — kontroler drzwi/bramy jest offline lub jego dane są nieaktualne.
  • 504 unlock_confirmation_timeout — polecenie zostało wysłane, ale przed upływem limitu czasu nie otrzymano pasującego potwierdzenia.

Żądanie

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"
  }'

Odpowiedź

{
  "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"
}

Odpowiedź z błędem

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

Rejestrowanie próby dostępu lub odmowy

Rejestruje próbę dostępu lub odmowę, o której Twój system już zdecydował. Kontroler drzwi/bramy nie jest kontaktowany, a drzwi nie zostają otwarte.

Używaj tego, gdy Twój system odmawia wejścia lub gdy próba ma się pojawić w Rejestry dostępu modułu Door & Gate Access bez otwierania drzwi. Performance Hub nie ocenia stanu członkostwa, godzin dostępu ani innych reguł dostępu.

Zdarzenie odmowy pojawia się w Rejestry dostępu modułu Door & Gate Access z wynikiem Denied, nazwą partnera, drzwiami, identyfikatorem członka (jeśli go przesyłasz) oraz kodem przyczyny w czytelnej postaci. Na przykład membership_expired jest wyświetlany jako „Membership Expired”. Wartości reason_display_text i user_email są zapisywane razem ze zdarzeniem.

Parametry

  • door_id string wymagany

    Identyfikator kontrolera drzwi/bramy zwrócony przez punkt końcowy listy.

  • facility_id string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Identyfikator obiektu w Performance Hub. Wymagany w przypadku integracji z bezpośrednim łączeniem.

  • linking_identifier string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Identyfikator obiektu partnera. Wymagany w przypadku integracji z identyfikatorem łączącym.

  • outcome string wymagany

    denied lub attempted.

  • reason string opcjonalny

    Kod przyczyny zapisany małymi literami w formacie snake_case, do 64 znaków. Wymagany, gdy outcome ma wartość denied. Przykład: membership_expired.

  • reason_display_text string opcjonalny

    Czytelny opis przyczyny, do 256 znaków. Przykład: Membership expired on 2026-04-01.

  • member_id string opcjonalny

    Identyfikator członka u partnera. Pomiń go, gdy poświadczenie nie pasowało do żadnego członka, np. w przypadku nieznanej karty.

  • user_email string opcjonalny

    Adres e-mail osoby, która próbowała uzyskać dostęp.

  • timestamp string opcjonalny

    Czas próby w formacie ISO 8601 ze strefą czasową. Przykład: 2026-05-18T10:15:30Z. Domyślnie jest to czas otrzymania żądania. Nie może wypadać więcej niż 5 minut w przyszłości ani być starszy niż 30 dni.

  • idempotency_key string opcjonalny

    Klucz chroniący przed ponownym odtworzeniem, do 128 znaków. Ponowne użycie tego samego klucza dla tego samego partnera, obiektu i drzwi zwraca pierwotny wynik.

Zwracane wartości

Zwraca 201, gdy zdarzenie zostanie zarejestrowane. Ponowne przesłanie tego samego idempotency_key zwraca 200 z polem idempotent ustawionym na true i nie tworzy kolejnego zdarzenia.

Klucz dry-run zwraca 200 z polem dry_run ustawionym na true. Nic nie jest rejestrowane.

Typowe błędy:

  • 400 — treść żądania jest nieprawidłowa, odmowa nie ma reason, znacznik czasu jest poza dozwolonym zakresem lub facility_id / linking_identifier nie pasuje do połączonego obiektu.
  • 403 — klucz jest tylko do odczytu.
  • 403 integration_not_enabled — Twoja integracja nie jest włączona dla obiektu. Przyczynę podaje pole message.
  • 404 — nie znaleziono kontrolera drzwi/bramy dla połączonego obiektu.

Żądanie

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"
  }'

Odpowiedź

{
  "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"
}

Ponowne odtworzenie idempotentne

{
  "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
}

Raporty obiektów

Zapis z określonego momentu, obejmujący kluczowe wskaźniki operacyjne i finansowe obiektu za określony okres.

Punkty końcowe

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

Obiekt Report Snapshot

Atrybuty

  • facility_id string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Unikatowy identyfikator obiektu z Performance Hub.

  • linking_identifier string jedno z dwóchPodaj typ identyfikatora obiektu skonfigurowany dla Twojej integracji: facility_id w przypadku integracji z bezpośrednim łączeniem lub linking_identifier w przypadku integracji z identyfikatorem łączącym. Nie wysyłaj obu; API używa typu identyfikatora skonfigurowanego dla Twojego konta partnera i ignoruje drugi. Więcej informacji

    Unikatowa wartość identyfikatora, której partner używa dla każdej lokalizacji (np. „Branch ID”, „Location Code”, „Store Number”). Więcej informacji

  • start_date string wymagany

    Data rozpoczęcia okresu migawki w formacie YYYY-MM-DD.

  • end_date string wymagany

    Data zakończenia okresu migawki w formacie YYYY-MM-DD.

  • metrics object wymagany

    Obiekt wskaźników zawierający dane o członkach i przychodach za dany okres.

Obiekt 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"
    }
  }
}

Zapisywanie migawek raportów

Przesyła wskaźniki operacyjne i finansowe obiektu za określony okres.

Parametry

  • snapshots array wymagany

    Tablica obiektów Report Snapshot do zapisania. Maksymalnie 25 elementów na żądanie. Każdy element musi zawierać facility_id (wymagany, jeśli nie używasz linking_identifier) lub linking_identifier (wymagany, jeśli nie używasz facility_id).

Zwracane wartości

Zwraca prosty komunikat potwierdzający operację synchronizacji.

Żądanie

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"
          }
        }
      }
    ]
  }'

Odpowiedź

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

Błędy

Partner API używa standardowych kodów stanu HTTP i treści odpowiedzi w formacie JSON, aby wyjaśnić, dlaczego żądanie się nie powiodło.

Struktura odpowiedzi z błędem

Większość błędów API zwraca treść JSON z komunikatem oraz, jeśli są dostępne, szczegółami w formie strukturalnej.

Kody stanu

Błędy Access Time Windows

Walidacja okien kończy się niepowodzeniem, zanim nieprawidłowa migawka zostanie zapisana. Typowe przyczyny, w przypadku których ponawianie nie pomoże:

  • Brak access_time_windows_revision, gdy obecne jest access_time_windows.
  • Wartości epoki w postaci ciągu znaków, liczby zmiennoprzecinkowej lub prawdopodobnie w milisekundach.
  • Nieprawidłowa strefa czasowa IANA, odwrócony przedział, zduplikowany external_id, nakładające się bloki tygodniowe lub niepodzielony blok nocny.
  • Wartość wykraczająca poza udokumentowane limity liczby, długości lub zakresu.

Powtórzona wersja z inną znormalizowaną zawartością powoduje błąd 409 Conflict. Uzgodnij dane z najnowszym wiarygodnym stanem i przydziel nowszą wersję; nie ponawiaj w kółko konfliktowej pary. Starsza wersja jest zgłaszana jako pominięta nieaktualna migawka i nie może nadpisać nowszego stanu. Nieznany lub niezmapowany scope_key powoduje odmowę autoryzacji i należy go traktować jako alert konfiguracyjny.

Jeśli dostarczenie przekroczy limit czasu lub otrzyma przejściowy błąd 5xx, ponów dokładnie tę samą znormalizowaną migawkę z tą samą wersją. Jeśli pobranie danych ze źródła nie powiodło się, całkowicie pomiń pole okien; nigdy nie zastępuj go pustą tablicą.

Wskazówki dotyczące ponawiania

Te błędy ponawiaj z ograniczonym wykładniczym wydłużaniem odstępów:

  • 429
  • 500
  • 502
  • 503
  • 504

Tych błędów nie ponawiaj bezrefleksyjnie:

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

W przypadku kontroli dostępu zawsze traktuj odpowiedzi o przekroczeniu limitu czasu i stanie offline jako nieudane otwarcia, chyba że Twoje własne reguły dostępu i procesy bezpieczeństwa stanowią inaczej.

Informacje, które należy przekazać pomocy technicznej

Kontaktując się z pomocą techniczną, podaj:

  • Punkt końcowy i metodę HTTP.
  • Znacznik czasu i strefę czasową.
  • Identyfikator klucza partnera, a nie tajny klucz.
  • Użyty identyfikator obiektu.
  • Identyfikator rekordu źródłowego z Twojego systemu.
  • Stan i treść odpowiedzi.
  • event_id lub command_id, jeśli są dostępne.
{
  "success": false,
  "message": "Request body.members[0].member_id is required"
}

Niektóre punkty końcowe specyficzne dla domeny zwracają jawny stan i przyczynę. Na przykład błędy kontroli dostępu zawierają pola takie jak reason, door_id, facility_id i 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

Żądanie ma nieprawidłowy format lub brakuje w nim wymaganych pól. Popraw żądanie przed ponowieniem.

401 Unauthorized

Uwierzytelnianie nie powiodło się. Sprawdź, czy używasz HTTP Basic Auth z tajnym kluczem API jako nazwą użytkownika i pustym hasłem.

403 Forbidden

Klucz jest prawidłowy, ale operacja jest niedozwolona. Typowe przyczyny to użycie klucza tylko do odczytu w operacji zapisu lub próba dostępu do obiektu, w którym Twoja integracja nie jest włączona.

404 Not Found

Nie znaleziono żądanego zasobu lub nie jest on dostępny dla Twojej integracji.

409 Conflict

Żądanie jest sprzeczne z bieżącym stanem zasobu. W przypadku kontroli dostępu może to oznaczać na przykład, że kontroler drzwi/bramy jest w trybie serwisowym.

422 Unprocessable Entity

Żądanie zawiera prawidłowy JSON, ale nie przechodzi walidacji semantycznej. Popraw dane przed ponowieniem.

429 Too Many Requests

Integracja przekroczyła udokumentowany limit liczby żądań. Ponów próbę z wykładniczym wydłużaniem odstępów.

500 Internal Server Error

Performance Hub nie mógł zrealizować żądania z powodu błędu wewnętrznego. Ponów próbę z wydłużaniem odstępów. Jeśli problem nie ustąpi, skontaktuj się z pomocą techniczną, podając punkt końcowy, znacznik czasu i treść odpowiedzi.

503 Service Unavailable

Zależna usługa lub urządzenie jest niedostępne. W przypadku otwierania kontrolera drzwi/bramy może to oznaczać, że kontroler jest offline.

504 Gateway Timeout

Upłynął limit czasu operacji. W przypadku otwierania kontrolera drzwi/bramy oznacza to, że otwarcie nie zostało potwierdzone przed upływem limitu czasu.

Wersjonowanie

Wersja Partner API jest określona w adresie URL. Bieżąca wersja to:

Zasady wprowadzania zmian

Performance Hub dąży do tego, aby w miarę możliwości wprowadzać zmiany addytywne i zgodne wstecz.

Przykłady zmian zgodnych wstecz:

  • Dodanie nowego opcjonalnego pola do żądania.
  • Dodanie nowego pola do odpowiedzi.
  • Dodanie nowego punktu końcowego.
  • Dodanie nowej wartości wyliczeniowej, gdy oczekuje się, że klienci obsługują nieznane wartości.
  • Ulepszenie komunikatów walidacji bez zmiany kontraktu kodów stanu.

access_time_windows i access_time_windows_revision to addytywne pola żądania dotyczącego członka. Istniejący klienci, którzy je pomijają, zachowują zapisaną migawkę Access Time Windows bez zmian. Ta reguła pomijania zapewnia zgodność z częściowymi operacjami upsert; pominięcie nie jest równoznaczne z wysłaniem pustej tablicy.

Przykłady zmian powodujących niezgodność:

  • Usunięcie pola lub zmiana jego nazwy.
  • Zmiana typu pola.
  • Zmiana opcjonalnego pola żądania na wymagane.
  • Usunięcie punktu końcowego.
  • Zmiana znaczenia istniejącego kodu stanu lub specyficznego dla domeny pola reason.

Wycofywanie

Gdy konieczna jest zmiana powodująca niezgodność, Performance Hub w miarę możliwości nie będzie zmieniać istniejącej wersji. Zamiast tego wprowadzimy nową wersję lub ścieżkę migracji i poinformujemy o zmianie partnerów, których ona dotyczy.

Powiadomienia o wycofaniu mogą obejmować:

  • Wpis w dzienniku zmian.
  • Bezpośrednią komunikację z partnerem.
  • Uwagi w Partner Console.
  • Wskazówki dotyczące migracji w dokumentacji.

Zalecenia dla klientów

Twórz klientów odpornych na zmiany addytywne:

  • Ignoruj pola odpowiedzi, z których nie korzystasz.
  • Traktuj nieznane wartości wyliczeniowe jako nieobsługiwane, zamiast doprowadzać do awarii.
  • Unikaj ścisłego porównywania odpowiedzi.
  • Rejestruj nierozpoznane wartości, aby świadomie aktualizować integrację.

W przypadku wersjonowanych części danych członka, takich jak Access Time Windows, przechowuj przesłaną wersję i znormalizowany ładunek do czasu poznania wyniku. Ponowne użycie wersji dla zmienionej zawartości powoduje konflikt, a ponowne odtworzenie tej samej zawartości jest idempotentne. Zobacz Access Time Windows.

Specyfikacje OpenAPI

Korzystaj z opublikowanych specyfikacji OpenAPI do generowania klientów, walidacji żądań i śledzenia zmian struktury API w czasie.

Zobacz Specyfikacje OpenAPI.

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

Dziennik zmian

Ten dziennik zmian rejestruje istotne zmiany w Partner API i Partner Console, które wpływają na działanie integracji.

2026-09-09

2026-05-06

2026-05-01

Kategorie zmian

Przyszłe wpisy będą używać następujących kategorii:

  • Dodano — nowy punkt końcowy, pole, przewodnik lub funkcja.
  • Zmieniono — zmiana działania lub dokumentacji bez wycofania obsługi.
  • Wycofywane — funkcja pozostaje dostępna, ale ma zaplanowaną ścieżkę migracji.
  • Usunięto — usunięto funkcję lub punkt końcowy.
  • Naprawiono — poprawka błędu lub korekta dokumentacji.
  • Bezpieczeństwo — zmiana dotycząca uwierzytelniania, autoryzacji, przetwarzania danych lub zarządzania kluczami.

Dodano

  • Dodano niezależne od dostawcy migawki access_time_windows członków z mieszanymi oknami bezwzględnymi i cyklicznymi tygodniowymi.
  • Dodano semantykę kolejności access_time_windows_revision, idempotentnego ponownego odtwarzania, konfliktów, pomijania nieaktualnych danych i jawnego odwoływania dostępu.
  • Dodano wskazówki dotyczące stref czasowych IANA, czasu letniego, logicznego mapowania scope_key, aktualności danych źródłowych, implementacji producenta i certyfikacji.

Dodano

  • Dodano dokumentację programu partnerskiego obejmującą typy partnerów, wdrażanie, sprawdzone metody, gotowość do uruchomienia produkcyjnego, błędy, wersjonowanie i wsparcie.
  • Dodano dedykowany proces zapytań Zostań partnerem dla potencjalnych partnerów technicznych i handlowych.
  • Dodano dokumentację opisującą, jak zatwierdzone integracje partnerów pojawiają się w katalogu partnerów Performance Hub w ramach podstawowej platformy Performance Hub.

Dodano

  • Dodano dokumentację kontroli dostępu dla kontrolerów drzwi/bram, obejmującą operacje listy, stanu i otwierania.
  • Dodano dokumentację synchronicznego otwierania: API zwraca sukces dopiero wtedy, gdy kontroler w obiekcie potwierdzi, że przekaźnik fizycznie zwolnił zamek.
  • Dodano dokumentację obsługi opcjonalnego idempotency_key w żądaniach otwarcia kontrolerów drzwi/bram.