소개
Performance Hub Partner API를 사용하면 외부 파트너 플랫폼이 Performance Hub의 핵심 모듈과 원활하게 통합할 수 있습니다. 이 API는 컴퓨터 비전, 분석, 회원 출입 기록, 시설 인사이트를 지원합니다.
요청 형식
API는 JSON으로 인코딩된 요청 본문을 받고 JSON으로 인코딩된 응답을 반환합니다.
속도 제한
공정한 사용과 시스템 안정성을 보장하기 위해 Partner API 계정은 다음 기본 제한으로 시작합니다.
- 엔드포인트당 초당 5개 요청
- 최적의 성능을 위해 배치 요청당 권장 최대 1000개 항목
- 페이로드 크기 최대 10MB
속도 제한은 조정할 수 있으며, Performance Hub 파트너 계정 관리자가 사례별로 구성할 수 있습니다. 출시, 마이그레이션, 보고서 백필 또는 대량 처리 시설을 위해 통합에 더 높은 처리량이 필요하다면 온보딩 중이나 계획된 변경 기간 전에 요청하십시오.
기본 URL
https://partner-api.performancehub.co/partner/v1/
인증
Partner API에 액세스하려면 API 비밀 키를 사용한 인증이 필요합니다. Partner Console에서 키를 생성하고 관리하십시오.
API 키는 파트너 리소스에 액세스하기 위한 자격 증명 역할을 합니다. 각 키는 특정 조직 데이터에 대한 액세스가 제한되며, 필요할 때 즉시 비활성화할 수 있습니다.
API 키는 계정에 대한 전체 액세스 권한을 제공하므로 신중하게 다루십시오! 공개 저장소, 클라이언트 측 애플리케이션 또는 유출될 수 있는 어떤 곳에도 이러한 키를 노출하지 마십시오.
API 키를 사용자 이름으로 전달하여 HTTP Basic Auth로 요청을 인증하십시오. 비밀번호는 비워 두십시오.
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.
인증 및 키 관리
- 비밀 키는 서버 측에만 저장됩니다.
- 키가 클라이언트 측 애플리케이션, 모바일 앱, 공개 저장소 또는 지원 티켓에 포함되어 있지 않습니다.
- 키 교체 및 취소를 테스트했습니다.
- 팀에서 각 환경에 어떤 키가 사용되는지 알고 있습니다.
데이터 유효성 검사
- 호출하는 모든 엔드포인트에 필수 필드가 있습니다.
- 시설 식별자가 구성된 연결 방법과 일치합니다.
- 귀사 시스템의 ID가 안정적이며 동기화 간에 변경되지 않습니다.
- 대규모 가져오기는 문서화된 제한 이내의 배치로 분할됩니다.
- 실패한 배치 항목을 식별하고 다시 보낼 수 있습니다.
엔드포인트 테스트
출시 전에 통합이 의존하는 모든 엔드포인트를 테스트하십시오.
- 조직과 시설을 읽을 수 있습니다.
- 회원을 저장하고 업데이트할 수 있습니다.
- 멤버십 플랜, 출입 구역, 출입 시간이 올바르게 동기화됩니다.
- 체크인이 수락되고 귀사 시스템과 다시 연관시킬 수 있습니다.
- 보고서 스냅샷이 예상한 보고 기간과 지표를 사용합니다.
- 해당하는 경우 Door/Gate Controller 흐름을 실제 하드웨어에서 테스트했습니다.
Access Time Window 준비
통합에서 Access Time Windows를 제공하는 경우:
- 절대 및 주간 예시가 생산자 인증 체크리스트를 통과합니다.
- epoch 값은 따옴표 없는 정수 Unix 초이며, 정확한
[from, to)경계를 테스트했습니다. - UTC 기본값, 통합의 사용자 지정 IANA 시간대, 관련 일광 절약 시간 전환을 확인했습니다.
- 지속적이고 단조 증가하는 하나의 회원/원본 리비전 스트림이 증분 업데이트, 조정, 재시도를 조율합니다.
- 운영자가 생략, 전체 교체, 멱등, 충돌, 오래된 데이터, 명시적
[]동작을 이해하고 있습니다. default를 포함한 모든scope_key에 승인된 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응답에는 백오프가 적용된 제한된 재시도 로직을 사용합니다.- 반복되는 실패는 귀사 시스템에서 알림을 생성합니다.
- 통합은 실패한 레코드를 절대 소리 없이 버리지 않습니다.
관찰 가능성
- 로그에 엔드포인트, 타임스탬프, 시설 식별자, 원본 레코드 ID, 요청 결과, 응답 본문이 포함됩니다.
- 지원팀이 회원 ID, 시설 ID, 체크인 ID 또는 잠금 해제 이벤트 ID로 검색할 수 있습니다.
- 실패한 동기화를 재실행하거나 조정할 방법이 있습니다.
프로덕션 출시
- Performance Hub가 프로덕션 액세스를 확인했습니다.
- 하나 이상의 프로덕션 시설에서 통합을 활성화했습니다.
- 프로덕션 키가 활성 상태입니다.
- 운영 및 기술 담당자 정보가 최신 상태입니다.
- 고객을 위한 지원 프로세스가 문서화되어 있습니다.
이러한 점검이 완료되면 구성된 통합이 핵심 Performance Hub 플랫폼 내의 Performance Hub 파트너 디렉터리에 표시됩니다.
모범 사례
다음 패턴을 사용하여 파트너 통합을 예측 가능하고, 관찰 가능하며, 시설에 안전하게 유지하십시오.
시설을 일관되게 식별
파트너 계정에 구성된 연결 방법을 선택하고 일관되게 사용하십시오.
- Direct Link - 시설 엔드포인트에서 반환된 Performance Hub
facility_id를 사용합니다. - Linking Identifier - 지점 ID, 위치 코드, 매장 번호 등 자체 위치 식별자를 사용합니다.
같은 요청에 두 식별자를 모두 보내지 마십시오. Performance Hub는 파트너 계정에 구성된 연결 방법을 사용하여 요청을 처리합니다.
설정 지침은 파트너 연결 방법을 참조하십시오.
신중하게 배치 쓰기
Partner API는 JSON 요청 본문을 허용하며, 문서화된 경우 배치 중심의 동기화 워크플로에 맞게 설계되었습니다. 배치 크기를 제한하고 재시도할 수 있도록 유지하십시오.
기본 지침:
- 최적의 성능을 위해 배치 요청당 최대 1000개 항목을 사용하십시오.
- 페이로드는 10MB 미만으로 유지하십시오.
- 엔드포인트당 초당 5개 요청 이내로 유지하십시오.
속도 제한은 조정할 수 있으며, Performance Hub 파트너 계정 관리자가 사례별로 구성할 수 있습니다. 대량 가져오기, 출시 트래픽 또는 보고서 백필이 예상되면 변경 기간 전에 필요한 처리량을 합의하십시오.
대규모 데이터 세트를 동기화해야 하는 경우 결정론적인 청크로 나누고 귀사 측에서 각 청크 ID를 기록하십시오. 이렇게 하면 실패한 재시도를 더 쉽게 파악할 수 있습니다.
안전하게 재시도
429, 500, 502, 503, 504와 같은 일시적인 실패에는 지수 백오프를 사용하십시오.
짧은 간격의 반복 재시도는 피하십시오. 다음과 같이 시작하는 것이 좋습니다.
- 1초 후 재시도합니다.
- 2초 후 재시도합니다.
- 4초 후 재시도합니다.
- 작업이 계속 실패하면 중지하고 알림을 보냅니다.
400 또는 422와 같은 유효성 검사 실패의 경우 재시도하기 전에 요청을 수정하십시오.
지원되는 경우 멱등성 사용
Door/Gate Controller 잠금 해제 엔드포인트는 선택적 idempotency_key를 지원합니다. 같은 파트너, 시설, 출입문에 같은 키를 다시 사용하면 기존 결과가 있는 경우 해당 결과를 반환합니다.
수행 중인 작업에 대해 안정적인 키를 사용하십시오. 예를 들어 귀사 시스템의 체크인 ID나 출입 이벤트 ID를 사용할 수 있습니다.
해당 엔드포인트에 문서화되어 있지 않은 한 모든 쓰기 엔드포인트가 멱등성을 지원한다고 가정하지 마십시오.
원본 데이터를 깨끗하게 유지
가능하면 안정적이고 정규화된 값을 보내십시오.
- 원본 시스템의 일관된 회원, 플랜, 시설, 체크인 ID를 사용하십시오.
- 날짜와 시간에는 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 요청 로그를 사용하십시오. 프로덕션에서는 다음 항목을 포함한 자체 로그도 유지하십시오.
- 요청 타임스탬프.
- 엔드포인트.
- 원본 레코드 ID.
- 시설 식별자.
- HTTP 상태 코드.
- Performance Hub 응답 본문 또는 오류 메시지.
이러한 필드가 있으면 고객이 무슨 일이 있었는지 물을 때 지원과 조정을 훨씬 빠르게 처리할 수 있습니다.
조직
Performance Hub 플랫폼과 통합된 하나 이상의 시설을 운영하는 최상위 사업체를 나타냅니다.
엔드포인트
GET /partner/v1/organisations - List all organisations
조직 객체
속성
org_id
string필수조직의 고유 식별자입니다.
name
string필수조직 이름입니다.
조직 객체
{
"org_id": "00000000-0000-0000-0000-000000000050",
"name": "Harbourside Group"
}
모든 조직 나열
파트너 계정에서 액세스할 수 있는 조직 목록을 반환합니다.
반환값
조직 객체 배열이 포함된 data 속성이 있는 JSON 객체를 반환합니다.
요청
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_id
string필수시설의 고유 식별자입니다.
org_id
string필수상위 조직의 고유 식별자입니다.
name
string필수시설 이름입니다.
brand
string선택시설에서 사용하는 브랜드 이름입니다.
website_url
string선택시설 웹사이트 URL입니다.
place_data
object선택국가, 서식이 지정된 주소, Google Place ID, 주/도, 도시가 포함된 Google Places API의 위치 데이터입니다.
social_links
object선택시설의 소셜 미디어 링크입니다.
timezone
string선택IANA 시간대 식별자입니다(예:
"Australia/Sydney","America/New_York").
시설 객체
{
"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"
}
모든 시설 나열
파트너 계정에서 액세스할 수 있는 시설 목록을 반환합니다.
반환값
시설 객체 배열이 포함된 data 속성이 있는 JSON 객체를 반환합니다.
요청
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_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).
멤버십 플랜 객체
이 예시에서는 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"]]
}
}
호텔 투숙객 – 24시간 연중무휴: 항상 출입할 수 있으며, 가장 일반적인 사용 사례입니다.
{
"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"]]
}
}
구역별 예시
객실 층은 24시간 출입할 수 있고 수영장은 이용 시간이 더 짧은 호텔 투숙객 플랜:
{
"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필수저장할 멤버십 플랜 객체의 배열입니다. 최적의 성능을 위해 요청당 최대 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 키 유형을 사용하는 경우의 부울 플래그(해당하는 경우)
회원
시설의 개별 고객을 나타냅니다. 리드, 잠재 고객, 정기 고객, 만료된 회원 또는 차단된 사용자일 수 있습니다.
회원 업서트에는 절대 시간 창과 주간 반복 출입을 포함하는, 리비전이 관리되는 완전한 access_time_windows 스냅샷도 포함될 수 있습니다. 이러한 필드를 생성하기 전에 Access Time Windows를 참조하십시오. 이 필드는 추가 권한이며 시설의 일반 규칙이나 영구 권한을 대체하지 않습니다.
엔드포인트
POST /partner/v1/members - Save a 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) - 우편번호/ZIP 코드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
integeraccess_time_windows와 함께 필수이 회원/원본 스트림에 대해 단조 증가하는, 음수가 아니고 JSON에서 안전한 정수입니다.
access_time_windows가 있을 때마다 필수입니다.
회원 객체
{
"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를 사용하면 Partner Member가 외부 시스템에서 제공하는 임시 또는 반복 출입 권한을 가질 수 있습니다. 이 페이지는 access_time_windows와 access_time_windows_revision에 대한 권위 있는 생산자 가이드입니다.
Access Time Windows는 허용만 하는 추가 권한입니다. 활성 시간 창은 출입을 허용할 수 있지만, 비활성, 만료, 오래되었거나 매핑되지 않은 시간 창이 일반 규칙이나 영구 권한에서 이미 허용한 출입을 거부하지는 않습니다. 사용자 비활성화, 명시적 출입문 차단, 유지 관리 모드, 지오펜싱, 속도 제한, 컨트롤러 가용성은 계속 적용됩니다.
특정 업스트림 시스템을 위한 구현은 별도의 어댑터입니다. 어댑터는 필드 의미를 변경하지 않고 원본 데이터를 이 공급업체 중립적인 계약으로 변환해야 합니다.
회원 스냅샷 필드
access_time_windows
array선택이 회원과 파트너 원본에 대한 완전한 Access Time Window 스냅샷입니다. 스냅샷에는
absolute시간 창과weekly시간 창을 함께 포함할 수 있습니다. 저장된 스냅샷을 변경하지 않으려면 필드를 생략하고, 이 원본이 소유한 모든 시간 창을 취소하려면[]를 보내십시오.access_time_windows_revision
integeraccess_time_windows와 함께 필수이 회원/원본 리비전 스트림에 대해 단조 증가하는, 음수가 아니고 JSON에서 안전한 정수입니다.
access_time_windows가 있을 때마다 필수이며9007199254740991을 초과할 수 없습니다.
각 스냅샷에는 최대 50개의 시간 창을 넣을 수 있습니다. external_id, scope_key, label은 최대 120자까지 허용됩니다. 절대 시간 창은 최대 90일까지 지정할 수 있습니다. 주간 시간 창의 하루에는 겹치지 않는 블록을 최대 8개까지 넣을 수 있습니다. 잘못된 데이터는 잘라내거나 추측하지 않고 거부됩니다.
시간 창 형식
절대 시간 창은 하나의 정확한 구간을 나타냅니다.
혼합된 전체 요청
이 요청은 회원의 이전 원본 소유 스냅샷을 하나의 절대 시간 창과 하나의 주간 시간 창으로 대체합니다.
시간 및 경계 규칙
from, to, active_from, active_until은 UTC 시점을 나타내는 JSON 정수 Unix 초입니다.
- 따옴표 없는 JSON 정수로 보내십시오. 숫자 문자열, 부동 소수점, RFC 3339 문자열, Unix 밀리초는 거부됩니다.
- 모든 구간은 반개구간
[from, to)입니다. 출입은 정확히from에 시작할 수 있으며, 정확히to에서 더 이상 활성 상태가 아닙니다. from은to보다 작아야 합니다. 주간 경계가 둘 다 있는 경우active_from은active_until보다 작아야 합니다.- 시간대 정보가 없는 현지 날짜/시간에서 epoch를 도출하지 마십시오. 먼저 원본 시간을 UTC 시점으로 변환한 다음 Unix 밀리초를 1000으로 나누고 결과가 정수인지 확인하십시오.
시간대 및 일광 절약 시간
timezone은 UTC, Australia/Perth, America/New_York과 같은 유효한 IANA 시간대여야 합니다. 생략하면 기본값은 UTC입니다.
- 절대 시간 창:
from과to는 이미 정확한 UTC 시점을 나타냅니다.timezone은 표시 및 감사용 메타데이터일 뿐이며, 변경해도 두 시점 모두 이동하지 않습니다. - 주간 시간 창:
timezone은access_hours를 평가하는 데 사용되는 현지 벽시계와 일광 절약 시간 규칙을 정의합니다. 주간 블록을 미리 UTC로 변환하지 마십시오. - 서머타임이 시작되어 시계가 앞당겨질 때 시간대에서 건너뛰는 현지 시간은 발생하지 않습니다.
- 서머타임이 끝나 시계가 되돌려질 때 반복되는 현지 시간에 해당하는 실제 두 시점 모두 주간 블록과 일치합니다.
- 주간 시간 창이 UTC가 아닌 시간대를 사용하더라도
active_from과active_until은 UTC 시점으로 유지됩니다.
access_hours는 소문자 sun부터 sat까지 사용합니다. 각 값은 0으로 채운 24시간 형식 HH:mm을 사용하는 [start, end] 쌍의 배열입니다. 블록은 비어 있지 않고, 순서대로 정렬되어 있으며, 겹치지 않아야 합니다. end는 포함되지 않습니다. 블록은 자정을 넘을 수 없습니다. 야간 원본 구간은 첫째 날의 늦은 블록과 다음 날의 이른 블록으로 분할하십시오.
안정적인 ID 및 범위 매핑
external_id는 논리적 시간 창의 수명 동안 안정적이어야 하며 회원 스냅샷 내에서 고유해야 합니다. 운영자와 감사 기록이 리비전을 연관시킬 수 있도록 시간이나 레이블이 변경되어도 동일하게 유지하십시오. 관련 없는 시간 창에 다시 사용하지 마십시오.
scope_key는 안정적인 논리적 출입 대상입니다. 기본값은 default입니다. 시설 관리자는 허용된 각 키를 Performance Hub의 시설 전체, 출입문 또는 접근 범위 대상에 매핑합니다.
완전한 스냅샷 및 리비전
두 필드를 회원 업서트 내에서 별도로 버전이 관리되는 파티션으로 취급하십시오.
| 입력 | 결과 |
|---|---|
access_time_windows 생략 |
기존 스냅샷이 변경되지 않으며 리비전이 필요하지 않습니다 |
| 더 새로운 리비전과 함께 제공 | 이 회원/원본에 대해 저장된 스냅샷 전체가 대체됩니다 |
| 같은 리비전과 같은 정규화 페이로드 | 멱등 재전송이며 스냅샷이 변경되지 않습니다 |
| 같은 리비전과 다른 정규화 페이로드 | 충돌입니다. 조정한 후 새 리비전을 할당하십시오 |
| 이전 리비전 | 오래된 스냅샷은 건너뛰며 더 새로운 상태를 덮어쓸 수 없습니다 |
더 새로운 리비전과 함께 access_time_windows: [] |
원본 소유 시간 창을 모두 명시적으로 취소합니다 |
스냅샷은 패치가 아닌 완전한 데이터입니다. 리비전 1842에 시간 창 A와 B가 있는 경우, B만 포함된 리비전 1843은 A를 제거합니다.
웹훅 작업자, 폴링, 재전송, 전체 조정 전반에서 파트너/회원별로 조율된 하나의 리비전 스트림을 유지하십시오. 지속적인 데이터베이스 시퀀스를 권장합니다. Unix 밀리초 값은 모든 작성자가 조율하여 엄격한 순서와 고유성을 보장하는 경우에만 리비전으로 사용할 수 있습니다. 이는 리비전 값이지 epoch 필드가 아닙니다.
API 응답을 알 수 있을 때까지 정확한 요청과 리비전을 보존하십시오. 제한 시간 초과나 일시적인 오류 후에는 같은 정규화 스냅샷을 같은 리비전으로 재시도하십시오. 전송 결과가 불확실하다는 이유만으로 새 리비전을 할당하지 마십시오.
취소, 만료 및 업스트림 실패
- 하나의 시간 창 취소: 신뢰할 수 있는 원본 상태를 성공적으로 조회하고, 해당 시간 창을 제거한 다음, 나머지 완전한 스냅샷을 더 새로운 리비전으로 보내십시오.
- 모든 시간 창 취소: 더 새로운 리비전과 함께
access_time_windows: []를 보내십시오. - 절대 시간 창 만료 처리:
to에서 허용이 중지됩니다. 스냅샷을 깔끔하게 유지하려면 이후 조정에서 만료된 항목을 제외하고 보내십시오. - 주간 시간 창 종료: 더 새로운 스냅샷에서 제거하거나, 원본에 알려진 종료 시점이 있으면
active_until을 사용하십시오. - 원본 조회 실패 또는 불완전:
[]를 보내지 말고 부분 스냅샷도 게시하지 마십시오. 알림을 보내고 조회를 재시도하십시오. 업스트림 실패를 빈 스냅샷으로 바꾸면 의도하지 않은 출입 권한 취소가 발생합니다. - Partner API 요청이 유효성 검사에 실패: 데이터를 수정하고, 정규화 스냅샷이 변경되는 경우에만 더 새로운 리비전을 보내십시오. 일시적인 실패는 원래 리비전으로 재시도하십시오.
원본 최신성은 통합별로 약속된 전송 및 조정 주기에 따라 구성됩니다. 활성화하기 전에 최대 원본 경과 시간, 이를 초과할 때의 처리, 알림 임계값, 운영자가 각 시간 창의 자체 경계에만 의존하는 것을 승인할 수 있는지 여부를 합의하십시오. 오래된 원본 시간 창은 절대 거부 규칙이 되지 않으며, 일반 규칙과 영구 권한이 대체 경로로 유지됩니다.
생산자 알고리즘
모든 회원 업데이트에 다음 언어 중립적인 워크플로를 사용하십시오.
인증 체크리스트
최종 scope_key 매핑을 사용하여 스테이지 시설에서 다음 점검을 완료하십시오.
-
timezone을 생략한 절대 시간 창이 수락되고 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를 사용하십시오. 둘 다 보내지 마십시오.
epoch 변환
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
원본에 1초 미만의 정밀도가 있다면 통합 테스트 전에 시작/종료 반올림 정책을 명확히 정의하십시오. 밀리초를 전달하고 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 시설, 출입문 또는 접근 범위 ID를 보내지 않습니다. 알 수 없거나, 비활성화되었거나, 매핑되지 않은 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, 겹치는 블록, 야간 블록, 하루 8개 초과 블록, 50개 초과 시간 창, 매핑되지 않은 범위 키에 대한 부정 벡터도 제출하십시오.
회원 저장
회원 레코드를 생성하거나 업데이트합니다. API는 member_id를 기준으로 생성할지 업데이트할지 결정합니다.
매개변수
members
array필수저장할 회원 객체의 배열입니다. 최적의 성능을 위해 요청당 최대 1000개 항목을 권장합니다. API는 처리를 위해 항목을 자동으로 배치로 묶습니다. 각 항목에는
facility_id(linking_identifier를 사용하지 않는 경우 필수) 또는linking_identifier(facility_id를 사용하지 않는 경우 필수)가 포함되어야 합니다.회원에
access_time_windows가 포함된 경우access_time_windows_revision도 포함해야 합니다. 이 배열은 패치가 아닌 완전한 원본 스냅샷입니다. 기존 스냅샷을 유지하려면 생략하고, 원본 소유 시간 창을 모두 취소하려면 더 새로운 리비전과 함께[]를 보내십시오. 이 필드를 활성화하기 전에 Access Time Windows 가이드를 읽으십시오.
반환값
동기화 작업을 확인하는 간단한 메시지를 반환합니다.
시간 창 스냅샷이 멱등 재전송 또는 오래된 데이터 건너뛰기로 보고되더라도 회원 프로필 필드는 일반 업서트로 처리됩니다. 같은 리비전/다른 페이로드로 충돌하는 스냅샷은 변경하지 않고 재시도할 수 없습니다. 원본 상태를 조정하고 더 새로운 리비전을 보내십시오.
요청
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_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_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필수저장할 체크인 객체의 배열입니다. 최적의 성능을 위해 요청당 최대 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는 통합이 활성화된 시설에서 Performance Hub Door/Gate Controller 하드웨어를 작동시킬 수 있습니다.
회원 관리 시스템에서 이미 해당 사람의 입장을 허용하기로 결정한 경우에 이 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 시설 ID입니다.
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를 반환합니다.
매개변수
facility_id
string선택 둘 중 하나통합에 구성된 시설 식별자 유형을 제공하십시오. 직접 연결 통합에는 facility_id를, 연결 식별자 통합에는 linking_identifier를 사용하십시오. 둘 다 보내지 마십시오. API는 파트너 계정에 구성된 식별자 유형을 사용하고 다른 하나는 무시합니다. 자세히 알아보기Performance Hub 시설 ID입니다. 직접 연결 통합에 사용하십시오.
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 ID입니다.
facility_id
string둘 중 하나통합에 구성된 시설 식별자 유형을 제공하십시오. 직접 연결 통합에는 facility_id를, 연결 식별자 통합에는 linking_identifier를 사용하십시오. 둘 다 보내지 마십시오. API는 파트너 계정에 구성된 식별자 유형을 사용하고 다른 하나는 무시합니다. 자세히 알아보기Performance Hub 시설 ID입니다. 직접 연결 통합에 필요합니다.
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 ID입니다.
facility_id
string둘 중 하나통합에 구성된 시설 식별자 유형을 제공하십시오. 직접 연결 통합에는 facility_id를, 연결 식별자 통합에는 linking_identifier를 사용하십시오. 둘 다 보내지 마십시오. API는 파트너 계정에 구성된 식별자 유형을 사용하고 다른 하나는 무시합니다. 자세히 알아보기Performance Hub 시설 ID입니다. 직접 연결 통합에 필요합니다.
linking_identifier
string둘 중 하나통합에 구성된 시설 식별자 유형을 제공하십시오. 직접 연결 통합에는 facility_id를, 연결 식별자 통합에는 linking_identifier를 사용하십시오. 둘 다 보내지 마십시오. API는 파트너 계정에 구성된 식별자 유형을 사용하고 다른 하나는 무시합니다. 자세히 알아보기파트너 시설 식별자입니다. 연결 식별자 통합에 필요합니다.
member_id
string필수파트너 회원 ID입니다. 감사 로깅과 이후의 데이터 연결에 사용됩니다.
first_name
string필수출입문을 여는 사람의 이름입니다.
last_name
string필수출입문을 여는 사람의 성입니다.
full_name
string선택선택 사항입니다. 생략하면 Performance Hub가
first_name과last_name을 결합합니다.check_in_id
string선택상호 연관을 위한 귀사 시스템의 선택적 체크인 ID입니다.
idempotency_key
string선택선택적 재전송 방지 키입니다. 같은 파트너, 시설, 출입문에 같은 키를 다시 사용하면 가능한 경우 기존 결과가 반환됩니다.
반환값
기기가 릴레이의 물리적 잠금 해제를 확인한 경우에만 200을 반환합니다. 출입문은 Performance Hub Device Management에 구성된 유지 시간을 사용하며, 파트너는 요청별로 릴레이 타이밍을 재정의할 수 없습니다. 대부분의 확인은 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 ID입니다.
facility_id
string둘 중 하나통합에 구성된 시설 식별자 유형을 제공하십시오. 직접 연결 통합에는 facility_id를, 연결 식별자 통합에는 linking_identifier를 사용하십시오. 둘 다 보내지 마십시오. API는 파트너 계정에 구성된 식별자 유형을 사용하고 다른 하나는 무시합니다. 자세히 알아보기Performance Hub 시설 ID입니다. 직접 연결 통합에 필요합니다.
linking_identifier
string둘 중 하나통합에 구성된 시설 식별자 유형을 제공하십시오. 직접 연결 통합에는 facility_id를, 연결 식별자 통합에는 linking_identifier를 사용하십시오. 둘 다 보내지 마십시오. API는 파트너 계정에 구성된 식별자 유형을 사용하고 다른 하나는 무시합니다. 자세히 알아보기파트너 시설 식별자입니다. 연결 식별자 통합에 필요합니다.
outcome
string필수denied또는attempted입니다.reason
string선택최대 64자의 소문자 snake_case 사유 코드입니다.
outcome이denied이면 필수입니다. 예:membership_expired.reason_display_text
string선택사람이 읽을 수 있는 최대 256자의 사유입니다. 예:
Membership expired on 2026-04-01.member_id
string선택파트너 회원 ID입니다. 알 수 없는 카드처럼 자격 증명이 회원과 일치하지 않으면 생략하십시오.
user_email
string선택출입을 시도한 사람의 이메일입니다.
timestamp
string선택시도가 발생한 시각으로, 시간대가 포함된 ISO 8601 형식입니다. 예:
2026-05-18T10:15:30Z. 기본값은 요청을 수신한 시각입니다. 미래로 5분 이상이거나 30일보다 오래된 값은 사용할 수 없습니다.idempotency_key
string선택최대 128자의 재전송 방지 키입니다. 같은 파트너, 시설, 출입문에 같은 키를 다시 사용하면 원래 결과가 반환됩니다.
반환값
이벤트가 기록되면 201을 반환합니다. 같은 idempotency_key를 재전송하면 idempotent가 true로 설정된 200을 반환하며 다른 이벤트를 만들지 않습니다.
dry-run 키는 dry_run이 true로 설정된 200을 반환합니다. 아무것도 기록되지 않습니다.
일반적인 실패:
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
보고서 스냅샷 객체
속성
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필수해당 기간의 회원 및 매출 데이터가 포함된 지표 객체입니다.
보고서 스냅샷 객체
{
"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필수저장할 보고서 스냅샷 객체의 배열입니다. 요청당 최대 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 Window 실패
시간 창 유효성 검사는 잘못된 스냅샷이 기록되기 전에 실패합니다. 재시도할 수 없는 일반적인 원인은 다음과 같습니다.
access_time_windows가 있는데access_time_windows_revision이 누락된 경우.- 문자열, 부동 소수점 또는 밀리초로 보이는 epoch 값.
- 잘못된 IANA 시간대, 역전된 구간, 중복된
external_id, 겹치는 주간 블록 또는 분할되지 않은 야간 블록. - 문서화된 개수, 길이 또는 기간 제한을 벗어난 값.
같은 리비전을 다른 정규화 콘텐츠로 반복하면 409 Conflict가 발생합니다. 최신의 신뢰할 수 있는 상태와 조정한 후 더 새로운 리비전을 할당하십시오. 충돌하는 쌍을 계속 재시도하지 마십시오. 이전 리비전은 더 새로운 상태를 덮어쓰지 않고 건너뛴 오래된 스냅샷으로 보고됩니다. 알 수 없거나 매핑되지 않은 scope_key는 권한 부여에서 거부 방향으로 실패하며, 구성 알림으로 취급해야 합니다.
전송 시간이 초과되거나 일시적인 5xx를 받으면 정확히 같은 정규화 스냅샷을 같은 리비전으로 재시도하십시오. 업스트림 원본 조회에 실패한 경우에는 시간 창 필드를 완전히 생략하십시오. 절대 빈 배열로 대체하지 마십시오.
재시도 지침
다음은 제한된 지수 백오프로 재시도하십시오.
429500502503504
다음은 무작정 재시도하지 마십시오.
400401403404409422
출입 통제의 경우 자체 출입 규칙과 안전 프로세스에서 달리 정하지 않는 한 제한 시간 초과 및 오프라인 응답을 항상 잠금 해제 실패로 처리하십시오.
지원 요청 시 포함할 세부 정보
지원팀에 문의할 때 다음을 포함하십시오.
- 엔드포인트 및 HTTP 메서드.
- 타임스탬프 및 시간대.
- 비밀 키가 아닌 파트너 키 ID.
- 사용한 시설 식별자.
- 귀사 시스템의 원본 레코드 ID.
- 응답 상태 및 본문.
- 가능한 경우
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
인증에 실패했습니다. API 비밀 키를 사용자 이름으로, 비밀번호를 빈 값으로 하여 HTTP Basic Auth를 사용하고 있는지 확인하십시오.
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는 가능한 한 추가 방식의 하위 호환 변경을 적용하는 것을 목표로 합니다.
하위 호환 변경의 예:
- 요청에 새로운 선택적 필드 추가.
- 응답에 새 필드 추가.
- 새 엔드포인트 추가.
- 클라이언트가 알 수 없는 값을 처리할 것으로 예상되는 경우 새 enum 값 추가.
- 상태 코드 계약을 변경하지 않고 유효성 검사 메시지 개선.
access_time_windows와 access_time_windows_revision은 추가된 회원 요청 필드입니다. 이 필드를 생략하는 기존 클라이언트는 저장된 Access Time Window 스냅샷이 변경되지 않은 상태로 유지됩니다. 이 생략 규칙은 부분 업서트 호환성을 유지하며, 생략은 빈 배열을 보내는 것과 같지 않습니다.
호환성이 깨지는 변경의 예:
- 필드 제거 또는 이름 변경.
- 필드 유형 변경.
- 선택적 요청 필드를 필수로 변경.
- 엔드포인트 제거.
- 기존 상태 코드 또는 도메인별
reason의 의미 변경.
사용 중단
호환성이 깨지는 변경이 필요한 경우 Performance Hub는 가능한 한 기존 버전을 그대로 변경하지 않습니다. 대신 새 버전이나 마이그레이션 경로를 도입하고 영향을 받는 파트너에게 변경 사항을 알립니다.
사용 중단 공지에는 다음이 포함될 수 있습니다.
- 변경 로그 항목.
- 파트너에게 직접 연락.
- Partner Console의 참고 사항.
- 문서의 마이그레이션 지침.
클라이언트 권장 사항
추가 방식의 변경을 허용하는 클라이언트를 구축하십시오.
- 사용하지 않는 응답 필드는 무시하십시오.
- 알 수 없는 enum 값은 충돌을 일으키지 말고 지원되지 않는 값으로 처리하십시오.
- 엄격한 응답 일치 검사는 피하십시오.
- 통합을 의도적으로 업데이트할 수 있도록 인식되지 않은 값을 기록하십시오.
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는 현장 컨트롤러가 릴레이의 물리적 잠금 해제를 확인한 후에만 성공을 반환합니다.
- Door/Gate Controller 잠금 해제 요청에 대한 선택적
idempotency_key지원 문서를 추가했습니다.