---
title: "Send messages only your users can read while Bird relays ciphertext."
canonical: "https://bird.com/realtime-api/features/end-to-end-encryption"
---

**thread.ts**

```typescript
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);
});
```

# 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](/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.

## 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.

## 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.

**send-message.ts**

```typescript
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](/realtime-api/features/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](/realtime-api/features/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. →](/realtime-api/features/security)

[Channels Route public broadcasts, private streams, encrypted payloads, and cached state by channel prefix. →](/realtime-api/features/channels)

[Use cases See how teams build live tracking, chat, notifications, and dashboards on Realtime. →](/realtime-api/use-cases)

[Pricing](/pricing/realtime)

[Getting started](/realtime-api/getting-started)

[Realtime API overview](/realtime-api)

## बिना नियंत्रण खोए स्केल करें।

टीमों को वर्कस्पेस में व्यवस्थित करें, API एक्सेस नियंत्रित करें, और ऑडिट लॉग से बदलावों को ट्रेस करें।

[वर्कस्पेस](/docs/guides/workspaces)[टीम की भूमिकाएँ](/docs/guides/users-teams-roles)[API प्रमाणीकरण](/docs/guides/authentication)
[Enterprise जानें](/enterprise)

## Start with Realtime. Build across channels with Bird.

[Get Started](/dashboard/signup?returnTo=%2Fdashboard%2Fw%2Frealtime) · [Contact Sales](/demo?product=realtime)

[Email](/email-api) · [SMS](/sms-api) · [WhatsApp](/whatsapp-api) · [Apple Messages](/apple-messages-api) · [Voice](/voice-api)



## Related resources

- [Send your first realtime event](/docs/get-started/send-your-first-realtime-event) (docs)
- [Build your first integration](/learn/paths/integration) (course)

[Get an implementation brief](/learn/workspace?topic=realtime)
