Tutorial 4 of 5

How to Make Your First Connection

Understand the connect() flow, then run a complete WebSocket connection example in JavaScript, Dart/Flutter, or Python.

15 min read~3 min video

Connecting is the first code you write after installing an SDK. This tutorial explains the connection flow conceptually, then walks through a complete, runnable example for each supported language.

What connect() Does

When you call connect(), the SDK performs two phases depending on transport.

Phase 1 — Authentication (All Transports)

  • Sends appId, appSecret, and userID to the DNotifier auth endpoint
  • Receives an auth token and plan limits
  • Sets aiEnabled, messageSizeLimit, and related properties on the client
  • If authentication fails (wrong secret, invalid app, plan issue), connect() throws an error.

Phase 2 — Transport Setup

TransportWhat happens after auth
wsOpens a WebSocket to DNotifier, sends a handshake frame with the token, waits for acknowledgment, then sets isConnected = true and calls onConnected
httpSkips the persistent socket; sets isConnected = true and calls onConnected immediately after auth

Constructor Options (Common to All SDKs)

OptionRequiredDescription
appIdYesFrom dashboard
secretYesFrom dashboard
transportYes"ws" or "http"
userIdYesYour end-user or service identifier
onConnectedRecommendedCalled when ready to send
onMessageRecommendedCalled for incoming WebSocket messages
onDisconnectedRecommendedCalled when the socket closes

Optional: logs, url (custom WebSocket URL), and platform-specific WebSocket injection (Node.js).

Connection Lifecycle

construct DNotifier
       │
       ▼
  connect()
       │
       ├──► HTTP auth (appId + secret + userId)
       │         │
       │         ▼
       │    token + plan limits
       │
       ├──► [ws only] open WebSocket + handshake
       │
       ▼
 onConnected()
       │
       ├── send(), sendBinary(), ...
       │
       ▼
 onMessage()  ◄── incoming frames (ws only)
       │
       ▼
 onDisconnected()  ◄── socket closed or network loss

After a Successful Connect

You can read:

  • notifier.isConnected — true when ready
  • notifier.getPlanLimits() — quotas from your plan
  • notifier.aiEnabled — whether AI features are on
  • notifier.messageSizeLimit — max message size in bytes
  • notifier.authToken — token from the last auth (avoid logging in production)

Prerequisites Checklist

  • App created with appId and secret
  • Credentials loaded from environment variables
  • SDK installed
  • Transport chosen — use ws for the first-message walkthrough

What Happens Under the Hood

  • SDK authenticates over HTTPS with your credentials
  • Auth returns a token and plan limits
  • WebSocket opens to the production host (WSS)
  • Client completes handshake with the token
  • Server acknowledges → onConnected fires

Common Errors

ErrorLikely cause
appId, secret, transport, and userId are requiredMissing constructor field
Authentication FailedWrong secret or invalid appId
WebSocket errors in NodeForgot WebSocketImpl: WebSocket
Immediate disconnectNetwork/firewall blocking wss://

JavaScript / TypeScript

This guide connects a DNotifier client over WebSocket from Node.js or the browser.

Complete Example (Node.js)

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-alice",
  WebSocketImpl: WebSocket,
  onConnected: () => {
    console.log("Connected — ready to send messages");
    console.log("Plan limits:", notifier.getPlanLimits());
  },
  onMessage: (msg) => {
    console.log("Incoming from:", msg.metadata.sender);
    console.log("Payload:", msg.payload.toJSON());
  },
  onDisconnected: () => {
    console.log("Disconnected");
  },
});

async function main() {
  try {
    await notifier.connect();
    console.log("isConnected:", notifier.isConnected);
    console.log("messageSizeLimit:", notifier.messageSizeLimit);
  } catch (err) {
    console.error("Connect failed:", err.message);
    process.exit(1);
  }
}

main();

Save as connect.js, set environment variables, and run:

export DNOTIFIER_APP_ID=your-app-id
export DNOTIFIER_SECRET=your-app-secret
node connect.js

Expected Output

Connected — ready to send messages
Plan limits: { aiEnabled: true, messagesHardLimit: ..., ... }
isConnected: true
messageSizeLimit: 32768

Complete Example (Browser)

Omit WebSocketImpl — the browser provides WebSocket globally:

import { DNotifier } from "@dnotifier-realtime/dnotifier";

