Send messages only your users can read while Bird relays ciphertext.
Deliver private chats, account alerts, and confidential documents to the browser in real time. The Bird Realtime API encrypts each payload inside your server with a key that never leaves your infrastructure, so the Realtime edge and every network hop in between only ever see sealed data.
import { BirdRealtime } from "@messagebird/realtime";
import { encryption } from "@messagebird/realtime/encrypted";
const bird = new BirdRealtime({
appKey: "your-app-key",
region: "us1",
authEndpoint: "/bird/auth",
encryption,
});
// Your auth endpoint hands over this channel's key. Bird never holds it.
const thread = bird.subscribe("private-encrypted-thread-8f2c");
thread.bind("message.created", (message) => {
render(message);
});
Keep the key on your servers
so message payloads stay encrypted at the relay.
You generate a 32-byte master key and give it only to your own publishers and authorization endpoint. It never appears in a request to Bird, and Bird has no copy to hand over, recover, or leak. Name a channel with the private-encrypted- prefix and the server SDK does the rest: no separate encryption service to run and no change to how your clients connect.
How a message stays sealed from your server to the screen
Encryption, key delivery, and decryption each happen on infrastructure you control, with your existing session rules deciding who can read.
- 01
Sealed in your process.
When you publish to an encrypted channel, the server SDK encrypts the payload before the request leaves your server. Bird receives a sealed envelope and fans it out to subscribers without being able to open it.
- 02
A separate key for every conversation.
Each encrypted channel derives its own key from your master key. A user approved for one chat thread or account feed cannot decrypt another, even if they learn its channel name.
- 03
Keys only for readers you approve.
Your authorization endpoint checks the user's session before it returns the channel's key, the same way it approves any private channel. Refuse the subscription and that browser never receives a key.
- 04
Plaintext only in the browser.
The browser client decrypts each event as it arrives, so your handlers receive ordinary JSON. Your application code reads messages exactly as it would on an unencrypted channel.
Publish
Encrypt on publish with the SDK you already use.
Add the master key to your realtime configuration and publish as usual. The SDK sees the channel's prefix and seals the message locally. Each encrypted publish targets one channel, because every channel has its own key; send to many conversations at once with a batch of one event per channel.
const bird = new BirdClient({
apiKey: process.env.BIRD_API_KEY!,
realtime: {
key: process.env.BIRD_REALTIME_KEY,
secret: process.env.BIRD_REALTIME_SECRET,
// 32 random bytes, yours alone. Never sent to Bird.
encryptionMasterKey: process.env.BIRD_REALTIME_MASTER_KEY,
},
});
await bird.realtime.publish(APP_ID, {
event: "message.created",
channels: ["private-encrypted-thread-8f2c"],
data: { from: "u_maya", body: "The signed contract is attached." },
});
Show the latest state without exposing it.
Combine encryption with cache channels and a user who opens the page later still sees the current balance, case status, or last message straight away. Bird stores the latest event sealed, exactly as it was published, and replays it to each newly approved subscriber.
Rotate a key without shipping a client update.
Deploy a new master key to your publishers and authorization endpoint together. New messages are sealed under the new key, and a connected browser that receives one fetches the new channel key on its own. Earlier messages stay sealed under the old key, so rotate whenever a key might be exposed.
Know what stays visible before you design.
Only the payload is encrypted. Channel and event names stay readable so Bird can route them, so use opaque identifiers rather than names that reveal what you are protecting. Encrypted channels cannot track presence or carry client-to-client events, so keep online status on a separate presence channel. Decryption is available in the browser client today; the iOS and Android clients do not yet subscribe to encrypted channels.
Keep building
with Realtime.
Pair encrypted channels with signed subscriptions, live presence, and the rest of your realtime stack on the same app.
Security
Sign subscriptions from your backend, require authenticated connections, and revoke sessions instantly.
→Channels
Route public broadcasts, private streams, encrypted payloads, and cached state by channel prefix.
→Use cases
See how teams build live tracking, chat, notifications, and dashboards on Realtime.
→Scale without
losing control.
Organize teams in workspaces, control API access, and trace changes through audit logs.
Organization
Harbor
Access stays in its workspace.
Production/API keys
Harbor backend
ActiveAlex Lee
Admin
Today · UTC
Audit log
Organization
Harbor
Access stays in its workspace.
Production/API keys
Harbor backend
ActiveAlex Lee
Admin
Today · UTC
Audit log
Organization
Harbor
Access stays in its workspace.
Production/API keys
Harbor backend
ActiveAlex Lee
Admin
Today · UTC
Audit log