How to Send and Receive Your First Message
Send a 1:1 realtime message over WebSocket and receive it on another client — with runnable examples in JavaScript, Dart/Flutter, and Python.
After a successful connection, you can send a 1:1 realtime message to another user. This tutorial explains the concept, then walks through a complete, runnable example for each supported language.
What You Are Building
A minimal flow with two logical users:
user-alice (your SDK) user-bob (another client)
│ │
│ send({ receiverId: "user-bob", ... }) │
├────────────────────────────────────►│
│ │
│◄────────────────────────────────────┤
│ onMessage on bob's client │Both users connect with the same appId but different userId values. Messages route by senderId and receiverId.
Requirements
- transport: "ws" — realtime send/receive uses WebSocket
- connect() completed — isConnected === true
- Receiver exists conceptually — the receiver does not need to be online; DNotifier delivers when they connect (subject to plan and app rules)
The send() Call
All SDKs expose a similar send() shape:
| Field | Description |
|---|---|
| senderId | Must match the connecting user's id (your userId) |
| receiverId | Target user's id (single recipient) |
| data | JSON-serializable payload — typically { type: "text", text: "..." } |
| saveHistory | Optional; default true — persist for chat history APIs |
Example payload:
{
"type": "text",
"text": "Hello from DNotifier!"
}Use any type string your app understands (text, image, audio, doc, custom types).
Receiving Messages
Incoming messages arrive on the onMessage callback registered at construction time. Each message has:
- metadata — sender, timestamp, id, type
- payload — body with helpers like toJSON()
Test with Two Clients
- Run two terminal processes (or two browser tabs)
- Connect as user-alice in one and user-bob in the other
- Send from alice to bob and watch bob's onMessage fire
JavaScript / TypeScript
Send your first 1:1 realtime text message after connecting over WebSocket. This example assumes you completed First Connection.
Complete Example
import WebSocket from "ws";
import { DNotifier } from "@dnotifier-realtime/dnotifier";
const MY_USER_ID = "user-alice";
const PEER_USER_ID = "user-bob";
const notifier = new DNotifier({
appId: process.env.DNOTIFIER_APP_ID,
secret: process.env.DNOTIFIER_SECRET,
transport: "ws",
userId: MY_USER_ID,
WebSocketImpl: WebSocket,
onConnected: async () => {
console.log("Connected as", MY_USER_ID);
await notifier.send({
senderId: MY_USER_ID,
receiverId: PEER_USER_ID,
data: {
type: "text",
text: "Hello from DNotifier!",
},
});
console.log("Message sent to", PEER_USER_ID);
},
onMessage: (msg) => {
const body = msg.payload.toJSON();
console.log(`[${msg.metadata.sender}]`, body);
},
onDisconnected: () => {
console.log("Disconnected");
},
});
await notifier.connect();Browser Variant
import { DNotifier } from "@dnotifier-realtime/dnotifier";
const MY_USER_ID = "user-alice";
const PEER_USER_ID = "user-bob";
const notifier = new DNotifier({
appId: import.meta.env.VITE_DNOTIFIER_APP_ID,
secret: import.meta.env.VITE_DNOTIFIER_SECRET,
transport: "ws",
userId: MY_USER_ID,
onConnected: () => console.log("Connected"),
onMessage: (msg) => console.log(msg.payload.toJSON()),
onDisconnected: () => {},
});
await notifier.connect();
await notifier.send({
senderId: MY_USER_ID,
receiverId: PEER_USER_ID,
data: { type: "text", text: "Hello from DNotifier!" },
});Send After Connect (Decoupled)
If you prefer not to send inside onConnected:
await notifier.connect();
await notifier.send({
senderId: "user-alice",
receiverId: "user-bob",
data: {
type: "text",
text: "Hello from DNotifier!",
},
saveHistory: true, // default — set false to skip chat history persistence
});Echo Test (Single Process)
Run two scripts in separate terminals to verify delivery.
Terminal 1 — bob (receiver):
// receive.js — user-bob listens
import WebSocket from "ws";
import { DNotifier } from "@dnotifier-realtime/dnotifier";
const notifier = new DNotifier({
appId: process.env.DNOTIFIER_APP_ID,
secret: process.env.DNOTIFIER_SECRET,
transport: "ws",
userId: "user-bob",
WebSocketImpl: WebSocket,
onConnected: () => console.log("Bob is online"),
onMessage: (msg) => console.log("Bob received:", msg.payload.toJSON()),
onDisconnected: () => {},
});
await notifier.connect();Terminal 2 — alice (sender): use the complete example at the top of this section.
Bob's terminal should print:
Bob received: { type: 'text', text: 'Hello from DNotifier!' }TypeScript
await notifier.send({
senderId: MY_USER_ID,
receiverId: PEER_USER_ID,
data: {
type: "text",
text: "Hello from DNotifier!",
} satisfies { type: string; text: string },
});Troubleshooting
| Issue | Check |
|---|---|
| Send throws before connect | Await connect() first; confirm isConnected |
| Bob never receives | Bob must be connected with same appId; verify receiverId spelling |
| Empty payload | Ensure data is JSON-serializable |
| Auth works but send fails | Confirm WebSocket transport, not HTTP |
Dart / Flutter
Send your first 1:1 realtime text message after connecting over WebSocket. This example assumes you completed First Connection.
Complete Example
import 'package:dnotifier/dnotifier.dart';
const myUserId = 'user-alice';
const peerUserId = 'user-bob';
Future<void> main() async {
final notifier = DNotifier(
appId: 'your-app-id',
secret: 'your-app-secret',
transport: 'ws',
userId: myUserId,
onConnected: () async {
print('Connected as $myUserId');
await notifier.send(
senderId: myUserId,
receiverId: peerUserId,
data: {
'type': 'text',
'text': 'Hello from DNotifier!',
},
);
print('Message sent to $peerUserId');
},
onMessage: (DNotifierMessage msg) {
print('[${msg.metadata.sender}] ${msg.payload.toJSON()}');
},
onDisconnected: ({code, reason}) {
print('Disconnected: $reason');
},
);
await notifier.connect();
}Replace credentials with your dashboard values or compile-time defines.
Run
dart run bin/send_first_message.dartSend After Connect (Decoupled)
await notifier.connect();
await notifier.send(
senderId: 'user-alice',
receiverId: 'user-bob',
data: {
'type': 'text',
'text': 'Hello from DNotifier!',
},
saveHistory: true, // default — set false to skip chat history persistence
);Flutter Button Example
ElevatedButton(
onPressed: () async {
if (!notifier.isConnected) return;
await notifier.send(
senderId: myUserId,
receiverId: peerUserId,
data: {'type': 'text', 'text': 'Hello from Flutter!'},
);
},
child: const Text('Send message'),
)Echo Test (Two Processes)
Process 1 — bob listens:
import 'package:dnotifier/dnotifier.dart';
Future<void> main() async {
final bob = DNotifier(
appId: 'your-app-id',
secret: 'your-app-secret',
transport: 'ws',
userId: 'user-bob',
onConnected: () => print('Bob is online'),
onMessage: (msg) => print('Bob received: ${msg.payload.toJSON()}'),
);
await bob.connect();
}Process 2 — alice sends: use the complete example at the top of this section.
Expected on bob's console:
Bob received: {type: text, text: Hello from DNotifier!}Troubleshooting
| Issue | Check |
|---|---|
| StateError: Not connected | Await connect() before send() |
| Receiver gets nothing | Receiver must use same appId and be connected |
| ArgumentError: receiverId or receiverIds required | Pass receiverId or receiverIds |
| Auth OK but no delivery | Use transport: 'ws', not 'http' |
Python
Send your first 1:1 realtime text message after connecting over WebSocket. This example assumes you completed First Connection.
Complete Example
import asyncio
from dnotifier import DNotifier
MY_USER_ID = "user-alice"
PEER_USER_ID = "user-bob"
async def on_connected(notifier: DNotifier):
print(f"Connected as {MY_USER_ID}")
await notifier.send(
sender_id=MY_USER_ID,
receiver_id=PEER_USER_ID,
data={"type": "text", "text": "Hello from DNotifier!"},
)
print(f"Message sent to {PEER_USER_ID}")
async def main():
notifier = DNotifier(
app_id="your-app-id",
secret="your-app-secret",
transport="ws",
user_id=MY_USER_ID,
on_connected=lambda: asyncio.create_task(on_connected(notifier)),
on_message=lambda msg: print(f"[{msg.metadata.sender}] {msg.payload.to_json()}"),
on_disconnected=lambda code=None, reason=None: print(f"Disconnected: {reason}"),
)
await notifier.connect()
await asyncio.sleep(3600) # keep alive for incoming messages
asyncio.run(main())Replace credentials with your dashboard values or environment variables.
Run
python send_first_message.pySend After Connect (Decoupled)
await notifier.connect()
await notifier.send(
sender_id="user-alice",
receiver_id="user-bob",
data={"type": "text", "text": "Hello from DNotifier!"},
save_history=True, # default — set False to skip chat history persistence
)Echo Test (Two Processes)
Process 1 — bob listens:
import asyncio
from dnotifier import DNotifier
async def main():
bob = DNotifier(
app_id="your-app-id",
secret="your-app-secret",
transport="ws",
user_id="user-bob",
on_connected=lambda: print("Bob is online"),
on_message=lambda msg: print(f"Bob received: {msg.payload.to_json()}"),
)
await bob.connect()
await asyncio.sleep(3600)
asyncio.run(main())Process 2 — alice sends: use the complete example at the top of this section.
Expected on bob's console:
Bob received: {'type': 'text', 'text': 'Hello from DNotifier!'}Troubleshooting
| Issue | Check |
|---|---|
| RuntimeError: Not connected | Await connect() before send() |
| Receiver gets nothing | Receiver must use same app_id and be connected |
| ValueError: receiver_id or receiver_ids required | Pass receiver_id or receiver_ids |
| Auth OK but no delivery | Use transport="ws", not "http" |
Watch: How to Send and Receive Your First Message
Same steps as above — use whichever format you prefer.
DNotifier Tutorial
Tutorial 5 of 5
- Tutorial 1How to Create a New Project
- Tutorial 2How to Install the DNotifier SDK
- Tutorial 3How to Choose a Transport
- Tutorial 4How to Make Your First Connection
- Tutorial 5How to Send and Receive Your First Message