Ring Calls

Creating ring calls

The Stream Video API offers a ringing flow that simulates traditional phone calls. This feature lets developers implement call experiences where users can receive incoming calls with ringtones and choose to accept or decline.

You can also show missed call notifications if someone doesn’t answer the call on time or is busy in another call.

To start the ringing flow, we need to set the ring flag to true and provide the list of members we want to call. It is important to note that the caller should also be included in the list of members.

Stream API allows reusing call ids (for example, to implement recurring meetings), but this is not something we advise for ring calls. You should create a unique id for every ring call (for example by using UUIDs).

// Make sure to use a unique id when creating ring calls
await client.call("default", crypto.randomUUID()).getOrCreate({
  ring: true,
  data: {
    created_by_id: "myself",
    members: [{ user_id: "myself" }, { user_id: "my friend" }],
  },
});

Accepting and rejecting ring calls

Accepting and rejecting calls are client-side operations, you can read more about them in SDK documentations.

Ring call events

The ring flow relies on the following events:

  • call.ring
  • call.accepted
  • call.rejected
  • call.missed

call.ring event

This is the start of the ring flow. This event is dispatched to call members when someone starts a call with the ring flag set to true.

It’s possible to send push notifications to call members on this event, for more information see Notification settings section

call.ring event reference

call.accepted event

This event is dispatched to the call members when a callee accepts an incoming call.

call.accepted event reference

call.rejected event

This event is dispatched to the call members when the caller or callee rejects the call.

There are multiple reasons why someone could reject a call (for example, someone explicitly rejecting a call with a “Decline” button is different from someone not answering the call). The call.rejected event contains a reason field to indicate why a call was rejected.

You can pass any string to the reason field, but the Stream API and the SDKs recognize the following values by default:

NameDescription
rejectedThe callee explicitly rejected the call (for example, with a “Decline” button)
cancelThe caller cancelled the call before it was answered
timeout1. When a callee is online but doesn’t answer the call in incoming_call_timeout_ms time.
2. When no callee answers the call in auto_cancel_timeout_ms time, the caller will send this event
busySignals that the callee is busy. By default, SDKs don’t send this reason; integrators can implement this in their own application logic.

call.rejected event reference

call.missed event

The call.missed event is dispatched to callees who didn’t answer (accept or reject) an incoming call within a given time.

The event is dispatched in the following scenarios:

  • The callee rejected the call with a timeout or busy reason
  • When a callee didn’t accept or reject the call in missed_call_timeout_ms time (probably the user was offline)
  • The caller rejected the call with any reason

It’s possible to send push notifications to call members on this event, for more information see Notification settings section

call.missed event reference

Ring call settings

Timeouts

You can control how much time to wait before automatic call rejections and missed call events are dispatched.

RingSettingsRequest

NameTypeDescriptionConstraints
auto_cancel_timeout_msintegerWhen none of the callees accept a ring call in this time a rejection will be sent by the caller with reason 'timeout' by the SDKsRequired, Minimum: 5000, Maximum: 180000
incoming_call_timeout_msintegerWhen a callee is online but doesn't answer a ring call in this time a rejection will be sent with reason 'timeout' by the SDKsRequired, Minimum: 5000, Maximum: 180000
missed_call_timeout_msintegerWhen a callee doesn't accept or reject a ring call in this time a missed call event will be sentMinimum: 5000, Maximum: 180000

These can be set on the call type level or on the call level:

// on call type level
client.video.updateCallType({
  name: callTypeName,
  settings: {
    ring: {
      incoming_call_timeout_ms: 10000,
      auto_cancel_timeout_ms: 15000,
      missed_call_timeout_ms: 15000,
    },
  },
});

// or on call level
call.update({
  settings_override: {
    ring: {
      incoming_call_timeout_ms: 10000,
      auto_cancel_timeout_ms: 15000,
      missed_call_timeout_ms: 15000,
    },
  },
});

Push notifications

You can enable/disable push notifications for the call.ring and call.missed events.

client.video.createCallType({
  name: "<call type name>",
  notification_settings: {
    enabled: true,
    call_notification: {
      apns: {
        title: "{{ user.display_name }} calls you",
        body: "{{ user.display_name }} calls you",
      },
      enabled: true,
    },
    call_ring: {
      apns: {
        title: "{{ user.display_name }} calls you",
        body: "{{ user.display_name }} calls you",
      },
      enabled: true,
    },
    call_live_started: {
      enabled: true,
      apns: {
        title: "{{ call.display_name }} started",
        body: "{{ user.display_name }} started",
      },
    },
    call_missed: {
      enabled: true,
      apns: {
        title: "missed call from {{ user.display_name }}",
        body: "missed call from {{ user.display_name }}",
      },
    },
    session_started: {
      enabled: true,
      apns: {
        title: "{{ call.display_name }} started",
        body: "{{ call.display_name }} started",
      },
    },
  },
});
© Getstream.io, Inc. All Rights Reserved.