> For the complete documentation index, see [llms.txt](https://tools.docs.sendbird.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://tools.docs.sendbird.com/plugins/client/add-voice-and-video-calls.md).

# Add voice and video calls

Add 1-to-1 voice and video calls with Sendbird Calls to an existing app, or create a new app with calls. The Sendbird Client plugin does both. Calls uses its own SDK, separate from the Chat SDK, and the same plugin sets up both.

## Before you begin

* Install the Sendbird Client plugin version 0.1.54 or later, and open your app project in Claude Code or Codex. See [How to use the plugin](/plugins/client.md#how-to-use-the-plugin). If you already have the plugin, [check its version](/plugins/client.md#check-the-installed-version).
* Use a Sendbird app with Calls turned on. If you create the app with Sendbird CLI, pass `--is-calls-enabled true` to `app create`. For an existing app, follow [Turn on Calls for an app](/readme/calls/turn-on-calls.md).
* Have your Sendbird App ID ready. The plugin asks for it the first time.
* Calls follows the same sign-in rule as Chat. During development, if your app allows users to connect without a token, users sign in to Calls with a user ID only. A user who has been issued a token can't sign in without it: Calls rejects the sign-in with error `9400302`, and Chat with `400302`. For the conditions, see [Add Chat](/plugins/client/add-chat.md#before-you-begin).
* For incoming calls on iOS, Android, or React Native, plan to set up push. On these platforms, a new incoming call arrives only through push. React needs no push setup. See [Set up incoming calls](#set-up-incoming-calls).

## Add calls to an existing app

### Ask like this

In the session, type:

```
Let the signed-in user place 1:1 voice and video calls to another user and accept or decline incoming calls with Sendbird Calls.
```

To start the same setup with a command, enter `/sendbird-client:setup --product calls`. In Codex, start the command with `$` instead of `/`.

### What the plugin asks

Your App ID, the first time only. See [Give the plugin your App ID](/plugins/client.md#give-the-plugin-your-app-id).

### What you get

* The Calls SDK, installed with the package manager your project already uses.
* Camera and microphone permission entries, which the plugin adds in these files. The app also asks the user for permission when it runs.
  * iOS: usage descriptions in `Info.plist`
  * Android: `RECORD_AUDIO`, `CAMERA`, and `BLUETOOTH_CONNECT` in the manifest
* Calls sign-in where your app finishes signing in, and Calls sign-out when the user signs out.
* An incoming-call listener and voice and video dialing.
* Accept, decline, and end actions.
* On React, a call panel with these parts:
  * A field for the other user's ID
  * **Voice call**, **Video call**, **Accept**, **Decline**, and **End** buttons
  * A video area
* A list of anything the plugin couldn't do, as steps left for you.

## Create a new app with calls

The plugin creates the code project, not the Sendbird app.

Open an empty folder in Claude Code or Codex and type:

```
Create a new Sendbird app in this folder.
```

To start the same setup with a command, enter `/sendbird-client:setup new-app`.

Answer the plugin's questions this way:

| Question                              | What to choose                                  |
| ------------------------------------- | ----------------------------------------------- |
| What should the app include?          | **Voice and video calls**, with or without Chat |
| Which call types should the app have? | **1:1 voice call**, **1:1 video call**, or both |
| Which platform should the app run on? | React, React Native, iOS, or Android            |

If you choose Chat too, see [Create a new chat app](/plugins/client/add-chat.md#create-a-new-chat-app) for the chat questions.

If you choose only calls, the plugin installs only the Calls SDK. When the user signs in, the app signs in to Calls, and when the user signs out, it signs out of Calls. Calls needs its own sign-in even in an app that also uses Chat.

## Set up incoming calls

On iOS, Android, and React Native, a new incoming call arrives only through push, even while the app is open. This is because the Calls SDK connects to the server only during a call. Placing a call works without push. On React, the app receives calls while it's connected, and there's no push for incoming calls.

| Platform     | What you set up                                                                                                                                                                             |
| ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| iOS          | Register an APNs VoIP certificate on Sendbird Dashboard. The plugin then adds PushKit and CallKit code.                                                                                     |
| Android      | Create a Firebase project and register its FCM credentials on Sendbird Dashboard. The plugin then adds the code that registers the FCM token and shows call notifications.                  |
| React Native | Prepare push by following [Make your first call](https://sendbird.com/docs/calls/sdk/v1/react-native/getting-started/make-first-call) in the Sendbird Calls documentation for React Native. |
| React        | Nothing.                                                                                                                                                                                    |

After you register the push credentials, ask:

```
Set up incoming calls for this app with Sendbird Calls.
```

To start the same setup with a command, enter `/sendbird-client:calls-incoming`.

## Run and test a call

Run the app with your platform's tools, the same way as in [Run the app](/plugins/client/add-chat.md#run-the-app). Then place a call between two users. The buttons below are from the React call panel; on other platforms, use the call controls the plugin added.

1. Sign in as two different users, one on each side. On React, use two browser windows. On iOS, Android, or React Native, use two devices.
2. On one side, enter the other user's ID and select **Video call** or **Voice call**.
3. On the other side, select **Accept**.
4. Select **End** to finish the call.

When you test calls:

* On iOS, use a real device. The simulator can't play call audio.
* On React, use HTTPS or localhost, because browsers allow the camera and microphone only there.
* For incoming calls on iOS, Android, or React Native, finish the [push setup](#set-up-incoming-calls) first.

## Check the changes

Review the changed files and finish the steps the plugin lists. Then ask:

```
Check that my Sendbird setup is correct.
```

In the changes, check:

* The Calls sign-in and sign-out code
* The incoming-call listener
* The call controls
* The camera and microphone permissions

## What you do yourself

If your app requires access or session tokens, your server issues them. The plugin writes the client code that uses the tokens. Give the plugin your server's token endpoint, as described in [Connect users with server-issued tokens](/plugins/client/add-chat.md#connect-users-with-server-issued-tokens). Don't paste real tokens or server keys into the conversation.

## Keep building

* To add chat to the same app, follow [Add Chat](/plugins/client/add-chat.md).
* To fix incoming calls that don't ring or in-call audio and video problems, ask the plugin, or enter `/sendbird-client:calls-incoming`.
* For more requests, see [Run a skill with a command](/plugins/client.md#run-a-skill-with-a-command).