const notifier = new DNotifier({
  appId: import.meta.env.VITE_DNOTIFIER_APP_ID,
  secret: import.meta.env.VITE_DNOTIFIER_SECRET,
  transport: "ws",
  userId: "user-alice",
  onConnected: () => console.log("Connected"),
  onMessage: (msg) => console.log(msg.payload.toJSON()),
  onDisconnected: () => console.log("Disconnected"),
});

await notifier.connect();

Complete Example (HTTP Transport)

Use HTTP when you only need AI/RAG/workflows — no persistent socket:

import { DNotifier } from "@dnotifier-realtime/dnotifier";

const notifier = new DNotifier({
  appId: process.env.DNOTIFIER_APP_ID,
  secret: process.env.DNOTIFIER_SECRET,
  transport: "http",
  userId: "user-alice",
  onConnected: () => console.log("Authenticated via HTTP"),
  onMessage: () => {},
  onDisconnected: () => {},
});

await notifier.connect();
// Ready for sendAI(), search(), runWorkflow(), etc.

TypeScript Variant

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-alice",
  WebSocketImpl: WebSocket,
  onConnected: (): void => {
    const limits = notifier.getPlanLimits();
    console.log("AI enabled:", limits?.aiEnabled);
  },
  onMessage: (msg): void => {
    const body = msg.payload.toJSON() as { type?: string; text?: string };
    if (body?.type === "text") {
      console.log(body.text);
    }
  },
  onDisconnected: (): void => {},
});

await notifier.connect();

Common Errors

ErrorLikely cause
appId, secret, transport, and userId are requiredMissing constructor field
Authentication FailedWrong secret or invalid appId
WebSocket errors in NodeForgot WebSocketImpl: WebSocket
Immediate disconnectNetwork/firewall blocking wss://

What Happens Under the Hood

  • SDK authenticates over HTTPS with your credentials
  • Auth returns a token and plan limits
  • WebSocket opens to the production host (WSS)
  • Client completes handshake with the token
  • Server acknowledges → onConnected fires

Dart / Flutter

This guide connects a DNotifier client over WebSocket from Dart or Flutter.

Complete Example

import 'package:dnotifier/dnotifier.dart';

Future<void> main() async {
  final notifier = DNotifier(
    appId: 'your-app-id',
    secret: 'your-app-secret',
    transport: 'ws',
    userId: 'user-alice',
    onConnected: () {
      print('Connected — ready to send messages');
      final limits = notifier.getPlanLimits();
      print('Plan limits: $limits');
    },
    onMessage: (DNotifierMessage msg) {
      print('Incoming from: ${msg.metadata.sender}');
      print('Payload: ${msg.payload.toJSON()}');
    },
    onDisconnected: ({code, reason}) {
      print('Disconnected: code=$code reason=$reason');
    },
  );

  try {
    await notifier.connect();
    print('isConnected: ${notifier.isConnected}');
    print('messageSizeLimit: ${notifier.messageSizeLimit}');
  } catch (e) {
    print('Connect failed: $e');
  }
}

Replace 'your-app-id' and 'your-app-secret' with values from the dashboard, or load them from environment defines.

Run in a Pure Dart Project

dart run bin/connect.dart

Run in Flutter

flutter run

Expected Console Output

Connected — ready to send messages
Plan limits: Instance of 'DNotifierPlanLimits'
isConnected: true
messageSizeLimit: 32768

Flutter Widget Example

import 'package:flutter/material.dart';
import 'package:dnotifier/dnotifier.dart';

class DNotifierScreen extends StatefulWidget {
  const DNotifierScreen({super.key});

  @override
  State<DNotifierScreen> createState() => _DNotifierScreenState();
}

class _DNotifierScreenState extends State<DNotifierScreen> {
  late final DNotifier _notifier;
  String _status = 'Connecting…';

  @override
  void initState() {
    super.initState();
    _notifier = DNotifier(
      appId: const String.fromEnvironment('DNOTIFIER_APP_ID'),
      secret: const String.fromEnvironment('DNOTIFIER_SECRET'),
      transport: 'ws',
      userId: 'user-alice',
      onConnected: () => setState(() => _status = 'Connected'),
      onMessage: (msg) {
        debugPrint('Message: ${msg.payload.toJSON()}');
      },
      onDisconnected: ({code, reason}) {
        setState(() => _status = 'Disconnected');
      },
    );
    _notifier.connect().catchError((e) {
      setState(() => _status = 'Error: $e');
    });
  }

