Agent Console

Developer Integration Guide

Integrate real-time support chatting widgets and voice channels into any application—whether it is a simple static website, a modern web app (React/Next.js/Vue), or a native mobile app (Android/iOS).

Prerequisites

Before integrating, make sure you have generated a Public API Key (begins with dosti_pub_...) by subscribing to a plan on our landing page.

1. Simple HTML / PHP Integration

For standard websites built with HTML, WordPress, PHP, or Shopify, simply paste this script tag at the bottom of your HTML body (before the closing </body> tag):

<script 
  src="https://api.dosti.space/widget.js" 
  data-key="YOUR_PUBLIC_API_KEY">
</script>

2. React / Next.js Integration

In a React or Next.js application, load the widget dynamically inside a layout or page hook:

import { useEffect } from 'react';

export default function ChatWidget() {
  useEffect(() => {
    const script = document.createElement('script');
    script.src = "https://api.dosti.space/widget.js";
    script.setAttribute('data-key', 'YOUR_PUBLIC_API_KEY');
    script.async = true;
    document.body.appendChild(script);

    return () => {
      document.body.removeChild(script);
    };
  }, []);

  return null;
}

3. Native Android Integration (Kotlin / Java)

Because the Dosti backend runs a standard Socket.IO server, native mobile apps can connect using Socket.IO clients directly. This bypasses the need for web embeds, allowing you to design a custom native chat interface.

Step A: Import Socket.IO Dependency

Add the dependency to your app/build.gradle file:

dependencies {
    implementation ('io.socket:socket.io-client:2.0.1') {
        exclude group: 'org.json', module: 'json'
    }
}

Step B: Establish Connection in Kotlin

Connect to the backend and pass your Public API Key and session variables in the query string:

import io.socket.client.IO
import io.socket.client.Socket
import org.json.JSONObject

// Initialize connection options
val options = IO.Options().apply {
    query = "apiKey=YOUR_PUBLIC_API_KEY&role=visitor&visitorId=android_user_789&visitorName=JohnDoe"
}

// Connect to socket backend
val socket = IO.socket("https://api.dosti.space", options)

socket.on(Socket.EVENT_CONNECT) {
    println("Connected to Dosti Support Room!")
}

// Send a chat message
val payload = JSONObject().apply {
    put("type", "saas")
    put("message", "Hello from Android Native App!")
}
socket.emit("send_message", payload)

// Listen for replies from support agent
socket.on("receive_message") { args ->
    val data = args[0] as JSONObject
    val message = data.getString("message")
    val senderName = data.getString("visitorName") // "Support"
    println("Received reply from $senderName: $message")
}

4. Native iOS Integration (Swift)

For native iOS development, install the Swift Socket.IO Client via Swift Package Manager and establish connection:

import SocketIO

let manager = SocketManager(socketURL: URL(string: "https://api.dosti.space")!, config: [
    .log(true),
    .compress,
    .connectParams(["apiKey": "YOUR_PUBLIC_API_KEY", "role": "visitor", "visitorId": "ios_user_555", "visitorName": "iOS User"])
])

let socket = manager.defaultSocket

socket.on(clientEvent: .connect) { data, ack in
    print("iOS App Connected to Dosti support!")
    
    // Send a message
    socket.emit("send_message", ["type": "saas", "message": "Hello from Swift!"])
}

// Listen for incoming messages
socket.on("receive_message") { data, ack in
    if let dict = data[0] as? [String: Any],
       let message = dict["message"] as? String {
        print("Received support message: \(message)")
    }
}

socket.connect()

5. Real-Time Events Protocol

If you are building custom clients on other platforms (e.g. Flutter, React Native, Unity), use these event names to handle the chat session:

Outgoing Events (App to Server)

  • send_message: Emits a message. Payload format: {"type": "saas", "message": "text"}
  • typing: Notifies the agent you are typing. Payload: {"type": "saas"}
  • stop_typing: Notifies the agent you stopped typing. Payload: {"type": "saas"}

Incoming Events (Server to App)

  • receive_message: Fired when agent replies. Payload structure: {"visitorId": "vis_...", "visitorName": "Support", "message": "text"}
  • partner_typing: Fired when agent is typing. Payload structure: {"deviceId": "agent"}
  • partner_stopped_typing: Fired when agent stops typing. Payload structure: {"deviceId": "agent"}
  • agent_joined: Fired when support agent connects to this session room.

6. Stateless HTTP REST API Pipeline

If you prefer a stateless HTTP request-response model over persistent WebSockets, Dosti provides simple REST endpoints. This is highly suitable for backend servers, IoT devices, or mobile environments where you want to design a custom chat experience and manually poll/send messages.

Endpoint 1: Send Message

