MiroTalk CME - Open Source Self-Hosted WebRTC Click-to-Call for Websites
Add video calling to your website with a self-hosted WebRTC Call-Me widget for instant customer communication.
Instant click-to-call video communication in your browser, no signup, no setup, powered by WebRTC.
Try Live Demo · Privacy · Documentation · Discord · Sponsor
## Getting Started
**Jump to:** [Features](#features) · [Quick Start](#quick-start) · [Click to Call](#click-to-call) · [Self-Hosting](#self-hosting) · [Fast Integration](#fast-integration) · [API](#api) · [Webhooks](#webhooks)
### Features
- `End-to-End Encryption` for secure and private communications.
- `Join` with a username or enter a name to `Call now`.
- `Join a room` (e.g. `Support`, `Reception`) to group users, everyone in the same room can see and call each other (defaults to `Public`).
- `Set your preferred language`.
- `Initiate video calls` by clicking the call button next to a recipient’s username.
- `Switch between cameras, microphones, and speakers` during a call.
- `Chat in real time` with participants.
- `Hide your video` feed when needed.
- `Toggle your microphone` (mute/unmute).
- `Toggle your camera` (video on/off).
- `Share your screen` (start/stop).
- `Share files` with other participants.
- `Hang up the call` when finished.
- `Enable Host Protection` mode with a password.
- `Enable Web Push Notifications` to get notified of incoming calls even when the app is in the background.
- `Use the REST API` to retrieve connected users, rooms, availability status, active calls and server stats, or to initiate a call.
- `Receive Webhooks` for call lifecycle events (user joined/left, call started/ended with duration) for external integrations.
---
### Quick Start
Using Node.js

**[Install Node.js and npm](https://nodejs.org/en/download)**
```shell
# Clone this repo
git clone https://github.com/miroslavpejic85/call-me.git
# Go to to dir call-me
cd call-me
# Copy the config file
cp public/config.template.js public/config.js
# Copy .env.template to .env
cp .env.template .env
# Install dependencies
npm install
# Start the application
npm start
```
---
Using Docker

Install [docker engine](https://docs.docker.com/engine/install/) and [docker compose](https://docs.docker.com/compose/install/)
```shell
# Clone this repo
git clone https://github.com/miroslavpejic85/call-me.git
# Go to to dir call-me
cd call-me
# Copy the config file
cp public/config.template.js public/config.js
# Copy .env.template to .env
cp .env.template .env
# Create your own docker-compose.yml
cp docker-compose.template.yml docker-compose.yml
# Get official image from Docker Hub
docker-compose pull
# Create and start containers
docker-compose up
```
---
1. `Open` your browser and visit [http://localhost:8000](http://localhost:8000).
2. `Join` with your username or `Call` the recipient directly.
3. `Select` the connected recipient's username and click `Call`.
4. `Enjoy` your one-to-one video call.
---
## Click to Call
Direct links, rooms, and per-room branding
Allows a user to `join` the room as a `user1`
- [http://localhost:8000/join?user=user1](http://localhost:8000/join?user=user1) (dev)
- [https://cme.mirotalk.com/join?user=user1](https://cme.mirotalk.com/join?user=user1) (prod)
Lets the `user2 join` the room and initiate a `call` to the `user1`
- [http://localhost:8000/join?user=user2&call=user1](http://localhost:8000/join?user=user2&call=user1) (dev)
- [https://cme.mirotalk.com/join?user=user2&call=user1](https://cme.mirotalk.com/join?user=user2&call=user1) (prod)
### Rooms
By default everyone joins the same shared `Public` room. You can optionally add a `room` parameter to group users into separate rooms (e.g. `Support`, `Reception`). Users only see and can call others **in the same room**.
Join a specific room as `user1`
- [http://localhost:8000/join?user=user1&room=Support](http://localhost:8000/join?user=user1&room=Support) (dev)
- [https://cme.mirotalk.com/join?user=user1&room=Support](https://cme.mirotalk.com/join?user=user1&room=Support) (prod)
Let `user2` join the **same** room and `call` the `user1`
- [http://localhost:8000/join?user=user2&call=user1&room=Support](http://localhost:8000/join?user=user2&call=user1&room=Support) (dev)
- [https://cme.mirotalk.com/join?user=user2&call=user1&room=Support](https://cme.mirotalk.com/join?user=user2&call=user1&room=Support) (prod)
> [!NOTE]
> The `call` target must be in the same `room` as the caller. If `room` is omitted, users join the default `Public` room.
You can explore a `widget` example that demonstrates this functionality [here](./integration/widget.html).
#### Per-room branding (optional)
Give each room its own name, subtitle, theme color, or GitHub visibility. Uncomment and edit the `rooms` map in your `public/config.js` (created from [`public/config.template.js`](./public/config.template.js)). Rooms without an entry keep the default look. Visual only — not a security feature.
#### MiroTalk app switcher (optional)
Set `appSwitcher.show: true` in your `public/config.js` to add a MiroTalk apps menu (SFU, P2P, C2C, BRO, CME, Cloud) to the home top bar. Use `domain`, `apps`, `urls`, and `docsUrl` to customize the links; it is hidden by default.
---
## Self-Hosting
Ubuntu requirements and install scripts

## **Requirements**
- A clean server running **Ubuntu 22.04 or 24.04 LTS**
- **Root access** to the Server
- A **domain or subdomain** pointing to your server’s public IPv4
---
## Note
When **prompted**, simply **enter your domain or subdomain**. Then wait for the installation to complete.
```bash
# Install
wget -qO cme-install.sh https://docs.mirotalk.com/scripts/cme/cme-install.sh \
&& chmod +x cme-install.sh \
&& ./cme-install.sh
```
```bash
# Uninstall
wget -qO cme-uninstall.sh https://docs.mirotalk.com/scripts/cme/cme-uninstall.sh \
&& chmod +x cme-uninstall.sh \
&& ./cme-uninstall.sh
```
```bash
# Update
wget -qO cme-update.sh https://docs.mirotalk.com/scripts/cme/cme-update.sh \
&& chmod +x cme-update.sh \
&& ./cme-update.sh
```
---
## Fast Integration

Easily integrate `Call-Me` into your website or application with a [simple iframe](https://codepen.io/Miroslav-Pejic/pen/qEWBaKP). Just add the following code to your project:
```html
```
---
## API
REST endpoints and curl examples
Get all connected users
```shell
# Get all connected users
curl -X GET "http://localhost:8000/api/v1/users" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
curl -X GET "https://cme.mirotalk.com/api/v1/users" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
# Get connected users in a specific room (optional `room` filter)
curl -X GET "http://localhost:8000/api/v1/users?room=Support" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
# Get detailed users info (room, media status, availability, connectedAt)
curl -X GET "http://localhost:8000/api/v1/users?details=true" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
# Generate call links for connected users to call
curl -X GET "http://localhost:8000/api/v1/connected?user=call-me" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
curl -X GET "https://cme.mirotalk.com/api/v1/connected?user=call-me" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
# Generate call links scoped to a room (adds `&room=...` to the links)
curl -X GET "http://localhost:8000/api/v1/connected?user=call-me&room=Support" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
```
Get rooms, active calls and server statistics
```shell
# List active rooms with user counts and active call counts
curl -X GET "http://localhost:8000/api/v1/rooms" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
# List active calls (optional `room` filter)
curl -X GET "http://localhost:8000/api/v1/calls" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
curl -X GET "http://localhost:8000/api/v1/calls?room=Support" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
# Get aggregate server statistics (version, uptime, users, rooms, active calls)
curl -X GET "http://localhost:8000/api/v1/stats" -H "authorization: call_me_api_key_secret" -H "Content-Type: application/json"
```
Docs: http://localhost:8000/api/v1/docs/ or you can check it out live in prod [here](https://cme.mirotalk.com/api/v1/docs/).
---
## Webhooks
Get notified of call lifecycle events (`user.joined`, `user.left`, `call.started`, `call.ended` with duration) in real time for external integrations. Enable it in your `.env`:
```shell
WEBHOOK_ENABLED=true
WEBHOOK_URL='http://localhost:9099/webhooks/call-me'
WEBHOOK_SECRET='your-shared-secret' # optional, enables HMAC-SHA256 request signing
```
A ready-to-run example receiver and the full event reference (payloads, signature verification) live in [`webhook/`](./webhook/README.md). Run it in parallel with `Call-Me` to watch events live:
```shell
node webhook/server.js
```
---
🌐 Explore the full MiroTalk suite (SFU, P2P, BRO, C2C, WEB, CME, ADM) → MiroTalk Overview
---