Documentation for developers who want to integrate Alohub's WebRTC phone into their website/web application.
AlohubPhone SDK v3 is a JavaScript library that allows embedding a WebRTC phone directly into a website. Employees can make and receive calls right in the browser without needing to install software.
Feature | Description |
|---|---|
1 JS file | Combines everything into a single file (~375KB, ~95KB gzip) |
2 parameters | Just need |
Security | SIP credentials are never exposed |
Shadow DOM | Completely isolated CSS, does not affect the website |
Cross-platform | WordPress, React, Vue, Angular, plain HTML, ... |
6 languages | Vietnamese, English, 日本語, 한국어, 中文, ภาษาไทย |
You need to have:
✅ API Key — Contact Alohub to obtain an API Key
✅ userName — Alohub account username (e.g.: admin.alohub)
Requirement | Details |
|---|---|
Browser | Chrome 60+, Firefox 55+, Edge 79+, Safari 11+, CocCoc |
HTTPS | Required in production (localhost is exempt) |
Microphone | Requires microphone access |
Note: The SDK only works with Alohub's PBX. Cannot be used with other PBXs. Contact Alohub to register for a PBX.
Add a script line to the HTML page:
<!-- Production -->
<script src="https://cdn.alohub.vn/sdk/v3/alohub-phone.prod.min.js"></script>
<!-- Development (server test) -->
<script src="https://cdn.alohub.vn/sdk/v3/alohub-phone.dev.min.js"></script>
Download the file alohub-phone.prod.min.js, place it in the static folder, add a script tag:
<script src="/assets/js/alohub-phone.prod.min.js"></script>
File | Server | Purpose |
|---|---|---|
|
| Test, development |
|
| Production |
Place the following code before the tag </body>:
<script src="https://cdn.alohub.vn/sdk/v3/alohub-phone.prod.min.js"></script>
<script>
AlohubPhone.init({
apiKey: 'YOUR_API_KEY', // Thay bằng API key thật
userName: 'your.username', // Thay bằng username thật
});
</script>
After adding the code, the phone widget appears in the bottom right corner of the webpage. The widget displays:
Header : Connection status (green dot = online) + extension number
Number input box : Enter the phone number to call + call button
Keypad : Press "Show Keypad" to display the full numpad
AlohubPhone.init({
apiKey: 'YOUR_API_KEY',
userName: 'your.username',
// Giao diện
theme: 'dark', // 'light' (mặc định) hoặc 'dark'
position: 'bottom-left', // Vị trí widget (xem bảng bên dưới)
language: 'vi', // vi, en, ja, ko, zh, th
// Hành vi
autoAnswer: false, // false = hiện popup khi có cuộc gọi đến
debug: true, // true = hiện log trong console
// Callbacks
onReady: function(phone) {
console.log('Sẵn sàng! Mic:', phone.getMicPermission());
},
onError: function(e) {
console.error('[' + e.code + ']', e.message);
},
onAuthFailed: function(e) {
console.error('Xác thực thất bại:', e.code, e.message);
}
});
Value | Position |
|---|---|
| Bottom right corner (default) |
| Bottom left corner |
| Top right corner |
| Top left corner |
The SDK provides 5 screens that automatically switch according to the call status:
Screen | When | Displays |
|---|---|---|
1. Dial | Default | Number input box + call button + "Show Keypad" |
2. Dial + Keypad | Press "Show Keypad" | Numpad 0-9, *, # with letters ABC/DEF + delete button ⌫ + large Call button |
3. Ringing | Outgoing call | Number being called + red "End" button |
4. Incoming | Incoming call | Incoming number + red "Decline" / green "Accept" button |
5. Answering | Answering | Number + timer + "End" + "Show Keypad" + "Transfer Call" |
Dot | Status | When |
|---|---|---|
🟢 Green | Online | SIP registered, ready to call |
🟡 Yellow (blinking) | Connecting | Connecting WebSocket/SIP |
🔴 Red | Offline | Disconnected / registration failed |
🔵 Blue (blinking) | Calling | In a call |
When you want to design your own interface , use headless: true. The SDK will not create any UI, only provide APIs and events.
AlohubPhone.init({
apiKey: 'YOUR_API_KEY',
userName: 'your.username',
headless: true, // ← Không tạo UI widget
onReady: function(phone) {
// phone là instance SDK — điều khiển hoàn toàn bằng code
console.log('Sẵn sàng!');
phone.on('incoming', function(data) {
showMyPopup('Cuộc gọi từ: ' + data.remoteNumber);
});
phone.on('answered', function(data) {
showMyCallScreen(data.remoteNumber);
});
phone.on('ended', function(data) {
hideMyCallScreen();
saveCallLog(data);
});
phone.on('error', function(e) {
showMyError(e.code, e.message);
});
}
});
With Widget (default) | Headless | |
|---|---|---|
Interface | Widget automatically | You code it yourself |
DTMF / Mute / Hold | Available on widget |
|
Events | Complete | Complete (same) |
| Available |
|
<!-- Nút gọi trong CRM -->
<button class="btn-call" data-phone="0901234567">📞 Gọi</button>
<script>
var phone = null;
AlohubPhone.init({
apiKey: 'YOUR_API_KEY',
userName: 'your.username',
headless: true,
onReady: function(p) {
phone = p;
// Ghi log cuộc gọi khi kết thúc
phone.on('ended', function(data) {
fetch('/api/call-logs', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
phone: data.remoteNumber,
duration: data.duration,
direction: data.direction
})
});
});
}
});
// Click-to-Call với extra SIP headers
document.querySelectorAll('.btn-call').forEach(function(btn) {
btn.addEventListener('click', function() {
if (phone) phone.call(this.dataset.phone, {
extraHeaders: ['X-CRM-INFO: lead|123']
});
});
});
</script>
The SDK provides 3 layers of error catching:
onAuthFailed(e) — Authentication failed (before SDK is ready): MISSING_API_KEY, MISSING_USERNAME, INVALID_API_KEY, DOMAIN_NOT_WHITELISTED
.catch(err) — SIP registration failed: REGISTRATION_FAILED, REGISTRATION_TIMEOUT
phone.on('error', fn) — All runtime errors: MIC_NOT_FOUND, MIC_DENIED, CALL_MEDIA_FAILED, CALL_NO_NUMBER, CALL_NOT_READY, ...
phone.on('error', function(e) {
// e.code — Mã lỗi chuẩn (AlohubPhone.ERROR.*)
// e.type — Nhóm: 'mic', 'call', 'dtmf', 'transfer'
// e.message — Mô tả chi tiết
switch (e.code) {
case AlohubPhone.ERROR.MIC_NOT_FOUND:
alert('Không tìm thấy microphone!');
break;
case AlohubPhone.ERROR.MIC_DENIED:
alert('Microphone bị từ chối.');
phone.requestMicPermission(); // Yêu cầu lại
break;
case AlohubPhone.ERROR.CALL_MEDIA_FAILED:
alert('Lỗi microphone khi gọi.');
break;
case AlohubPhone.ERROR.CALL_NOT_READY:
alert('Điện thoại chưa sẵn sàng.');
break;
}
});
// Cuộc gọi thất bại — có SIP code chi tiết
phone.on('failed', function(e) {
console.log(e.sipCode, e.sipReason);
// 480 "Temporarily Unavailable"
// 486 "Busy Here"
});
Error code | Group | Description |
|---|---|---|
| mic | No microphone |
| mic | Mic access denied |
| mic | Mic error during call (JsSIP |
| call | Missing phone number |
| call | SIP not registered |
| dtmf | Invalid DTMF character |
| transfer | Transfer when no call |
| api | Call via API failed |
SIP Code | Meaning |
|---|---|
480 | Temporarily Unavailable — Recipient not online |
486 | Busy Here — Busy |
487 | Request Terminated — Call canceled |
603 | Decline — Recipient declined |
404 | Not Found — Number does not exist |
The SDK automatically requests mic permission after SIP registration. If denied, it can request again:
// Kiểm tra trạng thái (đồng bộ)
phone.getMicPermission(); // 'granted' | 'denied' | 'unknown'
// Yêu cầu lại (hiện popup browser)
phone.requestMicPermission().then(function(status) {
console.log('Mic:', status); // 'granted' hoặc 'denied'
});
// Lắng nghe thay đổi
phone.on('micPermission', function(e) {
if (e.status === 'denied') {
alert('Vui lòng cho phép microphone!');
}
});
Note: If the user has clicked "Block" on the browser,
requestMicPermission()it will be denied immediately without showing a popup. The user must go to Settings > Site Settings > Microphone to unblock.
Group | Method | Description |
|---|---|---|
Call |
| Outgoing call (opts: |
| Answer | |
| End / decline | |
DTMF |
| Send key presses (0-9, *, #, A-D) |
Mic |
| Mute/unmute mic |
| Toggle status | |
Hold |
| Hold / resume |
| Toggle status | |
Transfer |
| Transfer call (blind transfer) |
Status |
| On call? |
| Mic is off? | |
| On hold? | |
| Call details | |
Disconnect |
| Logout SIP (keep WebSocket) |
| Completely disconnect | |
| Cancel instance + remove UI + clear credentials |
Code | Language | Interface Example |
|---|---|---|
| Vietnamese (default) | Phone number, End, Answer |
| English | Phone Number, Hang Up, Answer |
| 日本語 | 電話番号, 終了, 応答 |
| 한국어 | 전화번호, 종료, 받기 |
| 中文 | 电话号码, 挂断, 接听 |
| ภาษาไทย | หมายเลขโทรศัพท์, วางสาย, รับสาย |
// Cài đặt khi khởi tạo
AlohubPhone.init({ apiKey: '...', userName: '...', language: 'en' });
// Đổi ngôn ngữ runtime
phone.ui.setLanguage('ja');
// Custom ngôn ngữ riêng (ví dụ tiếng Đức)
phone.ui.setLanguage({
call: 'Anrufen',
hangup: 'Auflegen',
answer: 'Annehmen',
reject: 'Ablehnen'
// Các key thiếu sẽ fallback về tiếng Việt
});
cd v3/
node build.js --dev # → dist/alohub-phone.dev.js
node build.js --prod # → dist/alohub-phone.prod.js
node build.js # → cả hai
# Minify (cần cài terser)
npm install terser
node build.js # → thêm dist/*.min.js
If the website uses CSP, add:
Content-Security-Policy:
connect-src wss://*.alohub.vn https://*.alohub.vn;
media-src blob:;
script-src 'self' https://cdn.alohub.vn;
No. SDK v3 only works with Alohub IPCC.
Call phone.requestMicPermission()to request again. If blocked, the user must go to browser Settings > Site Settings > Microphone > unblock.
Yes. The SDK is vanilla JS, works on any framework. Use headless: trueand then integrate into the component.
Listen to the failedevent — returns sipCodeand sipReason(e.g.: 480 "Temporarily Unavailable").
phone.unregister()(only SIP) | phone.disconnect()(completely) | phone.destroy()(cancel + remove UI).
Yes, add allow="microphone"to the <iframe>tag.
Each SDK instance supports 1 call. An incoming call while on a call will emit the callWaitingevent and automatically decline.
AlohubPhone SDK v3 — Contact Alohub — support@alohub.vn