JSPM

  • Created
  • Published
  • Downloads 1364
  • Score
    100M100P100Q133047F
  • License UNLICENSED

VoIP SDK for CemScale multi-tenant platform — API client, WebRTC, React hooks

Package Exports

  • @cemscale-voip/voip-sdk
  • @cemscale-voip/voip-sdk/hooks

Readme

@cemscale-voip/voip-sdk

TypeScript SDK for integrating CemScale VoIP into your application.

Installation

npm install @cemscale-voip/voip-sdk

Authentication

Use an API Key to authenticate. Get one from the dashboard (API Keys page).

import { VoIPClient } from '@cemscale-voip/voip-sdk';

const voip = new VoIPClient({
  apiUrl: 'https://voip-api.cemscale.com',
  apiKey: 'csk_live_your_key_here',
});

// Ready. All methods work immediately.

That's it. No login, no passwords, no tokens to manage.

Examples

Click-to-call

// Call a phone number from extension 1001
const { callUuid } = await voip.originate({
  fromExtension: '1001',
  toNumber: '+15551234567',
});

// Control the call
await voip.holdCall(callUuid);
await voip.transfer(callUuid, { targetExtension: '1002', type: 'blind' });
await voip.hangup(callUuid);

Extensions

const { extensions } = await voip.listExtensions();
const { extension } = await voip.getExtension('ext-id');
await voip.createExtension({ extension: '1004', password: 'SecurePass1!', displayName: 'Dave' });

CRM User Mapping

// Link a CRM user to a VoIP extension
await voip.updateCrmMapping('ext-id', {
  crmUserId: 'crm-user-123',
  crmMetadata: { department: 'Sales' },
});

// Look up extension by CRM user (click-to-call from contact page)
const { extension } = await voip.getExtensionByCrmUser('crm-user-123');
await voip.originate({ fromExtension: extension.extension, toNumber: '+15551234567' });

Real-Time Events (WebSocket)

voip.connectWebSocket();

voip.onWsEvent('call_start', (event) => {
  console.log('New call:', event.data);
});

voip.onWsEvent('presence_change', (event) => {
  console.log(event.data.extension, event.data.status);
});

voip.onWsEvent('call_end', (event) => {
  // Log to CRM
  logCallToCRM(event.data);
});

Webhooks

await voip.createWebhook({
  name: 'CRM Events',
  url: 'https://your-crm.com/api/voip-webhook',
  events: ['call.started', 'call.answered', 'call.ended'],
});

Call Queues

const { queues } = await voip.listQueues();
const { stats } = await voip.getQueueStats('queue-id');
console.log(`Agents: ${stats.agents.available}/${stats.agents.total}`);
console.log(`Service level: ${stats.today.serviceLevel}%`);

Business Hours

await voip.createSchedule({
  name: 'Office Hours',
  timezone: 'America/New_York',
  schedules: [
    { day: 'monday', enabled: true, startTime: '09:00', endTime: '17:00' },
    { day: 'tuesday', enabled: true, startTime: '09:00', endTime: '17:00' },
  ],
  afterHoursAction: 'voicemail',
});

const { isOpen } = await voip.getScheduleStatus('schedule-id');

Blocklist

await voip.blockNumber({ number: '+15559999999', reason: 'Spam', direction: 'inbound' });
const { blocked } = await voip.checkBlocked('+15559999999'); // true

CDR Export

const csv = await voip.exportCalls({
  dateFrom: '2026-03-01',
  dateTo: '2026-03-31',
  direction: 'inbound',
});

API Key Management

// Create a key for a new integration
const { apiKey } = await voip.createApiKey({ name: 'Mobile App', role: 'readonly' });
console.log(apiKey.key); // csk_live_... — save this, shown only once

// List all keys
const { apiKeys } = await voip.listApiKeys();

// Revoke a key
await voip.revokeApiKey('key-id');

Connecting a WebRTC Softphone

Your app doesn't need to know or store SIP passwords. Use the API key to fetch credentials on the fly:

// 1. Get SIP credentials for the extension (API key handles auth)
const { sipCredentials } = await voip.getSipCredentialsByNumber('1001');

// sipCredentials = {
//   extension:    "1001",
//   displayName:  "Alice",
//   password:     "auto-provided",   <-- API returns it, your app doesn't store it
//   sipDomain:    "sip.cemscale.com",
//   wsUri:        "wss://sip.cemscale.com/ws",
//   registrar:    "sip:sip.cemscale.com"
// }

// 2. Also get TURN credentials for NAT traversal
const turn = await voip.getTurnCredentials();

Two methods available:

Method Use when
getSipCredentials(extensionId) You have the extension UUID
getSipCredentialsByNumber('1001') You have the extension number

WebRTC Softphone (Browser Only)

For building a browser-based softphone, use the WebRTCPhone class or the useVoIP React hook. These require SIP credentials (extension + password), not an API key.

import { useVoIP } from '@cemscale-voip/voip-sdk';

