Zugriffszeitfenster
Mit Access Time Windows kann ein Partnermitglied befristete oder wiederkehrende Zutrittsberechtigungen tragen, die von einem externen System geliefert werden. Diese Seite ist der maßgebliche Producer-Leitfaden für access_time_windows und access_time_windows_revision.
Access Time Windows sind zusätzliche, ausschließlich erlaubende Berechtigungen. Ein aktives Zeitfenster kann den Zutritt erlauben, aber ein inaktives, abgelaufenes, veraltetes oder nicht zugeordnetes Zeitfenster verweigert keinen Zutritt, den eine reguläre Regel oder eine dauerhafte Berechtigung bereits erlaubt. Die Deaktivierung von Benutzern, explizite Türsperren, der Wartungsmodus, Geofencing, Ratenbegrenzungen und die Verfügbarkeit des Controllers gelten weiterhin.
Implementierungen für bestimmte Quellsysteme sind separate Adapter. Sie müssen ihre Quelldaten in diesen herstellerneutralen Vertrag übersetzen, ohne die Bedeutung seiner Felder zu verändern.
Snapshot-Felder des Mitglieds
-
access_time_windows
arrayoptionalDer vollständige Access Time Windows-Snapshot für dieses Mitglied und diese Partnerquelle. Ein Snapshot kann
absolute- undweekly-Zeitfenster mischen. Lassen Sie das Feld weg, um den gespeicherten Snapshot unverändert zu lassen; senden Sie[], um alle Zeitfenster dieser Quelle zu widerrufen. -
access_time_windows_revision
integererforderlich mit access_time_windowsEine monoton steigende, nicht negative, JSON-sichere Ganzzahl für diesen Revisionsstrom aus Mitglied und Quelle. Sie ist immer dann erforderlich, wenn
access_time_windowsvorhanden ist, und darf9007199254740991nicht überschreiten.
Jeder Snapshot akzeptiert höchstens 50 Zeitfenster. external_id, scope_key und label akzeptieren höchstens 120 Zeichen. Absolute Zeitfenster dürfen höchstens 90 Tage umfassen. Ein Wochentag akzeptiert höchstens acht sich nicht überschneidende Blöcke. Ungültige Daten werden abgelehnt, statt gekürzt oder erraten zu werden.
Formen von Zeitfenstern
Ein absolutes Zeitfenster bezeichnet genau ein Intervall:
{
"external_id": "access-4b1782",
"kind": "absolute",
"from": 1792053000,
"to": 1792058400,
"timezone": "Australia/Perth",
"scope_key": "after_hours_entry",
"label": "Temporary site access"
}
Erforderliche Felder sind external_id, kind, from und to. timezone, scope_key und label sind optional.
Ein wöchentliches Zeitfenster bezeichnet wiederkehrende Intervalle in lokaler Uhrzeit, optional begrenzt durch UTC-Zeitpunkte:
{
"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"
}
Erforderliche Felder sind external_id, kind und access_hours. timezone, active_from, active_until, scope_key und label sind optional.
Vollständige gemischte Anfrage
Diese Anfrage ersetzt den bisherigen quelleigenen Snapshot des Mitglieds durch ein absolutes und ein wöchentliches Zeitfenster:
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"
}
]
}
]
}'
Verwenden Sie entsprechend Ihrer konfigurierten Verknüpfungsmethode entweder facility_id oder linking_identifier. Senden Sie nicht beide.
Regeln für Zeiten und Grenzen
from, to, active_from und active_until sind JSON-Ganzzahlen in Unix-Sekunden, die UTC-Zeitpunkte bezeichnen:
- Senden Sie eine JSON-Ganzzahl ohne Anführungszeichen. Numerische Strings, Gleitkommazahlen, RFC 3339-Strings und Unix-Millisekunden werden abgelehnt.
- Jedes Intervall ist halboffen:
[from, to). Der Zutritt kann genau beifrombeginnen; genau beitoist er nicht mehr aktiv. frommuss kleiner alstosein. Wenn beide wöchentlichen Grenzen vorhanden sind, mussactive_fromkleiner alsactive_untilsein.- Leiten Sie Epoch-Werte nicht aus einem lokalen Datum bzw. einer lokalen Uhrzeit ohne Zeitzone ab. Lösen Sie die Quellzeit zunächst in einen UTC-Zeitpunkt auf, teilen Sie dann die Unix-Millisekunden durch 1000 und prüfen Sie, ob das Ergebnis eine Ganzzahl ist.
Epoch-Umrechnung
2026-10-15T08:30:00Z wird in 1792053000 umgerechnet:
UTC instant Unix milliseconds Unix seconds sent
2026-10-15T08:30:00Z 1792053000000 1792053000
Sprachunabhängige Umrechnung:
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
Wenn die Quelle eine Genauigkeit unterhalb einer Sekunde hat, legen Sie vor den Integrationstests bewusst eine Rundungsrichtlinie für Start und Ende fest. Übergeben Sie niemals Millisekunden in der Erwartung, dass die API die Einheit erkennt.
Zeitzonen und Sommerzeit
timezone muss eine gültige IANA-Zeitzone sein, etwa UTC, Australia/Perth oder America/New_York. Wird sie weggelassen, gilt standardmäßig UTC.
- Absolute Zeitfenster:
fromundtobezeichnen bereits exakte UTC-Zeitpunkte.timezonedient nur als Metadatum für Anzeige und Audit; eine Änderung verschiebt keinen der beiden Zeitpunkte. - Wöchentliche Zeitfenster:
timezonelegt die lokale Uhrzeit und die Sommerzeitregeln fest, nach denenaccess_hoursausgewertet wird. Rechnen Sie wöchentliche Blöcke nicht vorab in UTC um. - Bei der Umstellung auf Sommerzeit tritt eine lokale Uhrzeit, die in der Zeitzone übersprungen wird, nie ein.
- Bei der Umstellung auf Winterzeit entsprechen beide realen Zeitpunkte mit der wiederholten lokalen Uhrzeit dem wöchentlichen Block.
active_fromundactive_untilbleiben UTC-Zeitpunkte, auch wenn ein wöchentliches Zeitfenster eine andere Zeitzone als UTC verwendet.
access_hours verwendet die Kleinbuchstaben sun bis sat. Jeder Wert ist ein Array von [start, end]-Paaren im 24-Stunden-Format HH:mm mit führenden Nullen. Blöcke müssen nicht leer, geordnet und überschneidungsfrei sein. end ist exklusiv. Ein Block darf nicht über Mitternacht reichen; teilen Sie ein Quellintervall über Nacht in einen späten Block am ersten Tag und einen frühen Block am folgenden Tag auf.
Stabile IDs und Bereichszuordnung
external_id muss während der gesamten Lebensdauer eines logischen Zeitfensters stabil und innerhalb des Mitglieder-Snapshots eindeutig sein. Halten Sie sie stabil, wenn sich Zeiten oder Bezeichnungen ändern, damit Betreiber und Audit-Datensätze Revisionen einander zuordnen können. Verwenden Sie sie nicht für ein unabhängiges Zeitfenster wieder.
scope_key ist Ihr stabiles logisches Zutrittsziel. Standardwert ist default. Ein Administrator der Einrichtung ordnet jeden zulässigen Schlüssel einem Ziel im Performance Hub zu: der gesamten Einrichtung, einer Tür oder einem Zugriffsbereich:
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
Partner senden innerhalb eines Zeitfensters keine Einrichtungs-, Tür- oder Zugriffsbereichs-IDs des Performance Hub. Ein unbekannter, deaktivierter oder nicht zugeordneter scope_key führt für dieses Zeitfenster zur Verweigerung (fail closed); er erweitert den Zutritt nicht. Vereinbaren und testen Sie die Zuordnungen vor dem Launch.
Vollständige Snapshots und Revisionen
Behandeln Sie die beiden Felder als separat versionierte Partition innerhalb des Mitglieder-Upserts:
| Eingabe | Ergebnis |
|---|---|
access_time_windows weggelassen | Der vorhandene Snapshot bleibt unverändert; keine Revision erforderlich |
| Vorhanden mit neuerer Revision | Der gesamte gespeicherte Snapshot für dieses Mitglied und diese Quelle wird ersetzt |
| Gleiche Revision und gleiche normalisierte Payload | Idempotente Wiederholung; keine Änderung am Snapshot |
| Gleiche Revision und abweichende normalisierte Payload | Konflikt; nach dem Abgleich eine neue Revision vergeben |
| Ältere Revision | Der veraltete Snapshot wird übersprungen; er kann keinen neueren Zustand überschreiben |
access_time_windows: [] mit neuerer Revision | Widerruft explizit alle quelleigenen Zeitfenster |
Ein Snapshot ist vollständig, kein Patch. Wenn Revision 1842 die Zeitfenster A und B enthält, entfernt Revision 1843, die nur B enthält, das Zeitfenster A.
Führen Sie pro Partner und Mitglied einen einzigen koordinierten Revisionsstrom über Webhook-Worker, Polling, Wiederholung und vollständigen Abgleich hinweg. Eine dauerhafte Datenbanksequenz wird bevorzugt. Ein Unix-Millisekundenwert kann nur dann als Revision verwendet werden, wenn alle Schreiber sich abstimmen und eine strikte Reihenfolge und Eindeutigkeit garantieren; es handelt sich um einen Revisionswert, nicht um ein Epoch-Feld.
Speichern Sie die exakte Anfrage und Revision, bis die API-Antwort bekannt ist. Wiederholen Sie nach einer Zeitüberschreitung oder einem vorübergehenden Fehler denselben normalisierten Snapshot mit derselben Revision. Vergeben Sie keine neue Revision, nur weil die Zustellung auf Transportebene unsicher ist.
Stornierung, Ablauf und Fehler der Quelle
- Ein Zeitfenster stornieren: Rufen Sie den maßgeblichen Quellzustand erfolgreich ab, entfernen Sie dieses Zeitfenster und senden Sie den verbleibenden vollständigen Snapshot mit einer neueren Revision.
- Alle Zeitfenster stornieren: Senden Sie
access_time_windows: []mit einer neueren Revision. - Ein absolutes Zeitfenster ablaufen lassen: Es erlaubt ab
tokeinen Zutritt mehr; senden Sie später einen Abgleich ohne den abgelaufenen Eintrag, um die Snapshots sauber zu halten. - Ein wöchentliches Zeitfenster beenden: Entfernen Sie es in einem neueren Snapshot oder verwenden Sie
active_until, wenn die Quelle einen bekannten Endzeitpunkt hat. - Abruf aus der Quelle schlägt fehl oder ist unvollständig: Senden Sie kein
[]und veröffentlichen Sie keinen unvollständigen Snapshot. Lösen Sie eine Warnung aus und wiederholen Sie den Abruf. Wird ein Fehler der Quelle in einen leeren Snapshot umgewandelt, führt das zu einem unbeabsichtigten Widerruf des Zutritts. - Anfrage an die Partner API besteht die Validierung nicht: Korrigieren Sie die Daten und senden Sie nur dann eine neuere Revision, wenn sich der normalisierte Snapshot ändert. Wiederholen Sie vorübergehende Fehler mit der ursprünglichen Revision.
Die Aktualität der Quelle wird pro Integration anhand der zugesagten Liefer- und Abgleichsfrequenz konfiguriert. Vereinbaren Sie vor der Aktivierung das maximale Alter der Quelldaten, was bei Überschreitung geschieht, Schwellenwerte für Warnungen und ob Betreiber bestätigen dürfen, sich nur auf die eigenen Grenzen jedes Zeitfensters zu verlassen. Ein veraltetes Quellzeitfenster wird nie zu einer Verweigerungsregel; reguläre Regeln und dauerhafte Berechtigungen bleiben Fallback-Pfade.
Producer-Algorithmus
Verwenden Sie diesen sprachunabhängigen Ablauf für jede Mitgliederaktualisierung:
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)
Zertifizierungscheckliste
Führen Sie diese Prüfungen in einer Stage-Einrichtung mit der endgültigen scope_key-Zuordnung durch:
- Ein absolutes Zeitfenster ohne Zeitzone wird akzeptiert und als UTC ausgewertet.
- Ein absolutes Zeitfenster mit benutzerdefinierter IANA-Zeitzone behält dieselben
from/to-Zeitpunkte bei. - Ein wöchentliches Zeitfenster mit benutzerdefinierter IANA-Zeitzone folgt der lokalen Uhrzeit über die Umstellungen auf Sommer- und Winterzeit hinweg.
- Ein gemischter Snapshot aus absoluten und wöchentlichen Zeitfenstern ersetzt den vorherigen Snapshot vollständig.
- Der Zutritt beginnt genau bei
fromund endet genau beito; auch die Enden wöchentlicher Blöcke sind exklusiv. - Die Aktualisierung von Zeiten unter derselben
external_idmit einer neueren Revision wird wirksam. - Das Weglassen von
access_time_windowsändert andere Mitgliederfelder, ohne die Zeitfenster zu ändern. - Die Wiederholung derselben Revision bzw. Payload ist idempotent.
- Gleiche Revision mit abweichender Payload gibt einen Konflikt zurück und ändert den Snapshot nicht.
- Eine ältere Revision, die außerhalb der Reihenfolge eintrifft, wird als veraltet gemeldet und kann den Zustand nicht zurücksetzen.
- Ein neueres
[]widerruft quelleigene Zeitfenster; bei einem fehlgeschlagenen Abruf aus der Quelle wird nichts gesendet. - Ein unbekannter oder nicht zugeordneter
scope_keyführt zur Verweigerung (fail closed) und erzeugt eine für Betreiber sichtbare Warnung. - Warnungen zum Alter der Quelldaten und die konfigurierte Richtlinie für veraltete Quellen funktionieren beim vereinbarten Schwellenwert.
- Webhook- und vollständige Abgleichspfade führen zum selben Snapshot und zur selben Revisionsreihenfolge.
- Die Zustellung über den Strom erreicht Door & Gate Access innerhalb des vereinbarten Ziels.
- Ein aktives Zeitfenster kann den Zutritt zur zugeordneten physischen Tür erlauben, aber weder die Deaktivierung von Benutzern,
blockAllAccess, die Wartung noch das Geofencing umgehen. - Vor, außerhalb und nach einem Zeitfenster erlauben reguläre Regeln und dauerhafte Berechtigungen weiterhin Benutzern den Zutritt, die ansonsten berechtigt sind.
Mindest-Testvektoren
[
{
"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."
}
]
Reichen Sie außerdem Negativvektoren ein für Unix-Millisekunden, numerische Strings, Gleitkommazahlen, ungültige IANA-Zonen, from >= to, doppelte external_id, sich überschneidende Blöcke, Blöcke über Mitternacht, mehr als acht Blöcke an einem Tag, mehr als 50 Zeitfenster und nicht zugeordnete Bereichsschlüssel.