How-to Guides
Migrate from Pusher / Ably / Sendbird
API mapping, auth differences, and history import patterns for FluxyChat.
Use this guide when replacing a third-party chat/realtime vendor with FluxyChat. For Pusher-specific parity details see Pusher Channels parity.
Quick mapping
| Pusher / Ably | Sendbird | FluxyChat |
|---|---|---|
| Channel | Group channel | Room (rooms.id) |
| Private channel | — | Room type: "group" + membership |
| Presence channel | Member list | WS presence / member_joined events |
socket_id | Session id | socketId on subscribe |
POST /events trigger | Admin message API | POST /events or FluxyChatClient.sendMessage |
| Channel auth endpoint | Token | POST /auth/channel + JWT |
| User auth | Access token | POST /auth/signin + user channel WS |
| Webhooks | Platform webhooks | Signed outbound webhooks + /webhooks dashboard |
Ably uses channels + capabilities; map each Ably channel name one-to-one to a Fluxy room id and issue JWTs with the same userId you used in Ably clientId.
Sendbird maps cleanly: group channel → room, open channel → public room, user → userId in JWT.
Auth migration
Pusher: server signs subscription to private-* channels.
FluxyChat: mint a member JWT on your backend:
// Your auth server
const token = await signFluxyMemberJwt({
projectId,
userId: pusherUserId,
roles: ["member"],
exp: "1h",
});Pass token to FluxyChatClient or ?token= on the WebSocket URL. No separate per-channel auth call unless you use the optional POST /auth/channel helper for Pusher-compatible clients.
Client SDK swap
// Before (Pusher)
const pusher = new Pusher(key, { cluster: "eu", authEndpoint: "/pusher/auth" });
const channel = pusher.subscribe("private-room-42");
channel.bind("new-message", handler);
// After (FluxyChat)
import { useChat } from "@fluxy-chat/react";
const { messages, sendMessage } = useChat("room-42");
// messages updates include history + live WSREST history: GET /rooms/{roomId}/messages replaces polling or Pusher cache channels.
Import message history
FluxyChat has no vendor lock-in import API — push history via REST:
# Batch import (server-side, admin JWT)
curl -X POST "$WORKER/rooms/support-1/messages" \
-H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{
"content": "Legacy message body",
"userId": "legacy-user-id",
"createdAt": "2024-06-01T12:00:00.000Z"
}'Recommended import script (repo root):
# messages.json → [{ "roomId", "content", "userId?", "createdAt?", "clientMessageId?" }]
FLUXY_WORKER_URL=https://your-worker FLUXY_ADMIN_JWT=eyJ... pnpm import-chat-history ./export/messages.jsonUses POST /admin/messages/import with optional backdated createdAt and legacy userId. clientMessageId keeps re-runs idempotent. Batch mode: up to 100 rows per request via /admin/messages/import/batch.
Single message example:
curl -X POST "$WORKER/admin/messages/import" \
-H "Authorization: Bearer $ADMIN_JWT" \
-H "Content-Type: application/json" \
-d '{
"roomId": "support-1",
"userId": "legacy-user-42",
"content": "Imported body",
"createdAt": "2024-06-01T12:00:00.000Z",
"clientMessageId": "pusher-991"
}'Legacy SDK skeleton (without admin backfill):
import { FluxyChatClient } from "@fluxy-chat/sdk";
async function importHistory(
client: FluxyChatClient,
rows: Array<{ roomId: string; userId: string; content: string; createdAt: string }>,
) {
for (const row of rows) {
await client.createMessage(row.roomId, row.content, null, undefined, undefined, {
createdAt: row.createdAt,
userId: row.userId,
});
await new Promise((r) => setTimeout(r, 50));
}
}Verify createMessage options against OpenAPI for your Worker version — use admin/service JWT for backdated createdAt.
Webhooks
| Pusher event | Fluxy webhook |
|---|---|
channel_vacated | room.vacated |
member_added | room.member_joined |
| Client events | client_event |
| — | message.created, message.updated, inbox events |
Re-point your backend URL in dashboard Webhooks and verify HMAC signature with the project secret.
Feature parity checklist
- Private/presence → room types + WS presence
- Client events →
client-*WS events (rate-limited) - Encrypted channels → room E2E (
e2eEnabled+/e2e-key) - User notifications → user channel +
useInbox - Push → Web push (VAPID) or mobile SDK
Rollout strategy
- Dual-write new messages to Fluxy while reading legacy for history
- Backfill history with import script
- Cut over WebSocket URL in client config flag
- Drain legacy vendor after 7-day read-only window