Clarification on Allowed Uses of VoIP Push Notifications for Ending/Updating CallKit State

Hello,

I’m implementing VoIP calling in an iOS application using PushKit (VoIP pushes) together with CallKit.

The standard call flow works correctly:

Happy scenario

  1. User A initiates a call.
  2. Server sends a VoIP push to User B.
  3. User B’s device receives the push and reports the incoming call using CallKit.
  4. User B answers the call.

However, I would like clarification about non-happy scenarios and when it is acceptable to use VoIP pushes to update or stop a CallKit ringing state.

Apple documentation warns that VoIP pushes must be used only when they result in a call-related action, so I want to ensure the following cases are compliant.

Scenario A — Caller Cancels Before Answer

  1. User A calls User B.
  2. Server sends a VoIP push to User B.
  3. User B’s device starts ringing via CallKit.
  4. Before User B answers, User A cancels the call.

Question:

Is it acceptable to send another VoIP push to User B indicating that the call has been cancelled so the device can:

    1. stop the CallKit ringing UI
    1. end the call
    1. optionally mark it as missed or cancelled

Or should this state change be handled using a regular remote push or another signaling mechanism instead of VoIP push?

Scenario B — Callee Rejects the Call

User B rejects the call from CallKit.

The server must inform User A that the call was rejected.

Question: Is it acceptable to send a VoIP push to User A to update the CallKit state and terminate the outgoing call UI?

Scenario C — Multiple Devices per User

User B may be logged in on multiple devices. User A calls User B. VoIP push is sent to all devices of User B. One device answers.

Question:

Is it acceptable to send a VoIP push to the remaining devices instructing them to:

  • stop ringing
  • end the CallKit incoming call UI
  • Or is there a recommended alternative pattern for this case?

Main Question

Aside from the initial incoming call VoIP push, in which situations is it considered acceptable to send additional VoIP pushes to terminate or update CallKit state (cancelled, rejected, answered on another device)?

The goal is to remain compliant with PushKit policies, particularly the guidance that VoIP pushes should only be used when they result in a call-related user action.

Any guidance on the recommended architecture for these cases would be greatly appreciated.

Thank you.

First off, as a side note, I'd strongly recommend reviewing this post to read about the newly introduced push delegate method, as it's a significant improvement over the previous API.

However, I would like clarification about non-happy scenarios and when it is acceptable to use VoIP pushes to update or stop a CallKit ringing state.

At a purely technical level, our only requirement is that your app must call "reportNewIncomingCall" for every VoIP push it receives. That also highlights the main downside of this approach, since inevitably means that your app will be forced to report "extra" calls which it would otherwise not have had to do.

Any guidance on the recommended architecture for these cases would be greatly appreciated.

My general view here is that this thinking:

The server must inform User A that the call was rejected.

...is somewhat misguided, as it fails to account for the "larger" context all of this is happening in. More specifically, the basic call handling sequence looks like this:

  1. App Receives VoIP push.
  2. App Reports new incoming call
  3. App Connects to server and prepares to handle call.
  4. User answers or cancels call.
  5. App informs server on #4 and either connects the call or shuts everything down.

The critical point here is that #3 begins at the same time your app reports the call. That also means that, in most cases, I'd expect your app to have an active connection to your server within a fairly short period of time (~1-5s?)... or not be able to connect the call at all. That is, there are very few situations where:

a) The app is unable to connect to its server within a fairly short period of time.

AND

b) The app WILL be able to complete the call.

Putting that in more concrete terms, if it's taking you "seconds" to connect to your server, then it's unlikely that the network connection is sufficiently robust to handle the connections in the first place.

Within that framework, call failure becomes relatively straightforward. Your app fails calls when:

  • The server it's already connected to tells it the call is over.

  • It takes “too long" to connect to the server.

...with the only real question being "how long is too long". That decision is ultimately up to you, but my main comment there is that I think many apps make this timeout much longer than necessary. The key point here is that the critical criterion isn't "can my app connect", it's "is the network going to be able to connect a call". Allowing the user to answer a call just to fail it later when you try and connect doesn't really help anyone.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Clarification on Allowed Uses of VoIP Push Notifications for Ending/Updating CallKit State
 
 
Q