A call is considered “started” in CallKit when the system begins processing the call lifecycle after an outgoing call request or an incoming call response.
For outgoing calls, this usually maps to:
CXStartCallAction
For incoming calls, the call effectively starts after the user answers:
CXAnswerCallAction
“Call started” does not always mean:
audio is connected and the remote user is talking.
It usually means:
CallKit has accepted the call lifecycle and your app should begin preparing the real communication layer.
For outgoing calls, the flow is:
User taps call
↓
App creates CXStartCallAction
↓
App sends CXTransaction
↓
System accepts request
↓
provider(_:perform: CXStartCallAction) fires
func provider(
_ provider: CXProvider,
perform action: CXStartCallAction
) {
print("Outgoing call started")
configureAudioSession()
callActive = true
action.fulfill()
provider.reportOutgoingCall(
with: action.callUUID,
connectedAt: nil
)
}