npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

jwt-sip.js

v0.1.0

Published

TypeScript SDK for SIP.js with JWT authentication and simplified VoIP functionality

Readme

jwt-sip.js

TypeScript SDK for SIP.js with JWT authentication and simplified VoIP functionality.

Installation

npm install jwt-sip.js

Quick Start

import { CallSDK } from 'jwt-sip.js';

const sdk = CallSDK.getInstance({
  serverUrl: 'wss://your-sip-server.com',
  appId: 'your-app-id',
  secret: 'your-secret',
  logLevel: 'info'
});

sdk.on('registered', () => console.log('Registered'));
sdk.on('callAnswered', () => console.log('Call answered'));

await sdk.register('1001', 'example.com', 'jwt-token');
await sdk.makeCall('sip:[email protected]');

Configuration

interface CallSDKConfig {
  serverUrl: string;                      // WebSocket URL (ws:// or wss://)
  appId: string;                          // Application ID
  secret: string;                         // Application secret
  logLevel?: 'debug' | 'info' | 'warn' | 'error';  // Log level (default: 'warn')
  audioDeviceId?: string;                 // Audio input device ID
  remoteAudioElement?: HTMLAudioElement;  // Custom audio element for remote audio
}

Complete API Reference

Initialization

CallSDK.getInstance(config?, registrationOptions?)

Get or create SDK singleton instance.

Parameters:

  • config (CallSDKConfig, optional): Configuration object (required on first call)
  • registrationOptions (RegistrationOptions, optional): Registration options

Returns: CallSDK instance

Example:

const sdk = CallSDK.getInstance({
  serverUrl: 'wss://sip.example.com',
  appId: 'my-app',
  secret: 'my-secret',
  logLevel: 'info',
  audioDeviceId: 'default'
});

Registration Methods

register(extension, domain, token)

Register with SIP server using JWT authentication.

Parameters:

  • extension (string): SIP extension number
  • domain (string): SIP domain
  • token (string): JWT authentication token

Returns: Promise

Example:

await sdk.register('1001', 'example.com', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');

Events: registered, registrationFailed, registrationForbidden


unregister()

Unregister from SIP server.

Returns: Promise

Example:

await sdk.unregister();

Events: unregistered


updateToken(token)

Update JWT token and trigger re-registration.

Parameters:

  • token (string): New JWT token

Returns: void

Example:

sdk.updateToken('eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...');

Call Management Methods

makeCall(targetUri, options?)

Initiate outbound call.

Parameters:

  • targetUri (string): Target SIP URI or phone number
  • options (MakeCallOptions, optional):
    • callId (string): Custom Call-ID (auto-generated if not provided)
    • did (string): DID/Caller ID for routing
    • trace (boolean): Enable trace timestamp header
    • businessVars (Record<string, string>): Custom business variables

Returns: Promise

Example:

await sdk.makeCall('sip:[email protected]', {
  did: '+84123456789',
  trace: true,
  businessVars: {
    campaign: 'summer-sale',
    agent: 'john-doe'
  }
});

Events: callCreated, callRinging, callAnswered, callFailed


hangup()

Terminate active call.

Returns: Promise

Example:

await sdk.hangup();

Events: callEnded


acceptCall()

Accept incoming call.

Returns: Promise

Example:

sdk.on('incomingCall', async (data) => {
  console.log('Incoming call from:', data.targetUri);
  await sdk.acceptCall();
});

Events: callAnswered


rejectCall()

Reject incoming call.

Returns: Promise

Example:

sdk.on('incomingCall', async () => {
  await sdk.rejectCall();
});

Events: callEnded


Call Operation Methods

hold()

Put active call on hold.

Returns: Promise

Example:

await sdk.hold();

Events: callHeld

Note: Uses SDP manipulation (sendonly direction)


unhold()

Resume held call.

Returns: Promise

Example:

await sdk.unhold();

Events: callResumed


mute()

Mute microphone (local only, no SIP signaling).

Returns: Promise

Example:

await sdk.mute();

Events: callMuted

Note: Uses WebRTC track.enabled property


unmute()

Unmute microphone.

Returns: Promise

Example:

await sdk.unmute();

Events: callUnmuted


blindTransfer(targetUri)

Transfer call to another destination (blind transfer).

Parameters:

  • targetUri (string): Transfer destination URI

Returns: Promise

Example:

await sdk.blindTransfer('sip:[email protected]');

Events: transferInitiated, transferSucceeded, transferFailed

Note: Uses SIP REFER method, automatically terminates original call on success


Audio Control Methods

setAudioDeviceId(deviceId)

Set audio input device ID.

Parameters:

  • deviceId (string): Device ID from getUserMedia

Returns: void

Example:

const devices = await navigator.mediaDevices.enumerateDevices();
const audioDevice = devices.find(d => d.kind === 'audioinput');
sdk.setAudioDeviceId(audioDevice.deviceId);

getAudioDeviceId()

Get current audio device ID.

Returns: string | null

Example:

const deviceId = sdk.getAudioDeviceId();
console.log('Current device:', deviceId);

getRemoteAudioElement()

Get HTML audio element for remote audio.

Returns: HTMLAudioElement | null

Example:

const audioElement = sdk.getRemoteAudioElement();
if (audioElement) {
  audioElement.volume = 0.5;
}

setInputVolume(volume)

Set input volume (0-1).

Parameters:

  • volume (number): Volume level (0.0 to 1.0)

Returns: void

Example:

sdk.setInputVolume(0.8);

getInputVolume()

Get current input volume.

Returns: number

Example:

const volume = sdk.getInputVolume();
console.log('Input volume:', volume);

setOutputVolume(volume)

Set output volume (0-1).

Parameters:

  • volume (number): Volume level (0.0 to 1.0)

Returns: void

Example:

sdk.setOutputVolume(0.5);

getOutputVolume()

Get current output volume.

Returns: number

Example:

const volume = sdk.getOutputVolume();
console.log('Output volume:', volume);

State Management Methods

getState()

Get current SDK state.

Returns: SdkState

interface SdkState {
  isInitialized: boolean;
  isRegistered: boolean;
  currentCall: CallSession | null;
  registrationState: string;
}

Example:

const state = sdk.getState();
console.log('Registered:', state.isRegistered);
console.log('Current call:', state.currentCall);

getConfig()

Get current configuration.

Returns: CallSDKConfig | null

Example:

const config = sdk.getConfig();
console.log('Server URL:', config?.serverUrl);

hasValidInputStream()

Check if valid input stream exists.

Returns: boolean

Example:

if (sdk.hasValidInputStream()) {
  await sdk.makeCall('sip:[email protected]');
}

getInputStreamTracks()

Get input stream tracks (deprecated).

Returns: MediaStreamTrack[]

Note: Deprecated - input streams are now created per call


Cleanup Methods

dispose()

Dispose SDK and cleanup resources.

Returns: Promise

Example:

await sdk.dispose();

Events: disposed

Note: Terminates active calls, unregisters, stops UserAgent, clears all listeners


Events Reference

Registration Events

registered

Emitted when registration succeeds.

Data:

interface RegisteredEventData {
  timestamp: number;
  expires: number;  // Registration expiry in seconds
}

unregistered

Emitted when unregistration completes.

Data:

interface UnregisteredEventData {
  timestamp: number;
}

registrationFailed

Emitted when registration fails.

Data:

interface RegistrationFailedEventData {
  timestamp: number;
  statusCode: number;
  reason: string;
}

registrationForbidden

Emitted when registration is forbidden (403).

Data:

interface RegistrationForbiddenEventData {
  timestamp: number;
  statusCode: number;
  reason: string;
}

Call Lifecycle Events

callCreated

Emitted when call is created (before INVITE sent).

Data:

interface CallCreatedEventData {
  callId: string;
  targetUri: string;
  timestamp: number;
  direction: 'inbound' | 'outbound';
}

callRinging

Emitted when call is ringing (180 Ringing received).

Data:

interface CallEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
}

callAnswered

Emitted when call is answered (200 OK received).

Data:

interface CallEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
}

callEnded

Emitted when call ends normally.

Data:

interface CallEndedEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
  reason?: string;
  duration?: number;  // Call duration in milliseconds
}

callFailed

Emitted when call fails.

Data:

interface CallFailedEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
  error: string;
  statusCode?: number;
}

incomingCall

Emitted when incoming call received.

Data:

interface CallCreatedEventData {
  callId: string;
  targetUri: string;
  timestamp: number;
  direction: 'inbound';
}

Call Operation Events

callHeld

Emitted when call is put on hold.

Data:

interface CallHeldEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
}

callResumed

Emitted when held call is resumed.

Data:

interface CallResumedEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
}

callMuted

Emitted when microphone is muted.

Data:

interface CallMutedEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
}

callUnmuted

Emitted when microphone is unmuted.

Data:

interface CallUnmutedEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
}

Transfer Events

transferInitiated

Emitted when transfer is initiated (REFER accepted).

Data:

interface TransferInitiatedEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
  transferTarget: string;
}

transferSucceeded

Emitted when transfer succeeds (NOTIFY with 200).

Data:

interface TransferSucceededEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
  transferTarget: string;
}

transferFailed

Emitted when transfer fails.

Data:

interface TransferFailedEventData {
  callId: string;
  targetUri?: string;
  timestamp: number;
  transferTarget: string;
  reason: string;
  statusCode?: number;
}

Audio Events

audioInputFailed

Emitted when audio input fails.

Data:

interface AudioInputFailedEventData {
  error: string;
  timestamp: number;
}

audioProcessingFailed

Emitted when audio processing fails.

Data:

interface AudioProcessingFailedEventData {
  error: string;
  timestamp: number;
}

Connection Events

connected

Emitted when WebSocket connection established.

Data:

{
  timestamp: number;
}

disconnected

Emitted when WebSocket connection lost.

Data:

{
  timestamp: number;
  error?: string;
}

disposed

Emitted when SDK is disposed.

Data:

{
  timestamp: number;
}

Error Handling

import { CallSDKError, ErrorCode } from 'jwt-sip.js';

try {
  await sdk.makeCall('sip:[email protected]');
} catch (error) {
  if (error instanceof CallSDKError) {
    console.error('Error code:', error.code);
    console.error('Message:', error.message);
    console.error('Details:', error.details);
    console.error('Timestamp:', error.timestamp);
  }
}

Error Codes

  • INVALID_CONFIG - Configuration validation failed
  • INVALID_URI - Malformed SIP URI
  • INVALID_STATE - Operation attempted in wrong state
  • CALL_IN_PROGRESS - Call already active
  • NO_ACTIVE_CALL - No active call for operation
  • REGISTRATION_FAILED - Registration error
  • CALL_FAILED - Call setup failed
  • OPERATION_FAILED - General operation failure
  • SDK_DISPOSED - SDK has been disposed
  • SDK_NOT_INITIALIZED - SDK not initialized
  • AUTHENTICATION_FAILED - Authentication failed
  • NETWORK_ERROR - Network connectivity error
  • TIMEOUT - Operation timeout
  • PERMISSION_DENIED - Browser permission denied

Audio Input Modes

Mode 1: Default (Auto)

SDK automatically requests microphone access per call.

const sdk = CallSDK.getInstance({
  serverUrl: 'wss://sip.example.com',
  appId: 'my-app',
  secret: 'my-secret'
});

Mode 2: Specific Device ID

SDK uses specified audio device for all calls.

const devices = await navigator.mediaDevices.enumerateDevices();
const audioDevice = devices.find(d => d.kind === 'audioinput');

const sdk = CallSDK.getInstance({
  serverUrl: 'wss://sip.example.com',
  appId: 'my-app',
  secret: 'my-secret',
  audioDeviceId: audioDevice.deviceId
});

Mode 3: Per-Call Stream (Manual)

Application manages MediaStream creation per call.

const sdk = CallSDK.getInstance({
  serverUrl: 'wss://sip.example.com',
  appId: 'my-app',
  secret: 'my-secret'
});

const stream = await navigator.mediaDevices.getUserMedia({
  audio: {
    echoCancellation: true,
    noiseSuppression: true,
    autoGainControl: true
  }
});

await sdk.makeCall('sip:[email protected]');

Auto-Answer Support

SDK automatically detects and handles auto-answer headers:

  • X-Auto-Answer: true
  • Call-Info: answer-after=0
  • Alert-Info: auto answer

When detected, SDK automatically calls acceptCall() after 100ms delay.

Example:

sdk.on('incomingCall', (data) => {
  console.log('Incoming call:', data);
});

sdk.on('callAnswered', () => {
  console.log('Call auto-answered');
});

Complete Usage Example

import { CallSDK, CallSDKError, ErrorCode } from 'jwt-sip.js';

const sdk = CallSDK.getInstance({
  serverUrl: 'wss://sip.example.com',
  appId: 'my-app',
  secret: 'my-secret',
  logLevel: 'info',
  audioDeviceId: 'default'
});

sdk.on('registered', (data) => {
  console.log('Registered, expires in:', data.expires, 'seconds');
});

sdk.on('callAnswered', () => {
  console.log('Call answered');
});

sdk.on('callEnded', (data) => {
  console.log('Call ended, duration:', data.duration, 'ms');
});

sdk.on('incomingCall', async (data) => {
  console.log('Incoming call from:', data.targetUri);
  await sdk.acceptCall();
});

try {
  await sdk.register('1001', 'example.com', 'jwt-token');
  
  await sdk.makeCall('sip:[email protected]', {
    did: '+84123456789',
    trace: true
  });
  
  await new Promise(resolve => setTimeout(resolve, 5000));
  
  await sdk.hold();
  await new Promise(resolve => setTimeout(resolve, 2000));
  await sdk.unhold();
  
  await sdk.mute();
  await new Promise(resolve => setTimeout(resolve, 2000));
  await sdk.unmute();
  
  await sdk.hangup();
  
  await sdk.unregister();
  await sdk.dispose();
  
} catch (error) {
  if (error instanceof CallSDKError) {
    console.error('SDK Error:', error.code, error.message);
  }
}

Examples

See examples/index.html for complete demo application with:

  • Registration management
  • Outbound/inbound calls
  • Call controls (hold, mute, transfer)
  • Audio device selection
  • Real-time event logging

Development

npm install
npm run build
npm run serve-examples

Visit http://localhost:3000/examples/


License

SEE LICENSE IN LICENSE