Channel sync
What flows where between FlatsBratislava and your booking channels (Beds24, Hospitable). The Channel sync section is the operator surface for that flow.
Open from V28 → Settings → Channel sync (per-property).
The "What syncs?" matrix (gh#620)
Each property has a capability matrix — rows are the kinds of data the platform can sync; columns are the channels. Each cell is one of:
- Enabled — toggle ON, the platform pushes/pulls this data with the channel.
- Disabled toggle — connector supports it but operator has it OFF.
- Not supported — the channel doesn't expose this capability; rendered disabled with a tooltip explaining why (e.g. "Not supported by Hospitable").
| Row | Beds24 | Hospitable |
|---|---|---|
| Rates push | ✓ | ✗ Not supported |
| Availability push | ✓ | ✗ Not supported |
| Property content push | ✓ | ✗ Not supported |
| Photos push | ✓ | ✗ Not supported |
| Reservations pull | ✓ | ✓ |
| Messages pull | ✓ | ✓ |
| Reviews pull | ✓ | ✓ |
Hospitable's push rows render disabled, not hidden — the operator sees the gap explicitly instead of "what features does this connector have?" being a guessing game.
How pushes actually fire
Pushes are event-driven and debounced (gh#620 Phase 3):
| Operator action | Trigger | Debounce |
|---|---|---|
| Edits rate in V28 dashboard | pushRates |
Per-property per-day cell |
| Reservation lands (availability changes) | pushAvailability |
Accumulating per cell |
| Edits property content (title / description / amenities) | pushContent |
Per-property |
| Adds / removes a photo | pushPhotos |
Per-property |
A burst of rate edits doesn't fan out into a burst of API calls. The accumulator collects per-cell deltas; when the debounce window expires, ONE push goes out with the combined deltas.
Credit back-pressure
Beds24 enforces a per-minute API credit budget. The platform tracks credits used against the budget and throttles pushes so a burst can't trip the channel's rate-limit. If you're editing many rates fast, you'll see "Throttled — syncing in N seconds" on the affected rows.
If the channel ever rejects a push (e.g. the calendar is locked by an operator-side action), the rejection lands as an operator task — "Beds24 push rejected for property X, rate edit at 2026-06-12 14:32". Open the task → see the rejection reason → resolve.
Idempotency
Every push carries a content hash. Re-pushing identical data is a no-op — the platform compares the hash against the last successful push and skips the API call when nothing changed. Saves credits, avoids accidental writes.
Per-property overrides
The matrix is per-property — different properties can have different sync policies. Edit per-property via the matrix; the override lives on properties.connectorCapabilityOverride.
If a property is sometimes managed externally (e.g. owner adjusts rates directly in Beds24 admin), turn the push toggle OFF for that property so operator edits in V28 don't fight the channel side.
Implements: gh#620 (Phase 3 channel sync orchestration engine + V28 "What syncs?" matrix), gh#619 (Phase 2 — shared provider-abstraction kit + capability-flag model + per-property override). Related epic: gh#614 (Universal PMS Connector, 8 phases). Related: gh#556 (Beds24 webhook handler thin-payload rewire).