391 lines
8.5 KiB
Plaintext
391 lines
8.5 KiB
Plaintext
---
|
|
title: Realtime API Reference
|
|
description: Manage realtime channels, inspect message history, and use raw Socket.IO pub/sub.
|
|
---
|
|
|
|
## Overview
|
|
|
|
Realtime has two surfaces:
|
|
|
|
- **REST API** for channel management, message history, delivery stats, permissions, and retention settings.
|
|
- **Socket.IO** for live subscribe, publish, presence, and delivered events.
|
|
|
|
<Note>
|
|
The REST API does not stream messages. Use the Socket.IO connection, or the [TypeScript SDK](/sdks/typescript/realtime), for live events.
|
|
</Note>
|
|
|
|
## Authentication
|
|
|
|
Admin REST endpoints require a project-admin token or API key.
|
|
|
|
```bash
|
|
Authorization: Bearer <project-admin-jwt-or-ik_api_key>
|
|
Content-Type: application/json
|
|
```
|
|
|
|
You can also pass API keys with:
|
|
|
|
```bash
|
|
X-API-Key: <ik_api_key>
|
|
```
|
|
|
|
Socket.IO connections authenticate through the Socket.IO `auth` object:
|
|
|
|
```javascript
|
|
const socket = io('https://your-app.insforge.app', {
|
|
auth: {
|
|
token: '<user-jwt-or-anon-token>'
|
|
}
|
|
});
|
|
```
|
|
|
|
Server/admin clients may pass an API key:
|
|
|
|
```javascript
|
|
const socket = io('https://your-app.insforge.app', {
|
|
auth: {
|
|
apiKey: '<ik_api_key>'
|
|
}
|
|
});
|
|
```
|
|
|
|
## Socket.IO Pub/Sub
|
|
|
|
Install the Socket.IO client when you are not using the InsForge SDK:
|
|
|
|
```bash
|
|
npm install socket.io-client
|
|
```
|
|
|
|
### Connect And Subscribe
|
|
|
|
```javascript
|
|
import { io } from 'socket.io-client';
|
|
|
|
const socket = io('https://your-app.insforge.app', {
|
|
auth: {
|
|
token: '<user-jwt-or-anon-token>'
|
|
}
|
|
});
|
|
|
|
socket.emit('realtime:subscribe', { channel: 'order:123' }, (response) => {
|
|
if (response.ok) {
|
|
console.log('Subscribed:', response.channel);
|
|
console.log('Presence:', response.presence.members);
|
|
} else {
|
|
console.error(response.error.code, response.error.message);
|
|
}
|
|
});
|
|
```
|
|
|
|
### Listen For Events
|
|
|
|
```javascript
|
|
socket.on('status_changed', (message) => {
|
|
console.log(message.status);
|
|
console.log(message.meta.messageId);
|
|
console.log(message.meta.senderType);
|
|
});
|
|
|
|
socket.on('presence:join', (message) => {
|
|
console.log('Joined:', message.member);
|
|
});
|
|
|
|
socket.on('presence:leave', (message) => {
|
|
console.log('Left:', message.member);
|
|
});
|
|
|
|
socket.on('realtime:error', (error) => {
|
|
console.error(error.channel, error.code, error.message);
|
|
});
|
|
```
|
|
|
|
### Publish
|
|
|
|
```javascript
|
|
socket.emit('realtime:publish', {
|
|
channel: 'order:123',
|
|
event: 'customer_viewed',
|
|
payload: {
|
|
viewedAt: new Date().toISOString()
|
|
}
|
|
});
|
|
```
|
|
|
|
<Warning>
|
|
The socket must successfully subscribe to a channel before it can publish to that channel.
|
|
</Warning>
|
|
|
|
### Unsubscribe
|
|
|
|
```javascript
|
|
socket.emit('realtime:unsubscribe', { channel: 'order:123' });
|
|
socket.disconnect();
|
|
```
|
|
|
|
### Socket Events
|
|
|
|
| Event | Direction | Description |
|
|
|-------|-----------|-------------|
|
|
| `realtime:subscribe` | Client to server | Subscribe to a channel. The acknowledgement returns success/error and a presence snapshot. |
|
|
| `realtime:unsubscribe` | Client to server | Leave a channel. |
|
|
| `realtime:publish` | Client to server | Insert a user message into the realtime pipeline. |
|
|
| Custom event name | Server to client | Delivered message, emitted under the message `eventName`. |
|
|
| `presence:join` | Server to client | A logical member became present in the channel. |
|
|
| `presence:leave` | Server to client | A logical member is no longer present in the channel. |
|
|
| `realtime:error` | Server to client | Subscribe or publish failed. |
|
|
|
|
## Channel Patterns
|
|
|
|
Create channel definitions before clients subscribe.
|
|
|
|
| Pattern | Matches |
|
|
|---------|---------|
|
|
| `orders` | `orders` |
|
|
| `order:%` | `order:123`, `order:456` |
|
|
| `chat:%:messages` | `chat:room-1:messages` |
|
|
|
|
Pattern matching uses SQL `LIKE`, so `%` is the wildcard. `_` is not accepted in channel patterns because it is also a SQL wildcard.
|
|
|
|
## Channels
|
|
|
|
### List Channels
|
|
|
|
```http
|
|
GET /api/realtime/channels
|
|
```
|
|
|
|
```bash
|
|
curl "https://your-app.insforge.app/api/realtime/channels" \
|
|
-H "Authorization: Bearer <project-admin-jwt-or-ik_api_key>"
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"pattern": "order:%",
|
|
"description": "Order updates",
|
|
"webhookUrls": ["https://example.com/webhook"],
|
|
"enabled": true,
|
|
"createdAt": "2026-04-25T17:00:00.000Z",
|
|
"updatedAt": "2026-04-25T17:00:00.000Z"
|
|
}
|
|
]
|
|
```
|
|
|
|
### Create Channel
|
|
|
|
```http
|
|
POST /api/realtime/channels
|
|
```
|
|
|
|
Request body:
|
|
|
|
| Field | Type | Required | Description |
|
|
|-------|------|----------|-------------|
|
|
| `pattern` | `string` | Yes | Channel pattern. |
|
|
| `description` | `string` | No | Human-readable description. |
|
|
| `webhookUrls` | `string[]` | No | Webhook URLs for every delivered message. |
|
|
| `enabled` | `boolean` | No | Defaults to `true`. Disabled channels cannot be joined or delivered to. |
|
|
|
|
```bash
|
|
curl -X POST "https://your-app.insforge.app/api/realtime/channels" \
|
|
-H "Authorization: Bearer <project-admin-jwt-or-ik_api_key>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"pattern": "chat:%",
|
|
"description": "Chat rooms",
|
|
"webhookUrls": ["https://example.com/realtime-webhook"],
|
|
"enabled": true
|
|
}'
|
|
```
|
|
|
|
### Get Channel
|
|
|
|
```http
|
|
GET /api/realtime/channels/{id}
|
|
```
|
|
|
|
### Update Channel
|
|
|
|
```http
|
|
PUT /api/realtime/channels/{id}
|
|
```
|
|
|
|
```bash
|
|
curl -X PUT "https://your-app.insforge.app/api/realtime/channels/550e8400-e29b-41d4-a716-446655440000" \
|
|
-H "Authorization: Bearer <project-admin-jwt-or-ik_api_key>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"description": "Active order updates",
|
|
"enabled": true
|
|
}'
|
|
```
|
|
|
|
### Delete Channel
|
|
|
|
```http
|
|
DELETE /api/realtime/channels/{id}
|
|
```
|
|
|
|
```json
|
|
{
|
|
"message": "Channel deleted"
|
|
}
|
|
```
|
|
|
|
Message history is preserved. Deleted channels set existing message `channelId` values to `null`.
|
|
|
|
## Messages
|
|
|
|
### List Messages
|
|
|
|
```http
|
|
GET /api/realtime/messages
|
|
```
|
|
|
|
Query parameters:
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `channelId` | `uuid` | Filter by channel ID. |
|
|
| `eventName` | `string` | Filter by event name. |
|
|
| `limit` | `integer` | 1 to 1000. Defaults to 100. |
|
|
| `offset` | `integer` | Defaults to 0. |
|
|
|
|
```bash
|
|
curl "https://your-app.insforge.app/api/realtime/messages?eventName=status_changed&limit=50" \
|
|
-H "Authorization: Bearer <project-admin-jwt-or-ik_api_key>"
|
|
```
|
|
|
|
Response:
|
|
|
|
```json
|
|
[
|
|
{
|
|
"id": "660e8400-e29b-41d4-a716-446655440000",
|
|
"eventName": "status_changed",
|
|
"channelId": "550e8400-e29b-41d4-a716-446655440000",
|
|
"channelName": "order:123",
|
|
"payload": {
|
|
"id": "123",
|
|
"status": "shipped"
|
|
},
|
|
"senderType": "system",
|
|
"senderId": null,
|
|
"wsAudienceCount": 5,
|
|
"whAudienceCount": 1,
|
|
"whDeliveredCount": 1,
|
|
"createdAt": "2026-04-25T17:00:00.000Z"
|
|
}
|
|
]
|
|
```
|
|
|
|
### Message Stats
|
|
|
|
```http
|
|
GET /api/realtime/messages/stats
|
|
```
|
|
|
|
Query parameters:
|
|
|
|
| Parameter | Type | Description |
|
|
|-----------|------|-------------|
|
|
| `channelId` | `uuid` | Filter stats by channel ID. |
|
|
| `since` | `date-time` | Include only messages created after this timestamp. |
|
|
|
|
```json
|
|
{
|
|
"totalMessages": 1250,
|
|
"whDeliveryRate": 0.98,
|
|
"topEvents": [
|
|
{
|
|
"eventName": "status_changed",
|
|
"count": 450
|
|
}
|
|
],
|
|
"retentionDays": null
|
|
}
|
|
```
|
|
|
|
`retentionDays: null` means messages are retained indefinitely.
|
|
|
|
## Permissions
|
|
|
|
```http
|
|
GET /api/realtime/permissions
|
|
```
|
|
|
|
Returns user-defined RLS policies for:
|
|
|
|
- Subscribe checks on `realtime.channels`.
|
|
- Publish checks on `realtime.messages`.
|
|
|
|
```json
|
|
{
|
|
"subscribe": {
|
|
"policies": [
|
|
{
|
|
"policyName": "users_subscribe_own_orders",
|
|
"tableName": "channels",
|
|
"command": "SELECT",
|
|
"roles": ["authenticated"],
|
|
"using": "pattern = 'order:%'",
|
|
"withCheck": null
|
|
}
|
|
]
|
|
},
|
|
"publish": {
|
|
"policies": []
|
|
}
|
|
}
|
|
```
|
|
|
|
## Configuration
|
|
|
|
### Get Realtime Config
|
|
|
|
```http
|
|
GET /api/realtime/config
|
|
```
|
|
|
|
```json
|
|
{
|
|
"retentionDays": null
|
|
}
|
|
```
|
|
|
|
### Update Realtime Config
|
|
|
|
```http
|
|
PATCH /api/realtime/config
|
|
```
|
|
|
|
```bash
|
|
curl -X PATCH "https://your-app.insforge.app/api/realtime/config" \
|
|
-H "Authorization: Bearer <project-admin-jwt-or-ik_api_key>" \
|
|
-H "Content-Type: application/json" \
|
|
-d '{
|
|
"retentionDays": 90
|
|
}'
|
|
```
|
|
|
|
Use `null` to keep messages indefinitely. Positive integers retain messages for that many days.
|
|
|
|
## Webhooks
|
|
|
|
When a channel has `webhookUrls`, each message delivered through that channel is posted to each URL.
|
|
|
|
The request body is the original message payload. Headers identify the delivery:
|
|
|
|
| Header | Value |
|
|
|--------|-------|
|
|
| `X-InsForge-Event` | Event name |
|
|
| `X-InsForge-Channel` | Resolved channel name |
|
|
| `X-InsForge-Message-Id` | Message UUID |
|
|
|
|
Delivery attempts are reflected in `whAudienceCount` and `whDeliveredCount` on message history.
|