Erişim Zaman Pencereleri

Access Time Windows, bir Partner Member'ın harici bir sistem tarafından sağlanan geçici veya yinelenen erişim taşımasını sağlar. Bu sayfa, access_time_windows ve access_time_windows_revision için yetkili üretici kılavuzudur.

Access Time Windows, yalnızca izin veren ek izinlerdir. Etkin bir pencere erişime izin verebilir; ancak etkin olmayan, süresi dolmuş, eski veya eşlenmemiş bir pencere, normal bir kuralın veya kalıcı bir iznin zaten verdiği erişimi reddetmez. Kullanıcının devre dışı bırakılması, açık kapı engellemesi, bakım modu, coğrafi sınırlama (geofencing), hız sınırları ve kontrol cihazının kullanılabilirliği yine geçerlidir.

Belirli üst kaynak sistemlere yönelik uygulamalar ayrı bağdaştırıcılardır. Bunlar, kaynak verilerini alan anlamlarını değiştirmeden bu sağlayıcıdan bağımsız sözleşmeye dönüştürmelidir.

Üye anlık görüntüsü alanları

  • access_time_windows array isteğe bağlı

    Bu üye ve iş ortağı kaynağı için eksiksiz Access Time Window anlık görüntüsü. Bir anlık görüntü absolute ve weekly pencereleri karışık olarak içerebilir. Saklanan anlık görüntüyü değiştirmeden bırakmak için alanı göndermeyin; bu kaynağa ait tüm pencereleri iptal etmek için [] gönderin.

  • access_time_windows_revision integer access_time_windows ile zorunlu

    Bu üye/kaynak revizyon akışı için tekdüze artan, negatif olmayan, JSON açısından güvenli bir tam sayı. access_time_windows mevcut olduğunda her zaman zorunludur ve 9007199254740991 değerini aşmamalıdır.

Her anlık görüntü en fazla 50 pencere kabul eder. external_id, scope_key ve label en fazla 120 karakter kabul eder. Mutlak pencereler en fazla 90 gün kapsayabilir. Haftalık bir gün, en fazla sekiz çakışmayan blok kabul eder. Geçersiz veriler kırpılmaz veya tahmin edilmez, reddedilir.

Pencere biçimleri

Mutlak bir pencere tek bir kesin aralığı tanımlar:

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

Zorunlu alanlar external_id, kind, from ve to alanlarıdır. timezone, scope_key ve label isteğe bağlıdır.

Haftalık bir pencere, isteğe bağlı olarak UTC anlarıyla sınırlandırılmış, yinelenen yerel duvar saati aralıklarını tanımlar:

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

Zorunlu alanlar external_id, kind ve access_hours alanlarıdır. timezone, active_from, active_until, scope_key ve label isteğe bağlıdır.

Eksiksiz karışık istek

Bu istek, üyenin kaynağa ait önceki anlık görüntüsünü bir mutlak ve bir haftalık pencereyle değiştirir:

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

Yapılandırdığınız bağlama yöntemine göre facility_id veya linking_identifier kullanın. İkisini birden göndermeyin.

Zaman ve sınır kuralları

from, to, active_from ve active_until, UTC anlarını tanımlayan JSON tam sayı Unix saniyeleridir:

  • Tırnaksız bir JSON tam sayısı gönderin. Sayısal dizeler, kayan noktalı sayılar, RFC 3339 dizeleri ve Unix milisaniyeleri reddedilir.
  • Her aralık yarı açıktır: [from, to). Erişim tam olarak from anında başlayabilir; tam olarak to anında artık etkin değildir.
  • from, to değerinden küçük olmalıdır. Her iki haftalık sınır da mevcut olduğunda active_from, active_until değerinden küçük olmalıdır.
  • Epoch değerlerini saat dilimi belirtilmemiş yerel bir tarih/saatten türetmeyin. Önce kaynak zamanı bir UTC anına çözümleyin, ardından Unix milisaniyelerini 1000'e bölün ve sonucun tam sayı olduğunu doğrulayın.

Epoch dönüştürme

2026-10-15T08:30:00Z, 1792053000 değerine dönüşür:

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

Dilden bağımsız dönüştürme:

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

Kaynak saniyenin altında hassasiyete sahipse entegrasyon testinden önce bilinçli bir başlangıç/bitiş yuvarlama ilkesi tanımlayın. Asla milisaniye gönderip birimi API'nin çıkarmasına güvenmeyin.

Saat dilimleri ve yaz saati uygulaması