Send a message from a visitor to the support team. This will immediately display the visitor in the Agent Console and alert the agents.

HTTP Method: POST

URL: https://business.dosti.space/api/chat/send

POST https://business.dosti.space/api/chat/send
Content-Type: application/json

{
  "apiKey": "YOUR_PUBLIC_API_KEY",
  "visitorId": "android_user_789",
  "visitorName": "John Doe",
  "message": "Hello from my custom chat interface!"
}

Endpoint 2: Poll Messages (GET or POST)

Retrieve chat messages for a visitor. You can optionally pass lastTimestamp (milliseconds Unix epoch) to fetch only new messages since the last poll.

HTTP Method: GET

URL: https://business.dosti.space/api/chat/poll?apiKey=YOUR_PUBLIC_API_KEY&visitorId=android_user_789&lastTimestamp=1781625600000

Or make a POST request:

POST https://business.dosti.space/api/chat/poll
Content-Type: application/json

{
  "apiKey": "YOUR_PUBLIC_API_KEY",
  "visitorId": "android_user_789",
  "lastTimestamp": 1781625600000
}

Response Format

{
  "success": true,
  "messages": [
    {
      "id": "msg_a1b2c3d4",
      "sender": "visitor",
      "senderName": "You",
      "message": "Hello from my custom chat interface!",
      "timestamp": 1781625601000
    },
    {
      "id": "msg_e5f6g7h8",
      "sender": "agent",
      "senderName": "Support",
      "message": "Hi John! How can I help you today?",
      "timestamp": 1781625615000
    }
  ]
}

Integration Example (PHP)

<?php
// 1. Send Message
$url = "https://business.dosti.space/api/chat/send";
$data = array(
    "apiKey" => "YOUR_PUBLIC_API_KEY",
    "visitorId" => "php_user_123",
    "visitorName" => "PHP Client",
    "message" => "Hello from PHP!"
);

$options = array(
    'http' => array(
        'header'  => "Content-Type: application/json\r\n",
        'method'  => 'POST',
        'content' => json_encode($data)
    )
);
$context  = stream_context_create($options);
$result = file_get_contents($url, false, $context);
$response = json_decode($result, true);

// 2. Poll messages (only new messages since 10 seconds ago)
$last_ts = (time() - 10) * 1000;
$poll_url = "https://business.dosti.space/api/chat/poll?apiKey=YOUR_PUBLIC_API_KEY&visitorId=php_user_123&lastTimestamp=" . $last_ts;
$poll_result = file_get_contents($poll_url);
$poll_response = json_decode($poll_result, true);

foreach ($poll_response['messages'] as $msg) {
    echo $msg['senderName'] . ": " . $msg['message'] . "\n";
}
?>

Integration Example (Android Kotlin - HTTP REST)

Bypass WebSockets and use standard HTTP requests to send and poll messages. Here is a simple implementation using OkHttp:

import okhttp3.*
import okhttp3.MediaType.Companion.toMediaType
import okhttp3.RequestBody.Companion.toRequestBody
import org.json.JSONObject
import java.io.IOException

class DostiChatClient(val apiKey: String, val visitorId: String, val visitorName: String) {
    private val client = OkHttpClient()
    private val JSON = "application/json; charset=utf-8".toMediaType()

    // Send a message
    fun sendMessage(messageText: String) {
        val payload = JSONObject().apply {
            put("apiKey", apiKey)
            put("visitorId", visitorId)
            put("visitorName", visitorName)
            put("message", messageText)
        }
        
        val request = Request.Builder()
            .url("https://business.dosti.space/api/chat/send")
            .post(payload.toString().toRequestBody(JSON))
            .build()

        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) { e.printStackTrace() }
            override fun onResponse(call: Call, response: Response) {
                println("Message sent successfully: \${response.body?.string()}")
            }
        })
    }

    // Poll for new messages since lastTimestamp
    fun pollMessages(lastTimestamp: Long, callback: (List<JSONObject>) -> Unit) {
        val url = "https://business.dosti.space/api/chat/poll?apiKey=\$apiKey&visitorId=\$visitorId&lastTimestamp=\$lastTimestamp"
        val request = Request.Builder().url(url).build()

        client.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) { e.printStackTrace() }
            override fun onResponse(call: Call, response: Response) {
                val responseData = response.body?.string() ?: return
                val json = JSONObject(responseData)
                if (json.getBoolean("success")) {
                    val messagesArray = json.getJSONArray("messages")
                    val list = mutableListOf<JSONObject>()
                    for (i in 0 until messagesArray.length()) {
                        list.add(messagesArray.getJSONObject(i))
                    }
                    callback(list)
                }
            }
        })
    }
}