function PhoneWidget() {
  const { isRegistered, currentCall, login, startPhone, call, answer, hangup, toggleHold, toggleMute } = useVoIP({
    apiUrl: 'https://voip-api.cemscale.com',
    sipDomain: 'sip.cemscale.com',
    wsUri: 'wss://sip.cemscale.com/ws',
  });

  return (
    <div>
      <p>{isRegistered ? 'Online' : 'Offline'}</p>
      {currentCall ? (
        <>
          <button onClick={hangup}>Hangup</button>
          <button onClick={toggleHold}>{currentCall.held ? 'Resume' : 'Hold'}</button>
          <button onClick={toggleMute}>{currentCall.muted ? 'Unmute' : 'Mute'}</button>
        </>
      ) : (
        <button onClick={() => call('+15551234567')}>Call</button>
      )}
    </div>
  );
}

All Methods

Calls

Method Description
originate({ fromExtension, toNumber }) Start a call
hangup(uuid) Hang up
transfer(uuid, { targetExtension, type }) Transfer (blind/attended)
holdCall(uuid, hold?) Hold / resume
parkCall(uuid, slot?) Park a call
getParkedCalls() List parked calls
listCalls(params?) CDR history
getCall(id) Single CDR record
getActiveCalls() Active calls
getCallStats(period?) Call statistics
exportCalls(params?) Export CDR as CSV

Extensions

Method Description
listExtensions() List all
getExtension(id) Get detail
createExtension(params) Create
updateExtension(id, params) Update
deleteExtension(id) Delete
setCallForward(id, params) Set forwarding
getCallForward(id) Get forwarding
getExtensionByCrmUser(crmUserId) Lookup by CRM user
updateCrmMapping(id, params) Set CRM mapping
getSipCredentials(id) SIP credentials by extension UUID
getSipCredentialsByNumber('1001') SIP credentials by extension number

Conferences

Method Description
listConferences() List active
getConference(name) Detail + members
kickFromConference(name, memberId) Remove member
muteConferenceMember(name, memberId, mute) Mute/unmute
lockConference(name, lock) Lock/unlock
recordConference(name, action) Start/stop recording

Ring Groups

Method Description
listRingGroups() List all
createRingGroup(params) Create
updateRingGroup(id, params) Update
deleteRingGroup(id) Delete

Call Queues

Method Description
listQueues() List all
createQueue(params) Create
updateQueue(id, params) Update
deleteQueue(id) Delete
pauseQueueAgent(queueId, agentId, paused) Pause/unpause
loginQueueAgent(queueId, agentId, loggedIn) Login/logout
getQueueStats(queueId) Real-time stats

IVR

Method Description
listIvrMenus() List all
getIvrMenu(id) Get detail
createIvrMenu(params) Create
updateIvrMenu(id, params) Update
deleteIvrMenu(id) Delete

Webhooks

Method Description
listWebhooks() List all
createWebhook(params) Create
updateWebhook(id, params) Update
deleteWebhook(id) Delete
testWebhook(id) Send test event
listWebhookDeliveries(id) Delivery history

Voicemail

Method Description
listVoicemails(params?) List messages
getVoicemail(id) Get single
getVoicemailAudioUrl(id) Audio URL
getVoicemailCount(extension?) Unread/total
markVoicemailRead(id) Mark as read
deleteVoicemail(id) Delete
bulkDeleteVoicemails(params?) Bulk delete

Blocklist

Method Description
listBlockedNumbers() List blocked
blockNumber(params) Block a number
unblockNumber(id) Unblock
checkBlocked(number) Check if blocked

Business Hours

Method Description
listSchedules() List schedules
getSchedule(id) Get detail
createSchedule(params) Create
updateSchedule(id, params) Update
deleteSchedule(id) Delete
getScheduleStatus(id) Open or closed?

SIP Trunks

Method Description
listTrunks() List trunks
getTrunk(id) Get detail
createTrunk(params) Create
updateTrunk(id, params) Update
deleteTrunk(id) Delete

API Keys

Method Description
listApiKeys() List keys
getApiKeyDetail(id) Get detail
createApiKey(params) Create (returns full key once)
updateApiKey(id, params) Update
revokeApiKey(id) Delete
regenerateApiKey(id) Regenerate (new key)

DIDs

Method Description
listDids() List numbers
createDid(params) Assign DID
updateDid(id, params) Update routing
deleteDid(id) Remove

Tenants (superadmin)

Method Description
listTenants() List all tenants
getTenant(id) Get detail
createTenant(params) Create tenant
updateTenant(id, params) Update tenant
deleteTenant(id) Delete tenant
getTenantStats(id) Tenant statistics

Recordings

Method Description
listRecordings(params?) List recordings
getRecordingUrl(id) Get audio URL
deleteRecording(id) Delete

Presence

Method Description
getPresence() Simple map
getPresenceDetailed() Detailed with call info

Reports

Method Description
getDashboardStats() Dashboard numbers
getCallsByDay(params?) Daily breakdown
getTopExtensions(params?) Most active extensions

WebSocket Events

Event Data
presence_snapshot Full presence state on connect
presence_change { extension, status, callUuid }
call_start { callUuid, caller, destination, direction }
call_answer { callUuid }
call_end { callUuid, duration, hangupCause }

Feature Codes (Phone Dial Pad)

Code Function
*3 Conference room
*70 Park call
*71XX Retrieve parked call from slot XX
*97 Check voicemail