timezone, UTC, Australia/Perth veya America/New_York gibi geçerli bir IANA saat dilimi olmalıdır. Belirtilmezse varsayılan olarak UTC olur.

  • Mutlak pencereler: from ve to zaten kesin UTC anlarını tanımlar. timezone yalnızca görüntüleme ve denetim meta verisidir; değiştirilmesi iki andan hiçbirini kaydırmaz.
  • Haftalık pencereler: timezone, access_hours değerlendirmesinde kullanılan yerel duvar saatini ve yaz saati kurallarını tanımlar. Haftalık blokları önceden UTC'ye dönüştürmeyin.
  • İleri alma değişikliği sırasında, saat diliminin atladığı bir yerel saat hiç gerçekleşmez.
  • Geri alma değişikliği sırasında, yinelenen yerel saati taşıyan her iki gerçek an da haftalık blokla eşleşir.
  • Haftalık bir pencere UTC dışı bir saat dilimi kullansa bile active_from ve active_until UTC anları olarak kalır.

access_hours, küçük harfli sun ile sat arasındaki değerleri kullanır. Her değer, başında sıfır olan 24 saatlik HH:mm biçiminde [start, end] çiftlerinden oluşan bir dizidir. Bloklar boş olmamalı, sıralı olmalı ve çakışmamalıdır. end hariçtir. Bir blok gece yarısını geçemez; gece boyunca süren bir kaynak aralığını ilk gün için geç bir bloğa ve sonraki gün için erken bir bloğa bölün.

Sabit kimlikler ve kapsam eşlemesi

external_id, mantıksal bir pencerenin ömrü boyunca sabit ve üye anlık görüntüsü içinde benzersiz olmalıdır. Operatörlerin ve denetim kayıtlarının revizyonları ilişkilendirebilmesi için saatler veya etiketler değiştiğinde de sabit tutun. İlgisiz bir pencere için yeniden kullanmayın.

scope_key, sabit mantıksal erişim hedefinizdir. Varsayılan değeri default olur. Bir tesis yöneticisi, izin verilen her anahtarı Performance Hub'ın tesis geneli, kapı veya Erişim Kapsamı hedeflerine eşler:

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

İş ortakları bir pencere içinde Performance Hub tesis, kapı veya Erişim Kapsamı kimlikleri göndermez. Bilinmeyen, devre dışı bırakılmış veya eşlenmemiş bir scope_key, o pencere için kapalı başarısız olur (fail closed); erişimi genişletmez. Eşlemeleri lansmandan önce kararlaştırın ve test edin.

Eksiksiz anlık görüntüler ve revizyonlar

İki alanı, Member upsert işlemi içinde ayrı olarak sürümlenen bir bölüm olarak ele alın:

GirdiSonuç
access_time_windows gönderilmediMevcut anlık görüntü değişmeden kalır; revizyon gerekmez
Daha yeni bir revizyonla mevcutBu üye/kaynak için saklanan anlık görüntünün tamamı değiştirilir
Aynı revizyon ve aynı normalleştirilmiş yükIdempotent yeniden oynatma; anlık görüntü değişmez
Aynı revizyon ve farklı normalleştirilmiş yükÇakışma; mutabakattan sonra yeni bir revizyon atayın
Daha eski revizyonEski anlık görüntü atlanır; daha yeni durumun üzerine yazamaz
Daha yeni bir revizyonla access_time_windows: []Kaynağa ait tüm pencereleri açıkça iptal eder

Bir anlık görüntü yama değil, eksiksiz bir bütündür. 1842 revizyonunda A ve B pencereleri varsa, yalnızca B'yi içeren 1843 revizyonu A'yı kaldırır.

Webhook çalışanları, yoklama, yeniden oynatma ve tam mutabakat genelinde iş ortağı/üye başına tek bir koordineli revizyon akışı sürdürün. Kalıcı bir veritabanı dizisi tercih edilir. Bir Unix milisaniye değeri, yalnızca her yazıcı koordineli çalışıp katı sıralama ve benzersizliği garanti ettiğinde revizyon olarak kullanılabilir; bu bir revizyon değeridir, epoch alanı değildir.

API yanıtı bilinene kadar tam isteği ve revizyonu kalıcı olarak saklayın. Bir zaman aşımı veya geçici hatadan sonra aynı normalleştirilmiş anlık görüntüyü aynı revizyonla yeniden deneyin. Yalnızca aktarım teslimatı belirsiz olduğu için yeni bir revizyon atamayın.

