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.
Files changed (413) hide show
  1. wxcli/__init__.py +4 -0
  2. wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
  3. wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
  4. wxcli/_playbook/.claude/rules/cleanup.md +29 -0
  5. wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
  6. wxcli/_playbook/.claude/rules/org-health.md +14 -0
  7. wxcli/_playbook/.claude/settings.json +8 -0
  8. wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
  9. wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
  10. wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
  11. wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
  12. wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
  13. wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
  14. wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
  15. wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
  16. wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
  17. wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
  18. wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
  19. wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
  20. wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
  21. wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
  22. wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
  23. wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
  24. wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
  25. wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
  26. wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
  27. wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
  28. wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
  29. wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
  30. wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
  31. wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
  32. wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
  33. wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
  34. wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
  35. wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
  36. wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
  37. wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
  38. wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
  39. wxcli/_playbook/CLAUDE.md +373 -0
  40. wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
  41. wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
  42. wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
  43. wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
  44. wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
  45. wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
  46. wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
  47. wxcli/_playbook/docs/reference/admin-partner.md +357 -0
  48. wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
  49. wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
  50. wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
  51. wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
  52. wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
  53. wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
  54. wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
  55. wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
  56. wxcli/_playbook/docs/reference/authentication.md +965 -0
  57. wxcli/_playbook/docs/reference/call-control.md +1205 -0
  58. wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
  59. wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
  60. wxcli/_playbook/docs/reference/call-routing.md +2304 -0
  61. wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
  62. wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
  63. wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
  64. wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
  65. wxcli/_playbook/docs/reference/devices-core.md +1869 -0
  66. wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
  67. wxcli/_playbook/docs/reference/devices-platform.md +467 -0
  68. wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
  69. wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
  70. wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
  71. wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
  72. wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
  73. wxcli/_playbook/docs/reference/meetings-content.md +473 -0
  74. wxcli/_playbook/docs/reference/meetings-core.md +903 -0
  75. wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
  76. wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
  77. wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
  78. wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
  79. wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
  80. wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
  81. wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
  82. wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
  83. wxcli/_playbook/docs/reference/provisioning.md +1366 -0
  84. wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
  85. wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
  86. wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
  87. wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
  88. wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
  89. wxcli/_version.py +24 -0
  90. wxcli/auth.py +137 -0
  91. wxcli/commands/__init__.py +0 -0
  92. wxcli/commands/_registry.py +181 -0
  93. wxcli/commands/activation_email.py +103 -0
  94. wxcli/commands/admin_recordings.py +585 -0
  95. wxcli/commands/analytics.py +105 -0
  96. wxcli/commands/announcement_playlists.py +219 -0
  97. wxcli/commands/announcements.py +519 -0
  98. wxcli/commands/archive_users.py +36 -0
  99. wxcli/commands/attachment_actions.py +60 -0
  100. wxcli/commands/audit_events.py +83 -0
  101. wxcli/commands/authorizations.py +113 -0
  102. wxcli/commands/auto_attendant.py +642 -0
  103. wxcli/commands/broadworks_billing_reports.py +126 -0
  104. wxcli/commands/broadworks_enterprises.py +160 -0
  105. wxcli/commands/broadworks_subscribers.py +319 -0
  106. wxcli/commands/broadworks_workspaces.py +108 -0
  107. wxcli/commands/call_controls.py +1304 -0
  108. wxcli/commands/call_park.py +494 -0
  109. wxcli/commands/call_pickup.py +229 -0
  110. wxcli/commands/call_queue.py +1878 -0
  111. wxcli/commands/call_recording.py +707 -0
  112. wxcli/commands/call_routing.py +1610 -0
  113. wxcli/commands/call_settings_for_me_phase_5.py +212 -0
  114. wxcli/commands/caller_reputation.py +169 -0
  115. wxcli/commands/calling_service.py +305 -0
  116. wxcli/commands/cc_address_book.py +770 -0
  117. wxcli/commands/cc_agent_greetings.py +242 -0
  118. wxcli/commands/cc_agent_summaries.py +39 -0
  119. wxcli/commands/cc_agent_wellbeing.py +216 -0
  120. wxcli/commands/cc_agents.py +425 -0
  121. wxcli/commands/cc_ai_assistant.py +55 -0
  122. wxcli/commands/cc_ai_feature.py +294 -0
  123. wxcli/commands/cc_audio_files.py +149 -0
  124. wxcli/commands/cc_auto_csat.py +311 -0
  125. wxcli/commands/cc_aux_code.py +458 -0
  126. wxcli/commands/cc_business_hour.py +353 -0
  127. wxcli/commands/cc_call_monitoring.py +228 -0
  128. wxcli/commands/cc_callbacks.py +194 -0
  129. wxcli/commands/cc_campaign.py +212 -0
  130. wxcli/commands/cc_captures.py +39 -0
  131. wxcli/commands/cc_contact_list.py +169 -0
  132. wxcli/commands/cc_contact_number.py +295 -0
  133. wxcli/commands/cc_data_sources.py +235 -0
  134. wxcli/commands/cc_desktop_layout.py +380 -0
  135. wxcli/commands/cc_desktop_profile.py +322 -0
  136. wxcli/commands/cc_dial_number.py +511 -0
  137. wxcli/commands/cc_dial_plan.py +347 -0
  138. wxcli/commands/cc_dnc.py +101 -0
  139. wxcli/commands/cc_entry_point.py +545 -0
  140. wxcli/commands/cc_ewt.py +51 -0
  141. wxcli/commands/cc_flow.py +477 -0
  142. wxcli/commands/cc_global_vars.py +430 -0
  143. wxcli/commands/cc_holiday_list.py +335 -0
  144. wxcli/commands/cc_journey.py +1261 -0
  145. wxcli/commands/cc_legacy_flows.py +49 -0
  146. wxcli/commands/cc_multimedia_profile.py +436 -0
  147. wxcli/commands/cc_notification.py +51 -0
  148. wxcli/commands/cc_outdial_ani.py +604 -0
  149. wxcli/commands/cc_overrides.py +341 -0
  150. wxcli/commands/cc_queue.py +1083 -0
  151. wxcli/commands/cc_queue_stats.py +55 -0
  152. wxcli/commands/cc_realtime.py +51 -0
  153. wxcli/commands/cc_resource_collection.py +312 -0
  154. wxcli/commands/cc_search.py +46 -0
  155. wxcli/commands/cc_site.py +400 -0
  156. wxcli/commands/cc_skill.py +350 -0
  157. wxcli/commands/cc_skill_profile.py +289 -0
  158. wxcli/commands/cc_subscriptions.py +426 -0
  159. wxcli/commands/cc_summaries.py +130 -0
  160. wxcli/commands/cc_tasks.py +844 -0
  161. wxcli/commands/cc_team.py +325 -0
  162. wxcli/commands/cc_user_profiles.py +349 -0
  163. wxcli/commands/cc_users.py +701 -0
  164. wxcli/commands/cc_work_types.py +363 -0
  165. wxcli/commands/cdr.py +89 -0
  166. wxcli/commands/classifications.py +38 -0
  167. wxcli/commands/cleanup.py +1427 -0
  168. wxcli/commands/client_settings.py +72 -0
  169. wxcli/commands/conference.py +328 -0
  170. wxcli/commands/configure.py +72 -0
  171. wxcli/commands/converged_recordings.py +347 -0
  172. wxcli/commands/converged_recordings_export.py +310 -0
  173. wxcli/commands/cq_playlists.py +42 -0
  174. wxcli/commands/cucm.py +2794 -0
  175. wxcli/commands/cucm_config.py +129 -0
  176. wxcli/commands/customer_assist.py +373 -0
  177. wxcli/commands/data_sources.py +227 -0
  178. wxcli/commands/dect_devices.py +787 -0
  179. wxcli/commands/device_configurations.py +77 -0
  180. wxcli/commands/device_dynamic_settings.py +320 -0
  181. wxcli/commands/device_settings.py +1489 -0
  182. wxcli/commands/devices.py +280 -0
  183. wxcli/commands/domains.py +142 -0
  184. wxcli/commands/ecm.py +178 -0
  185. wxcli/commands/emergency_services.py +827 -0
  186. wxcli/commands/events.py +83 -0
  187. wxcli/commands/external_voicemail.py +52 -0
  188. wxcli/commands/groups.py +206 -0
  189. wxcli/commands/guest_management.py +76 -0
  190. wxcli/commands/hds.py +340 -0
  191. wxcli/commands/hot_desk.py +67 -0
  192. wxcli/commands/hot_desking_members.py +118 -0
  193. wxcli/commands/hot_desking_portal.py +124 -0
  194. wxcli/commands/hunt_group.py +577 -0
  195. wxcli/commands/hybrid_clusters.py +71 -0
  196. wxcli/commands/hybrid_connectors.py +67 -0
  197. wxcli/commands/identity_org.py +159 -0
  198. wxcli/commands/init_playbook.py +155 -0
  199. wxcli/commands/licenses.py +106 -0
  200. wxcli/commands/live_monitoring.py +40 -0
  201. wxcli/commands/location_call_handling.py +577 -0
  202. wxcli/commands/location_schedules.py +341 -0
  203. wxcli/commands/location_settings.py +1297 -0
  204. wxcli/commands/location_voicemail.py +494 -0
  205. wxcli/commands/locations.py +336 -0
  206. wxcli/commands/meeting_captions.py +110 -0
  207. wxcli/commands/meeting_chats.py +63 -0
  208. wxcli/commands/meeting_invitees.py +234 -0
  209. wxcli/commands/meeting_messages.py +28 -0
  210. wxcli/commands/meeting_participants.py +278 -0
  211. wxcli/commands/meeting_polls.py +111 -0
  212. wxcli/commands/meeting_preferences.py +515 -0
  213. wxcli/commands/meeting_qa.py +78 -0
  214. wxcli/commands/meeting_qualities.py +43 -0
  215. wxcli/commands/meeting_reports.py +101 -0
  216. wxcli/commands/meeting_session_types.py +105 -0
  217. wxcli/commands/meeting_site.py +57 -0
  218. wxcli/commands/meeting_slido.py +44 -0
  219. wxcli/commands/meeting_summaries.py +92 -0
  220. wxcli/commands/meeting_tracking_codes.py +233 -0
  221. wxcli/commands/meeting_transcripts.py +230 -0
  222. wxcli/commands/meetings.py +1997 -0
  223. wxcli/commands/memberships.py +164 -0
  224. wxcli/commands/messages.py +213 -0
  225. wxcli/commands/mode_management.py +244 -0
  226. wxcli/commands/my_call_settings.py +3577 -0
  227. wxcli/commands/numbers.py +405 -0
  228. wxcli/commands/operating_modes.py +410 -0
  229. wxcli/commands/org_contacts.py +284 -0
  230. wxcli/commands/org_health_cli.py +55 -0
  231. wxcli/commands/org_settings.py +71 -0
  232. wxcli/commands/organizations.py +83 -0
  233. wxcli/commands/paging_group.py +257 -0
  234. wxcli/commands/partner_admins.py +141 -0
  235. wxcli/commands/partner_reports.py +188 -0
  236. wxcli/commands/partner_tags.py +216 -0
  237. wxcli/commands/people.py +279 -0
  238. wxcli/commands/person_call_settings.py +71 -0
  239. wxcli/commands/pstn.py +280 -0
  240. wxcli/commands/recording_report.py +154 -0
  241. wxcli/commands/report_templates.py +38 -0
  242. wxcli/commands/reports.py +144 -0
  243. wxcli/commands/resource_group_memberships.py +160 -0
  244. wxcli/commands/resource_groups.py +67 -0
  245. wxcli/commands/roles.py +63 -0
  246. wxcli/commands/room_tabs.py +160 -0
  247. wxcli/commands/rooms.py +225 -0
  248. wxcli/commands/scim_bulk.py +46 -0
  249. wxcli/commands/scim_groups.py +246 -0
  250. wxcli/commands/scim_schemas.py +82 -0
  251. wxcli/commands/scim_users.py +283 -0
  252. wxcli/commands/security_audit.py +54 -0
  253. wxcli/commands/service_apps.py +51 -0
  254. wxcli/commands/single_number_reach.py +209 -0
  255. wxcli/commands/team_memberships.py +155 -0
  256. wxcli/commands/teams.py +153 -0
  257. wxcli/commands/ucm_profile.py +42 -0
  258. wxcli/commands/update.py +219 -0
  259. wxcli/commands/user_settings.py +5116 -0
  260. wxcli/commands/video_mesh.py +1090 -0
  261. wxcli/commands/virtual_extensions.py +502 -0
  262. wxcli/commands/virtual_line_settings.py +2072 -0
  263. wxcli/commands/webhooks.py +176 -0
  264. wxcli/commands/wholesale_billing_reports.py +147 -0
  265. wxcli/commands/wholesale_provisioning.py +523 -0
  266. wxcli/commands/workspace_locations.py +339 -0
  267. wxcli/commands/workspace_metrics.py +103 -0
  268. wxcli/commands/workspace_personalization.py +70 -0
  269. wxcli/commands/workspace_settings.py +3347 -0
  270. wxcli/commands/workspaces.py +279 -0
  271. wxcli/commands/xapi.py +114 -0
  272. wxcli/config.py +139 -0
  273. wxcli/errors.py +77 -0
  274. wxcli/main.py +210 -0
  275. wxcli/migration/CLAUDE.md +106 -0
  276. wxcli/migration/__init__.py +1 -0
  277. wxcli/migration/advisory/CLAUDE.md +196 -0
  278. wxcli/migration/advisory/__init__.py +46 -0
  279. wxcli/migration/advisory/advisor.py +107 -0
  280. wxcli/migration/advisory/advisory_patterns.py +2552 -0
  281. wxcli/migration/advisory/recommendation_rules.py +835 -0
  282. wxcli/migration/cucm/CLAUDE.md +74 -0
  283. wxcli/migration/cucm/__init__.py +5 -0
  284. wxcli/migration/cucm/connection.py +265 -0
  285. wxcli/migration/cucm/discovery.py +225 -0
  286. wxcli/migration/cucm/extractors/__init__.py +1 -0
  287. wxcli/migration/cucm/extractors/announcements.py +92 -0
  288. wxcli/migration/cucm/extractors/base.py +90 -0
  289. wxcli/migration/cucm/extractors/device_profiles.py +98 -0
  290. wxcli/migration/cucm/extractors/devices.py +193 -0
  291. wxcli/migration/cucm/extractors/e911.py +103 -0
  292. wxcli/migration/cucm/extractors/features.py +309 -0
  293. wxcli/migration/cucm/extractors/helpers.py +73 -0
  294. wxcli/migration/cucm/extractors/informational.py +295 -0
  295. wxcli/migration/cucm/extractors/locations.py +221 -0
  296. wxcli/migration/cucm/extractors/moh.py +100 -0
  297. wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
  298. wxcli/migration/cucm/extractors/routing.py +493 -0
  299. wxcli/migration/cucm/extractors/shared_lines.py +146 -0
  300. wxcli/migration/cucm/extractors/templates.py +229 -0
  301. wxcli/migration/cucm/extractors/tier4.py +173 -0
  302. wxcli/migration/cucm/extractors/users.py +240 -0
  303. wxcli/migration/cucm/extractors/voicemail.py +243 -0
  304. wxcli/migration/cucm/extractors/workspaces.py +88 -0
  305. wxcli/migration/cucm/unity_connection.py +304 -0
  306. wxcli/migration/execute/CLAUDE.md +372 -0
  307. wxcli/migration/execute/__init__.py +303 -0
  308. wxcli/migration/execute/batch.py +277 -0
  309. wxcli/migration/execute/dependency.py +483 -0
  310. wxcli/migration/execute/engine.py +964 -0
  311. wxcli/migration/execute/handlers.py +2232 -0
  312. wxcli/migration/execute/planner.py +1939 -0
  313. wxcli/migration/execute/runtime.py +571 -0
  314. wxcli/migration/export/CLAUDE.md +49 -0
  315. wxcli/migration/export/__init__.py +8 -0
  316. wxcli/migration/export/csv_export.py +126 -0
  317. wxcli/migration/export/deployment_plan.py +479 -0
  318. wxcli/migration/export/json_export.py +60 -0
  319. wxcli/migration/models.py +941 -0
  320. wxcli/migration/phone_models.py +50 -0
  321. wxcli/migration/preflight/CLAUDE.md +52 -0
  322. wxcli/migration/preflight/__init__.py +89 -0
  323. wxcli/migration/preflight/checks.py +911 -0
  324. wxcli/migration/preflight/runner.py +293 -0
  325. wxcli/migration/rate_limiter.py +144 -0
  326. wxcli/migration/report/CLAUDE.md +245 -0
  327. wxcli/migration/report/__init__.py +7 -0
  328. wxcli/migration/report/appendix.py +2437 -0
  329. wxcli/migration/report/assembler.py +183 -0
  330. wxcli/migration/report/charts.py +263 -0
  331. wxcli/migration/report/executive.py +776 -0
  332. wxcli/migration/report/explainer.py +704 -0
  333. wxcli/migration/report/helpers.py +74 -0
  334. wxcli/migration/report/ingest.py +152 -0
  335. wxcli/migration/report/notice_templates.py +192 -0
  336. wxcli/migration/report/score.py +375 -0
  337. wxcli/migration/report/styles.py +1052 -0
  338. wxcli/migration/report/user_diff.py +1052 -0
  339. wxcli/migration/report/user_notice.py +425 -0
  340. wxcli/migration/state.py +139 -0
  341. wxcli/migration/store.py +860 -0
  342. wxcli/migration/transform/CLAUDE.md +107 -0
  343. wxcli/migration/transform/__init__.py +12 -0
  344. wxcli/migration/transform/analysis_pipeline.py +453 -0
  345. wxcli/migration/transform/analyzers/__init__.py +142 -0
  346. wxcli/migration/transform/analyzers/css_permission.py +189 -0
  347. wxcli/migration/transform/analyzers/css_routing.py +335 -0
  348. wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
  349. wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
  350. wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
  351. wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
  352. wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
  353. wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
  354. wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
  355. wxcli/migration/transform/analyzers/missing_data.py +300 -0
  356. wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
  357. wxcli/migration/transform/analyzers/shared_line.py +170 -0
  358. wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
  359. wxcli/migration/transform/analyzers/workspace_license.py +212 -0
  360. wxcli/migration/transform/cross_reference.py +1136 -0
  361. wxcli/migration/transform/cucm_pattern.py +246 -0
  362. wxcli/migration/transform/decisions.py +301 -0
  363. wxcli/migration/transform/e164.py +145 -0
  364. wxcli/migration/transform/engine.py +256 -0
  365. wxcli/migration/transform/mappers/CLAUDE.md +123 -0
  366. wxcli/migration/transform/mappers/__init__.py +76 -0
  367. wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
  368. wxcli/migration/transform/mappers/base.py +190 -0
  369. wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
  370. wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
  371. wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
  372. wxcli/migration/transform/mappers/css_mapper.py +868 -0
  373. wxcli/migration/transform/mappers/dect_mapper.py +367 -0
  374. wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
  375. wxcli/migration/transform/mappers/device_mapper.py +227 -0
  376. wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
  377. wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
  378. wxcli/migration/transform/mappers/e911_mapper.py +129 -0
  379. wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
  380. wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
  381. wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
  382. wxcli/migration/transform/mappers/line_mapper.py +310 -0
  383. wxcli/migration/transform/mappers/location_mapper.py +235 -0
  384. wxcli/migration/transform/mappers/moh_mapper.py +114 -0
  385. wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
  386. wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
  387. wxcli/migration/transform/mappers/routing_mapper.py +821 -0
  388. wxcli/migration/transform/mappers/snr_mapper.py +201 -0
  389. wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
  390. wxcli/migration/transform/mappers/user_mapper.py +264 -0
  391. wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
  392. wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
  393. wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
  394. wxcli/migration/transform/normalizers.py +2008 -0
  395. wxcli/migration/transform/pattern_converter.py +106 -0
  396. wxcli/migration/transform/pipeline.py +271 -0
  397. wxcli/migration/transform/rules.py +255 -0
  398. wxcli/org_health/CLAUDE.md +63 -0
  399. wxcli/org_health/__init__.py +7 -0
  400. wxcli/org_health/analyze.py +93 -0
  401. wxcli/org_health/checks.py +458 -0
  402. wxcli/org_health/collector.py +62 -0
  403. wxcli/org_health/models.py +78 -0
  404. wxcli/org_health/report.py +300 -0
  405. wxcli/output.py +101 -0
  406. wxcli-1.2.0.dist-info/METADATA +505 -0
  407. wxcli-1.2.0.dist-info/RECORD +413 -0
  408. wxcli-1.2.0.dist-info/WHEEL +5 -0
  409. wxcli-1.2.0.dist-info/entry_points.txt +2 -0
  410. wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
  411. wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
  412. wxcli-1.2.0.dist-info/scm_version.json +8 -0
  413. 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.