Table of Contents

Handling inbound calls

Inbound calls arrive as INVITEs on a registered line. There are two ways to observe them.

using var subscription = client.OnIncomingCall(async call =>
{
    // Decide per call:
    await call.AcceptAsync();                 // answer
    await client.AttachDefaultAudioAsync(call);
});

Dispose the returned IDisposable to stop handling.

Raw events

client.IncomingCall += (_, e) => { /* e.Call */ };
// or per line:
line.IncomingCall += (_, e) => { /* … */ };

Both fire on the signaling thread — keep the handler non-blocking (see Events).

Accept, reject, redirect

await call.AcceptAsync();               // 200 OK
await call.RejectAsync(/* reason */);   // decline (CallActionResult)
await call.RedirectAsync(/* target */); // 3xx (CallActionResult)

AcceptAsync throws if the call is not acceptable; RejectAsync/RedirectAsync return a CallActionResult for foreseeable outcomes.

Caller identity (screen-pop)

An inbound ICall exposes the caller and the dialed number, parsed by the SDK — no header parsing needed:

client.OnIncomingCall(async call =>
{
    var dialedDid = call.CalledNumber;       // which DID / trunk line the call arrived on
    var caller    = call.RemoteNumber;       // caller's number
    var name      = call.RemoteDisplayName;  // caller's display name (or null)

    ScreenPop(dialedDid, caller, name);      // and route by dialedDid if you serve many DIDs

    await call.AcceptAsync();
});

CalledNumber is the number that selected the receiving line — branch on it for per-DID routing. All four identity properties (CalledNumber, LocalParty, RemoteNumber, RemoteDisplayName) are null on outbound calls; see Calls.

Guarding inbound media

Set VoipConfiguration.InboundMediaTimeout (default 15 s) so answered calls that never produce media are torn down instead of lingering. For held calls that go silent, HangupHeldCallOnMediaSilence ends them automatically.

Trunk inbound

For calls addressed to DIDs rather than your AOR, list the numbers on the account:

new SipAccount
{
    Username = "trunkuser", Password = "secret", SipServer = "trunk.example",
    InboundNumbers = new[] { "4930123456", "4930123457" },
    AcceptTrunkInbound = true
};

See NAT and SIP trunks and the interop matrix.