Skip to content

Getting Started

GitHub
  1. Install the package

    Terminal window
    bun add @capgo/capacitor-incoming-call-kit
  2. Sync native projects

    Terminal window
    bunx cap sync
  3. Choose your ring source Decide whether the incoming-call event comes from your backend, an SDK such as Twilio or Stream, or a native push path such as FCM or PushKit.

This plugin only owns native incoming-call presentation. Your app still owns transport, authentication, and the actual media session.

The common production pattern is:

  1. Your backend or calling SDK emits a ring event.
  2. Your app calls showIncomingCall().
  3. The plugin presents native incoming-call UI.
  4. callAccepted tells your app to join the actual room or VoIP session.
  5. callDeclined, callEnded, or callTimedOut tells your app to clean up remote state.
import { IncomingCallKit } from '@capgo/capacitor-incoming-call-kit';
await IncomingCallKit.requestPermissions();
await IncomingCallKit.requestFullScreenIntentPermission();
await IncomingCallKit.addListener('callAccepted', async ({ call }) => {
console.log('Accepted', call.callId, call.extra);
// Start or join your real call session here.
});
await IncomingCallKit.addListener('callDeclined', ({ call }) => {
console.log('Declined', call.callId);
// Tell your backend or SDK that the user declined.
});
await IncomingCallKit.addListener('callTimedOut', ({ call }) => {
console.log('Timed out', call.callId);
// Clear ringing state in your backend or SDK.
});
await IncomingCallKit.showIncomingCall({
callId: 'call-42',
callerName: 'Ada Lovelace',
handle: '+39 555 010 020',
appName: 'Capgo Phone',
hasVideo: true,
timeoutMs: 45_000,
extra: {
roomId: 'room-42',
callerUserId: 'user_ada',
},
android: {
channelId: 'calls',
channelName: 'Incoming Calls',
showFullScreen: true,
},
ios: {
handleType: 'phoneNumber',
},
});
  • callId: stable identifier reused later with endCall()
  • timeoutMs: best-effort unanswered timeout
  • extra: arbitrary JSON echoed back in listener payloads
  • android.channelId and android.channelName: Android notification channel tuning
  • android.showFullScreen: requests the Android full-screen incoming-call activity
  • ios.handleType: choose generic, phoneNumber, or emailAddress for CallKit
const { calls } = await IncomingCallKit.getActiveCalls();
await IncomingCallKit.endCall({
callId: 'call-42',
reason: 'remote-ended',
});
await IncomingCallKit.endAllCalls({
reason: 'session-reset',
});
  • incomingCallDisplayed: native UI was shown successfully
  • callAccepted: user accepted from the native UI
  • callDeclined: user declined before joining
  • callEnded: your app or the platform ended the tracked call
  • callTimedOut: the call stayed unanswered until timeoutMs

Each event carries the normalized call payload and your original extra object.

  • Read the iOS guide before wiring CallKit into a PushKit or APNs flow.
  • Read the Android guide before relying on full-screen intents on Android 14 and later.
  • Web is not supported.

If you are using Getting Started to plan dashboard and API operations, connect it with Using @capgo/capacitor-incoming-call-kit for the native capability in Using @capgo/capacitor-incoming-call-kit, API Overview for the implementation detail in API Overview, Introduction for the implementation detail in Introduction, API Keys for the implementation detail in API Keys, and Devices for the implementation detail in Devices.