  @override
  void dispose() {
    _notifier.disconnect();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('DNotifier')),
      body: Center(child: Text(_status)),
    );
  }
}

HTTP Transport Example

For AI/RAG/workflows without a persistent socket:

final notifier = DNotifier(
  appId: 'your-app-id',
  secret: 'your-app-secret',
  transport: 'http',
  userId: 'user-alice',
  onConnected: () => print('Authenticated via HTTP'),
);

await notifier.connect();
// Ready for sendAI(), search(), runWorkflow(), etc.

Common Errors

ErrorLikely cause
ArgumentError: appId, secret, and userId are requiredEmpty constructor argument
Exception: Authentication failedWrong secret or appId
StateError: Not connectedCalled send() before connect() finished
Socket errors on deviceNetwork or certificate issues

What Happens Under the Hood

  • SDK sends credentials to the DNotifier auth endpoint
  • Auth returns token and plan limits
  • WebSocket connects to the DNotifier realtime endpoint
  • Client sends handshake with token
  • Server acknowledges → onConnected callback runs

Python

This guide connects a DNotifier client over WebSocket from Python.

Complete Example

import asyncio
from dnotifier import DNotifier

async def main():
    notifier = DNotifier(
        app_id="your-app-id",
        secret="your-app-secret",
        transport="ws",
        user_id="user-alice",
        on_connected=lambda: print("Connected — ready to send messages"),
        on_message=lambda msg: print(
            f"Incoming from: {msg.metadata.sender}\nPayload: {msg.payload.to_json()}"
        ),
        on_disconnected=lambda code=None, reason=None: print(
            f"Disconnected: code={code} reason={reason}"
        ),
    )

    try:
        await notifier.connect()
        print(f"is_connected: {notifier.is_connected}")
        print(f"message_size_limit: {notifier.message_size_limit}")
        limits = notifier.get_plan_limits()
        print(f"Plan limits: {limits}")
    except Exception as e:
        print(f"Connect failed: {e}")

asyncio.run(main())

Replace 'your-app-id' and 'your-app-secret' with values from the dashboard, or load them from environment variables.

Run

python connect.py

Expected Console Output

Connected — ready to send messages
is_connected: True
message_size_limit: 32768
Plan limits: DNotifierPlanLimits(...)

FastAPI Lifespan Example

import os
from contextlib import asynccontextmanager
from fastapi import FastAPI
from dnotifier import DNotifier

notifier: DNotifier | None = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    global notifier
    notifier = DNotifier(
        app_id=os.environ["DNOTIFIER_APP_ID"],
        secret=os.environ["DNOTIFIER_SECRET"],
        transport="ws",
        user_id="user-alice",
        on_connected=lambda: print("Connected"),
        on_message=lambda msg: print(msg.payload.to_json()),
    )
    await notifier.connect()
    yield
    await notifier.disconnect()

app = FastAPI(lifespan=lifespan)

HTTP Transport Example

For AI/RAG/workflows without a persistent socket:

notifier = DNotifier(
    app_id="your-app-id",
    secret="your-app-secret",
    transport="http",
    user_id="user-alice",
    on_connected=lambda: print("Authenticated via HTTP"),
)

await notifier.connect()
# Ready for send_ai(), search(), run_workflow(), etc.

Common Errors

ErrorLikely cause
ValueError: app_id, secret, transport, and user_id are requiredEmpty constructor argument
RuntimeError: Authentication failedWrong secret or app_id
RuntimeError: Not connectedCalled send() before connect() finished
Connection errorsNetwork or certificate issues

What Happens Under the Hood

  • SDK sends credentials to the DNotifier auth endpoint (api.dnotifier.com)
  • Auth returns token and plan limits
  • WebSocket connects to the DNotifier realtime endpoint
  • Client sends handshake with token
  • Server acknowledges → on_connected callback runs

Next step

After you connect successfully, you're ready to send your first 1:1 message: How to send and receive your first message.

Watch: How to Make Your First Connection

Same steps as above — use whichever format you prefer.

DNotifier Tutorial

Tutorial 4 of 5

  1. Tutorial 1How to Create a New Project
  2. Tutorial 2How to Install the DNotifier SDK
  3. Tutorial 3How to Choose a Transport
  4. Tutorial 4How to Make Your First Connection
  5. Tutorial 5How to Send and Receive Your First Message