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,1426 @@
1
+ <!-- Updated by playbook session 2026-03-18 -->
2
+
3
+ # Devices & Workspaces — wxc_sdk Reference
4
+
5
+ ## Sources
6
+
7
+ - wxc_sdk v1.30.0
8
+ - OpenAPI spec: specs/webex-device.json
9
+ - developer.webex.com Workspace APIs
10
+
11
+ Workspaces represent physical places where people work — conference rooms, meeting spaces, lobbies, desks. Devices are associated with workspaces. The wxc_sdk provides four API modules for managing workspaces and their configurations.
12
+
13
+ **SDK access path:** `api.workspaces`, `api.workspace_settings`, `api.workspace_locations`, `api.workspace_personalization`
14
+
15
+ ---
16
+
17
+ ## Table of Contents
18
+
19
+ - [Workspaces API](#workspaces-api)
20
+ - [Data Models](#workspace-data-models)
21
+ - [WorkspacesApi Methods](#workspacesapi-methods)
22
+ - [Workspace Settings API](#workspace-settings-api)
23
+ - [Calling Settings Sub-APIs](#calling-settings-sub-apis)
24
+ - [Workspace Devices API](#workspace-devices-api)
25
+ - [Workspace Numbers API](#workspace-numbers-api)
26
+ - [Workspace Locations API (Legacy)](#workspace-locations-api-legacy)
27
+ - [Location Data Models](#workspace-location-data-models)
28
+ - [WorkspaceLocationApi Methods](#workspacelocationapi-methods)
29
+ - [Floor Management](#floor-management)
30
+ - [Workspace Personalization API](#workspace-personalization-api)
31
+ - [Required Scopes](#required-scopes)
32
+ - [Code Examples](#code-examples)
33
+ - [Raw HTTP](#raw-http)
34
+ - [CLI Examples](#cli-examples)
35
+ - [Workspaces CRUD](#workspaces-crud)
36
+ - [Workspace Settings](#workspace-settings)
37
+ - [Workspace Locations (Legacy)](#workspace-locations-legacy)
38
+
39
+ ---
40
+
41
+ ## Workspaces API
42
+
43
+ `api.workspaces` — CRUD operations on workspaces, including calling enablement, calendar integration, hotdesking, and device association.
44
+
45
+ ### Workspace Data Models
46
+
47
+ #### WorkSpaceType
48
+
49
+ Enum defining workspace purpose:
50
+
51
+ | Value | Enum Member | Description |
52
+ |-------|------------|-------------|
53
+ | `notSet` | `WorkSpaceType.not_set` | No workspace type set |
54
+ | `focus` | `WorkSpaceType.focus` | High concentration |
55
+ | `huddle` | `WorkSpaceType.huddle` | Brainstorm/collaboration |
56
+ | `meetingRoom` | `WorkSpaceType.meeting_room` | Dedicated meeting space |
57
+ | `open` | `WorkSpaceType.open` | Open space |
58
+ | `desk` | `WorkSpaceType.desk` | Individual desk |
59
+ | `other` | `WorkSpaceType.other` | Unspecified |
60
+
61
+ #### CallingType
62
+
63
+ Enum defining the calling configuration for a workspace:
64
+
65
+ | Value | Enum Member | Description |
66
+ |-------|------------|-------------|
67
+ | `freeCalling` | `CallingType.free` | Free Calling |
68
+ | `hybridCalling` | `CallingType.hybrid` | Hybrid Calling (on-premise CUCM + cloud) |
69
+ | `webexEdgeForDevices` | `CallingType.edge_for_devices` | Webex Edge For Devices |
70
+ | `thirdPartySipCalling` | `CallingType.third_party` | Third-party SIP calling |
71
+ | `webexCalling` | `CallingType.webex` | Webex Calling |
72
+ | `none` | `CallingType.none` | No calling |
73
+
74
+ #### CalendarType
75
+
76
+ Enum for calendar integration:
77
+
78
+ | Value | Enum Member | Description |
79
+ |-------|------------|-------------|
80
+ | `none` | `CalendarType.none` | No calendar |
81
+ | `google` | `CalendarType.google` | Google Calendar |
82
+ | `microsoft` | `CalendarType.microsoft` | Microsoft Exchange or Office 365 |
83
+
84
+ #### WorkspaceSupportedDevices
85
+
86
+ Enum for device types a workspace supports:
87
+
88
+ | Value | Enum Member | Description |
89
+ |-------|------------|-------------|
90
+ | `collaborationDevices` | `WorkspaceSupportedDevices.collaboration_devices` | Collaboration devices (Room/Board/Desk series) |
91
+ | `phones` | `WorkspaceSupportedDevices.phones` | MPP phones |
92
+
93
+ #### HotdeskingStatus
94
+
95
+ | Value | Enum Member |
96
+ |-------|------------|
97
+ | `on` | `HotdeskingStatus.on` |
98
+ | `off` | `HotdeskingStatus.off` |
99
+ | `none` | `HotdeskingStatus.none_` |
100
+
101
+ #### Calendar
102
+
103
+ ```python
104
+ class Calendar(ApiModel):
105
+ calendar_type: Optional[CalendarType] # alias: 'type'
106
+ email_address: Optional[str] # not set when type is 'none'
107
+ resource_group_id: Optional[str] # only for on-premise Microsoft calendar
108
+ ```
109
+
110
+ #### WorkspaceCalling
111
+
112
+ ```python
113
+ class WorkspaceCalling(ApiModel):
114
+ type: Optional[CallingType]
115
+ hybrid_calling: Optional[WorkspaceCallingHybridCalling] # only when type is hybridCalling
116
+ webex_calling: Optional[WorkspaceWebexCalling] # only when type is webexCalling
117
+ ```
118
+
119
+ **Important:** Due to a backend limitation, `webex_calling` details are never returned by the workspace GET API. They are only used when creating a workspace.
120
+
121
+ #### WorkspaceWebexCalling
122
+
123
+ ```python
124
+ class WorkspaceWebexCalling(ApiModel):
125
+ phone_number: Optional[str]
126
+ extension: Optional[str]
127
+ location_id: Optional[str] # Calling location ID
128
+ licenses: Optional[list[str]] # Webex Calling license IDs
129
+ ```
130
+
131
+ #### Workspace
132
+
133
+ The main workspace model with all fields:
134
+
135
+ ```python
136
+ class Workspace(ApiModel):
137
+ workspace_id: Optional[str] # alias: 'id'
138
+ org_id: Optional[str]
139
+ location_id: Optional[str] # preferred; use /locations API
140
+ workspace_location_id: Optional[str] # legacy; prefer location_id
141
+ floor_id: Optional[str]
142
+ display_name: Optional[str]
143
+ capacity: Optional[int]
144
+ workspace_type: Optional[WorkSpaceType] # alias: 'type'
145
+ sip_address: Optional[str]
146
+ created: Optional[datetime.datetime]
147
+ calling: Optional[WorkspaceCalling]
148
+ hybrid_calling: Optional[WorkspaceEmail]
149
+ calendar: Optional[Calendar]
150
+ notes: Optional[str]
151
+ hotdesking_status: Optional[HotdeskingStatus]
152
+ supported_devices: Optional[WorkspaceSupportedDevices]
153
+ device_hosted_meetings: Optional[DeviceHostedMeetings]
154
+ device_platform: Optional[DevicePlatform]
155
+ indoor_navigation: Optional[WorkspaceIndoorNavigation]
156
+ health: Optional[WorkspaceHealth]
157
+ devices: Optional[list[Device]]
158
+ capabilities: Optional[CapabilityMap]
159
+ planned_maintenance: Optional[WorkspacePlannedMaintenance]
160
+ ```
161
+
162
+ **Key constraints:**
163
+ - `location_id` and `supported_devices` **cannot be changed** once set on creation.
164
+ - `sip_address`, `created`, `health`, and `devices` are read-only.
165
+ - Use `Workspace.create(display_name="name")` as a factory for minimal create payloads.
166
+
167
+ #### CapabilityMap
168
+
169
+ Sensor/feature capabilities of workspace devices:
170
+
171
+ ```python
172
+ class CapabilityMap(ApiModel):
173
+ occupancy_detection: Optional[SupportAndConfiguredInfo]
174
+ presence_detection: Optional[SupportAndConfiguredInfo]
175
+ ambient_noise: Optional[SupportAndConfiguredInfo]
176
+ sound_level: Optional[SupportAndConfiguredInfo]
177
+ temperature: Optional[SupportAndConfiguredInfo]
178
+ air_quality: Optional[SupportAndConfiguredInfo]
179
+ relative_humidity: Optional[SupportAndConfiguredInfo]
180
+ hot_desking: Optional[SupportAndConfiguredInfo]
181
+ check_in: Optional[SupportAndConfiguredInfo]
182
+ adhoc_booking: Optional[SupportAndConfiguredInfo]
183
+ ```
184
+
185
+ Each `SupportAndConfiguredInfo` has `.supported` (bool) and `.configured` (bool).
186
+
187
+ #### WorkspaceHealth
188
+
189
+ ```python
190
+ class WorkspaceHealth(ApiModel):
191
+ level: Optional[WorkspaceHealthLevel] # error | warning | info | ok
192
+ issues: Optional[list[WorkspaceHealthIssue]]
193
+ ```
194
+
195
+ Each `WorkspaceHealthIssue` has: `id`, `created_at`, `title`, `description`, `recommended_action`, `level`.
196
+
197
+ ### WorkspacesApi Methods
198
+
199
+ #### list
200
+
201
+ ```python
202
+ def list(
203
+ self,
204
+ location_id: str = None,
205
+ workspace_location_id: str = None, # deprecated, use location_id
206
+ floor_id: str = None,
207
+ display_name: str = None,
208
+ capacity: int = None, # -1 = no capacity set
209
+ workspace_type: WorkSpaceType = None,
210
+ calling: CallingType = None,
211
+ supported_devices: WorkspaceSupportedDevices = None,
212
+ calendar: CalendarType = None,
213
+ device_hosted_meetings_enabled: bool = None,
214
+ device_platform: DevicePlatform = None,
215
+ health_level: WorkspaceHealthLevel = None,
216
+ include_devices: bool = None,
217
+ include_capabilities: bool = None,
218
+ planned_maintenance: MaintenanceMode = None,
219
+ custom_attribute: str = None,
220
+ org_id: str = None,
221
+ **params
222
+ ) -> Generator[Workspace, None, None]
223
+ ```
224
+
225
+ Returns a paginated generator of `Workspace` instances. Use `include_devices=True` to embed device details in the response.
226
+
227
+ #### create
228
+
229
+ ```python
230
+ def create(
231
+ self,
232
+ settings: Workspace,
233
+ org_id: str = None
234
+ ) -> Workspace
235
+ ```
236
+
237
+ Creates a new workspace. Omitting `calling` defaults to free calling. Omitting `calendar` defaults to no calendar.
238
+
239
+ **Webex Calling workspace requirements (non-hotdesk):**
240
+ - `location_id` is required
241
+ - Either `phone_number` or `extension` (or both) in `webex_calling` is required
242
+ - `licenses` list is optional; if omitted, the oldest suitable license is auto-applied
243
+
244
+ **Hot desk only workspace restrictions:**
245
+ - `phone_number` and `extension` are not applicable
246
+ - `device_hosted_meetings` and `calendar` are not applicable
247
+
248
+ #### details
249
+
250
+ ```python
251
+ def details(
252
+ self,
253
+ workspace_id: str,
254
+ include_devices: bool = None
255
+ ) -> Workspace
256
+ ```
257
+
258
+ Get full details for a single workspace by ID.
259
+
260
+ #### update
261
+
262
+ ```python
263
+ def update(
264
+ self,
265
+ workspace_id: str,
266
+ settings: Workspace
267
+ ) -> Workspace
268
+ ```
269
+
270
+ Updates a workspace. Include all fields from a GET response. Omitting optional fields (`capacity`, `type`, `notes`) clears them. `location_id`, `supported_devices`, `calendar`, and `calling` are preserved when omitted.
271
+
272
+ **Restrictions:**
273
+ - `calling` can only be updated if current type is `freeCalling`, `none`, `thirdPartySipCalling`, or `webexCalling`.
274
+ - Cannot change `calling` to `none`, `thirdPartySipCalling`, or `webexCalling` if devices are present.
275
+ - `location_id` and `supported_devices` cannot be changed after initial creation.
276
+
277
+ #### delete_workspace
278
+
279
+ ```python
280
+ def delete_workspace(
281
+ self,
282
+ workspace_id: str
283
+ ) -> None
284
+ ```
285
+
286
+ Deletes the workspace and all associated devices. Deleted devices must be reactivated.
287
+
288
+ #### capabilities
289
+
290
+ ```python
291
+ def capabilities(
292
+ self,
293
+ workspace_id: str
294
+ ) -> CapabilityMap
295
+ ```
296
+
297
+ Returns the capability map (sensor/feature status) for a workspace.
298
+
299
+ ---
300
+
301
+ ## Workspace Settings API
302
+
303
+ `api.workspace_settings` — calling-related settings for workspaces. Most settings mirror the person settings API; pass the workspace ID as the `person_id` parameter.
304
+
305
+ ### Calling Settings Sub-APIs
306
+
307
+ All sub-APIs below use `ApiSelector.workspace` internally. When calling methods on these, pass the **workspace ID** as the `person_id` parameter.
308
+
309
+ | Attribute | API Class | Purpose |
310
+ |-----------|-----------|---------|
311
+ | `anon_calls` | `AnonCallsApi` | Anonymous call rejection |
312
+ | `barge` | `BargeApi` | Barge-in settings |
313
+ | `call_bridge` | `CallBridgeApi` | Call bridge settings |
314
+ | `call_intercept` | `CallInterceptApi` | Call intercept |
315
+ | `call_policy` | `CallPolicyApi` | Call policy |
316
+ | `call_waiting` | `CallWaitingApi` | Call waiting |
317
+ | `caller_id` | `CallerIdApi` | Caller ID configuration |
318
+ | `dnd` | `DndApi` | Do Not Disturb |
319
+ | `ecbn` | `ECBNApi` | Emergency callback number |
320
+ | `forwarding` | `PersonForwardingApi` | Call forwarding rules |
321
+ | `monitoring` | `MonitoringApi` | Monitoring (busy lamp field) |
322
+ | `music_on_hold` | `MusicOnHoldApi` | Music on hold |
323
+ | `permissions_in` | `IncomingPermissionsApi` | Incoming call permissions |
324
+ | `permissions_out` | `OutgoingPermissionsApi` | Outgoing call permissions |
325
+ | `priority_alert` | `PriorityAlertApi` | Priority alert |
326
+ | `privacy` | `PrivacyApi` | Privacy settings |
327
+ | `push_to_talk` | `PushToTalkApi` | Push to talk |
328
+ | `selective_accept` | `SelectiveAcceptApi` | Selective call acceptance |
329
+ | `selective_forward` | `SelectiveForwardApi` | Selective call forwarding |
330
+ | `selective_reject` | `SelectiveRejectApi` | Selective call rejection |
331
+ | `sequential_ring` | `SequentialRingApi` | Sequential ring |
332
+ | `sim_ring` | `SimRingApi` | Simultaneous ring |
333
+ | `voicemail` | `VoicemailApi` | Voicemail settings |
334
+ | `available_numbers` | `AvailableNumbersApi` | Available number lookup |
335
+
336
+ ### Workspace Devices API
337
+
338
+ `api.workspace_settings.devices` — manages telephony devices assigned to a workspace.
339
+
340
+ **Base path:** `telephony/config/workspaces`
341
+
342
+ #### list
343
+
344
+ ```python
345
+ def list(
346
+ self,
347
+ workspace_id: str,
348
+ org_id: str = None
349
+ ) -> Generator[TelephonyDevice, None, None]
350
+ ```
351
+
352
+ Returns a paginated generator of `TelephonyDevice` instances for the workspace.
353
+
354
+ #### list_and_counts
355
+
356
+ ```python
357
+ def list_and_counts(
358
+ self,
359
+ workspace_id: str,
360
+ org_id: str = None
361
+ ) -> DeviceList
362
+ ```
363
+
364
+ Returns a `DeviceList` object with devices and count metadata (not paginated — single response).
365
+
366
+ #### modify_hoteling
367
+
368
+ ```python
369
+ def modify_hoteling(
370
+ self,
371
+ workspace_id: str,
372
+ hoteling: Hoteling,
373
+ org_id: str = None
374
+ ) -> None
375
+ ```
376
+
377
+ Modifies hoteling settings for workspace devices. The `Hoteling` model comes from `wxc_sdk.person_settings`.
378
+
379
+ ### Workspace Numbers API
380
+
381
+ `api.workspace_settings.numbers` — manages PSTN phone numbers associated with a workspace.
382
+
383
+ #### Data Models
384
+
385
+ ```python
386
+ class WorkspaceNumbers(ApiModel):
387
+ distinctive_ring_enabled: Optional[bool]
388
+ phone_numbers: list[UserNumber] # primary and alternate numbers
389
+ workspace: IdOnly # workspace identifier
390
+ location: IdAndName # location identifier + name
391
+ organization: IdAndName # org identifier + name
392
+ ```
393
+
394
+ ```python
395
+ class UpdateWorkspacePhoneNumber(ApiModel):
396
+ primary: Optional[bool] # marks as primary number
397
+ action: Optional[PatternAction] # 'ADD' or 'DELETE'
398
+ direct_number: Optional[str] # E.164 phone number
399
+ extension: Optional[str] # extension
400
+ ring_pattern: Optional[RingPattern] # ring pattern for this number
401
+ ```
402
+
403
+ #### read
404
+
405
+ ```python
406
+ def read(
407
+ self,
408
+ workspace_id: str,
409
+ org_id: str = None
410
+ ) -> WorkspaceNumbers
411
+ ```
412
+
413
+ Lists PSTN phone numbers associated with the workspace, including location and organization info.
414
+
415
+ #### update
416
+
417
+ ```python
418
+ def update(
419
+ self,
420
+ workspace_id: str,
421
+ phone_numbers: list[UpdateWorkspacePhoneNumber],
422
+ distinctive_ring_enabled: bool = None,
423
+ org_id: str = None
424
+ ) -> None
425
+ ```
426
+
427
+ Assign or unassign alternate phone numbers. Phone numbers must follow E.164 format (National format also accepted for US).
428
+
429
+ **Note:** This API is only available for **professional licensed** workspaces.
430
+
431
+ ---
432
+
433
+ ## Workspace Locations API (Legacy)
434
+
435
+ > **Deprecation warning:** The SDK logs `'use of the workspace locations API is not recommended. use locations API instead'` on every call. Prefer the `/locations` API (`api.locations`) for new integrations.
436
+
437
+ `api.workspace_locations` — manages legacy workspace location records (physical location metadata with coordinates).
438
+
439
+ ### Workspace Location Data Models
440
+
441
+ #### WorkspaceLocation
442
+
443
+ ```python
444
+ class WorkspaceLocation(ApiModel):
445
+ id: str
446
+ location_id: Optional[str]
447
+ display_name: str
448
+ address: str
449
+ country_code: str # ISO 3166-1
450
+ city_name: str
451
+ longitude: Optional[float]
452
+ latitude: Optional[float]
453
+ notes: Optional[str]
454
+ ```
455
+
456
+ Helper properties:
457
+ - `.id_uuid` — extracts the UUID portion from the base64-encoded ID
458
+ - `.org_id_uuid` — extracts the org UUID from the base64-encoded ID
459
+
460
+ #### WorkspaceLocationFloor
461
+
462
+ ```python
463
+ class WorkspaceLocationFloor(ApiModel):
464
+ id: str
465
+ location_id: str
466
+ floor_number: int
467
+ display_name: str
468
+ ```
469
+
470
+ ### WorkspaceLocationApi Methods
471
+
472
+ #### list
473
+
474
+ ```python
475
+ def list(
476
+ self,
477
+ display_name: str = None,
478
+ address: str = None,
479
+ country_code: str = None,
480
+ city_name: str = None,
481
+ org_id: str = None,
482
+ **params
483
+ ) -> Generator[WorkspaceLocation, None, None]
484
+ ```
485
+
486
+ #### create
487
+
488
+ ```python
489
+ def create(
490
+ self,
491
+ display_name: str,
492
+ address: str,
493
+ country_code: str,
494
+ latitude: float,
495
+ longitude: float,
496
+ city_name: str = None,
497
+ notes: str = None,
498
+ org_id: str = None
499
+ ) -> WorkspaceLocation
500
+ ```
501
+
502
+ #### details
503
+
504
+ ```python
505
+ def details(
506
+ self,
507
+ location_id: str,
508
+ org_id: str = None
509
+ ) -> WorkspaceLocation
510
+ ```
511
+
512
+ #### update
513
+
514
+ ```python
515
+ def update(
516
+ self,
517
+ location_id: str,
518
+ settings: WorkspaceLocation,
519
+ org_id: str = None
520
+ ) -> WorkspaceLocation
521
+ ```
522
+
523
+ Include all fields from a GET response. Omitting `city_name` or `notes` (setting to `None`) clears them.
524
+
525
+ #### delete
526
+
527
+ ```python
528
+ def delete(
529
+ self,
530
+ location_id: str,
531
+ org_id: str = None
532
+ ) -> None
533
+ ```
534
+
535
+ Workspaces associated with the deleted location lose their location but can be reassigned.
536
+
537
+ ### Floor Management
538
+
539
+ `api.workspace_locations.floors` — CRUD for floors within a workspace location.
540
+
541
+ #### floors.list
542
+
543
+ ```python
544
+ def list(
545
+ self,
546
+ location_id: str,
547
+ org_id: str = None
548
+ ) -> Generator[WorkspaceLocationFloor, None, None]
549
+ ```
550
+
551
+ #### floors.create
552
+
553
+ ```python
554
+ def create(
555
+ self,
556
+ location_id: str,
557
+ floor_number: int,
558
+ display_name: str = None,
559
+ org_id: str = None
560
+ ) -> WorkspaceLocationFloor
561
+ ```
562
+
563
+ #### floors.details
564
+
565
+ ```python
566
+ def details(
567
+ self,
568
+ location_id: str,
569
+ floor_id: str,
570
+ org_id: str = None
571
+ ) -> WorkspaceLocationFloor
572
+ ```
573
+
574
+ #### floors.update
575
+
576
+ ```python
577
+ def update(
578
+ self,
579
+ location_id: str,
580
+ floor_id: str,
581
+ settings: WorkspaceLocationFloor,
582
+ org_id: str = None
583
+ ) -> WorkspaceLocationFloor
584
+ ```
585
+
586
+ #### floors.delete
587
+
588
+ ```python
589
+ def delete(
590
+ self,
591
+ location_id: str,
592
+ floor_id: str,
593
+ org_id: str = None
594
+ ) -> None
595
+ ```
596
+
597
+ ---
598
+
599
+ ## Workspace Personalization API
600
+
601
+ `api.workspace_personalization` — enables Personal Mode on Webex Edge registered devices. This is a one-time migration operation from on-premise to cloud-registered personal mode.
602
+
603
+ **Applies only to Webex Edge registered devices.**
604
+
605
+ ### Prerequisites
606
+
607
+ - Workspace must contain a **single** Webex Edge registered, shared mode device
608
+ - Workspace must have **no calendars** configured
609
+ - The device must be **online**
610
+
611
+ ### personalize_a_workspace
612
+
613
+ ```python
614
+ def personalize_a_workspace(
615
+ self,
616
+ workspace_id: str,
617
+ email: str
618
+ ) -> None
619
+ ```
620
+
621
+ Initiates asynchronous personalization for the given user email. Returns a `Location` header with a URL pointing to the task status endpoint. The task typically completes in ~30 seconds.
622
+
623
+ ### get_personalization_task
624
+
625
+ ```python
626
+ def get_personalization_task(
627
+ self,
628
+ workspace_id: str
629
+ ) -> WorkspacePersonalizationTaskResponse
630
+ ```
631
+
632
+ Returns task status:
633
+ - While in progress: returns `Accepted` with `Retry-After` header
634
+ - On completion: returns `OK` with result body
635
+
636
+ ```python
637
+ class WorkspacePersonalizationTaskResponse(ApiModel):
638
+ success: Optional[bool]
639
+ error_description: Optional[str] # populated on failure
640
+ ```
641
+
642
+ ---
643
+
644
+ ## Required Scopes
645
+
646
+ | API Module | Read Scope | Write Scope |
647
+ |-----------|-----------|-------------|
648
+ | Workspaces | `spark-admin:workspaces_read` | `spark-admin:workspaces_write` |
649
+ | Workspace Settings (devices) | `spark-admin:telephony_config_read` | `spark-admin:telephony_config_write` |
650
+ | Workspace Settings (numbers) | `spark-admin:workspaces_read` | `spark-admin:workspaces_write` |
651
+ | Workspace Locations | `spark-admin:workspace_locations_read` | `spark-admin:workspace_locations_write` |
652
+ | Workspace Personalization | — | `spark-admin:devices_write`, `spark:xapi_commands`, `spark:xapi_statuses`, `Identity:one_time_password` |
653
+
654
+ Partner administrators can manage workspaces in other organizations by supplying `org_id`.
655
+
656
+ ---
657
+
658
+ ## Code Examples
659
+
660
+ ### Create a Webex Calling workspace with a 3rd-party phone
661
+
662
+ From `workspace_w_3rd_party.py` — the key provisioning logic:
663
+
664
+ ```python
665
+ from wxc_sdk.workspaces import (
666
+ CallingType, Workspace, WorkspaceCalling,
667
+ WorkspaceSupportedDevices, WorkspaceWebexCalling,
668
+ )
669
+ from wxc_sdk.common import DevicePlatform
670
+
671
+ # Build workspace settings
672
+ settings = Workspace(
673
+ location_id=location.location_id,
674
+ display_name="My Workspace",
675
+ type=WorkSpaceType.desk,
676
+ capacity=1,
677
+ supported_devices=WorkspaceSupportedDevices.phones,
678
+ device_platform=DevicePlatform.cisco,
679
+ calling=WorkspaceCalling(
680
+ type=CallingType.webex,
681
+ webex_calling=WorkspaceWebexCalling(
682
+ licenses=[calling_license_id],
683
+ extension="2001",
684
+ location_id=location.location_id,
685
+ ),
686
+ ),
687
+ )
688
+
689
+ # Create the workspace
690
+ workspace = await api.workspaces.create(settings=settings)
691
+
692
+ # Create a device in the workspace by MAC address
693
+ device = await api.devices.create_by_mac_address(
694
+ mac="DEADDEAD0001",
695
+ workspace_id=workspace.workspace_id,
696
+ model="Generic IPPhone Customer Managed",
697
+ password="generated_password",
698
+ )
699
+
700
+ # Get device details (SIP credentials, outbound proxy)
701
+ details = await api.telephony.devices.details(device_id=device.device_id)
702
+ sip_user = details.owner.sip_user_name
703
+ line_port = details.owner.line_port
704
+ outbound_proxy = details.proxy.outbound_proxy
705
+ ```
706
+
707
+ ### Add a user as secondary line on a workspace device
708
+
709
+ From `workspaces_and_users.py`:
710
+
711
+ ```python
712
+ from wxc_sdk.common import UserType
713
+ from wxc_sdk.telephony.devices import DeviceMember
714
+
715
+ # Find workspace by name
716
+ ws_list = await api.workspaces.list(display_name='Classroom')
717
+ target_ws = next(ws for ws in ws_list if ws.display_name == 'Classroom')
718
+
719
+ # Get devices in the workspace
720
+ ws_devices = await api.workspace_settings.devices.list(
721
+ workspace_id=target_ws.workspace_id
722
+ )
723
+
724
+ # Get current members for each device
725
+ device_members = await asyncio.gather(
726
+ *[api.telephony.devices.members(device_id=d.device_id) for d in ws_devices]
727
+ )
728
+
729
+ # Keep the workspace (place) membership as line 1, add user as line 2
730
+ for device, dmr in zip(ws_devices, device_members):
731
+ new_members = [m for m in dmr.members if m.member_type == UserType.place]
732
+ new_members.append(DeviceMember(member_id=user.person_id))
733
+ await api.telephony.devices.update_members(
734
+ device_id=device.device_id, members=new_members
735
+ )
736
+ await api.telephony.devices.apply_changes(device_id=device.device_id)
737
+ ```
738
+
739
+ ### List workspaces filtered by calling type
740
+
741
+ ```python
742
+ from wxc_sdk import WebexSimpleApi
743
+ from wxc_sdk.workspaces import CallingType
744
+
745
+ api = WebexSimpleApi(tokens=tokens)
746
+
747
+ # Get all Webex Calling workspaces with device details
748
+ for ws in api.workspaces.list(calling=CallingType.webex, include_devices=True):
749
+ print(f"{ws.display_name} — SIP: {ws.sip_address}")
750
+ if ws.devices:
751
+ for device in ws.devices:
752
+ print(f" Device: {device.display_name}")
753
+ ```
754
+
755
+ ### Read and update workspace phone numbers
756
+
757
+ ```python
758
+ # Read current numbers
759
+ ws_numbers = api.workspace_settings.numbers.read(workspace_id=workspace_id)
760
+ for num in ws_numbers.phone_numbers:
761
+ print(f" {num.external} (primary={num.primary})")
762
+
763
+ # Add an alternate number
764
+ from wxc_sdk.workspace_settings.numbers import UpdateWorkspacePhoneNumber
765
+ from wxc_sdk.common import PatternAction
766
+
767
+ api.workspace_settings.numbers.update(
768
+ workspace_id=workspace_id,
769
+ phone_numbers=[
770
+ UpdateWorkspacePhoneNumber(
771
+ action=PatternAction.add, # PatternAction.add = 'ADD', PatternAction.delete = 'DELETE'
772
+ direct_number="+14155551234",
773
+ primary=False,
774
+ )
775
+ ],
776
+ )
777
+ ```
778
+
779
+ ### Delete a workspace
780
+
781
+ ```python
782
+ # WARNING: Also deletes all associated devices (they must be reactivated)
783
+ await api.workspaces.delete_workspace(workspace_id=workspace.workspace_id)
784
+ ```
785
+
786
+ ---
787
+
788
+ ## Raw HTTP
789
+ <!-- Updated by playbook session 2026-03-18 -->
790
+
791
+ All workspace operations can be performed via raw HTTP using `api.session.rest_*()`. This is the preferred execution pattern -- wxc_sdk handles auth and session management, while you control the exact request.
792
+
793
+ ```python
794
+ from wxc_sdk import WebexSimpleApi
795
+ from wxc_sdk.rest import RestError
796
+
797
+ api = WebexSimpleApi()
798
+ BASE = "https://webexapis.com/v1"
799
+ ```
800
+
801
+ ### Workspaces CRUD
802
+
803
+ ```python
804
+ # ── List workspaces ──────────────────────────────────────────────
805
+ result = api.session.rest_get(f"{BASE}/workspaces", params={
806
+ "max": 1000,
807
+ "calling": "webexCalling", # filter by calling type
808
+ "includeDevices": "true", # embed device details
809
+ })
810
+ workspaces = result.get("items", []) # NOTE: response key is "items", NOT "workspaces"
811
+
812
+ # ── List with location filter ────────────────────────────────────
813
+ result = api.session.rest_get(f"{BASE}/workspaces", params={
814
+ "locationId": location_id,
815
+ "max": 1000,
816
+ })
817
+ workspaces = result.get("items", [])
818
+
819
+ # ── Get workspace details ────────────────────────────────────────
820
+ ws = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}")
821
+
822
+ # ── Get workspace details with devices ───────────────────────────
823
+ ws = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}", params={
824
+ "includeDevices": "true",
825
+ })
826
+
827
+ # ── Create a workspace ───────────────────────────────────────────
828
+ body = {
829
+ "displayName": "Lobby Phone",
830
+ "locationId": location_id,
831
+ "type": "desk",
832
+ "capacity": 1,
833
+ "supportedDevices": "phones",
834
+ "hotdeskingStatus": "off",
835
+ "calling": {
836
+ "type": "webexCalling",
837
+ "webexCalling": {
838
+ "extension": "2001",
839
+ "locationId": location_id,
840
+ "licenses": [calling_license_id],
841
+ },
842
+ },
843
+ }
844
+ result = api.session.rest_post(f"{BASE}/workspaces", json=body)
845
+ new_ws_id = result["id"]
846
+
847
+ # ── Update a workspace (full PUT -- include all fields) ──────────
848
+ ws = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}")
849
+ ws["displayName"] = "Lobby Phone (Updated)"
850
+ result = api.session.rest_put(f"{BASE}/workspaces/{workspace_id}", json=ws)
851
+
852
+ # ── Delete a workspace ───────────────────────────────────────────
853
+ # WARNING: Also deletes all associated devices (they must be reactivated)
854
+ api.session.rest_delete(f"{BASE}/workspaces/{workspace_id}")
855
+
856
+ # ── Get workspace capabilities ───────────────────────────────────
857
+ caps = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/capabilities")
858
+ ```
859
+
860
+ ### Workspace Call Settings (Features)
861
+
862
+ Workspace call settings use the `/workspaces/{workspaceId}/features/` path:
863
+
864
+ ```python
865
+ # ── Call Forwarding ──────────────────────────────────────────────
866
+ fwd = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/callForwarding")
867
+ body = {"callForwarding": {"always": {"enabled": True, "destination": "+15551234567"}}}
868
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/callForwarding", json=body)
869
+
870
+ # ── Call Waiting ─────────────────────────────────────────────────
871
+ cw = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/callWaiting")
872
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/callWaiting", json={"enabled": True})
873
+
874
+ # ── Caller ID ────────────────────────────────────────────────────
875
+ cid = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/callerId")
876
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/callerId", json={
877
+ "selected": "DIRECT_LINE",
878
+ "externalCallerIdNamePolicy": "DIRECT_LINE",
879
+ })
880
+
881
+ # ── Monitoring (BLF) ────────────────────────────────────────────
882
+ mon = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/monitoring")
883
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/monitoring", json={
884
+ "enableCallParkNotification": True,
885
+ })
886
+
887
+ # ── Numbers ──────────────────────────────────────────────────────
888
+ nums = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/numbers")
889
+
890
+ # ── Incoming Permission ──────────────────────────────────────────
891
+ perm_in = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/incomingPermission")
892
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/incomingPermission", json={
893
+ "useCustomEnabled": False,
894
+ "externalTransfer": "ALLOW_ALL_EXTERNAL",
895
+ })
896
+
897
+ # ── Outgoing Permission ─────────────────────────────────────────
898
+ perm_out = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/outgoingPermission")
899
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/outgoingPermission", json={
900
+ "useCustomEnabled": False,
901
+ })
902
+
903
+ # ── Outgoing Permission Access Codes ─────────────────────────────
904
+ codes = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/outgoingPermission/accessCodes")
905
+ access_codes = codes.get("accessCodes", [])
906
+
907
+ api.session.rest_post(f"{BASE}/workspaces/{workspace_id}/features/outgoingPermission/accessCodes", json={
908
+ "code": "1234",
909
+ "description": "Long distance override",
910
+ })
911
+
912
+ # ── Auto Transfer Numbers ────────────────────────────────────────
913
+ xfer = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/outgoingPermission/autoTransferNumbers")
914
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/outgoingPermission/autoTransferNumbers", json={
915
+ "useCustomTransferNumbers": True,
916
+ "autoTransferNumber1": "+15551234567",
917
+ })
918
+
919
+ # ── Call Intercept ───────────────────────────────────────────────
920
+ intercept = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/intercept")
921
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/intercept", json={
922
+ "enabled": True,
923
+ })
924
+ ```
925
+
926
+ ### Workspace Telephony Devices
927
+
928
+ Workspace telephony device operations use the `/telephony/config/workspaces/` path:
929
+
930
+ ```python
931
+ # ── List telephony devices for workspace ─────────────────────────
932
+ result = api.session.rest_get(f"{BASE}/telephony/config/workspaces/{workspace_id}/devices")
933
+ devices = result.get("devices", [])
934
+
935
+ # ── Modify hoteling ─────────────────────────────────────────────
936
+ api.session.rest_put(f"{BASE}/telephony/config/workspaces/{workspace_id}/devices/hoteling", json={
937
+ "enabled": True,
938
+ "limitGuestUse": True,
939
+ "guestHotelingLimit": 12,
940
+ })
941
+ ```
942
+
943
+ ### Raw HTTP Gotchas
944
+
945
+ 1. **Response key is `items` not `workspaces`** -- When listing workspaces, the response uses the generic `items` key, not `workspaces`. This differs from most telephony APIs that use a domain-specific key (e.g., `virtualLines`, `virtualExtensions`).
946
+ 2. **No auto-pagination** -- Use `max=1000` for the first page. The Workspaces API does not auto-paginate; check for a `next` link in the response if you have more than 1000 workspaces.
947
+ 3. **`includeDevices` and `includeCapabilities` are strings** -- Pass `"true"` not `True` in query params.
948
+ 4. **Two different base paths** -- CRUD and features use `/workspaces/{id}` and `/workspaces/{id}/features/*`. Telephony device operations use `/telephony/config/workspaces/{id}/devices`.
949
+ 5. **Update is full PUT** -- Omitting optional fields (`capacity`, `type`, `notes`) clears them. `locationId`, `supportedDevices`, `calendar`, and `calling` are preserved when omitted.
950
+ 6. **`webexCalling` details not returned on GET** -- The `calling.webexCalling` object is write-only (used on create). GET responses only include `calling.type`.
951
+ 7. **Migration tool populates workspace `call_settings` from CUCM common-area phones.** `WorkspaceMapper._extract_workspace_call_settings` translates CUCM `dndStatus`, `voiceMailProfile`, per-line `callForward*`, and `privacy` into Webex `/telephony/config/workspaces/{id}/{feature}` PUT bodies. Output is license-gated: Workspace-tier workspaces only keep `doNotDisturb` and `musicOnHold`; everything else requires Professional Workspace. See the spec at `docs/superpowers/specs/2026-04-10-workspace-call-settings.md`. Under the default license-tier inference, most workspaces land at Workspace tier, so only `doNotDisturb` actually migrates — `voicemail`, `callForwarding`, and `privacy` only activate when an operator overrides the tier to Professional Workspace during decision review.
952
+
953
+ ---
954
+
955
+ ## CLI Examples
956
+
957
+ Three `wxcli` command groups cover workspace operations:
958
+
959
+ | CLI Group | Commands | Purpose |
960
+ |-----------|----------|---------|
961
+ | `wxcli workspaces` | 6 | Workspace CRUD + capabilities |
962
+ | `wxcli workspace-settings` | 96 | Workspace call settings (mirrors person settings) |
963
+ | `wxcli workspace-locations` | 10 | Legacy workspace locations + floors |
964
+
965
+ ### Workspaces CRUD
966
+
967
+ ```bash
968
+ # List all workspaces (table output by default)
969
+ wxcli workspaces list
970
+
971
+ # List Webex Calling workspaces only
972
+ wxcli workspaces list --calling webexCalling
973
+
974
+ # List workspaces at a specific location
975
+ wxcli workspaces list --location-id <location_id>
976
+
977
+ # List workspaces with device details included
978
+ wxcli workspaces list --calling webexCalling --include-devices true
979
+
980
+ # Filter by workspace type (desk, meetingRoom, huddle, focus, open, other)
981
+ wxcli workspaces list --type meetingRoom
982
+
983
+ # Filter by supported device type
984
+ wxcli workspaces list --supported-devices phones
985
+
986
+ # Show workspace details (JSON output by default)
987
+ wxcli workspaces show <workspace_id>
988
+
989
+ # Show workspace details in table format
990
+ wxcli workspaces show <workspace_id> -o table
991
+
992
+ # Get workspace capabilities (sensor/feature support)
993
+ wxcli workspaces show-capabilities <workspace_id>
994
+
995
+ # Create a workspace (simple — flat options)
996
+ wxcli workspaces create --display-name "Lobby Phone" --type desk --capacity 1
997
+
998
+ # Create a Webex Calling workspace (requires --json-body for nested calling config)
999
+ wxcli workspaces create --json-body '{
1000
+ "displayName": "Conference Room B",
1001
+ "locationId": "<location_id>",
1002
+ "type": "meetingRoom",
1003
+ "capacity": 10,
1004
+ "supportedDevices": "phones",
1005
+ "calling": {
1006
+ "type": "webexCalling",
1007
+ "webexCalling": {
1008
+ "extension": "2050",
1009
+ "locationId": "<location_id>"
1010
+ }
1011
+ }
1012
+ }'
1013
+
1014
+ # Update a workspace display name
1015
+ wxcli workspaces update <workspace_id> --display-name "Lobby Phone (Updated)"
1016
+
1017
+ # Update workspace type and capacity
1018
+ wxcli workspaces update <workspace_id> --type meetingRoom --capacity 12
1019
+
1020
+ # Enable hotdesking on a workspace
1021
+ wxcli workspaces update <workspace_id> --hotdesking-status on
1022
+
1023
+ # Delete a workspace (prompts for confirmation)
1024
+ wxcli workspaces delete <workspace_id>
1025
+
1026
+ # Delete without confirmation prompt
1027
+ wxcli workspaces delete <workspace_id> --force
1028
+ ```
1029
+
1030
+ ### Workspace Settings
1031
+
1032
+ > **License note:** Most `/telephony/config/workspaces/{id}/` settings require **Professional** license. Basic workspaces only support `musicOnHold` and `doNotDisturb` at this path. For Basic workspaces, use the `/workspaces/{id}/features/` path family (callForwarding, callWaiting, callerId, intercept, monitoring). See the [endpoint access by license tier table](#key-patterns-and-gotchas) in Gotchas for the full matrix.
1033
+
1034
+ The `wxcli workspace-settings` group has 96 commands mirroring person call settings. All take a `workspace_id` as a positional argument.
1035
+
1036
+ #### Call Handling
1037
+
1038
+ ```bash
1039
+ # ── Call Forwarding ──────────────────────────────────────────────
1040
+ # Show call forwarding settings
1041
+ wxcli workspace-settings show <workspace_id>
1042
+
1043
+ # Enable always-forward to a destination (nested config requires --json-body)
1044
+ wxcli workspace-settings update <workspace_id> --json-body '{
1045
+ "callForwarding": {
1046
+ "always": {
1047
+ "enabled": true,
1048
+ "destination": "+15551234567",
1049
+ "ringReminderEnabled": true
1050
+ }
1051
+ }
1052
+ }'
1053
+
1054
+ # Enable busy-forward and no-answer-forward
1055
+ wxcli workspace-settings update <workspace_id> --json-body '{
1056
+ "callForwarding": {
1057
+ "busy": {"enabled": true, "destination": "+15559876543"},
1058
+ "noAnswer": {"enabled": true, "destination": "+15559876543", "numberOfRings": 5}
1059
+ },
1060
+ "businessContinuity": {"enabled": true, "destination": "+15550001111"}
1061
+ }'
1062
+
1063
+ # ── Call Waiting ─────────────────────────────────────────────────
1064
+ # Show call waiting settings
1065
+ wxcli workspace-settings show-call-waiting <workspace_id>
1066
+
1067
+ # Enable call waiting
1068
+ wxcli workspace-settings update-call-waiting <workspace_id> --enabled
1069
+
1070
+ # Disable call waiting
1071
+ wxcli workspace-settings update-call-waiting <workspace_id> --no-enabled
1072
+
1073
+ # ── Do Not Disturb ───────────────────────────────────────────────
1074
+ # Show DND settings (works on Basic + Professional)
1075
+ wxcli workspace-settings show-do-not-disturb <workspace_id>
1076
+
1077
+ # Enable DND with ring splash
1078
+ wxcli workspace-settings update-do-not-disturb <workspace_id> --enabled --ring-splash-enabled
1079
+
1080
+ # Disable DND
1081
+ wxcli workspace-settings update-do-not-disturb <workspace_id> --no-enabled
1082
+
1083
+ # ── Call Intercept ───────────────────────────────────────────────
1084
+ # Show intercept settings
1085
+ wxcli workspace-settings show-intercept <workspace_id>
1086
+
1087
+ # Enable call intercept (simple toggle)
1088
+ wxcli workspace-settings update-intercept <workspace_id> --enabled
1089
+
1090
+ # Enable with full config (intercept all incoming, allow outgoing to a destination)
1091
+ wxcli workspace-settings update-intercept <workspace_id> --json-body '{
1092
+ "enabled": true,
1093
+ "incoming": {
1094
+ "type": "INTERCEPT_ALL",
1095
+ "voicemailEnabled": true
1096
+ },
1097
+ "outgoing": {
1098
+ "type": "INTERCEPT_ALL",
1099
+ "transferEnabled": true,
1100
+ "destination": "+15551234567"
1101
+ }
1102
+ }'
1103
+
1104
+ # Disable call intercept
1105
+ wxcli workspace-settings update-intercept <workspace_id> --no-enabled
1106
+ ```
1107
+
1108
+ #### Voicemail & Media
1109
+
1110
+ ```bash
1111
+ # ── Voicemail (Professional license required) ────────────────────
1112
+ # Show voicemail settings
1113
+ wxcli workspace-settings show-voicemail <workspace_id>
1114
+
1115
+ # Enable voicemail with send-all-calls
1116
+ wxcli workspace-settings update-voicemail <workspace_id> --json-body '{
1117
+ "enabled": true,
1118
+ "sendAllCalls": {"enabled": false},
1119
+ "sendBusyCalls": {"enabled": true, "greeting": "DEFAULT"},
1120
+ "sendUnansweredCalls": {"enabled": true, "greeting": "DEFAULT", "numberOfRings": 6}
1121
+ }'
1122
+
1123
+ # Disable voicemail
1124
+ wxcli workspace-settings update-voicemail <workspace_id> --no-enabled
1125
+
1126
+ # ── Caller ID ────────────────────────────────────────────────────
1127
+ # Show caller ID settings
1128
+ wxcli workspace-settings list <workspace_id>
1129
+
1130
+ # Set caller ID to direct line
1131
+ wxcli workspace-settings update-caller-id <workspace_id> --selected DIRECT_LINE
1132
+
1133
+ # Set caller ID to location number
1134
+ wxcli workspace-settings update-caller-id <workspace_id> \
1135
+ --selected LOCATION_NUMBER \
1136
+ --external-caller-id-name-policy LOCATION
1137
+
1138
+ # Set caller ID to custom number
1139
+ wxcli workspace-settings update-caller-id <workspace_id> \
1140
+ --selected CUSTOM --custom-number "+15551234567"
1141
+
1142
+ # ── Music on Hold (works on Basic + Professional) ────────────────
1143
+ # Show music on hold settings
1144
+ wxcli workspace-settings show-music-on-hold <workspace_id>
1145
+
1146
+ # Enable music on hold with default greeting
1147
+ wxcli workspace-settings update-music-on-hold <workspace_id> --moh-enabled --greeting DEFAULT
1148
+
1149
+ # Enable with custom audio file
1150
+ wxcli workspace-settings update-music-on-hold <workspace_id> --json-body '{
1151
+ "mohEnabled": true,
1152
+ "greeting": "CUSTOM",
1153
+ "audioAnnouncementFile": {
1154
+ "id": "<announcement_file_id>",
1155
+ "fileName": "lobby-music.wav",
1156
+ "mediaFileType": "WAV",
1157
+ "level": "ORGANIZATION"
1158
+ }
1159
+ }'
1160
+
1161
+ # Disable music on hold
1162
+ wxcli workspace-settings update-music-on-hold <workspace_id> --no-moh-enabled
1163
+
1164
+ # ── Call Recording (Professional license required) ───────────────
1165
+ # Show call recording settings
1166
+ wxcli workspace-settings show-call-recordings <workspace_id>
1167
+
1168
+ # Enable always-on recording
1169
+ wxcli workspace-settings update-call-recordings <workspace_id> --enabled --record Always
1170
+
1171
+ # Enable on-demand recording with voicemail recording
1172
+ wxcli workspace-settings update-call-recordings <workspace_id> \
1173
+ --enabled --record "On Demand with User Initiated Start" --record-voicemail-enabled
1174
+
1175
+ # Enable with notification beep and start/stop announcements
1176
+ wxcli workspace-settings update-call-recordings <workspace_id> --json-body '{
1177
+ "enabled": true,
1178
+ "record": "Always",
1179
+ "recordVoicemailEnabled": true,
1180
+ "notification": {"type": "Beep", "enabled": true},
1181
+ "startStopAnnouncement": {
1182
+ "internalCallsEnabled": true,
1183
+ "pstnCallsEnabled": true
1184
+ }
1185
+ }'
1186
+
1187
+ # Disable call recording
1188
+ wxcli workspace-settings update-call-recordings <workspace_id> --no-enabled
1189
+ ```
1190
+
1191
+ #### Permissions
1192
+
1193
+ ```bash
1194
+ # ── Incoming Permissions ─────────────────────────────────────────
1195
+ # Show incoming permission settings
1196
+ wxcli workspace-settings show-incoming-permission <workspace_id>
1197
+
1198
+ # ── Outgoing Permissions ─────────────────────────────────────────
1199
+ # Show outgoing permission settings (table output by default)
1200
+ wxcli workspace-settings list-outgoing-permission <workspace_id>
1201
+
1202
+ # Show in JSON
1203
+ wxcli workspace-settings list-outgoing-permission <workspace_id> -o json
1204
+
1205
+ # ── Access Codes ─────────────────────────────────────────────────
1206
+ # List access codes for outgoing permissions
1207
+ wxcli workspace-settings list-access-codes <workspace_id>
1208
+
1209
+ # ── Anonymous Call Reject (Professional license required) ────────
1210
+ # Show anonymous call reject settings
1211
+ wxcli workspace-settings show-anonymous-call-reject <workspace_id>
1212
+
1213
+ # ── Barge In (Professional license required) ─────────────────────
1214
+ # Show barge-in settings
1215
+ wxcli workspace-settings show-barge-in <workspace_id>
1216
+
1217
+ # ── Privacy (Professional license required) ──────────────────────
1218
+ # Show privacy settings
1219
+ wxcli workspace-settings list-privacy <workspace_id>
1220
+ ```
1221
+
1222
+ #### Behavior & Numbers
1223
+
1224
+ ```bash
1225
+ # ── Monitoring (BLF) ────────────────────────────────────────────
1226
+ # Show monitoring settings
1227
+ wxcli workspace-settings show-monitoring <workspace_id>
1228
+
1229
+ # ── Numbers ──────────────────────────────────────────────────────
1230
+ # List phone numbers assigned to a workspace
1231
+ wxcli workspace-settings list-numbers <workspace_id>
1232
+
1233
+ # Assign an alternate number (nested config requires --json-body)
1234
+ wxcli workspace-settings update-numbers <workspace_id> --json-body '{
1235
+ "distinctiveRingEnabled": true,
1236
+ "phoneNumbers": [
1237
+ {
1238
+ "action": "ADD",
1239
+ "directNumber": "+15551234567",
1240
+ "extension": "2051",
1241
+ "primary": false
1242
+ }
1243
+ ]
1244
+ }'
1245
+
1246
+ # Remove a number
1247
+ wxcli workspace-settings update-numbers <workspace_id> --json-body '{
1248
+ "phoneNumbers": [
1249
+ {
1250
+ "action": "DELETE",
1251
+ "directNumber": "+15551234567"
1252
+ }
1253
+ ]
1254
+ }'
1255
+
1256
+ # List available phone numbers for a workspace
1257
+ wxcli workspace-settings list-available-numbers-workspaces
1258
+
1259
+ # List available ECBN numbers
1260
+ wxcli workspace-settings list-available-numbers-emergency-callback-number <workspace_id>
1261
+
1262
+ # List available call forwarding numbers
1263
+ wxcli workspace-settings list-available-numbers-call-forwarding <workspace_id>
1264
+ ```
1265
+
1266
+ #### Full Command Reference
1267
+
1268
+ All 96 `workspace-settings` commands:
1269
+
1270
+ | Category | Commands |
1271
+ |----------|----------|
1272
+ | **Call Forwarding** | `show`, `update` |
1273
+ | **Call Waiting** | `show-call-waiting`, `update-call-waiting` |
1274
+ | **Caller ID** | `list` (show), `update-caller-id` |
1275
+ | **Monitoring** | `show-monitoring`, `update-monitoring` |
1276
+ | **Numbers** | `list-numbers`, `update-numbers` |
1277
+ | **Incoming Permissions** | `show-incoming-permission`, `update-incoming-permission` |
1278
+ | **Outgoing Permissions** | `list-outgoing-permission`, `update-outgoing-permission` |
1279
+ | **Access Codes** | `list-access-codes`, `create`, `update-access-codes`, `delete`, `delete-access-codes` |
1280
+ | **Intercept** | `show-intercept`, `update-intercept`, `upload-call-intercept` |
1281
+ | **Auto Transfer Numbers** | `show-auto-transfer-numbers`, `update-auto-transfer-numbers` |
1282
+ | **Music on Hold** | `show-music-on-hold`, `update-music-on-hold` |
1283
+ | **Digit Patterns** | `list-digit-patterns`, `create-digit-patterns`, `show-digit-patterns`, `update-digit-patterns-outgoing-permission`, `update-digit-patterns-outgoing-permission-1`, `delete-digit-patterns-outgoing-permission`, `delete-digit-patterns-outgoing-permission-1` |
1284
+ | **Call Recording** | `show-call-recordings`, `update-call-recordings` |
1285
+ | **Anonymous Call Reject** | `show-anonymous-call-reject`, `update-anonymous-call-reject` |
1286
+ | **Barge In** | `show-barge-in`, `update-barge-in` |
1287
+ | **DND** | `show-do-not-disturb`, `update-do-not-disturb` |
1288
+ | **Call Bridge** | `show-call-bridge`, `update-call-bridge` |
1289
+ | **Push to Talk** | `list-push-to-talk`, `update-push-to-talk` |
1290
+ | **Privacy** | `list-privacy`, `update-privacy` |
1291
+ | **Voicemail** | `show-voicemail`, `update-voicemail`, `update-passcode`, `configure-busy-voicemail`, `configure-no-answer` |
1292
+ | **Sequential Ring** | `list-sequential-ring`, `update-sequential-ring`, `show-criteria-sequential-ring`, `update-criteria-sequential-ring`, `delete-criteria-sequential-ring`, `create-criteria-sequential-ring` |
1293
+ | **Call Policies** | `show-call-policies`, `update-call-policies` |
1294
+ | **Simultaneous Ring** | `list-simultaneous-ring`, `update-simultaneous-ring`, `show-criteria-simultaneous-ring`, `update-criteria-simultaneous-ring`, `delete-criteria-simultaneous-ring`, `create-criteria-simultaneous-ring` |
1295
+ | **Selective Reject** | `list-selective-reject`, `update-selective-reject`, `show-criteria-selective-reject`, `update-criteria-selective-reject`, `delete-criteria-selective-reject`, `create-criteria-selective-reject` |
1296
+ | **Selective Accept** | `list-selective-accept`, `update-selective-accept`, `show-criteria-selective-accept`, `update-criteria-selective-accept`, `delete-criteria-selective-accept`, `create-criteria-selective-accept` |
1297
+ | **Priority Alert** | `list-priority-alert`, `update-priority-alert`, `show-criteria-priority-alert`, `update-criteria-priority-alert`, `delete-criteria-priority-alert`, `create-criteria-priority-alert` |
1298
+ | **Selective Forward** | `list-selective-forward`, `update-selective-forward`, `show-criteria-selective-forward`, `update-criteria-selective-forward`, `delete-criteria-selective-forward`, `create-criteria-selective-forward` |
1299
+ | **Available Numbers** | `list-available-numbers-workspaces`, `list-available-numbers-emergency-callback-number`, `list-available-numbers-call-forwarding`, `list-available-numbers-call-intercept`, `list-available-numbers-fax-message`, `list-available-numbers-secondary` |
1300
+
1301
+ ### Workspace Locations (Legacy)
1302
+
1303
+ > **Deprecation note:** Workspace Locations is a legacy API. Prefer `wxcli locations` for new work.
1304
+
1305
+ ```bash
1306
+ # List all workspace locations
1307
+ wxcli workspace-locations list
1308
+
1309
+ # Filter by country
1310
+ wxcli workspace-locations list --country-code US
1311
+
1312
+ # Filter by city
1313
+ wxcli workspace-locations list --city-name "San Francisco"
1314
+
1315
+ # Filter by display name
1316
+ wxcli workspace-locations list --display-name "HQ"
1317
+
1318
+ # Show workspace location details
1319
+ wxcli workspace-locations show <location_id>
1320
+
1321
+ # List floors for a workspace location
1322
+ wxcli workspace-locations list-floors <location_id>
1323
+
1324
+ # Show floor details
1325
+ wxcli workspace-locations show-floors <location_id> <floor_id>
1326
+ ```
1327
+
1328
+ ---
1329
+
1330
+ ## Key Patterns and Gotchas
1331
+
1332
+ 1. **`location_id` vs `workspace_location_id`** — Always use `location_id` (from the `/locations` API). `workspace_location_id` is legacy and deprecated.
1333
+
1334
+ 2. **`supported_devices` and `location_id` are immutable** — Set correctly on creation; they cannot be changed afterward.
1335
+
1336
+ 3. **`webex_calling` details not returned on GET** — Due to a backend limitation, the `WorkspaceCalling.webex_calling` field is never populated in API responses. It is only used when creating a workspace.
1337
+
1338
+ 4. **Workspace settings mirror person settings** — Most `api.workspace_settings.*` sub-APIs are the same classes used for person settings but with `ApiSelector.workspace`. Pass the workspace ID as `person_id`.
1339
+
1340
+ 5. **Workspace Locations API is deprecated** — The SDK emits a warning on every call. Use `api.locations` instead for new code.
1341
+
1342
+ 6. **Hot desk workspaces** — When creating with `hotdesking_status=on`, `phone_number`, `extension`, `device_hosted_meetings`, and `calendar` are not applicable and will cause errors if provided.
1343
+
1344
+ 7. **License handling** — When creating a Webex Calling workspace, you can provide multiple license IDs; the oldest suitable one is applied. If omitted, auto-assigned from active subscriptions.
1345
+
1346
+ 8. **Device cleanup on workspace delete** — Deleting a workspace deletes all associated devices. Those devices must be reactivated to be reused.
1347
+
1348
+ 9. **Personalization is one-time** — The Workspace Personalization API is for migrating Edge devices from shared to personal mode. It requires the device to be online and the workspace to have no calendar configured.
1349
+
1350
+ 10. **Workspace call settings endpoint access by license tier.**
1351
+
1352
+ **Rule of thumb:** Under `/telephony/config/workspaces/{id}/`, only `musicOnHold` and `doNotDisturb` work on Basic. Everything else returns 405 "Invalid Professional Place". For Basic workspaces, use the `/workspaces/{id}/features/` path family instead (5 endpoints listed below).
1353
+
1354
+ | Endpoint Path | Basic | Professional | Notes |
1355
+ |---------------|:-----:|:------------:|-------|
1356
+ | **`/workspaces/{id}/features/` path (works on Basic)** | | | |
1357
+ | `/workspaces/{id}/features/callForwarding` | 200 | 200 | |
1358
+ | `/workspaces/{id}/features/callWaiting` | 200 | 200 | |
1359
+ | `/workspaces/{id}/features/callerId` | 200 | 200 | |
1360
+ | `/workspaces/{id}/features/intercept` | 200 | 200 | |
1361
+ | `/workspaces/{id}/features/monitoring` | 200 | 200 | |
1362
+ | `/workspaces/{id}/features/incomingPermission` | 200 | 200 | |
1363
+ | `/workspaces/{id}/features/outgoingPermission` | 200 | 200 | |
1364
+ | `/workspaces/{id}/features/voicemail` | 404 | N/A | Wrong path for voicemail; use `/telephony/config/` |
1365
+ | **`/telephony/config/workspaces/{id}/` path (Basic exceptions)** | | | |
1366
+ | `/telephony/config/workspaces/{id}/musicOnHold` | 200 | 200 | Basic exception |
1367
+ | `/telephony/config/workspaces/{id}/doNotDisturb` | 200 | 200 | Basic exception |
1368
+ | **`/telephony/config/workspaces/{id}/` path (Professional only)** | | | |
1369
+ | `/telephony/config/workspaces/{id}/anonymousCallReject` | 405 | 200 | |
1370
+ | `/telephony/config/workspaces/{id}/bargeIn` | 405 | 200 | |
1371
+ | `/telephony/config/workspaces/{id}/callBridge` | 405 | 200 | |
1372
+ | `/telephony/config/workspaces/{id}/callForwarding` | 405 | 200 | Duplicate of `/features/` path |
1373
+ | `/telephony/config/workspaces/{id}/callPolicies` | 405 | 200 | |
1374
+ | `/telephony/config/workspaces/{id}/callRecording` | 405 | 200 | |
1375
+ | `/telephony/config/workspaces/{id}/callWaiting` | 405 | 200 | Duplicate of `/features/` path |
1376
+ | `/telephony/config/workspaces/{id}/callerId` | 405 | 200 | Duplicate of `/features/` path |
1377
+ | `/telephony/config/workspaces/{id}/ecbn` | 405 | 200 | |
1378
+ | `/telephony/config/workspaces/{id}/intercept` | 405 | 200 | Duplicate of `/features/` path |
1379
+ | `/telephony/config/workspaces/{id}/monitoring` | 405 | 200 | Duplicate of `/features/` path |
1380
+ | `/telephony/config/workspaces/{id}/numbers` | 405 | 200 | |
1381
+ | `/telephony/config/workspaces/{id}/priorityAlert` | 405 | 200 | |
1382
+ | `/telephony/config/workspaces/{id}/privacy` | 405 | 200 | |
1383
+ | `/telephony/config/workspaces/{id}/pushToTalk` | 405 | 200 | |
1384
+ | `/telephony/config/workspaces/{id}/selectiveAccept` | 405 | 200 | |
1385
+ | `/telephony/config/workspaces/{id}/selectiveForward` | 405 | 200 | |
1386
+ | `/telephony/config/workspaces/{id}/selectiveReject` | 405 | 200 | |
1387
+ | `/telephony/config/workspaces/{id}/sequentialRing` | 405 | 200 | |
1388
+ | `/telephony/config/workspaces/{id}/simultaneousRing` | 405 | 200 | |
1389
+ | `/telephony/config/workspaces/{id}/voicemail` | 405 | 200 | |
1390
+
1391
+ ## CLI: `workspace-metrics` (Workspace Sensor Metrics)
1392
+
1393
+ The `workspace-metrics` CLI group retrieves environmental sensor data and usage duration metrics from workspace devices (RoomOS endpoints with sensors).
1394
+
1395
+ | Command | Description |
1396
+ |---------|-------------|
1397
+ | `workspace-metrics list` | Get workspace sensor metrics (sound, temperature, humidity, etc.) |
1398
+ | `workspace-metrics list-workspace-duration-metrics` | Get workspace usage duration metrics (time used, time booked) |
1399
+
1400
+ ```bash
1401
+ # Get temperature readings for a workspace (last 24 hours, daily aggregation)
1402
+ wxcli workspace-metrics list --workspace-id <workspace_id> --metric-name temperature --aggregation daily
1403
+
1404
+ # Get people count data in Fahrenheit
1405
+ wxcli workspace-metrics list --workspace-id <workspace_id> --metric-name peopleCount --aggregation hourly
1406
+
1407
+ # Get ambient noise levels with a time range
1408
+ wxcli workspace-metrics list --workspace-id <workspace_id> --metric-name ambientNoise \
1409
+ --from 2026-03-01T00:00:00Z --to 2026-03-21T00:00:00Z
1410
+
1411
+ # Get workspace usage duration (how long the room was actually used)
1412
+ wxcli workspace-metrics list-workspace-duration-metrics --workspace-id <workspace_id> \
1413
+ --measurement timeUsed --aggregation daily
1414
+
1415
+ # Get booked vs used comparison
1416
+ wxcli workspace-metrics list-workspace-duration-metrics --workspace-id <workspace_id> \
1417
+ --measurement timeBooked --aggregation daily
1418
+ ```
1419
+
1420
+ ---
1421
+
1422
+ ## See Also
1423
+
1424
+ - **[devices-core.md](devices-core.md)** — Device activation codes, MAC provisioning, and telephony device settings (members/lines, line key templates, layouts). Use that API for device-level operations after associating a device with a workspace.
1425
+ - **[devices-dect.md](devices-dect.md)** — DECT network and handset management, including DECT workspace associations and hot desking session management.
1426
+ - **[emergency-services.md](emergency-services.md)** — Emergency callback number (ECBN) configuration. The `ecbn` sub-API listed in the calling settings table above is documented in detail there.