wxcli 1.2.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- wxcli/__init__.py +4 -0
- wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
- wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
- wxcli/_playbook/.claude/rules/cleanup.md +29 -0
- wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
- wxcli/_playbook/.claude/rules/org-health.md +14 -0
- wxcli/_playbook/.claude/settings.json +8 -0
- wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
- wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
- wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
- wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
- wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
- wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
- wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
- wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
- wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
- wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
- wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
- wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
- wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
- wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
- wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
- wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
- wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
- wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
- wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
- wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
- wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
- wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
- wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
- wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
- wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
- wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
- wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
- wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
- wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
- wxcli/_playbook/CLAUDE.md +373 -0
- wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
- wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
- wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
- wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
- wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
- wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
- wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
- wxcli/_playbook/docs/reference/admin-partner.md +357 -0
- wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
- wxcli/_playbook/docs/reference/authentication.md +965 -0
- wxcli/_playbook/docs/reference/call-control.md +1205 -0
- wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
- wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
- wxcli/_playbook/docs/reference/call-routing.md +2304 -0
- wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
- wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
- wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
- wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
- wxcli/_playbook/docs/reference/devices-core.md +1869 -0
- wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
- wxcli/_playbook/docs/reference/devices-platform.md +467 -0
- wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
- wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
- wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
- wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
- wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
- wxcli/_playbook/docs/reference/meetings-content.md +473 -0
- wxcli/_playbook/docs/reference/meetings-core.md +903 -0
- wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
- wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
- wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
- wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
- wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
- wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
- wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
- wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
- wxcli/_playbook/docs/reference/provisioning.md +1366 -0
- wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
- wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
- wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
- wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
- wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
- wxcli/_version.py +24 -0
- wxcli/auth.py +137 -0
- wxcli/commands/__init__.py +0 -0
- wxcli/commands/_registry.py +181 -0
- wxcli/commands/activation_email.py +103 -0
- wxcli/commands/admin_recordings.py +585 -0
- wxcli/commands/analytics.py +105 -0
- wxcli/commands/announcement_playlists.py +219 -0
- wxcli/commands/announcements.py +519 -0
- wxcli/commands/archive_users.py +36 -0
- wxcli/commands/attachment_actions.py +60 -0
- wxcli/commands/audit_events.py +83 -0
- wxcli/commands/authorizations.py +113 -0
- wxcli/commands/auto_attendant.py +642 -0
- wxcli/commands/broadworks_billing_reports.py +126 -0
- wxcli/commands/broadworks_enterprises.py +160 -0
- wxcli/commands/broadworks_subscribers.py +319 -0
- wxcli/commands/broadworks_workspaces.py +108 -0
- wxcli/commands/call_controls.py +1304 -0
- wxcli/commands/call_park.py +494 -0
- wxcli/commands/call_pickup.py +229 -0
- wxcli/commands/call_queue.py +1878 -0
- wxcli/commands/call_recording.py +707 -0
- wxcli/commands/call_routing.py +1610 -0
- wxcli/commands/call_settings_for_me_phase_5.py +212 -0
- wxcli/commands/caller_reputation.py +169 -0
- wxcli/commands/calling_service.py +305 -0
- wxcli/commands/cc_address_book.py +770 -0
- wxcli/commands/cc_agent_greetings.py +242 -0
- wxcli/commands/cc_agent_summaries.py +39 -0
- wxcli/commands/cc_agent_wellbeing.py +216 -0
- wxcli/commands/cc_agents.py +425 -0
- wxcli/commands/cc_ai_assistant.py +55 -0
- wxcli/commands/cc_ai_feature.py +294 -0
- wxcli/commands/cc_audio_files.py +149 -0
- wxcli/commands/cc_auto_csat.py +311 -0
- wxcli/commands/cc_aux_code.py +458 -0
- wxcli/commands/cc_business_hour.py +353 -0
- wxcli/commands/cc_call_monitoring.py +228 -0
- wxcli/commands/cc_callbacks.py +194 -0
- wxcli/commands/cc_campaign.py +212 -0
- wxcli/commands/cc_captures.py +39 -0
- wxcli/commands/cc_contact_list.py +169 -0
- wxcli/commands/cc_contact_number.py +295 -0
- wxcli/commands/cc_data_sources.py +235 -0
- wxcli/commands/cc_desktop_layout.py +380 -0
- wxcli/commands/cc_desktop_profile.py +322 -0
- wxcli/commands/cc_dial_number.py +511 -0
- wxcli/commands/cc_dial_plan.py +347 -0
- wxcli/commands/cc_dnc.py +101 -0
- wxcli/commands/cc_entry_point.py +545 -0
- wxcli/commands/cc_ewt.py +51 -0
- wxcli/commands/cc_flow.py +477 -0
- wxcli/commands/cc_global_vars.py +430 -0
- wxcli/commands/cc_holiday_list.py +335 -0
- wxcli/commands/cc_journey.py +1261 -0
- wxcli/commands/cc_legacy_flows.py +49 -0
- wxcli/commands/cc_multimedia_profile.py +436 -0
- wxcli/commands/cc_notification.py +51 -0
- wxcli/commands/cc_outdial_ani.py +604 -0
- wxcli/commands/cc_overrides.py +341 -0
- wxcli/commands/cc_queue.py +1083 -0
- wxcli/commands/cc_queue_stats.py +55 -0
- wxcli/commands/cc_realtime.py +51 -0
- wxcli/commands/cc_resource_collection.py +312 -0
- wxcli/commands/cc_search.py +46 -0
- wxcli/commands/cc_site.py +400 -0
- wxcli/commands/cc_skill.py +350 -0
- wxcli/commands/cc_skill_profile.py +289 -0
- wxcli/commands/cc_subscriptions.py +426 -0
- wxcli/commands/cc_summaries.py +130 -0
- wxcli/commands/cc_tasks.py +844 -0
- wxcli/commands/cc_team.py +325 -0
- wxcli/commands/cc_user_profiles.py +349 -0
- wxcli/commands/cc_users.py +701 -0
- wxcli/commands/cc_work_types.py +363 -0
- wxcli/commands/cdr.py +89 -0
- wxcli/commands/classifications.py +38 -0
- wxcli/commands/cleanup.py +1427 -0
- wxcli/commands/client_settings.py +72 -0
- wxcli/commands/conference.py +328 -0
- wxcli/commands/configure.py +72 -0
- wxcli/commands/converged_recordings.py +347 -0
- wxcli/commands/converged_recordings_export.py +310 -0
- wxcli/commands/cq_playlists.py +42 -0
- wxcli/commands/cucm.py +2794 -0
- wxcli/commands/cucm_config.py +129 -0
- wxcli/commands/customer_assist.py +373 -0
- wxcli/commands/data_sources.py +227 -0
- wxcli/commands/dect_devices.py +787 -0
- wxcli/commands/device_configurations.py +77 -0
- wxcli/commands/device_dynamic_settings.py +320 -0
- wxcli/commands/device_settings.py +1489 -0
- wxcli/commands/devices.py +280 -0
- wxcli/commands/domains.py +142 -0
- wxcli/commands/ecm.py +178 -0
- wxcli/commands/emergency_services.py +827 -0
- wxcli/commands/events.py +83 -0
- wxcli/commands/external_voicemail.py +52 -0
- wxcli/commands/groups.py +206 -0
- wxcli/commands/guest_management.py +76 -0
- wxcli/commands/hds.py +340 -0
- wxcli/commands/hot_desk.py +67 -0
- wxcli/commands/hot_desking_members.py +118 -0
- wxcli/commands/hot_desking_portal.py +124 -0
- wxcli/commands/hunt_group.py +577 -0
- wxcli/commands/hybrid_clusters.py +71 -0
- wxcli/commands/hybrid_connectors.py +67 -0
- wxcli/commands/identity_org.py +159 -0
- wxcli/commands/init_playbook.py +155 -0
- wxcli/commands/licenses.py +106 -0
- wxcli/commands/live_monitoring.py +40 -0
- wxcli/commands/location_call_handling.py +577 -0
- wxcli/commands/location_schedules.py +341 -0
- wxcli/commands/location_settings.py +1297 -0
- wxcli/commands/location_voicemail.py +494 -0
- wxcli/commands/locations.py +336 -0
- wxcli/commands/meeting_captions.py +110 -0
- wxcli/commands/meeting_chats.py +63 -0
- wxcli/commands/meeting_invitees.py +234 -0
- wxcli/commands/meeting_messages.py +28 -0
- wxcli/commands/meeting_participants.py +278 -0
- wxcli/commands/meeting_polls.py +111 -0
- wxcli/commands/meeting_preferences.py +515 -0
- wxcli/commands/meeting_qa.py +78 -0
- wxcli/commands/meeting_qualities.py +43 -0
- wxcli/commands/meeting_reports.py +101 -0
- wxcli/commands/meeting_session_types.py +105 -0
- wxcli/commands/meeting_site.py +57 -0
- wxcli/commands/meeting_slido.py +44 -0
- wxcli/commands/meeting_summaries.py +92 -0
- wxcli/commands/meeting_tracking_codes.py +233 -0
- wxcli/commands/meeting_transcripts.py +230 -0
- wxcli/commands/meetings.py +1997 -0
- wxcli/commands/memberships.py +164 -0
- wxcli/commands/messages.py +213 -0
- wxcli/commands/mode_management.py +244 -0
- wxcli/commands/my_call_settings.py +3577 -0
- wxcli/commands/numbers.py +405 -0
- wxcli/commands/operating_modes.py +410 -0
- wxcli/commands/org_contacts.py +284 -0
- wxcli/commands/org_health_cli.py +55 -0
- wxcli/commands/org_settings.py +71 -0
- wxcli/commands/organizations.py +83 -0
- wxcli/commands/paging_group.py +257 -0
- wxcli/commands/partner_admins.py +141 -0
- wxcli/commands/partner_reports.py +188 -0
- wxcli/commands/partner_tags.py +216 -0
- wxcli/commands/people.py +279 -0
- wxcli/commands/person_call_settings.py +71 -0
- wxcli/commands/pstn.py +280 -0
- wxcli/commands/recording_report.py +154 -0
- wxcli/commands/report_templates.py +38 -0
- wxcli/commands/reports.py +144 -0
- wxcli/commands/resource_group_memberships.py +160 -0
- wxcli/commands/resource_groups.py +67 -0
- wxcli/commands/roles.py +63 -0
- wxcli/commands/room_tabs.py +160 -0
- wxcli/commands/rooms.py +225 -0
- wxcli/commands/scim_bulk.py +46 -0
- wxcli/commands/scim_groups.py +246 -0
- wxcli/commands/scim_schemas.py +82 -0
- wxcli/commands/scim_users.py +283 -0
- wxcli/commands/security_audit.py +54 -0
- wxcli/commands/service_apps.py +51 -0
- wxcli/commands/single_number_reach.py +209 -0
- wxcli/commands/team_memberships.py +155 -0
- wxcli/commands/teams.py +153 -0
- wxcli/commands/ucm_profile.py +42 -0
- wxcli/commands/update.py +219 -0
- wxcli/commands/user_settings.py +5116 -0
- wxcli/commands/video_mesh.py +1090 -0
- wxcli/commands/virtual_extensions.py +502 -0
- wxcli/commands/virtual_line_settings.py +2072 -0
- wxcli/commands/webhooks.py +176 -0
- wxcli/commands/wholesale_billing_reports.py +147 -0
- wxcli/commands/wholesale_provisioning.py +523 -0
- wxcli/commands/workspace_locations.py +339 -0
- wxcli/commands/workspace_metrics.py +103 -0
- wxcli/commands/workspace_personalization.py +70 -0
- wxcli/commands/workspace_settings.py +3347 -0
- wxcli/commands/workspaces.py +279 -0
- wxcli/commands/xapi.py +114 -0
- wxcli/config.py +139 -0
- wxcli/errors.py +77 -0
- wxcli/main.py +210 -0
- wxcli/migration/CLAUDE.md +106 -0
- wxcli/migration/__init__.py +1 -0
- wxcli/migration/advisory/CLAUDE.md +196 -0
- wxcli/migration/advisory/__init__.py +46 -0
- wxcli/migration/advisory/advisor.py +107 -0
- wxcli/migration/advisory/advisory_patterns.py +2552 -0
- wxcli/migration/advisory/recommendation_rules.py +835 -0
- wxcli/migration/cucm/CLAUDE.md +74 -0
- wxcli/migration/cucm/__init__.py +5 -0
- wxcli/migration/cucm/connection.py +265 -0
- wxcli/migration/cucm/discovery.py +225 -0
- wxcli/migration/cucm/extractors/__init__.py +1 -0
- wxcli/migration/cucm/extractors/announcements.py +92 -0
- wxcli/migration/cucm/extractors/base.py +90 -0
- wxcli/migration/cucm/extractors/device_profiles.py +98 -0
- wxcli/migration/cucm/extractors/devices.py +193 -0
- wxcli/migration/cucm/extractors/e911.py +103 -0
- wxcli/migration/cucm/extractors/features.py +309 -0
- wxcli/migration/cucm/extractors/helpers.py +73 -0
- wxcli/migration/cucm/extractors/informational.py +295 -0
- wxcli/migration/cucm/extractors/locations.py +221 -0
- wxcli/migration/cucm/extractors/moh.py +100 -0
- wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
- wxcli/migration/cucm/extractors/routing.py +493 -0
- wxcli/migration/cucm/extractors/shared_lines.py +146 -0
- wxcli/migration/cucm/extractors/templates.py +229 -0
- wxcli/migration/cucm/extractors/tier4.py +173 -0
- wxcli/migration/cucm/extractors/users.py +240 -0
- wxcli/migration/cucm/extractors/voicemail.py +243 -0
- wxcli/migration/cucm/extractors/workspaces.py +88 -0
- wxcli/migration/cucm/unity_connection.py +304 -0
- wxcli/migration/execute/CLAUDE.md +372 -0
- wxcli/migration/execute/__init__.py +303 -0
- wxcli/migration/execute/batch.py +277 -0
- wxcli/migration/execute/dependency.py +483 -0
- wxcli/migration/execute/engine.py +964 -0
- wxcli/migration/execute/handlers.py +2232 -0
- wxcli/migration/execute/planner.py +1939 -0
- wxcli/migration/execute/runtime.py +571 -0
- wxcli/migration/export/CLAUDE.md +49 -0
- wxcli/migration/export/__init__.py +8 -0
- wxcli/migration/export/csv_export.py +126 -0
- wxcli/migration/export/deployment_plan.py +479 -0
- wxcli/migration/export/json_export.py +60 -0
- wxcli/migration/models.py +941 -0
- wxcli/migration/phone_models.py +50 -0
- wxcli/migration/preflight/CLAUDE.md +52 -0
- wxcli/migration/preflight/__init__.py +89 -0
- wxcli/migration/preflight/checks.py +911 -0
- wxcli/migration/preflight/runner.py +293 -0
- wxcli/migration/rate_limiter.py +144 -0
- wxcli/migration/report/CLAUDE.md +245 -0
- wxcli/migration/report/__init__.py +7 -0
- wxcli/migration/report/appendix.py +2437 -0
- wxcli/migration/report/assembler.py +183 -0
- wxcli/migration/report/charts.py +263 -0
- wxcli/migration/report/executive.py +776 -0
- wxcli/migration/report/explainer.py +704 -0
- wxcli/migration/report/helpers.py +74 -0
- wxcli/migration/report/ingest.py +152 -0
- wxcli/migration/report/notice_templates.py +192 -0
- wxcli/migration/report/score.py +375 -0
- wxcli/migration/report/styles.py +1052 -0
- wxcli/migration/report/user_diff.py +1052 -0
- wxcli/migration/report/user_notice.py +425 -0
- wxcli/migration/state.py +139 -0
- wxcli/migration/store.py +860 -0
- wxcli/migration/transform/CLAUDE.md +107 -0
- wxcli/migration/transform/__init__.py +12 -0
- wxcli/migration/transform/analysis_pipeline.py +453 -0
- wxcli/migration/transform/analyzers/__init__.py +142 -0
- wxcli/migration/transform/analyzers/css_permission.py +189 -0
- wxcli/migration/transform/analyzers/css_routing.py +335 -0
- wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
- wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
- wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
- wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
- wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
- wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
- wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
- wxcli/migration/transform/analyzers/missing_data.py +300 -0
- wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
- wxcli/migration/transform/analyzers/shared_line.py +170 -0
- wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
- wxcli/migration/transform/analyzers/workspace_license.py +212 -0
- wxcli/migration/transform/cross_reference.py +1136 -0
- wxcli/migration/transform/cucm_pattern.py +246 -0
- wxcli/migration/transform/decisions.py +301 -0
- wxcli/migration/transform/e164.py +145 -0
- wxcli/migration/transform/engine.py +256 -0
- wxcli/migration/transform/mappers/CLAUDE.md +123 -0
- wxcli/migration/transform/mappers/__init__.py +76 -0
- wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
- wxcli/migration/transform/mappers/base.py +190 -0
- wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
- wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
- wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
- wxcli/migration/transform/mappers/css_mapper.py +868 -0
- wxcli/migration/transform/mappers/dect_mapper.py +367 -0
- wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
- wxcli/migration/transform/mappers/device_mapper.py +227 -0
- wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
- wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
- wxcli/migration/transform/mappers/e911_mapper.py +129 -0
- wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
- wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
- wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
- wxcli/migration/transform/mappers/line_mapper.py +310 -0
- wxcli/migration/transform/mappers/location_mapper.py +235 -0
- wxcli/migration/transform/mappers/moh_mapper.py +114 -0
- wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
- wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
- wxcli/migration/transform/mappers/routing_mapper.py +821 -0
- wxcli/migration/transform/mappers/snr_mapper.py +201 -0
- wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
- wxcli/migration/transform/mappers/user_mapper.py +264 -0
- wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
- wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
- wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
- wxcli/migration/transform/normalizers.py +2008 -0
- wxcli/migration/transform/pattern_converter.py +106 -0
- wxcli/migration/transform/pipeline.py +271 -0
- wxcli/migration/transform/rules.py +255 -0
- wxcli/org_health/CLAUDE.md +63 -0
- wxcli/org_health/__init__.py +7 -0
- wxcli/org_health/analyze.py +93 -0
- wxcli/org_health/checks.py +458 -0
- wxcli/org_health/collector.py +62 -0
- wxcli/org_health/models.py +78 -0
- wxcli/org_health/report.py +300 -0
- wxcli/output.py +101 -0
- wxcli-1.2.0.dist-info/METADATA +505 -0
- wxcli-1.2.0.dist-info/RECORD +413 -0
- wxcli-1.2.0.dist-info/WHEEL +5 -0
- wxcli-1.2.0.dist-info/entry_points.txt +2 -0
- wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
- wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
- wxcli-1.2.0.dist-info/scm_version.json +8 -0
- wxcli-1.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,1122 @@
|
|
|
1
|
+
<!-- Updated by playbook session 2026-03-18 -->
|
|
2
|
+
<!-- Updated by playbook session 2026-03-18 -->
|
|
3
|
+
|
|
4
|
+
# Emergency Services & E911
|
|
5
|
+
|
|
6
|
+
## Overview
|
|
7
|
+
|
|
8
|
+
Webex Calling E911 compliance requires three interlocking configurations:
|
|
9
|
+
|
|
10
|
+
| Layer | What It Configures | SDK API |
|
|
11
|
+
|-------|--------------------|---------|
|
|
12
|
+
| **Emergency Call Notifications** | Org-level email alerts when any emergency call is placed | `OrgEmergencyServicesApi` |
|
|
13
|
+
| **Emergency Addresses** | Physical civic addresses associated with locations and phone numbers | `EmergencyAddressApi` |
|
|
14
|
+
| **Emergency Callback Number (ECBN)** | Per-person/workspace/virtual-line callback number for return calls from PSAP | `ECBNApi` |
|
|
15
|
+
|
|
16
|
+
All three are needed for full E911 compliance in the United States. Emergency call notifications satisfy **Kari's Law** (U.S. Public Law 115-127), which requires that any emergency call from within an organization generates a notification. Emergency addresses and ECBN satisfy **RAY BAUM's Act** requirements for dispatchable location information.
|
|
17
|
+
|
|
18
|
+
## Table of Contents
|
|
19
|
+
|
|
20
|
+
1. [Emergency Call Notifications (Org-Level)](#1-emergency-call-notifications-org-level)
|
|
21
|
+
2. [Emergency Addresses](#2-emergency-addresses)
|
|
22
|
+
3. [Emergency Callback Number (ECBN)](#3-emergency-callback-number-ecbn)
|
|
23
|
+
4. [E911 Compliance Checklist](#4-e911-compliance-checklist)
|
|
24
|
+
5. [Raw HTTP Endpoints](#5-raw-http-endpoints)
|
|
25
|
+
6. [Gotchas (Cross-Cutting)](#gotchas-cross-cutting)
|
|
26
|
+
7. [See Also](#see-also)
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## 1. Emergency Call Notifications (Org-Level)
|
|
31
|
+
|
|
32
|
+
### What It Does
|
|
33
|
+
|
|
34
|
+
When enabled, sends an email to a specified address every time someone in the organization dials emergency services (911 in the U.S.). This is the org-wide kill switch for Kari's Law compliance.
|
|
35
|
+
|
|
36
|
+
### SDK Access
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
api = wxc_api.telephony.emergency_services # OrgEmergencyServicesApi instance
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Base path: `telephony/config/emergencyCallNotification`
|
|
43
|
+
|
|
44
|
+
Required scopes:
|
|
45
|
+
- **Read**: `spark-admin:telephony_config_read`
|
|
46
|
+
- **Write**: `spark-admin:telephony_config_write`
|
|
47
|
+
|
|
48
|
+
### Read Notification Settings
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
OrgEmergencyServicesApi.read_emergency_call_notification(
|
|
52
|
+
org_id: str = None,
|
|
53
|
+
) -> OrgEmergencyCallNotification
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Update Notification Settings
|
|
57
|
+
|
|
58
|
+
```python
|
|
59
|
+
OrgEmergencyServicesApi.update_emergency_call_notification(
|
|
60
|
+
setting: OrgEmergencyCallNotification,
|
|
61
|
+
org_id: str = None,
|
|
62
|
+
) -> None
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
**Example -- enable emergency call notifications:**
|
|
66
|
+
```python
|
|
67
|
+
from wxc_sdk.telephony.emergency_services import OrgEmergencyCallNotification
|
|
68
|
+
|
|
69
|
+
setting = OrgEmergencyCallNotification(
|
|
70
|
+
emergency_call_notification_enabled=True,
|
|
71
|
+
allow_email_notification_all_location_enabled=True,
|
|
72
|
+
email_address="security@company.com"
|
|
73
|
+
)
|
|
74
|
+
api.telephony.emergency_services.update_emergency_call_notification(setting=setting)
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
### Data Model
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
class OrgEmergencyCallNotification(ApiModel):
|
|
81
|
+
# When True, sends email on any emergency call
|
|
82
|
+
emergency_call_notification_enabled: Optional[bool]
|
|
83
|
+
# When True, sends notifications for ALL locations (not just specific ones)
|
|
84
|
+
allow_email_notification_all_location_enabled: Optional[bool]
|
|
85
|
+
# Email address that receives the notification
|
|
86
|
+
email_address: Optional[str]
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
### CLI Examples
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
# Read org-level emergency call notification settings
|
|
93
|
+
wxcli emergency-services show-emergency-call-notification-config
|
|
94
|
+
|
|
95
|
+
# Enable org-level emergency call notifications for all locations
|
|
96
|
+
wxcli emergency-services update-emergency-call-notification-config \
|
|
97
|
+
--emergency-call-notification-enabled \
|
|
98
|
+
--allow-email-notification-all-location-enabled \
|
|
99
|
+
--email-address "security@company.com"
|
|
100
|
+
|
|
101
|
+
# Read location-level emergency call notification settings
|
|
102
|
+
wxcli emergency-services show-emergency-call-notification-locations Y2lzY29...locationId
|
|
103
|
+
|
|
104
|
+
# Enable location-level emergency call notification with a floor-specific email
|
|
105
|
+
wxcli emergency-services update-emergency-call-notification-locations Y2lzY29...locationId \
|
|
106
|
+
--emergency-call-notification-enabled \
|
|
107
|
+
--email-address "floor3-security@company.com"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
## 2. Emergency Addresses
|
|
113
|
+
|
|
114
|
+
### What They Are
|
|
115
|
+
|
|
116
|
+
Emergency addresses are the physical civic addresses associated with phone numbers and locations. When someone dials 911, this address is transmitted to the PSAP (Public Safety Answering Point) so first responders know where to go.
|
|
117
|
+
|
|
118
|
+
Emergency addresses can be set at two levels:
|
|
119
|
+
- **Location level** -- default address for all numbers at that location
|
|
120
|
+
- **Phone number level** -- per-number override (e.g., for users on different floors or in different buildings at the same location)
|
|
121
|
+
|
|
122
|
+
### SDK Access
|
|
123
|
+
|
|
124
|
+
```python
|
|
125
|
+
api = wxc_api.telephony.emergency_address # EmergencyAddressApi instance
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
Base path: `telephony/pstn`
|
|
129
|
+
|
|
130
|
+
Required scopes:
|
|
131
|
+
- **Read/Lookup**: `spark-admin:telephony_pstn_read`
|
|
132
|
+
- **Write**: `spark-admin:telephony_pstn_write`
|
|
133
|
+
|
|
134
|
+
### Operations
|
|
135
|
+
|
|
136
|
+
#### Add Emergency Address to a Location
|
|
137
|
+
|
|
138
|
+
```python
|
|
139
|
+
EmergencyAddressApi.add_to_location(
|
|
140
|
+
location_id: str, # Required
|
|
141
|
+
address: Union[EmergencyAddress, SuggestedEmergencyAddress], # Required
|
|
142
|
+
org_id: str = None,
|
|
143
|
+
) -> str # Returns the new emergency address ID
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
**Example:**
|
|
147
|
+
```python
|
|
148
|
+
from wxc_sdk.telephony.emergency_address import EmergencyAddress
|
|
149
|
+
|
|
150
|
+
addr = EmergencyAddress(
|
|
151
|
+
address1="100 Main Street",
|
|
152
|
+
address2="Suite 400",
|
|
153
|
+
city="San Jose",
|
|
154
|
+
state="CA",
|
|
155
|
+
postal_code="95110",
|
|
156
|
+
country="US"
|
|
157
|
+
)
|
|
158
|
+
addr_id = api.telephony.emergency_address.add_to_location(
|
|
159
|
+
location_id="loc_id_123",
|
|
160
|
+
address=addr
|
|
161
|
+
)
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
#### Lookup / Validate an Address
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
EmergencyAddressApi.lookup_for_location(
|
|
168
|
+
location_id: str, # Required
|
|
169
|
+
address: Union[EmergencyAddress, SuggestedEmergencyAddress], # Required
|
|
170
|
+
org_id: str = None,
|
|
171
|
+
) -> list[SuggestedEmergencyAddress]
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
Returns a list of suggested addresses. If the input address is valid and unchanged, no errors are returned. If corrections were needed, the response includes the corrected address along with error details in each `SuggestedEmergencyAddress.errors` list.
|
|
175
|
+
|
|
176
|
+
**Always validate before adding.** The PSAP database requires standardized addresses. This lookup normalizes the input and flags issues.
|
|
177
|
+
|
|
178
|
+
**Example:**
|
|
179
|
+
```python
|
|
180
|
+
suggestions = api.telephony.emergency_address.lookup_for_location(
|
|
181
|
+
location_id="loc_id_123",
|
|
182
|
+
address=EmergencyAddress(
|
|
183
|
+
address1="100 Main St",
|
|
184
|
+
city="San Jose",
|
|
185
|
+
state="CA",
|
|
186
|
+
postal_code="95110",
|
|
187
|
+
country="US"
|
|
188
|
+
)
|
|
189
|
+
)
|
|
190
|
+
if suggestions and not suggestions[0].errors:
|
|
191
|
+
# Address is valid, use the suggested (normalized) version
|
|
192
|
+
validated_addr = suggestions[0]
|
|
193
|
+
addr_id = api.telephony.emergency_address.add_to_location(
|
|
194
|
+
location_id="loc_id_123",
|
|
195
|
+
address=validated_addr
|
|
196
|
+
)
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
#### Update Emergency Address for a Location
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
EmergencyAddressApi.update_for_location(
|
|
203
|
+
location_id: str, # Required
|
|
204
|
+
address_id: str, # Required -- ID of existing address to update
|
|
205
|
+
address: Union[EmergencyAddress, SuggestedEmergencyAddress], # Required
|
|
206
|
+
org_id: str = None,
|
|
207
|
+
) -> None
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
#### Update Emergency Address for a Phone Number
|
|
211
|
+
|
|
212
|
+
```python
|
|
213
|
+
EmergencyAddressApi.update_for_phone_number(
|
|
214
|
+
phone_number: str, # Required -- the E.164 phone number
|
|
215
|
+
emergency_address: Union[EmergencyAddress, SuggestedEmergencyAddress] = None,
|
|
216
|
+
org_id: str = None,
|
|
217
|
+
) -> None
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Use this to set a per-number emergency address that overrides the location default. **Passing an empty/None address deletes the custom address** and reverts the number to the location's default emergency address.
|
|
221
|
+
|
|
222
|
+
### Data Models
|
|
223
|
+
|
|
224
|
+
#### EmergencyAddress
|
|
225
|
+
|
|
226
|
+
```python
|
|
227
|
+
class EmergencyAddress(ApiModel):
|
|
228
|
+
address1: Optional[str] # Primary street (e.g., "100 Main Street")
|
|
229
|
+
address2: Optional[str] # Secondary (e.g., "Suite 400", "Floor 3")
|
|
230
|
+
city: Optional[str]
|
|
231
|
+
state: Optional[str] # State / Province / Region
|
|
232
|
+
postal_code: Optional[str]
|
|
233
|
+
country: Optional[str] # Country code (e.g., "US")
|
|
234
|
+
```
|
|
235
|
+
|
|
236
|
+
#### SuggestedEmergencyAddress
|
|
237
|
+
|
|
238
|
+
Extends `EmergencyAddress` with validation metadata:
|
|
239
|
+
|
|
240
|
+
```python
|
|
241
|
+
class SuggestedEmergencyAddress(EmergencyAddress):
|
|
242
|
+
meta: Optional[dict] # Additional metadata
|
|
243
|
+
errors: Optional[list[AddressLookupError]] # Validation errors (present when input was corrected)
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
#### AddressLookupError
|
|
247
|
+
|
|
248
|
+
```python
|
|
249
|
+
class AddressLookupError(ApiModel):
|
|
250
|
+
code: Optional[str] # Error code
|
|
251
|
+
title: Optional[str] # Error title
|
|
252
|
+
detail: Optional[str] # Detailed error message
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### CLI Examples
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
# Validate/lookup an emergency address for a location (always do this first)
|
|
259
|
+
wxcli pstn create Y2lzY29...locationId \
|
|
260
|
+
--address1 "100 Main Street" \
|
|
261
|
+
--city "San Jose" \
|
|
262
|
+
--state "CA" \
|
|
263
|
+
--postal-code "95110" \
|
|
264
|
+
--country "US"
|
|
265
|
+
|
|
266
|
+
# Add a validated emergency address to a location
|
|
267
|
+
wxcli pstn create-emergency-address Y2lzY29...locationId \
|
|
268
|
+
--address1 "100 Main Street" \
|
|
269
|
+
--address2 "Suite 400" \
|
|
270
|
+
--city "San Jose" \
|
|
271
|
+
--state "CA" \
|
|
272
|
+
--postal-code "95110" \
|
|
273
|
+
--country "US"
|
|
274
|
+
|
|
275
|
+
# Update an existing emergency address for a location
|
|
276
|
+
wxcli pstn update-emergency-addresses Y2lzY29...locationId Y2lzY29...addressId \
|
|
277
|
+
--address1 "200 Main Street" \
|
|
278
|
+
--city "San Jose" \
|
|
279
|
+
--state "CA" \
|
|
280
|
+
--postal-code "95110" \
|
|
281
|
+
--country "US"
|
|
282
|
+
|
|
283
|
+
# Update the emergency address for a specific phone number (per-number override)
|
|
284
|
+
wxcli pstn update-emergency-address "+15551234567" \
|
|
285
|
+
--json-body '{"emergencyAddress": {"address1": "100 Main Street", "address2": "Floor 3", "city": "San Jose", "state": "CA", "postalCode": "95110", "country": "US"}}'
|
|
286
|
+
|
|
287
|
+
# Clear a per-number override (reverts to location default) -- pass empty emergencyAddress
|
|
288
|
+
wxcli pstn update-emergency-address "+15551234567" \
|
|
289
|
+
--json-body '{"emergencyAddress": null}'
|
|
290
|
+
```
|
|
291
|
+
|
|
292
|
+
---
|
|
293
|
+
|
|
294
|
+
## 3. Emergency Callback Number (ECBN)
|
|
295
|
+
|
|
296
|
+
### What It Is
|
|
297
|
+
|
|
298
|
+
The Emergency Callback Number (ECBN) is the phone number that the PSAP (Public Safety Answering Point) uses to call back if an emergency call is disconnected. This is critical for extension-only users who don't have a direct DID -- without an ECBN, the PSAP has no number to call back.
|
|
299
|
+
|
|
300
|
+
ECBN applies to:
|
|
301
|
+
- **People** (users)
|
|
302
|
+
- **Workspaces**
|
|
303
|
+
- **Virtual lines**
|
|
304
|
+
|
|
305
|
+
### SDK Access
|
|
306
|
+
|
|
307
|
+
```python
|
|
308
|
+
# For person ECBN:
|
|
309
|
+
api = wxc_api.person_settings.ecbn # ECBNApi instance
|
|
310
|
+
|
|
311
|
+
# For virtual line ECBN:
|
|
312
|
+
api = wxc_api.telephony.virtual_lines.ecbn # ECBNApi instance (virtual line selector)
|
|
313
|
+
```
|
|
314
|
+
|
|
315
|
+
The `ECBNApi` is a `PersonSettingsApiChild` that works across entity types via the `ApiSelector`:
|
|
316
|
+
- `ApiSelector.person` -- URL: `telephony/config/people/{id}/emergencyCallbackNumber`
|
|
317
|
+
- `ApiSelector.workspace` -- URL: `telephony/config/workspaces/{id}/emergencyCallbackNumber`
|
|
318
|
+
- `ApiSelector.virtual_line` -- URL: `telephony/config/virtualLines/{id}/emergencyCallbackNumber`
|
|
319
|
+
|
|
320
|
+
Required scopes:
|
|
321
|
+
- **Read**: `spark-admin:telephony_config_read`
|
|
322
|
+
- **Write**: `spark-admin:telephony_config_write`
|
|
323
|
+
|
|
324
|
+
### ECBN Selection Options
|
|
325
|
+
|
|
326
|
+
There are multiple sources for where the ECBN comes from, in order of specificity:
|
|
327
|
+
|
|
328
|
+
| Selection | Enum Value | When To Use |
|
|
329
|
+
|-----------|-----------|-------------|
|
|
330
|
+
| **Direct Line** | `DIRECT_LINE` | User has their own DID -- PSAP calls back that number directly |
|
|
331
|
+
| **Location ECBN** | `LOCATION_ECBN` | Location has a dedicated ECBN different from the main number -- used for extension-only users |
|
|
332
|
+
| **Location Member Number** | `LOCATION_MEMBER_NUMBER` | Another user/workspace/virtual line's number at the same location -- used for multi-floor/multi-building locations to get a more accurate ESA |
|
|
333
|
+
| **None** | `NONE` | No selection (falls back to system default) |
|
|
334
|
+
|
|
335
|
+
### Operations
|
|
336
|
+
|
|
337
|
+
#### Read ECBN Settings
|
|
338
|
+
|
|
339
|
+
```python
|
|
340
|
+
ECBNApi.read(
|
|
341
|
+
entity_id: str, # Person ID, workspace ID, or virtual line ID
|
|
342
|
+
org_id: str = None,
|
|
343
|
+
) -> PersonECBN
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
Returns the current ECBN configuration including the selected source, direct line info, location ECBN info, location member info, and the default fallback info.
|
|
347
|
+
|
|
348
|
+
**Example:**
|
|
349
|
+
```python
|
|
350
|
+
ecbn = api.person_settings.ecbn.read(entity_id="person_id_123")
|
|
351
|
+
print(f"Selected: {ecbn.selected}")
|
|
352
|
+
print(f"Effective value: {ecbn.direct_line_info.effective_value}")
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
#### Configure ECBN
|
|
356
|
+
|
|
357
|
+
```python
|
|
358
|
+
ECBNApi.configure(
|
|
359
|
+
entity_id: str, # Required
|
|
360
|
+
selected: SelectedECBN, # Required -- DIRECT_LINE, LOCATION_ECBN, or LOCATION_MEMBER_NUMBER
|
|
361
|
+
location_member_id: str = None, # Required when selected=LOCATION_MEMBER_NUMBER
|
|
362
|
+
org_id: str = None,
|
|
363
|
+
) -> None
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
**Example -- set a user to use their direct line as ECBN:**
|
|
367
|
+
```python
|
|
368
|
+
from wxc_sdk.person_settings.ecbn import SelectedECBN
|
|
369
|
+
|
|
370
|
+
api.person_settings.ecbn.configure(
|
|
371
|
+
entity_id="person_id_123",
|
|
372
|
+
selected=SelectedECBN.direct_line
|
|
373
|
+
)
|
|
374
|
+
```
|
|
375
|
+
|
|
376
|
+
**Example -- set an extension-only user to use the location ECBN:**
|
|
377
|
+
```python
|
|
378
|
+
api.person_settings.ecbn.configure(
|
|
379
|
+
entity_id="person_id_456",
|
|
380
|
+
selected=SelectedECBN.location_ecbn
|
|
381
|
+
)
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Example -- set ECBN to another member's number (multi-floor scenario):**
|
|
385
|
+
```python
|
|
386
|
+
api.person_settings.ecbn.configure(
|
|
387
|
+
entity_id="person_id_789",
|
|
388
|
+
selected=SelectedECBN.location_member_number,
|
|
389
|
+
location_member_id="other_person_id_on_same_floor"
|
|
390
|
+
)
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
#### Read ECBN Dependencies
|
|
394
|
+
|
|
395
|
+
```python
|
|
396
|
+
ECBNApi.dependencies(
|
|
397
|
+
entity_id: str, # Person ID, workspace ID, or virtual line ID
|
|
398
|
+
org_id: str = None,
|
|
399
|
+
) -> ECBNDependencies
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
Check what depends on this entity's ECBN before making changes. Returns:
|
|
403
|
+
- Whether this entity is the location's default ECBN
|
|
404
|
+
- Whether this entity uses itself as ECBN
|
|
405
|
+
- How many other members use this entity as their ECBN
|
|
406
|
+
|
|
407
|
+
**Example:**
|
|
408
|
+
```python
|
|
409
|
+
deps = api.person_settings.ecbn.dependencies(entity_id="person_id_123")
|
|
410
|
+
if deps.dependent_member_count and deps.dependent_member_count > 0:
|
|
411
|
+
print(f"WARNING: {deps.dependent_member_count} other members use this person's number as ECBN")
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
### ECBN Fallback Logic
|
|
415
|
+
|
|
416
|
+
The system applies fallback rules when the configured ECBN source is unavailable:
|
|
417
|
+
|
|
418
|
+
1. If `DIRECT_LINE` is selected but the user has no valid DID, falls back to location ECBN
|
|
419
|
+
2. If `LOCATION_ECBN` is selected but no location ECBN is configured, falls back to the location's main number
|
|
420
|
+
3. If `LOCATION_MEMBER_NUMBER` is selected but the member's number is invalid, falls back to location ECBN or location main number
|
|
421
|
+
|
|
422
|
+
The `effective_level` and `effective_value` fields on the response models show which ECBN will actually be used after fallback resolution.
|
|
423
|
+
|
|
424
|
+
### Data Models
|
|
425
|
+
|
|
426
|
+
#### PersonECBN (Main Response)
|
|
427
|
+
|
|
428
|
+
```python
|
|
429
|
+
class PersonECBN(ApiModel):
|
|
430
|
+
# The selected ECBN source
|
|
431
|
+
selected: Optional[ECBNSelection] # DIRECT_LINE, LOCATION_ECBN, LOCATION_MEMBER_NUMBER, NONE
|
|
432
|
+
# Info for the direct line option
|
|
433
|
+
direct_line_info: Optional[PersonECBNDirectLine]
|
|
434
|
+
# Info for the location ECBN option
|
|
435
|
+
location_ecbn_info: Optional[PersonECBNDirectLine] # Note: aliased from 'locationECBNInfo'
|
|
436
|
+
# Info for the location member option
|
|
437
|
+
location_member_info: Optional[ECBNLocationMember]
|
|
438
|
+
# Default fallback info when nothing else is configured
|
|
439
|
+
default_info: Optional[ECBNDefault]
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
#### PersonECBNDirectLine
|
|
443
|
+
|
|
444
|
+
```python
|
|
445
|
+
class PersonECBNDirectLine(ApiModel):
|
|
446
|
+
phone_number: Optional[str] # The callback phone number
|
|
447
|
+
first_name: Optional[str]
|
|
448
|
+
last_name: Optional[str]
|
|
449
|
+
effective_level: Optional[ECBNEffectiveLevel] # What actually gets used after fallback
|
|
450
|
+
effective_value: Optional[str] # The actual ECBN number after fallback
|
|
451
|
+
quality: Optional[ECBNQuality] # RECOMMENDED, NOT_RECOMMENDED, or INVALID
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
#### ECBNLocationMember
|
|
455
|
+
|
|
456
|
+
```python
|
|
457
|
+
class ECBNLocationMember(ApiModel):
|
|
458
|
+
phone_number: Optional[str] # Member's callback number
|
|
459
|
+
first_name: Optional[str]
|
|
460
|
+
last_name: Optional[str]
|
|
461
|
+
member_id: Optional[str] # User/workspace/virtual line ID
|
|
462
|
+
member_type: Optional[UserType] # Type of the member
|
|
463
|
+
effective_level: Optional[ECBNLocationEffectiveLevel]
|
|
464
|
+
effective_value: Optional[str]
|
|
465
|
+
quality: Optional[ECBNQuality]
|
|
466
|
+
```
|
|
467
|
+
|
|
468
|
+
#### ECBNDependencies
|
|
469
|
+
|
|
470
|
+
```python
|
|
471
|
+
class ECBNDependencies(ApiModel):
|
|
472
|
+
is_location_ecbn_default: Optional[bool] # Is this the location's default ECBN?
|
|
473
|
+
is_self_ecbn_default: Optional[bool] # Does this entity use itself as ECBN?
|
|
474
|
+
dependent_member_count: Optional[int] # How many others reference this entity's number
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
#### ECBNDefault
|
|
478
|
+
|
|
479
|
+
```python
|
|
480
|
+
class ECBNDefault(ApiModel):
|
|
481
|
+
effective_value: Optional[str] # The fallback ECBN number
|
|
482
|
+
quality: Optional[ECBNQuality] # RECOMMENDED, NOT_RECOMMENDED, or INVALID
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
#### Enums
|
|
486
|
+
|
|
487
|
+
```python
|
|
488
|
+
class ECBNSelection(str, Enum):
|
|
489
|
+
direct_line = 'DIRECT_LINE'
|
|
490
|
+
location_ecbn = 'LOCATION_ECBN'
|
|
491
|
+
location_member_number = 'LOCATION_MEMBER_NUMBER'
|
|
492
|
+
none_ = 'NONE'
|
|
493
|
+
|
|
494
|
+
class SelectedECBN(str, Enum):
|
|
495
|
+
"""Used in configure() -- does not include NONE"""
|
|
496
|
+
direct_line = 'DIRECT_LINE'
|
|
497
|
+
location_ecbn = 'LOCATION_ECBN'
|
|
498
|
+
location_member_number = 'LOCATION_MEMBER_NUMBER'
|
|
499
|
+
|
|
500
|
+
class ECBNEffectiveLevel(str, Enum):
|
|
501
|
+
direct_line = 'DIRECT_LINE'
|
|
502
|
+
location_ecbn = 'LOCATION_ECBN'
|
|
503
|
+
location_number = 'LOCATION_NUMBER'
|
|
504
|
+
location_member_number = 'LOCATION_MEMBER_NUMBER'
|
|
505
|
+
none_ = 'NONE'
|
|
506
|
+
|
|
507
|
+
class ECBNQuality(str, Enum):
|
|
508
|
+
recommended = 'RECOMMENDED' # Activated number on a user/workspace
|
|
509
|
+
not_recommended = 'NOT_RECOMMENDED' # Activated number on AA/HG/etc.
|
|
510
|
+
invalid = 'INVALID' # Inactive or non-existent number
|
|
511
|
+
```
|
|
512
|
+
|
|
513
|
+
### CLI Examples
|
|
514
|
+
|
|
515
|
+
```bash
|
|
516
|
+
# --- Person ECBN ---
|
|
517
|
+
|
|
518
|
+
# Read a person's ECBN settings
|
|
519
|
+
wxcli emergency-services show-emergency-callback-number-people Y2lzY29...personId
|
|
520
|
+
|
|
521
|
+
# Set a person to use their direct line as ECBN
|
|
522
|
+
wxcli emergency-services update-emergency-callback-number-people Y2lzY29...personId \
|
|
523
|
+
--json-body '{"selected": "DIRECT_LINE"}'
|
|
524
|
+
|
|
525
|
+
# Set an extension-only user to use the location ECBN
|
|
526
|
+
wxcli emergency-services update-emergency-callback-number-people Y2lzY29...personId \
|
|
527
|
+
--json-body '{"selected": "LOCATION_ECBN"}'
|
|
528
|
+
|
|
529
|
+
# Set ECBN to another member's number (multi-floor scenario)
|
|
530
|
+
wxcli emergency-services update-emergency-callback-number-people Y2lzY29...personId \
|
|
531
|
+
--location-member-id Y2lzY29...otherPersonId \
|
|
532
|
+
--json-body '{"selected": "LOCATION_MEMBER_NUMBER", "locationMemberId": "Y2lzY29...otherPersonId"}'
|
|
533
|
+
|
|
534
|
+
# Check person ECBN dependencies before changing
|
|
535
|
+
wxcli emergency-services show-dependencies-emergency-callback-number-1 Y2lzY29...personId
|
|
536
|
+
|
|
537
|
+
# --- Workspace ECBN ---
|
|
538
|
+
|
|
539
|
+
# Read a workspace's ECBN settings
|
|
540
|
+
wxcli emergency-services show-emergency-callback-number-workspaces Y2lzY29...workspaceId
|
|
541
|
+
|
|
542
|
+
# Update a workspace's ECBN to use its direct line
|
|
543
|
+
wxcli emergency-services update-emergency-callback-number-workspaces Y2lzY29...workspaceId \
|
|
544
|
+
--json-body '{"selected": "DIRECT_LINE"}'
|
|
545
|
+
|
|
546
|
+
# Check workspace ECBN dependencies
|
|
547
|
+
wxcli emergency-services show-dependencies-emergency-callback-number-2 Y2lzY29...workspaceId
|
|
548
|
+
|
|
549
|
+
# --- Virtual Line ECBN ---
|
|
550
|
+
|
|
551
|
+
# Read a virtual line's ECBN settings
|
|
552
|
+
wxcli emergency-services show-emergency-callback-number-virtual-lines Y2lzY29...virtualLineId
|
|
553
|
+
|
|
554
|
+
# Set a virtual line to use the location ECBN
|
|
555
|
+
wxcli emergency-services update-emergency-callback-number-virtual-lines Y2lzY29...virtualLineId \
|
|
556
|
+
--json-body '{"selected": "LOCATION_ECBN"}'
|
|
557
|
+
|
|
558
|
+
# Check virtual line ECBN dependencies
|
|
559
|
+
wxcli emergency-services show-dependencies-emergency-callback-number-3 Y2lzY29...virtualLineId
|
|
560
|
+
|
|
561
|
+
# --- Hunt Group ECBN Dependencies ---
|
|
562
|
+
|
|
563
|
+
# Check hunt group ECBN dependencies (read-only -- no update for hunt groups)
|
|
564
|
+
wxcli emergency-services show-dependencies-emergency-callback-number Y2lzY29...huntGroupId
|
|
565
|
+
|
|
566
|
+
# --- ECBN Available Numbers ---
|
|
567
|
+
|
|
568
|
+
# List available ECBN numbers for a person
|
|
569
|
+
wxcli user-settings list-available-numbers-emergency-callback-number Y2lzY29...personId
|
|
570
|
+
|
|
571
|
+
# List available ECBN numbers for a workspace
|
|
572
|
+
wxcli workspace-settings list-available-numbers-emergency-callback-number Y2lzY29...workspaceId
|
|
573
|
+
|
|
574
|
+
# List available ECBN numbers for a virtual line
|
|
575
|
+
wxcli virtual-line-settings list-available-numbers-emergency-callback-number Y2lzY29...virtualLineId
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
---
|
|
579
|
+
|
|
580
|
+
## 4. E911 Compliance Checklist
|
|
581
|
+
|
|
582
|
+
To be fully compliant with Kari's Law and RAY BAUM's Act, an organization should:
|
|
583
|
+
|
|
584
|
+
### Kari's Law (Emergency Call Notifications)
|
|
585
|
+
|
|
586
|
+
- [ ] Enable `emergency_call_notification_enabled` at the org level
|
|
587
|
+
- [ ] Set `allow_email_notification_all_location_enabled` to `True` (covers all locations)
|
|
588
|
+
- [ ] Configure `email_address` to a monitored mailbox (e.g., security, facilities)
|
|
589
|
+
- [ ] Optionally configure location-level notification overrides via `/telephony/config/locations/{locationId}/emergencyCallNotification` (separate from org-level settings; the location-level GET also returns the org-level settings in an `organization` object for reference)
|
|
590
|
+
|
|
591
|
+
### RAY BAUM's Act (Dispatchable Location)
|
|
592
|
+
|
|
593
|
+
- [ ] Every location has a validated emergency address (use `lookup_for_location` before `add_to_location`)
|
|
594
|
+
- [ ] Multi-building/multi-floor locations have per-number emergency addresses (use `update_for_phone_number`)
|
|
595
|
+
- [ ] All users with DIDs have `DIRECT_LINE` ECBN (default for users with phone numbers)
|
|
596
|
+
- [ ] Extension-only users have `LOCATION_ECBN` or `LOCATION_MEMBER_NUMBER` configured
|
|
597
|
+
- [ ] Virtual lines that can place calls have ECBN configured
|
|
598
|
+
- [ ] Location ECBN quality is `RECOMMENDED` (not `NOT_RECOMMENDED` or `INVALID`)
|
|
599
|
+
- [ ] Run `ECBNApi.dependencies()` before changing any ECBN to avoid breaking other users' callbacks
|
|
600
|
+
|
|
601
|
+
### Ongoing Maintenance
|
|
602
|
+
|
|
603
|
+
- When adding new locations: validate and add emergency address, configure location ECBN
|
|
604
|
+
- When adding new users: verify ECBN is correctly set (especially extension-only users)
|
|
605
|
+
- When moving users between locations: update both emergency address and ECBN
|
|
606
|
+
- When deactivating numbers: check ECBN dependencies first -- other users may reference that number
|
|
607
|
+
|
|
608
|
+
---
|
|
609
|
+
|
|
610
|
+
## Source
|
|
611
|
+
|
|
612
|
+
- SDK source: `wxc_sdk/telephony/emergency_services/__init__.py`
|
|
613
|
+
- SDK source: `wxc_sdk/telephony/emergency_address/__init__.py`
|
|
614
|
+
- SDK source: `wxc_sdk/person_settings/ecbn.py`
|
|
615
|
+
- SDK source: `wxc_sdk/person_settings/common.py` (ApiSelector, URL routing for ECBN)
|
|
616
|
+
- U.S. Public Law 115-127 (Kari's Law) -- multi-line telephone system notification requirements
|
|
617
|
+
- RAY BAUM's Act Section 506 -- dispatchable location requirements for 911
|
|
618
|
+
|
|
619
|
+
---
|
|
620
|
+
|
|
621
|
+
## 5. Raw HTTP Endpoints
|
|
622
|
+
|
|
623
|
+
All endpoints below use the `api.session.rest_*` methods from `wxc_sdk`. URLs confirmed from working CLI implementations.
|
|
624
|
+
|
|
625
|
+
```python
|
|
626
|
+
from wxc_sdk import WebexSimpleApi
|
|
627
|
+
api = WebexSimpleApi(tokens='<token>')
|
|
628
|
+
BASE = "https://webexapis.com/v1"
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
### CLI Examples (RedSky)
|
|
632
|
+
|
|
633
|
+
```bash
|
|
634
|
+
# Retrieve RedSky account details for the org
|
|
635
|
+
wxcli emergency-services show
|
|
636
|
+
|
|
637
|
+
# Create a RedSky account
|
|
638
|
+
wxcli emergency-services create --email "admin@company.com"
|
|
639
|
+
|
|
640
|
+
# Update RedSky service settings (enable the service with company credentials)
|
|
641
|
+
wxcli emergency-services update \
|
|
642
|
+
--enabled \
|
|
643
|
+
--company-id "company_id" \
|
|
644
|
+
--secret "secret_key"
|
|
645
|
+
|
|
646
|
+
# Get org-level RedSky compliance status
|
|
647
|
+
wxcli emergency-services show-status-red-sky
|
|
648
|
+
|
|
649
|
+
# Update org-level RedSky compliance status
|
|
650
|
+
wxcli emergency-services update-status-red-sky \
|
|
651
|
+
--json-body '{"complianceStatus": "ROUTING_ENABLED"}'
|
|
652
|
+
|
|
653
|
+
# Get org compliance status with per-location breakdown
|
|
654
|
+
wxcli emergency-services show-compliance-status --max 1000
|
|
655
|
+
|
|
656
|
+
# Login to RedSky admin account
|
|
657
|
+
wxcli emergency-services login-to-a \
|
|
658
|
+
--email "admin@company.com" \
|
|
659
|
+
--password "password"
|
|
660
|
+
|
|
661
|
+
# Get a location's RedSky parameters
|
|
662
|
+
wxcli emergency-services show-red-sky Y2lzY29...locationId
|
|
663
|
+
|
|
664
|
+
# Get a location's RedSky compliance status
|
|
665
|
+
wxcli emergency-services show-status-red-sky-1 Y2lzY29...locationId
|
|
666
|
+
|
|
667
|
+
# Update a location's RedSky compliance status
|
|
668
|
+
wxcli emergency-services update-status-red-sky-1 Y2lzY29...locationId \
|
|
669
|
+
--json-body '{"complianceStatus": "ROUTING_ENABLED"}'
|
|
670
|
+
|
|
671
|
+
# Create a RedSky building address for a location
|
|
672
|
+
wxcli emergency-services create-building Y2lzY29...locationId \
|
|
673
|
+
--alerting-email "security@company.com"
|
|
674
|
+
|
|
675
|
+
# Update a RedSky building address for a location
|
|
676
|
+
wxcli emergency-services update-building Y2lzY29...locationId \
|
|
677
|
+
--json-body '{"alertingEmail": "new-security@company.com"}'
|
|
678
|
+
```
|
|
679
|
+
|
|
680
|
+
### Emergency Call Notifications (Org-Level)
|
|
681
|
+
|
|
682
|
+
#### Read Notification Settings
|
|
683
|
+
|
|
684
|
+
```
|
|
685
|
+
GET https://webexapis.com/v1/telephony/config/emergencyCallNotification
|
|
686
|
+
```
|
|
687
|
+
|
|
688
|
+
```python
|
|
689
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/emergencyCallNotification")
|
|
690
|
+
# Returns: {
|
|
691
|
+
# "emergencyCallNotificationEnabled": true,
|
|
692
|
+
# "allowEmailNotificationAllLocationEnabled": true,
|
|
693
|
+
# "emailAddress": "security@company.com"
|
|
694
|
+
# }
|
|
695
|
+
```
|
|
696
|
+
|
|
697
|
+
#### Update Notification Settings
|
|
698
|
+
|
|
699
|
+
```
|
|
700
|
+
PUT https://webexapis.com/v1/telephony/config/emergencyCallNotification
|
|
701
|
+
```
|
|
702
|
+
|
|
703
|
+
```python
|
|
704
|
+
body = {
|
|
705
|
+
"emergencyCallNotificationEnabled": True,
|
|
706
|
+
"allowEmailNotificationAllLocationEnabled": True,
|
|
707
|
+
"emailAddress": "security@company.com"
|
|
708
|
+
}
|
|
709
|
+
api.session.rest_put(f"{BASE}/telephony/config/emergencyCallNotification", json=body)
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
### Emergency Call Notifications (Location-Level)
|
|
713
|
+
|
|
714
|
+
#### Read Location Notification Settings
|
|
715
|
+
|
|
716
|
+
```
|
|
717
|
+
GET https://webexapis.com/v1/telephony/config/locations/{locationId}/emergencyCallNotification
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
```python
|
|
721
|
+
result = api.session.rest_get(
|
|
722
|
+
f"{BASE}/telephony/config/locations/{location_id}/emergencyCallNotification")
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
#### Update Location Notification Settings
|
|
726
|
+
|
|
727
|
+
```
|
|
728
|
+
PUT https://webexapis.com/v1/telephony/config/locations/{locationId}/emergencyCallNotification
|
|
729
|
+
```
|
|
730
|
+
|
|
731
|
+
```python
|
|
732
|
+
body = {
|
|
733
|
+
"emergencyCallNotificationEnabled": True,
|
|
734
|
+
"emailAddress": "floor3-security@company.com"
|
|
735
|
+
}
|
|
736
|
+
api.session.rest_put(
|
|
737
|
+
f"{BASE}/telephony/config/locations/{location_id}/emergencyCallNotification", json=body)
|
|
738
|
+
```
|
|
739
|
+
|
|
740
|
+
### Emergency Callback Number (ECBN) -- Person
|
|
741
|
+
|
|
742
|
+
#### Read Person ECBN
|
|
743
|
+
|
|
744
|
+
```
|
|
745
|
+
GET https://webexapis.com/v1/telephony/config/people/{personId}/emergencyCallbackNumber
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
```python
|
|
749
|
+
result = api.session.rest_get(
|
|
750
|
+
f"{BASE}/telephony/config/people/{person_id}/emergencyCallbackNumber")
|
|
751
|
+
# Returns: {
|
|
752
|
+
# "selected": "DIRECT_LINE",
|
|
753
|
+
# "directLineInfo": {"phoneNumber": "+15551234567", "effectiveLevel": "DIRECT_LINE", ...},
|
|
754
|
+
# "locationEcbnInfo": {...},
|
|
755
|
+
# "locationMemberInfo": {...},
|
|
756
|
+
# "defaultInfo": {"effectiveValue": "+15551230000", "quality": "RECOMMENDED"}
|
|
757
|
+
# }
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
#### Update Person ECBN
|
|
761
|
+
|
|
762
|
+
```
|
|
763
|
+
PUT https://webexapis.com/v1/telephony/config/people/{personId}/emergencyCallbackNumber
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
```python
|
|
767
|
+
body = {
|
|
768
|
+
"selected": "DIRECT_LINE"
|
|
769
|
+
# or "selected": "LOCATION_ECBN"
|
|
770
|
+
# or "selected": "LOCATION_MEMBER_NUMBER", "locationMemberId": "other_person_id"
|
|
771
|
+
}
|
|
772
|
+
api.session.rest_put(
|
|
773
|
+
f"{BASE}/telephony/config/people/{person_id}/emergencyCallbackNumber", json=body)
|
|
774
|
+
```
|
|
775
|
+
|
|
776
|
+
#### Read Person ECBN Dependencies
|
|
777
|
+
|
|
778
|
+
```
|
|
779
|
+
GET https://webexapis.com/v1/telephony/config/people/{personId}/emergencyCallbackNumber/dependencies
|
|
780
|
+
```
|
|
781
|
+
|
|
782
|
+
```python
|
|
783
|
+
result = api.session.rest_get(
|
|
784
|
+
f"{BASE}/telephony/config/people/{person_id}/emergencyCallbackNumber/dependencies")
|
|
785
|
+
# Returns: {
|
|
786
|
+
# "isLocationEcbnDefault": false,
|
|
787
|
+
# "isSelfEcbnDefault": true,
|
|
788
|
+
# "dependentMemberCount": 3
|
|
789
|
+
# }
|
|
790
|
+
```
|
|
791
|
+
|
|
792
|
+
### Emergency Callback Number (ECBN) -- Workspace
|
|
793
|
+
|
|
794
|
+
#### Read Workspace ECBN
|
|
795
|
+
|
|
796
|
+
```
|
|
797
|
+
GET https://webexapis.com/v1/telephony/config/workspaces/{workspaceId}/emergencyCallbackNumber
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
```python
|
|
801
|
+
result = api.session.rest_get(
|
|
802
|
+
f"{BASE}/telephony/config/workspaces/{workspace_id}/emergencyCallbackNumber")
|
|
803
|
+
```
|
|
804
|
+
|
|
805
|
+
#### Update Workspace ECBN
|
|
806
|
+
|
|
807
|
+
```
|
|
808
|
+
PUT https://webexapis.com/v1/telephony/config/workspaces/{workspaceId}/emergencyCallbackNumber
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
```python
|
|
812
|
+
body = {"selected": "DIRECT_LINE"}
|
|
813
|
+
api.session.rest_put(
|
|
814
|
+
f"{BASE}/telephony/config/workspaces/{workspace_id}/emergencyCallbackNumber", json=body)
|
|
815
|
+
```
|
|
816
|
+
|
|
817
|
+
#### Read Workspace ECBN Dependencies
|
|
818
|
+
|
|
819
|
+
```
|
|
820
|
+
GET https://webexapis.com/v1/telephony/config/workspaces/{workspaceId}/emergencyCallbackNumber/dependencies
|
|
821
|
+
```
|
|
822
|
+
|
|
823
|
+
```python
|
|
824
|
+
result = api.session.rest_get(
|
|
825
|
+
f"{BASE}/telephony/config/workspaces/{workspace_id}/emergencyCallbackNumber/dependencies")
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
### Emergency Callback Number (ECBN) -- Virtual Line
|
|
829
|
+
|
|
830
|
+
#### Read Virtual Line ECBN
|
|
831
|
+
|
|
832
|
+
```
|
|
833
|
+
GET https://webexapis.com/v1/telephony/config/virtualLines/{virtualLineId}/emergencyCallbackNumber
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
```python
|
|
837
|
+
result = api.session.rest_get(
|
|
838
|
+
f"{BASE}/telephony/config/virtualLines/{vl_id}/emergencyCallbackNumber")
|
|
839
|
+
```
|
|
840
|
+
|
|
841
|
+
#### Update Virtual Line ECBN
|
|
842
|
+
|
|
843
|
+
```
|
|
844
|
+
PUT https://webexapis.com/v1/telephony/config/virtualLines/{virtualLineId}/emergencyCallbackNumber
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
```python
|
|
848
|
+
body = {
|
|
849
|
+
"selected": "LOCATION_ECBN"
|
|
850
|
+
# or "selected": "LOCATION_MEMBER_NUMBER", "locationMemberId": "member_id"
|
|
851
|
+
}
|
|
852
|
+
api.session.rest_put(
|
|
853
|
+
f"{BASE}/telephony/config/virtualLines/{vl_id}/emergencyCallbackNumber", json=body)
|
|
854
|
+
```
|
|
855
|
+
|
|
856
|
+
#### Read Virtual Line ECBN Dependencies
|
|
857
|
+
|
|
858
|
+
```
|
|
859
|
+
GET https://webexapis.com/v1/telephony/config/virtualLines/{virtualLineId}/emergencyCallbackNumber/dependencies
|
|
860
|
+
```
|
|
861
|
+
|
|
862
|
+
```python
|
|
863
|
+
result = api.session.rest_get(
|
|
864
|
+
f"{BASE}/telephony/config/virtualLines/{vl_id}/emergencyCallbackNumber/dependencies")
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
### Emergency Callback Number (ECBN) -- Hunt Group
|
|
868
|
+
|
|
869
|
+
#### Read Hunt Group ECBN Dependencies
|
|
870
|
+
|
|
871
|
+
```
|
|
872
|
+
GET https://webexapis.com/v1/telephony/config/huntGroups/{huntGroupId}/emergencyCallbackNumber/dependencies
|
|
873
|
+
```
|
|
874
|
+
|
|
875
|
+
```python
|
|
876
|
+
result = api.session.rest_get(
|
|
877
|
+
f"{BASE}/telephony/config/huntGroups/{hg_id}/emergencyCallbackNumber/dependencies")
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
### RedSky E911 Integration
|
|
881
|
+
|
|
882
|
+
RedSky is a third-party E911 service provider. These endpoints manage the integration.
|
|
883
|
+
|
|
884
|
+
#### Get RedSky Account Details
|
|
885
|
+
|
|
886
|
+
```
|
|
887
|
+
GET https://webexapis.com/v1/telephony/config/redSky
|
|
888
|
+
```
|
|
889
|
+
|
|
890
|
+
```python
|
|
891
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/redSky")
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
#### Create RedSky Account
|
|
895
|
+
|
|
896
|
+
```
|
|
897
|
+
POST https://webexapis.com/v1/telephony/config/redSky
|
|
898
|
+
```
|
|
899
|
+
|
|
900
|
+
```python
|
|
901
|
+
body = {
|
|
902
|
+
"email": "admin@company.com",
|
|
903
|
+
"orgPrefix": "ACME",
|
|
904
|
+
# "partnerRedskyOrgId": "partner_org_id"
|
|
905
|
+
}
|
|
906
|
+
result = api.session.rest_post(f"{BASE}/telephony/config/redSky", json=body)
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
#### Get RedSky Service Settings
|
|
910
|
+
<!-- Updated by playbook session 2026-03-18 -->
|
|
911
|
+
|
|
912
|
+
```
|
|
913
|
+
GET https://webexapis.com/v1/telephony/config/redSky/serviceSettings
|
|
914
|
+
```
|
|
915
|
+
|
|
916
|
+
```python
|
|
917
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/redSky/serviceSettings")
|
|
918
|
+
# Returns: {"enabled": true, "companyId": "...", "secret": "...", ...}
|
|
919
|
+
```
|
|
920
|
+
|
|
921
|
+
#### Update RedSky Service Settings
|
|
922
|
+
|
|
923
|
+
```
|
|
924
|
+
PUT https://webexapis.com/v1/telephony/config/redSky/serviceSettings
|
|
925
|
+
```
|
|
926
|
+
|
|
927
|
+
```python
|
|
928
|
+
body = {
|
|
929
|
+
"enabled": True,
|
|
930
|
+
"companyId": "company_id",
|
|
931
|
+
"secret": "secret_key",
|
|
932
|
+
# "externalTenantEnabled": False,
|
|
933
|
+
# "email": "admin@company.com",
|
|
934
|
+
# "password": "password"
|
|
935
|
+
}
|
|
936
|
+
api.session.rest_put(f"{BASE}/telephony/config/redSky/serviceSettings", json=body)
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
#### RedSky Login
|
|
940
|
+
|
|
941
|
+
```
|
|
942
|
+
POST https://webexapis.com/v1/telephony/config/redSky/actions/login/invoke
|
|
943
|
+
```
|
|
944
|
+
|
|
945
|
+
```python
|
|
946
|
+
body = {
|
|
947
|
+
"email": "admin@company.com",
|
|
948
|
+
"password": "password",
|
|
949
|
+
# "redSkyOrgId": "org_id"
|
|
950
|
+
}
|
|
951
|
+
result = api.session.rest_post(f"{BASE}/telephony/config/redSky/actions/login/invoke", json=body)
|
|
952
|
+
```
|
|
953
|
+
|
|
954
|
+
#### RedSky Compliance Status (Org)
|
|
955
|
+
|
|
956
|
+
```
|
|
957
|
+
GET https://webexapis.com/v1/telephony/config/redSky/status
|
|
958
|
+
PUT https://webexapis.com/v1/telephony/config/redSky/status
|
|
959
|
+
GET https://webexapis.com/v1/telephony/config/redSky/complianceStatus
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
```python
|
|
963
|
+
# Get org status
|
|
964
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/redSky/status")
|
|
965
|
+
|
|
966
|
+
# Update org compliance status
|
|
967
|
+
body = {"complianceStatus": "ROUTING_ENABLED"}
|
|
968
|
+
api.session.rest_put(f"{BASE}/telephony/config/redSky/status", json=body)
|
|
969
|
+
|
|
970
|
+
# Get compliance status with per-location breakdown
|
|
971
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/redSky/complianceStatus", params={
|
|
972
|
+
"max": 1000,
|
|
973
|
+
# "order": "ASC|DSC"
|
|
974
|
+
})
|
|
975
|
+
```
|
|
976
|
+
|
|
977
|
+
#### RedSky Location Settings
|
|
978
|
+
|
|
979
|
+
```
|
|
980
|
+
GET https://webexapis.com/v1/telephony/config/locations/{locationId}/redSky
|
|
981
|
+
GET https://webexapis.com/v1/telephony/config/locations/{locationId}/redSky/status
|
|
982
|
+
PUT https://webexapis.com/v1/telephony/config/locations/{locationId}/redSky/status
|
|
983
|
+
```
|
|
984
|
+
|
|
985
|
+
```python
|
|
986
|
+
# Get location RedSky parameters
|
|
987
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/locations/{location_id}/redSky")
|
|
988
|
+
|
|
989
|
+
# Get location compliance status
|
|
990
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/locations/{location_id}/redSky/status")
|
|
991
|
+
|
|
992
|
+
# Update location compliance status
|
|
993
|
+
body = {"complianceStatus": "ROUTING_ENABLED"}
|
|
994
|
+
api.session.rest_put(f"{BASE}/telephony/config/locations/{location_id}/redSky/status", json=body)
|
|
995
|
+
```
|
|
996
|
+
|
|
997
|
+
#### RedSky Building Address
|
|
998
|
+
|
|
999
|
+
```
|
|
1000
|
+
POST https://webexapis.com/v1/telephony/config/locations/{locationId}/redSky/building
|
|
1001
|
+
PUT https://webexapis.com/v1/telephony/config/locations/{locationId}/redSky/building
|
|
1002
|
+
```
|
|
1003
|
+
|
|
1004
|
+
```python
|
|
1005
|
+
# Create building address with alert email
|
|
1006
|
+
body = {"alertingEmail": "security@company.com"}
|
|
1007
|
+
result = api.session.rest_post(
|
|
1008
|
+
f"{BASE}/telephony/config/locations/{location_id}/redSky/building", json=body)
|
|
1009
|
+
|
|
1010
|
+
# Update building address
|
|
1011
|
+
api.session.rest_put(
|
|
1012
|
+
f"{BASE}/telephony/config/locations/{location_id}/redSky/building", json=body)
|
|
1013
|
+
```
|
|
1014
|
+
|
|
1015
|
+
### Emergency Address (PSTN)
|
|
1016
|
+
|
|
1017
|
+
These endpoints are in the PSTN API surface, not the emergency services surface. The SDK access path is `api.telephony.emergency_address`.
|
|
1018
|
+
|
|
1019
|
+
#### Lookup/Validate Emergency Address
|
|
1020
|
+
|
|
1021
|
+
```
|
|
1022
|
+
POST https://webexapis.com/v1/telephony/pstn/emergencyAddress/lookup
|
|
1023
|
+
```
|
|
1024
|
+
|
|
1025
|
+
```python
|
|
1026
|
+
body = {
|
|
1027
|
+
"locationId": "loc_id",
|
|
1028
|
+
"address": {
|
|
1029
|
+
"address1": "100 Main Street",
|
|
1030
|
+
"city": "San Jose",
|
|
1031
|
+
"state": "CA",
|
|
1032
|
+
"postalCode": "95110",
|
|
1033
|
+
"country": "US"
|
|
1034
|
+
}
|
|
1035
|
+
}
|
|
1036
|
+
result = api.session.rest_post(f"{BASE}/telephony/pstn/emergencyAddress/lookup", json=body)
|
|
1037
|
+
# Returns: list of SuggestedEmergencyAddress with corrections and/or errors
|
|
1038
|
+
```
|
|
1039
|
+
|
|
1040
|
+
#### Add Emergency Address to a Location
|
|
1041
|
+
|
|
1042
|
+
```
|
|
1043
|
+
POST https://webexapis.com/v1/telephony/pstn/emergencyAddress
|
|
1044
|
+
```
|
|
1045
|
+
|
|
1046
|
+
```python
|
|
1047
|
+
body = {
|
|
1048
|
+
"locationId": "loc_id",
|
|
1049
|
+
"address": {
|
|
1050
|
+
"address1": "100 Main Street",
|
|
1051
|
+
"address2": "Suite 400",
|
|
1052
|
+
"city": "San Jose",
|
|
1053
|
+
"state": "CA",
|
|
1054
|
+
"postalCode": "95110",
|
|
1055
|
+
"country": "US"
|
|
1056
|
+
}
|
|
1057
|
+
}
|
|
1058
|
+
result = api.session.rest_post(f"{BASE}/telephony/pstn/emergencyAddress", json=body)
|
|
1059
|
+
address_id = result.get("id")
|
|
1060
|
+
```
|
|
1061
|
+
|
|
1062
|
+
#### Update Emergency Address for a Location
|
|
1063
|
+
|
|
1064
|
+
```
|
|
1065
|
+
PUT https://webexapis.com/v1/telephony/pstn/emergencyAddress/{addressId}
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
```python
|
|
1069
|
+
body = {
|
|
1070
|
+
"locationId": "loc_id",
|
|
1071
|
+
"address": {
|
|
1072
|
+
"address1": "200 Main Street",
|
|
1073
|
+
"city": "San Jose",
|
|
1074
|
+
"state": "CA",
|
|
1075
|
+
"postalCode": "95110",
|
|
1076
|
+
"country": "US"
|
|
1077
|
+
}
|
|
1078
|
+
}
|
|
1079
|
+
api.session.rest_put(f"{BASE}/telephony/pstn/emergencyAddress/{address_id}", json=body)
|
|
1080
|
+
```
|
|
1081
|
+
|
|
1082
|
+
#### Update Emergency Address for a Phone Number
|
|
1083
|
+
|
|
1084
|
+
```
|
|
1085
|
+
PUT https://webexapis.com/v1/telephony/pstn/phoneNumbers/{phoneNumber}/emergencyAddress
|
|
1086
|
+
```
|
|
1087
|
+
|
|
1088
|
+
```python
|
|
1089
|
+
body = {
|
|
1090
|
+
"emergencyAddress": {
|
|
1091
|
+
"address1": "100 Main Street",
|
|
1092
|
+
"address2": "Floor 3",
|
|
1093
|
+
"city": "San Jose",
|
|
1094
|
+
"state": "CA",
|
|
1095
|
+
"postalCode": "95110",
|
|
1096
|
+
"country": "US"
|
|
1097
|
+
}
|
|
1098
|
+
}
|
|
1099
|
+
api.session.rest_put(
|
|
1100
|
+
f"{BASE}/telephony/pstn/phoneNumbers/{phone_number}/emergencyAddress", json=body)
|
|
1101
|
+
```
|
|
1102
|
+
|
|
1103
|
+
**Gotcha:** Passing an empty/None `emergencyAddress` deletes the custom address and reverts the number to the location's default.
|
|
1104
|
+
|
|
1105
|
+
---
|
|
1106
|
+
|
|
1107
|
+
## Gotchas (Cross-Cutting)
|
|
1108
|
+
|
|
1109
|
+
- **ECBN update commands use `--json-body` for the `selected` field.** The `selected` enum value (`DIRECT_LINE`, `LOCATION_ECBN`, `LOCATION_MEMBER_NUMBER`) is a body parameter, not a CLI flag. Always pass it via `--json-body '{"selected": "DIRECT_LINE"}'`.
|
|
1110
|
+
- **Always validate before adding an emergency address.** Use `wxcli pstn create <locationId>` (the lookup/validate endpoint) before `wxcli pstn create-emergency-address`. The PSAP database requires standardized addresses; the lookup normalizes your input and flags corrections.
|
|
1111
|
+
- **Passing null emergencyAddress deletes the per-number override.** When using `wxcli pstn update-emergency-address`, sending `--json-body '{"emergencyAddress": null}'` reverts the phone number to its location's default emergency address.
|
|
1112
|
+
- **Check ECBN dependencies before deactivating numbers.** Run `show-dependencies-emergency-callback-number-*` for the entity type before deactivating a number or changing ECBN. Other users may reference that number as their ECBN via `LOCATION_MEMBER_NUMBER`.
|
|
1113
|
+
- **Hunt groups only support dependency reads, not ECBN updates.** The `show-dependencies-emergency-callback-number` command (hunt group variant) is read-only. Hunt groups do not have a configurable ECBN -- they inherit from the location.
|
|
1114
|
+
- **RedSky commands are separate from native E911.** The `emergency-services show/create/update` commands (RedSky) are for third-party E911 integration and are distinct from the native Webex emergency call notification and ECBN commands. Not all orgs use RedSky.
|
|
1115
|
+
- **Location-level notification settings are separate from org-level.** The org-level `show-emergency-call-notification-config` and the location-level `show-emergency-call-notification-locations` are independent endpoints. Enabling at the org level with `allow-email-notification-all-location-enabled` covers all locations, but individual locations can have their own email addresses.
|
|
1116
|
+
|
|
1117
|
+
---
|
|
1118
|
+
|
|
1119
|
+
## See Also
|
|
1120
|
+
|
|
1121
|
+
- **[person-call-settings-behavior.md](person-call-settings-behavior.md)** — The ECBNApi is shared between person, workspace, and virtual line settings. That doc covers the same ECBN sub-API from the person-settings perspective, including how ECBN integrates with other call behavior settings.
|
|
1122
|
+
- **[virtual-lines.md](virtual-lines.md)** — Virtual lines that can place calls need ECBN configured. The `.ecbn` sub-API is listed in the virtual line call settings table there.
|