Skip to main content

Server-Sent Events (SSE)

Real-time updates via Server-Sent Events for appointment and availability changes. This endpoint powers the live update functionality in the admin calendar, providing instant synchronization across multiple browser sessions.

Endpoint

GET /wc-appointments/v2/sse

Purpose: Receive real-time updates when appointments or availabilities are created, updated, or deleted.

Permissions: Private to logged-in admins/staff. Requires a valid wp_rest nonce and session cookies.

Authentication

Nonce Methods (any of):

  • Query parameter: nonce or _wpnonce
  • Header: X-WP-Nonce

Requirements:

  • Request must include logged-in admin cookies
  • EventSource automatically includes cookies when used from the same origin
  • Nonce must be valid wp_rest nonce tied to the logged-in admin session

Behavior

  • One-shot stream - Emits up to 50 events, flushes, and exits
  • Client reconnection - Client should reconnect after stream ends
  • Resume support - Use since_id parameter or Last-Event-ID header to resume from last event

Query Parameters

ParameterTypeDescription
noncestringwp_rest nonce tied to the logged-in admin session
_wpnoncestringAlternate WordPress nonce parameter
since_idintLast event ID received; server only emits events with id > since_id

Event Topics

Appointment Events

  • appointment.created - New appointment created
  • appointment.updated - Appointment updated
  • appointment.deleted - Appointment deleted
  • appointment.trashed - Appointment moved to trash
  • appointment.rescheduled - Appointment rescheduled
  • appointment.cancelled - Appointment cancelled

Availability Events

  • availability.created - New availability rule created
  • availability.updated - Availability rule updated
  • availability.deleted - Availability rule deleted

Event Payload

Format: JSON in data: field

Structure:

{
"topic": "appointment.created",
"resource": "appointment",
"resource_id": 123,
"payload": {
"id": 123,
"start": 1733044800,
"end": 1733048400,
"product_id": 456,
"staff_ids": [5],
"staff_id": 5,
"status": "confirmed",
"customer_id": 789,
"order_id": 101112,
"order_item_id": 131415,
"cost": "50.00",
"all_day": false,
"customer_status": "expected"
},
"ts": 1733044800
}

Payload Fields (for appointments):

  • id, start, end, product_id
  • staff_ids, staff_id
  • status, customer_id
  • order_id, order_item_id
  • cost, all_day, customer_status

Example: Browser EventSource

// On an admin page with a localized wp_rest nonce
const restBase = wpApiSettings?.root || wcAppointmentsReactCalendar?.restUrl;
const nonce = wcAppointmentsReactCalendar?.nonce;
const lastId = parseInt(localStorage.getItem('wca:lastEventId') || '0', 10);
const u = new URL(restBase.replace(/\/$/, '/') + 'wc-appointments/v2/sse');
if (nonce) u.searchParams.set('nonce', nonce);
if (lastId > 0) u.searchParams.set('since_id', String(lastId));

const src = new EventSource(u.toString(), { withCredentials: true });
src.addEventListener('appointment.created', (e) => {
const d = JSON.parse(e.data);
// Handle new appointment in calendar view...
localStorage.setItem('wca:lastEventId', d.id);
});
src.addEventListener('appointment.updated', (e) => {
const d = JSON.parse(e.data);
// Update appointment in calendar view...
localStorage.setItem('wca:lastEventId', d.id);
});
src.addEventListener('error', () => {
// Let EventSource auto-reconnect; optionally trigger a refetch if needed.
setTimeout(() => {
// Reconnect logic
}, 5000);
});

Example: cURL (requires cookies)

# Note: You must include your admin session cookies for nonce verification.
# Replace COOKIE_FILE with a cookie jar exported from your browser or created via curl login.
curl -i \
-H "X-WP-Nonce: <wp_rest_nonce>" \
-b COOKIE_FILE \
"https://example.com/wp-json/wc-appointments/v2/sse?since_id=0"

Error Handling

401 Unauthorized:

Returned when:

  • Called without valid cookies (anonymous)
  • Stale/invalid nonce provided

Response:

HTTP/1.1 401 Unauthorized
Content-Type: application/json

{
"code": "rest_forbidden",
"message": "Sorry, you are not allowed to do that.",
"data": {
"status": 401
}
}

Headers

Response Headers:

  • Content-Type: text/event-stream
  • X-Accel-Buffering: no (minimizes proxy buffering)
  • Cache-Control: no-cache

Best Practices

  1. Reconnect on error - EventSource will auto-reconnect, but handle errors gracefully
  2. Store last event ID - Use since_id to avoid missing events on reconnection
  3. Handle one-shot nature - Reconnect after stream ends (50 events or timeout)
  4. Use withCredentials - Ensure cookies are sent with EventSource requests
  5. Debounce updates - Batch UI updates if receiving many events quickly

Limitations

  • One-shot stream - Intentionally limited to avoid long-lived PHP processes
  • 50 event limit - Stream ends after 50 events; client must reconnect
  • Admin only - Not available for public/frontend use
  • Requires cookies - Cannot be used with API key authentication