İptal, süre sonu ve üst kaynak hataları

  • Tek bir pencereyi iptal etme: yetkili kaynak durumunu başarıyla alın, o pencereyi kaldırın ve kalan eksiksiz anlık görüntüyü daha yeni bir revizyonla gönderin.
  • Tüm pencereleri iptal etme: daha yeni bir revizyonla access_time_windows: [] gönderin.
  • Mutlak bir pencerenin süresinin dolmasına izin verme: pencere to anında izin vermeyi durdurur; anlık görüntüleri temiz tutmak için süresi dolan kaydı içermeyen daha sonraki bir mutabakat gönderin.
  • Haftalık bir pencereyi sonlandırma: onu daha yeni bir anlık görüntüde kaldırın veya kaynağın bilinen bir bitiş anı varsa active_until kullanın.
  • Kaynak sorgusu başarısız veya eksik: [] göndermeyin ve kısmi bir anlık görüntü yayımlamayın. Uyarı verin ve sorguyu yeniden deneyin. Bir üst kaynak hatasını boş bir anlık görüntüye dönüştürmek istenmeyen bir erişim iptalidir.
  • Partner API isteği doğrulamadan geçemiyor: verileri düzeltin ve yalnızca normalleştirilmiş anlık görüntü değişirse daha yeni bir revizyon gönderin. Geçici hataları orijinal revizyonla yeniden deneyin.

Kaynak güncelliği, her entegrasyon için taahhüt edilen teslimat ve mutabakat sıklığına göre yapılandırılır. Etkinleştirmeden önce maksimum kaynak yaşını, aşıldığında ne olacağını, uyarı eşiklerini ve operatörlerin yalnızca her pencerenin kendi sınırlarına güvenmeyi onaylayıp onaylayamayacağını kararlaştırın. Eski bir kaynak penceresi asla bir reddetme kuralına dönüşmez; normal kurallar ve kalıcı izinler yedek yollar olarak kalır.

Üretici algoritması

Her üye güncellemesi için bu dilden bağımsız iş akışını kullanın:

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)

Sertifikasyon kontrol listesi

Bu kontrolleri son scope_key eşlemesini kullanarak bir stage tesisinde tamamlayın:

  • Saat dilimi belirtilmemiş mutlak bir pencere kabul ediliyor ve UTC olarak değerlendiriliyor.
  • Özel IANA saat dilimli mutlak bir pencere aynı from/to anlarını koruyor.
  • Özel IANA saat dilimli haftalık bir pencere, ileri ve geri alma geçişlerinde yerel duvar saatini izliyor.
  • Karışık mutlak/haftalık bir anlık görüntü önceki anlık görüntünün tamamen yerini alıyor.
  • Erişim tam olarak from anında başlıyor ve tam olarak to anında duruyor; haftalık blok sonları da hariç tutuluyor.
  • Aynı external_id altında saatlerin daha yeni bir revizyonla güncellenmesi etkili oluyor.
  • access_time_windows gönderilmediğinde diğer Member alanları pencereler değişmeden güncelleniyor.
  • Aynı revizyonun/yükün yeniden oynatılması idempotent.
  • Aynı revizyon/farklı yük bir çakışma döndürüyor ve anlık görüntüyü değiştirmiyor.
  • Sırası bozuk, daha eski bir revizyon eski olarak bildiriliyor ve durumu geri alamıyor.
  • Daha yeni bir [] kaynağa ait pencereleri iptal ediyor; bir üst kaynak sorgu hatası hiçbir şey göndermiyor.
  • Bilinmeyen veya eşlenmemiş bir scope_key kapalı başarısız oluyor ve operatörün görebileceği bir uyarı oluşturuyor.
  • Kaynak yaşı uyarıları ve yapılandırılmış eski kaynak ilkesi kararlaştırılan eşikte çalışıyor.
  • Webhook ve tam mutabakat yolları aynı anlık görüntü ve revizyon sırasında birleşiyor.
  • Akış teslimatı, kararlaştırılan hedef süre içinde Door & Gate Access'e ulaşıyor.
  • Etkin bir pencere eşlenen fiziksel kapıya izin verebiliyor ancak kullanıcı devre dışı bırakmayı, blockAllAccess ayarını, bakımı veya coğrafi sınırlamayı atlayamıyor.
  • Bir pencereden önce, pencere dışında ve pencereden sonra, normal kurallar ve kalıcı izinler başka açılardan uygun olan kullanıcılara hâlâ izin veriyor.

Minimum test vektörleri

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

Ayrıca Unix milisaniyeleri, sayısal dizeler, kayan noktalı sayılar, geçersiz IANA saat dilimleri, from >= to, yinelenen external_id, çakışan bloklar, gece blokları, bir günde sekizden fazla blok, 50'den fazla pencere ve eşlenmemiş kapsam anahtarları için negatif vektörler gönderin.