Jendela Waktu Akses
Access Time Windows memungkinkan Partner Member membawa akses sementara atau berulang yang disediakan oleh sistem eksternal. Halaman ini adalah panduan produsen otoritatif untuk access_time_windows dan access_time_windows_revision.
Access Time Windows adalah izin tambahan yang hanya bersifat mengizinkan. Jendela yang aktif dapat mengizinkan akses, tetapi jendela yang tidak aktif, kedaluwarsa, usang, atau tidak dipetakan tidak menolak akses yang sudah diizinkan oleh aturan reguler atau izin permanen. Penonaktifan pengguna, pemblokiran pintu secara eksplisit, mode pemeliharaan, geofencing, batas laju, dan ketersediaan pengontrol tetap berlaku.
Implementasi untuk sistem upstream tertentu merupakan adaptor terpisah. Adaptor tersebut harus menerjemahkan data sumbernya ke dalam kontrak netral vendor ini tanpa mengubah makna bidangnya.
Bidang snapshot anggota
-
access_time_windows
arrayopsionalSnapshot Access Time Window lengkap untuk anggota dan sumber mitra ini. Satu snapshot dapat menggabungkan jendela
absolutedanweekly. Hilangkan bidang ini agar snapshot yang tersimpan tidak berubah; kirim[]untuk mencabut setiap jendela yang dimiliki sumber ini. -
access_time_windows_revision
integerwajib bersama access_time_windowsBilangan bulat non-negatif yang aman untuk JSON dan terus meningkat secara monoton untuk aliran revisi anggota/sumber ini. Bidang ini wajib setiap kali
access_time_windowsada dan tidak boleh melebihi9007199254740991.
Setiap snapshot menerima paling banyak 50 jendela. external_id, scope_key, dan label menerima paling banyak 120 karakter. Jendela absolut dapat mencakup paling lama 90 hari. Satu hari mingguan menerima paling banyak delapan blok yang tidak tumpang tindih. Data yang tidak valid ditolak, bukan dipotong atau ditebak.
Bentuk jendela
Jendela absolut mengidentifikasi satu interval yang tepat:
{
"external_id": "access-4b1782",
"kind": "absolute",
"from": 1792053000,
"to": 1792058400,
"timezone": "Australia/Perth",
"scope_key": "after_hours_entry",
"label": "Temporary site access"
}
Bidang wajib adalah external_id, kind, from, dan to. timezone, scope_key, dan label bersifat opsional.
Jendela mingguan mengidentifikasi interval waktu jam dinding lokal yang berulang, yang secara opsional dibatasi oleh instan 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"
}
Bidang wajib adalah external_id, kind, dan access_hours. timezone, active_from, active_until, scope_key, dan label bersifat opsional.
Permintaan gabungan lengkap
Permintaan ini mengganti snapshot milik sumber sebelumnya untuk anggota tersebut dengan satu jendela absolut dan satu jendela mingguan:
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"
}
]
}
]
}'
Gunakan facility_id atau linking_identifier sesuai dengan metode penautan yang Anda konfigurasi. Jangan kirim keduanya.
Aturan waktu dan batas
from, to, active_from, dan active_until adalah bilangan bulat JSON berupa detik Unix yang mengidentifikasi instan UTC:
- Kirim bilangan bulat JSON tanpa tanda kutip. String numerik, bilangan float, string RFC 3339, dan milidetik Unix ditolak.
- Setiap interval bersifat setengah terbuka:
[from, to). Akses dapat dimulai tepat padafrom; akses tidak lagi aktif tepat padato. fromharus lebih kecil darito. Jika kedua batas mingguan ada,active_fromharus lebih kecil dariactive_until.- Jangan menurunkan epoch dari tanggal/waktu lokal tanpa zona waktu. Selesaikan terlebih dahulu waktu sumber menjadi instan UTC, lalu bagi milidetik Unix dengan 1000 dan pastikan hasilnya berupa bilangan bulat.
Konversi epoch
2026-10-15T08:30:00Z dikonversi menjadi 1792053000:
UTC instant Unix milliseconds Unix seconds sent
2026-10-15T08:30:00Z 1792053000000 1792053000
Konversi yang netral bahasa:
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
Jika sumber memiliki presisi di bawah satu detik, tetapkan kebijakan pembulatan awal/akhir yang disengaja sebelum pengujian integrasi. Jangan pernah mengirimkan milidetik dan mengandalkan API untuk menebak satuannya.
Zona waktu dan waktu musim panas
timezone harus berupa zona waktu IANA yang valid seperti UTC, Australia/Perth, atau America/New_York. Nilai default-nya adalah UTC jika dihilangkan.
- Jendela absolut:
fromdantosudah mengidentifikasi instan UTC yang tepat.timezonehanya merupakan metadata tampilan dan audit; mengubahnya tidak pernah menggeser kedua instan tersebut. - Jendela mingguan:
timezonemenentukan jam dinding lokal dan aturan waktu musim panas yang digunakan untuk mengevaluasiaccess_hours. Jangan mengonversi blok mingguan ke UTC terlebih dahulu. - Saat perubahan maju (spring-forward), waktu lokal yang dilewati oleh zona waktu tidak pernah terjadi.
- Saat perubahan mundur (fall-back), kedua instan nyata yang memiliki waktu lokal berulang tersebut cocok dengan blok mingguan.
active_fromdanactive_untiltetap merupakan instan UTC meskipun jendela mingguan menggunakan zona waktu selain UTC.
access_hours menggunakan huruf kecil sun hingga sat. Setiap nilai berupa array pasangan [start, end] dengan format 24 jam HH:mm yang diawali nol. Blok tidak boleh kosong, harus berurutan, dan tidak boleh tumpang tindih. end bersifat eksklusif. Blok tidak boleh melewati tengah malam; pisahkan interval sumber semalam menjadi blok larut pada hari pertama dan blok pagi pada hari berikutnya.
ID stabil dan pemetaan cakupan
external_id harus stabil selama masa berlaku jendela logis dan unik di dalam snapshot anggota. Pertahankan agar tetap stabil saat waktu atau label berubah sehingga operator dan catatan audit dapat menghubungkan revisi. Jangan menggunakannya kembali untuk jendela yang tidak terkait.
scope_key adalah target akses logis Anda yang stabil. Nilai default-nya adalah default. Administrator fasilitas memetakan setiap kunci yang diizinkan ke target di seluruh fasilitas, pintu, atau Ruang Lingkup Akses di Performance Hub:
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
Mitra tidak mengirimkan ID fasilitas, pintu, atau Ruang Lingkup Akses Performance Hub di dalam jendela. Untuk scope_key yang tidak dikenal, dinonaktifkan, atau tidak dipetakan, jendela tersebut tidak memberikan akses apa pun; kunci tersebut tidak memperluas akses. Sepakati dan uji pemetaan sebelum peluncuran.
Snapshot lengkap dan revisi
Perlakukan kedua bidang ini sebagai partisi berversi terpisah di dalam upsert Member:
| Input | Hasil |
|---|---|
access_time_windows dihilangkan | Snapshot yang ada tetap tidak berubah; revisi tidak diperlukan |
| Ada dengan revisi yang lebih baru | Seluruh snapshot tersimpan untuk anggota/sumber ini diganti |
| Revisi sama dan payload ternormalisasi sama | Pemutaran ulang idempoten; snapshot tidak berubah |
| Revisi sama dan payload ternormalisasi berbeda | Konflik; alokasikan revisi baru setelah rekonsiliasi |
| Revisi lebih lama | Snapshot usang dilewati; tidak dapat menimpa status yang lebih baru |
access_time_windows: [] dengan revisi yang lebih baru | Secara eksplisit mencabut semua jendela milik sumber |
Snapshot bersifat lengkap, bukan patch. Jika revisi 1842 memiliki jendela A dan B, maka revisi 1843 yang hanya berisi B akan menghapus A.
Kelola satu aliran revisi terkoordinasi per mitra/anggota di seluruh worker webhook, polling, pemutaran ulang, dan rekonsiliasi penuh. Sekuens database yang tahan lama lebih disarankan. Nilai milidetik Unix dapat digunakan sebagai revisi hanya jika setiap penulis berkoordinasi dan menjamin urutan serta keunikan yang ketat; nilai ini adalah nilai revisi, bukan bidang epoch.
Simpan permintaan dan revisi yang persis sama hingga respons API diketahui. Coba ulang snapshot ternormalisasi yang sama dengan revisi yang sama setelah batas waktu atau kesalahan sementara. Jangan mengalokasikan revisi baru hanya karena pengiriman transport tidak pasti.
Pembatalan, kedaluwarsa, dan kegagalan upstream
- Membatalkan satu jendela: berhasil mengambil status sumber otoritatif, hapus jendela tersebut, dan kirim snapshot lengkap yang tersisa dengan revisi yang lebih baru.
- Membatalkan semua jendela: kirim
access_time_windows: []dengan revisi yang lebih baru. - Membiarkan jendela absolut kedaluwarsa: jendela berhenti mengizinkan pada
to; kirim rekonsiliasi berikutnya tanpa entri yang kedaluwarsa agar snapshot tetap bersih. - Mengakhiri jendela mingguan: hapus jendela tersebut dalam snapshot yang lebih baru, atau gunakan
active_untiljika sumber memiliki instan akhir yang diketahui. - Pengambilan sumber gagal atau tidak lengkap: jangan kirim
[]dan jangan memublikasikan snapshot parsial. Kirim peringatan dan coba ulang pengambilan. Mengubah kegagalan upstream menjadi snapshot kosong merupakan pencabutan akses yang tidak disengaja. - Permintaan Partner API gagal validasi: perbaiki data dan kirim revisi yang lebih baru hanya jika snapshot ternormalisasi berubah. Coba ulang kegagalan sementara dengan revisi aslinya.
Kesegaran sumber dikonfigurasi per integrasi berdasarkan frekuensi pengiriman dan rekonsiliasi yang dijanjikan. Sebelum aktivasi, sepakati usia sumber maksimum, apa yang terjadi jika batas tersebut terlampaui, ambang peringatan, dan apakah operator boleh menyetujui untuk hanya mengandalkan batas masing-masing jendela. Jendela sumber yang usang tidak pernah menjadi aturan penolakan; aturan reguler dan izin permanen tetap menjadi jalur cadangan.
Algoritma produsen
Gunakan alur kerja yang netral bahasa ini untuk setiap pembaruan anggota:
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)
Daftar periksa sertifikasi
Selesaikan pemeriksaan ini di fasilitas staging menggunakan pemetaan scope_key final:
- Jendela absolut diterima dengan zona waktu dihilangkan dan dievaluasi sebagai UTC.
- Jendela absolut dengan IANA kustom mempertahankan instan
from/toyang sama. - Jendela mingguan dengan IANA kustom mengikuti waktu jam dinding lokal melewati transisi maju (spring-forward) dan mundur (fall-back).
- Snapshot gabungan absolut/mingguan mengganti snapshot sebelumnya sepenuhnya.
- Akses dimulai tepat pada
fromdan berhenti tepat padato; akhir blok mingguan juga bersifat eksklusif. - Memperbarui waktu di bawah
external_idyang sama dengan revisi yang lebih baru akan berlaku. - Menghilangkan
access_time_windowsmengubah bidang Member lainnya tanpa mengubah jendela. - Memutar ulang revisi/payload yang sama bersifat idempoten.
- Revisi sama/payload berbeda mengembalikan konflik dan tidak mengubah snapshot.
- Revisi lama yang datang tidak berurutan dilaporkan usang dan tidak dapat mengembalikan status ke belakang.
-
[]yang lebih baru mencabut jendela milik sumber; kegagalan pengambilan upstream tidak mengirimkan apa pun. -
scope_keyyang tidak dikenal atau tidak dipetakan tidak memberikan akses apa pun dan memunculkan peringatan yang terlihat oleh operator. - Peringatan usia sumber dan kebijakan sumber usang yang dikonfigurasi berfungsi pada ambang yang disepakati.
- Jalur webhook dan rekonsiliasi penuh menghasilkan snapshot dan urutan revisi yang sama.
- Pengiriman aliran mencapai Door & Gate Access dalam target yang disepakati.
- Jendela aktif dapat mengizinkan pintu fisik yang dipetakan, tetapi tidak dapat melewati penonaktifan pengguna,
blockAllAccess, pemeliharaan, atau geofencing. - Sebelum, di luar, dan setelah jendela, aturan reguler dan izin permanen tetap mengizinkan pengguna yang memenuhi syarat.
Vektor uji minimum
[
{
"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."
}
]
Kirimkan juga vektor negatif untuk milidetik Unix, string numerik, bilangan float, zona IANA yang tidak valid, from >= to, external_id duplikat, blok yang tumpang tindih, blok semalam, lebih dari delapan blok dalam sehari, lebih dari 50 jendela, dan kunci cakupan yang tidak dipetakan.