Built for app developers. Engineered for privacy.

DropOnAir gives your app secure messaging primitives without forcing you to build and maintain messaging infrastructure.

Security

End-to-end encryption by default

Messages are encrypted on the sender's device before they leave. The DropOnAir server relays encrypted blobs, it never has access to plaintext content.

  • ✓  Client-side key generation per conversation
  • ✓  Blind relay, server cannot read content
  • ✓  Forward secrecy support
  • ✓  Zero knowledge at rest
// Encryption is automatic, just send
const { messageId } = await client.sendMessage('user-456', 'Hello!');

// Server only ever sees:
"eyJhbGciOiJFQ0RILUVTIiwiZW5jIjoiQTI1NkdDTSJ9..."

// Recipient gets plaintext via onMessage
client.onMessage(msg => console.log(msg.plaintext));
📡

Message queued for offline user

Waiting for reconnection…

Delivered automatically on reconnect ✓

Reliability

Offline message delivery

When a recipient is offline, messages are durably queued and pushed to their device the moment they reconnect, no polling, no missed messages.

  • ✓  Configurable queue size per user
  • ✓  FIFO delivery order preserved
  • ✓  Works across mobile app restarts
  • ✓  Configurable message retention window
Visibility

Delivery receipts & read status

Know exactly what happened to every message. Receipts are pushed to the sender in real-time via the same WebSocket connection.

PENDING

In local queue

📤
SENT

Reached server

📬
DELIVERED

Recipient device

👀
READ

Opened by user

// Listen for delivery & read events
client.onEvent(event => {
  const { messageId, type } = event;
  // type: MESSAGE_DELIVERED | MESSAGE_READ
  updateUI(messageId, type);
});
Calling

Voice & video calls, built in

Add real-time voice and video calling to your app in minutes. DropOnAir handles the signaling layer over the same encrypted WebSocket used for messages, you supply the WebRTC peer connection.

  • ✓  Invite, ring, accept, reject, end, full lifecycle
  • ✓  SDP offer/answer + ICE candidate relay
  • ✓  Toggle video on/off mid-call
  • ✓  Short-lived TURN credentials for NAT traversal
  • ✓  Voice-only or video calls
// Start a call
const callId = await client.startCall('user-id');

// React to events
client.onCallEvent(event => {
  if (event.type === 'CALL_ACCEPTED')
    startWebRtcNegotiation(event.callId);
});

// End the call
await client.endCall(callId);
📱
💻
🖥️

Same user, multiple devices

Each device has its own E2EE keypair. Messages are encrypted per-device and delivered everywhere simultaneously.

Multi-Device

Seamless multi-device support

Users can log in from phone, tablet, and desktop at the same time. The SDK generates a unique keypair per device, encrypts a separate payload for each, and the server fans messages out to every active session.

  • ✓  Per-device X25519 keypairs
  • ✓  Transparent per-device encryption
  • ✓  Server-side fan-out to all devices
  • ✓  Backward compatible with single-device clients
  • ✓  No client code changes required
Flexibility

Messages (ClearText)

Not every use case needs end-to-end encryption. Messages (ClearText) lets you skip key exchange and send plaintext over the same WebSocket, perfect for notifications, bot messages, support widgets, and public chat rooms.

  • ✓  No key exchange or crypto setup required
  • ✓  Same WebSocket transport as E2EE messages
  • ✓  Offline delivery & delivery receipts included
  • ✓  Works alongside E2EE, choose per message
  • ✓  Available on all plans
// JavaScript
// No key exchange needed, send instantly
await client.sendCleartextMessage(
  'user-456',
  'Welcome to the platform!'
);

// Receive, same onMessage callback
client.onMessage(msg => {
  console.log(msg.plaintext);
});
Scale

Broadcast / Pub-Sub channels

Publish messages to named channels and deliver them to every subscriber in real time. Ideal for live feeds, announcements, collaborative features, and any one-to-many messaging pattern.

  • ✓  Real-time fan-out via WebSocket
  • ✓  Per-channel subscriber management
  • ✓  Message history with auto-expiring TTL
  • ✓  REST API for subscribe / unsubscribe
  • ✓  Per-plan channel limits and quotas
// JavaScript
// Subscribe to a channel
await client.subscribeBroadcast('announcements');

// Listen for broadcasts
client.onBroadcast(msg => {
  console.log(msg.channelId, msg.plaintext);
});

// Publish to a channel
await client.publishBroadcast(
  'announcements',
  'Version 2.0 is live!'
);
Groups

Group messaging

Create groups, add and remove members, and send E2EE or cleartext messages to all participants at once. The SDK handles sender-side fan-out with per-member encryption, the server never sees plaintext.

  • ✓  E2EE group messages (sender-side fan-out)
  • ✓  Cleartext group messages for public groups
  • ✓  REST API for group CRUD + member management
  • ✓  Per-plan limits on groups, members, and messages
  • ✓  Offline delivery for group messages
// JavaScript
// Create a group
const group = await client.createGroup(
  'Project Chat',
  ['user-1', 'user-2']
);

// Send E2EE group message
await client.sendGroupMessage(
  group.groupId, 'Hello team!'
);

// Listen for group messages
client.onGroupMessage(msg => {
  console.log(msg.groupId, msg.plaintext);
});
Groups

Group voice & video calls

Start mesh WebRTC group calls with signaling handled over the same encrypted WebSocket. The SDK provides call lifecycle events, you render the UI.

  • ✓  Mesh topology, each peer connects directly
  • ✓  WebSocket-based call signaling (SDP/ICE)
  • ✓  Per-plan participant limits (up to 32)
  • ✓  Join / leave / end events for all participants
  • ✓  Usage-metered group call minutes
// JavaScript
// Start a group call
await client.startGroupCall(
  group.groupId, 'video'
);

// Listen for group call events
client.onGroupCallEvent(event => {
  if (event.type === 'OFFER') {
    // Handle incoming SDP offer
  }
});

Open-source SDKs for every platform

Native SDKs for Android and iOS ship alongside the JavaScript SDK. Integration patterns stay consistent, same crypto, same proto wire format, same API shape.

🌐 Web / JS🟦 TypeScript🤖 Android (Kotlin)🍎 iOS (Swift)⚡ Ionic / Capacitor⚛ React / React Native🅰️ Angular🟢 Vue
Native SDKs

First-class Android & iOS SDKs

Build truly native messaging apps with the same E2EE guarantees as the JS SDK. CryptoKit on iOS, BouncyCastle on Android, no third-party crypto wrappers needed.

  • ✓  Swift Package Manager (SPM) distribution
  • ✓  Gradle / Maven artifact for Android
  • ✓  Keychain & Keystore secure key storage
  • ✓  Same protobuf wire format across all platforms
  • ✓  Cross-platform test vectors for E2EE verification
// iOS (Swift)
DropOnAir.initialize(config: DropOnAirConfig(
  appId: "your-app-id",
  publicApiKey: "your-key",
  getUserJwt: { try await authService.getJwt() },
  tokenExchangeEndpoint: "/api/droponair/token",
  keyDirectoryEndpoint: "/api/droponair/keys"
))

// Android (Kotlin)
DropOnAir.initialize(context, DropOnAirConfig(
  appId = "your-app-id",
  publicApiKey = "your-key",
  getUserJwt = { authService.getJwt() }
))