Realtime Events Quickstart¶
Get live updates in your application with Centrali's Realtime service. Subscribe to record events and receive instant notifications when data changes.
Overview¶
Centrali Realtime uses Server-Sent Events (SSE) to stream record changes to your application in real-time. No polling required.
// Subscribe to order updates
centrali.realtime.subscribe({
structures: ['order'],
events: ['record_created', 'record_updated'],
onEvent: (event) => {
console.log(`Order ${event.recordId} was ${event.event}`);
}
});
Installation¶
Install the Centrali SDK:
Quick Start¶
1. Initialize the SDK¶
import { CentraliSDK } from '@centrali-io/centrali-sdk';
const centrali = new CentraliSDK({
baseUrl: 'https://api.centrali.io',
workspaceId: 'my-workspace',
token: 'your-bearer-token' // or use clientId/clientSecret
});
2. Subscribe to Events¶
const subscription = centrali.realtime.subscribe({
// Filter by structures (optional)
structures: ['order', 'customer'],
// Filter by event types (optional)
events: ['record_created', 'record_updated'],
// Handle incoming events
onEvent: (event) => {
console.log('Event received:', event);
console.log('Structure:', event.recordSlug);
console.log('Record ID:', event.recordId);
console.log('Data:', event.data);
},
// Handle errors (optional)
onError: (error) => {
console.error('Realtime error:', error.code, error.message);
},
// Connection callbacks (optional)
onConnected: () => console.log('Connected!'),
onDisconnected: (reason) => console.log('Disconnected:', reason)
});
3. Unsubscribe When Done¶
Event Types¶
| Event | Description |
|---|---|
record_created | A new record was created |
record_updated | An existing record was modified |
record_deleted | A record was deleted |
Event Payload¶
Each event includes:
interface RealtimeRecordEvent {
event: 'record_created' | 'record_updated' | 'record_deleted';
workspaceSlug: string;
recordSlug: string; // Structure's slug (e.g., "order")
recordId: string;
data: object; // Record data (or {before, after} for updates)
timestamp: string; // ISO timestamp
createdBy?: string; // User who created (for creates)
updatedBy?: string; // User who updated (for updates)
}
Complete Example: React Dashboard¶
import { useEffect, useState } from 'react';
import { CentraliSDK, RealtimeRecordEvent } from '@centrali-io/centrali-sdk';
function OrderDashboard() {
const [orders, setOrders] = useState<Order[]>([]);
const [connected, setConnected] = useState(false);
useEffect(() => {
const centrali = new CentraliSDK({
baseUrl: 'https://api.centrali.io',
workspaceId: 'my-workspace',
token: localStorage.getItem('token')
});
// 1. Fetch initial data
centrali.queryRecords('order', { sort: '-createdAt', limit: 50 })
.then(response => setOrders(response.data));
// 2. Subscribe to realtime updates
const subscription = centrali.realtime.subscribe({
structures: ['order'],
onEvent: (event) => {
switch (event.event) {
case 'record_created':
setOrders(prev => [event.data as Order, ...prev]);
break;
case 'record_updated':
setOrders(prev => prev.map(o =>
o.id === event.recordId ? event.data.after : o
));
break;
case 'record_deleted':
setOrders(prev => prev.filter(o => o.id !== event.recordId));
break;
}
},
onConnected: () => setConnected(true),
onDisconnected: () => setConnected(false)
});
// 3. Cleanup on unmount
return () => subscription.unsubscribe();
}, []);
return (
<div>
<div className={connected ? 'status-online' : 'status-offline'}>
{connected ? 'Live' : 'Reconnecting...'}
</div>
<ul>
{orders.map(order => (
<li key={order.id}>{order.customerName} - ${order.total}</li>
))}
</ul>
</div>
);
}
Filtering Events¶
By Structure¶
Only receive events for specific structures:
centrali.realtime.subscribe({
structures: ['order', 'invoice'], // Only these structures
onEvent: handleEvent
});
By Event Type¶
Only receive specific event types:
centrali.realtime.subscribe({
events: ['record_created'], // Only new records
onEvent: handleEvent
});
By Data Values (CFL Filter)¶
Filter events based on record data using Centrali Filter Language:
centrali.realtime.subscribe({
structures: ['order'],
filter: 'data.status:shipped', // Only shipped orders
onEvent: handleEvent
});
See Filtering Guide for complete filter syntax.
Important: Initial Sync Pattern¶
Realtime only delivers events that occur after you connect. To build a complete UI:
- Fetch current data first - Query records to get the initial state
- Subscribe to realtime - Start receiving live updates
- Merge updates - Apply incoming events to your local state
// 1. Fetch initial data
const initialData = await centrali.queryRecords('order', { limit: 100 });
setOrders(initialData.data);
// 2. Subscribe to updates (events are applied to initialData)
const subscription = centrali.realtime.subscribe({
structures: ['order'],
onEvent: (event) => {
// Merge event into existing state
updateLocalState(event);
}
});
Connection Behavior¶
Automatic Reconnection¶
The SDK automatically reconnects with exponential backoff: - Initial delay: 1 second - Max delay: 30 seconds - Max attempts: 10
Connection Timeout¶
Connections automatically close after 1 hour. The SDK will reconnect automatically.
Keep-Alive¶
The server sends ping comments every 30 seconds to maintain the connection.
Next Steps¶
- Authentication - Token management for realtime
- Filtering - Advanced event filtering with CFL
- Troubleshooting - Common issues and solutions
- API Reference - HTTP API details