Teams E911 Emergency Call Alerts
PremiumTeams E911 Emergency Call Alerts use structured, real-time Microsoft Graph emergency-call events. They are configured in Alerts → CDR Alerts, alongside Cisco CDR alerts, but they are a separate call stream with a separate lifecycle and readiness gate.
This guide documents the operator contract planned in the canonical implementation plan. Keep structured dispatch disabled until the deployment exposes the Teams emergency-events source, pre-dispatch transport readiness is green, and the mandatory two-pass controlled 933 UAT is complete.
Teams E911 alerts do not ingest delayed Microsoft Graph callRecords. They do not use or expose IP addresses, BSSIDs, CMR, media-quality, Microsoft Place, room, floor, free-form additionalInfo, or coordinates as matching keys. A delayed call record is never evidence that a real-time emergency alert worked.
Understand the two source panels
The CDR Alerts page has two distinct source concepts:
| Panel | Purpose | What an operator does there |
|---|---|---|
| Enabled call streams | Event streams that can evaluate alert profiles. Cisco CDR and Teams emergency events are separate streams. | Select the source when creating a profile; read its health and readiness. |
| Enrichment Sources | Already-synchronized provider context that can be joined to an alert. Initial Cisco, Meraki, and Teams discovery adapters use Pre-synced inventory. | Inspect freshness and status; use the settings link to configure the owning integration. |
An enrichment source never runs a collector on the emergency-call path. A quiet, paused, or degraded enabled call stream remains visible so it can be corrected; disabled streams are not presented as active alert inputs.
Prerequisites and Graph delivery
Have an Azure/Entra administrator, a Teams administrator, and a Call Telemetry administrator coordinate this setup. The organization must have a supported Teams integration, an Azure Event Hubs namespace, and an approved non-production emergency test policy.
- Create an Entra application registration for the Call Telemetry integration. Record the tenant ID, application ID, and the public certificate identifier used for Graph rich-notification encryption. Keep private-key material only in the approved Call Telemetry secret store.
- Grant and admin-consent the application permission
CallEvents-Emergency.Read.All. Do not substitute chat-reading delegated permissions for this emergency-event subscription. - Create the Event Hubs delivery path and assign Azure Event Hubs Data Sender to the Microsoft Graph Change Tracking service principal at the Event Hubs namespace scope. This role is for Graph to publish events; it is not an Event Hubs connection-string/SAS workaround.
- Configure the Teams connector with the tenant, Event Hubs consumer details, encryption certificate, and every emergency policy that should be covered. Call Telemetry creates and renews the Graph subscription for
communications/calls/getEmergencyEventsByPolicy(policyName='...')withchangeType: updatedandincludeResourceData: true. - Confirm that the source reports Event Hubs + Entra RBAC delivery as ready. Webhook-only and SAS-only delivery are not a supported ready state for this feature.
Event Hubs delivery is at-least-once and events can arrive out of order. Call Telemetry persists an idempotent inbox receipt before it advances a checkpoint. A repeated delivery may be recorded as a duplicate; it must not create a second notification lifecycle.
Verify pre-dispatch transport readiness
Open Alerts → CDR Alerts → Enabled call streams → Teams emergency events while the per-organization structured-dispatch flag remains disabled. Before UAT, verify the transport and subscription checks below:
- the Event Hubs consumer is receiving and checkpointing without staleness;
- the Graph permission, encryption certificate, and subscription renewal state are valid;
- every active emergency policy is covered, with no uncovered policy warning;
- the channel is not unexpectedly quiet and a recent decrypted event is visible;
- the email provider path probe succeeds; and
- location routes have valid fallback contacts for every enabled Teams profile.
Healthy, Attention, Failed, and Paused describe source health. Execution state such as queued or running is separate. These transport checks do not enable dispatch: the feature flag remains disabled throughout UAT. A checkpoint pause or stale consumer is a non-green condition with a possible event gap warning; Call Telemetry does not backfill that gap from Graph call records.
Create a Teams alert profile
- Select New Alert, then choose Teams emergency events as the source. A profile has exactly one source and the source cannot be changed after creation.
- Enable Call started, Call ended, or both. At least one lifecycle delivery must be enabled.
- Optionally filter only on Called Number and Emergency Policy, using equals or an explicit list. Do not use Cisco CDR or CMR fields for a Teams profile.
- Configure email on call started and email on call ended independently. A start email does not imply an end email, and vice versa.
- Optionally enable Update emergency chat. This is a separate channel from email and cannot prevent email delivery.
- Add a fallback route and location-specific routes before enabling the profile. Test both a resolved and an unresolved location, but keep the per-organization dispatch flag disabled until the required UAT passes.
Distinct emergency calls are never suppressed by an ordinary CDR rate window. Exact duplicate delivery keys, explicitly disabled delivery, and typed failures are the only suppression states, and each is shown in history.
Match locations and route recipients
Call Telemetry matches a Teams claimed address only from structured civic fields and only to a committed internal E911 address or an explicit mapping. It normalizes ordinary civic components such as address line, city, state/province, postal code, and country into a deterministic key.
It deliberately excludes Microsoft Place, room, floor, additionalInfo, caller identity, policy, and coordinates from the matching key. There is no fuzzy or confidence-based automatic match.
For each Teams profile:
- Set one fallback route with enabled email contacts. The fallback receives unmatched and unconfigured mapped locations, with the reason preserved in history.
- Create an optional route for each internal E911 address. Classify its contacts (for example, Security, Facilities, or Site Manager), order them, and enable only the contacts that should receive alerts.
- Use the unmatched-locations queue to review structured civic observations. Map a row to an internal address only after checking the organization and civic fields.
- Use Export to download the mapping template. For imports, provide stable internal address IDs and structured civic fields, run Preview, correct rejected or ambiguous rows, then apply using the preview receipt. Partial imports and cross-organization IDs are rejected.
At call start, Call Telemetry snapshots the address match, fallback/route choice, enabled contacts, and effective templates. Call-end delivery uses that snapshot even if an administrator later edits or removes the mapping, route, or recipient.
Write source-safe templates
Teams templates can use only the source-provided groups:
| Group | Examples |
|---|---|
call.* | {{ call.event_id }}, {{ call.event_type }}, {{ call.occurred_at }} |
caller.* | {{ caller.display_name }}, {{ caller.upn }}, {{ caller.number }} |
claimed_location.* | Structured claimed civic components only |
resolved_location.* | Matched internal E911 location and address context, subject to authorization |
teams.* | Tenant and emergency-policy metadata |
alert.* | Organization, profile, severity, and lifecycle metadata |
Use separate subject/body templates for call start and call end. Location route templates may inherit the profile template or override it. Missing optional values should leave the message understandable; preview both matched and unmatched start/end cases before enabling.
Cisco namespaces such as cdr.*, phone/network context, CMR measurements, IP addresses, BSSID, Place, and delayed-call-record tokens are intentionally unavailable to Teams profiles.
Optional emergency-chat updates
When Update emergency chat is enabled, Call Telemetry first correlates the structured event to an observed emergency chat. It records whether the correlation was exact or a bounded fallback; an ambiguous result is a typed skip, not a guess.
Before each start or end post, Call Telemetry verifies that the configured Call Telemetry agent is a current member of that chat. If the agent is absent or membership cannot be confirmed, history records skipped_agent_not_member (or the relevant typed reason). The system does not invite the agent and it does not fail email delivery. Chat uses the same start-time route/template snapshot as email.
Review history and troubleshoot
Open Alerts → CDR Alerts → History to trace a lifecycle from Event Hubs receipt through match, route snapshot, email, and optional chat outcome. A Teams row identifies the source, start/end lifecycle, called number, match state, fallback reason when applicable, and independent channel results.
| Symptom | Check | Response |
|---|---|---|
| No event after a test call | Policy coverage, Graph subscription, Event Hubs sender RBAC, then consumer/checkpoint health | Record the UTC test window and resolve the first non-green readiness check. Do not look for a delayed call record. |
| Possible-gap warning | Checkpoint staleness or paused consumption | Treat events in the gap as potentially missed; restore consumption and repeat controlled 933 UAT. |
| Event is unmatched | Claimed structured civic address and explicit mapping | Configure the exact civic mapping or keep the fallback route. Do not map from Place, room, floor, or coordinates. |
| Email skipped or failed | Lifecycle setting, route snapshot, contact state, provider result | Correct the route/contact or provider issue, then test the applicable start/end lifecycle. |
| Chat skipped | Correlation method and agent-membership result | Resolve membership or the source condition; email can still be successful. |
API and access contract
All calls re-derive organization ownership; knowing a profile or call UUID is not authorization. The source-read endpoints require the existing cdr_reports or cdr_admin read authorization. Profile and route mutations require the organization roles configured for CDR Alert administration and location routing.
| Endpoint | Use |
|---|---|
GET /api/org/:org_id/cdr-alerts/sources?enabled=true | Show enabled call streams and their authoritative health/readiness. |
GET /api/org/:org_id/cdr-alerts/sources/:source_key | Read one stream summary. |
GET /api/org/:org_id/cdr-alerts/sources/:source_key/fields | Read source-specific filter fields. |
GET /api/org/:org_id/cdr-alerts/sources/:source_key/tokens | Read source-specific template token groups. |
GET /api/org/:org_id/cdr-alerts/enrichment-sources | Read provider-context cards, join modes, freshness, and configuration routes. |
| `GET | PUT /api/org/:org_id/cdr-alerts/profiles/:id/fallback-route` |
GET /api/org/:org_id/cdr-alerts/profiles/:id/location-routes | Read profile location routes. |
PUT /api/org/:org_id/cdr-alerts/profiles/:id/location-routes/:address_id | Create or update one route. |
GET /api/org/:org_id/cdr-alerts/profiles/:id/unmatched-locations | Review unmatched civic observations. |
POST /api/org/:org_id/cdr-alerts/profiles/:id/unmatched-locations/:call_id/map | Apply an approved mapping to a future event. |
GET /api/org/:org_id/cdr-alerts/profiles/:id/location-routes/export | Export CSV mapping rows. |
POST /api/org/:org_id/cdr-alerts/profiles/:id/location-routes/import/preview | Validate a CSV before application. |
POST /api/org/:org_id/cdr-alerts/profiles/:id/location-routes/import | Apply a validated preview receipt. |
For cdr_reports users without location_read, API responses retain only coarse match state and location_details_redacted: true. They do not include claimed civic fields, coordinates, internal address IDs, resolved locations, routes, contacts, or protected snapshots. Secrets, certificates, encrypted payloads, and arbitrary Graph additionalData are never returned.
State changes and event outcomes emit registered telemetry and durable user_activity_logs records. Audit records capture the actor, organization, safe before/after metadata, source, and typed reason without putting caller or location data in telemetry labels.
Controlled rollout, SLO, and rollback
Use an approved 933 test policy (or your region's approved non-production equivalent), never a live emergency number. Keep the per-organization structured-dispatch flag disabled while completing both mandatory passes for every configured emergency policy and site class:
- Pass 1 — email lifecycle: Disable emergency-chat updates. Run a start and end event with start/end email enabled, and confirm both lifecycle emails and their route snapshots.
- Pass 2 — member-gated chat: Confirm the Call Telemetry agent is a current member of the emergency chat, then run a start and end event with emergency-chat updates enabled. Confirm the independent email and chat outcomes. This pass is mandatory even when chat updates will not be enabled for the first production profile.
- Failure acceptance: Pause Event Hubs consumption/checkpointing in the controlled environment. Prove the Teams source becomes non-green with an explicit possible event gap warning, retain that evidence, then restore consumption/checkpointing and re-establish green pre-dispatch readiness before continuing.
For every controlled run, retain evidence of Event Hubs receipt time, dispatch queue time, provider acceptance, event-history row, address match, route snapshot reuse, chat skip/send reason, the failure-acceptance warning, and audit row. The start-email target is 95% provider acceptance within 15 seconds of Event Hubs receipt and 99% within 60 seconds.
After initial acceptance, schedule a non-notifying 933 heartbeat for each policy/site class. The default interval is 30 days and must be configurable from 7 through 90 days. Due heartbeats produce Attention; missed grace periods produce Failed.
Enable the per-organization structured-dispatch flag only after pre-dispatch transport readiness is green and both mandatory UAT passes (including the checkpoint/consumer failure acceptance) have evidence for every policy/site class. To roll back, disable that flag and pause Teams dispatch for the organization; preserve inbox, checkpoint, history, and audit evidence for investigation. Do not claim legal or regulatory compliance from this technical workflow alone; review Kari's Law or other compliance wording with the approved product/legal owner.