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,1329 @@
1
+ # Person Call Settings — Permissions, Executive & Feature Access
2
+
3
+ Reference for managing incoming/outgoing call permissions, feature access controls, executive/assistant pairing, and call policy settings via `wxc_sdk`.
4
+
5
+ **Source files:**
6
+ - `wxc_sdk/person_settings/permissions_in.py`
7
+ - `wxc_sdk/person_settings/permissions_out.py`
8
+ - `wxc_sdk/person_settings/feature_access/__init__.py`
9
+ - `wxc_sdk/person_settings/executive/__init__.py`
10
+ - `wxc_sdk/person_settings/exec_assistant.py`
11
+ - `wxc_sdk/person_settings/call_policy.py`
12
+
13
+ ---
14
+
15
+ ## 1. Incoming Permissions
16
+
17
+ Controls who can call a person and how incoming external calls can be transferred.
18
+
19
+ **API class:** `IncomingPermissionsApi` (extends `PersonSettingsApiChild`)
20
+ - Feature path segment: `incomingPermission`
21
+ - Also used for: virtual lines, workspaces
22
+
23
+ ### Data Models
24
+
25
+ #### `ExternalTransfer` (enum)
26
+
27
+ | Value | Meaning |
28
+ |-------|---------|
29
+ | `ALLOW_ALL_EXTERNAL` | Allow transfer/forward for all external calls including transferred ones |
30
+ | `ALLOW_ONLY_TRANSFERRED_EXTERNAL` | Only allow transferred calls to be re-transferred/forwarded |
31
+ | `BLOCK_ALL_EXTERNAL` | Block all external calls from being transferred or forwarded |
32
+
33
+ #### `IncomingPermissions` (model)
34
+
35
+ | Field | Type | Description |
36
+ |-------|------|-------------|
37
+ | `use_custom_enabled` | `bool` | When `true`, person uses custom permissions instead of org defaults |
38
+ | `external_transfer` | `ExternalTransfer` | Transfer behavior for incoming external calls |
39
+ | `internal_calls_enabled` | `bool` | Whether internal calls are allowed to be received |
40
+ | `collect_calls_enabled` | `bool` | Whether collect calls are allowed to be received |
41
+
42
+ **Static helpers:**
43
+ - `IncomingPermissions.allow_all()` — custom enabled, allow all external, internal+collect enabled
44
+ - `IncomingPermissions.default()` — custom disabled, allow all external, internal+collect enabled
45
+
46
+ ### Methods
47
+
48
+ #### `read`
49
+
50
+ ```python
51
+ def read(self, entity_id: str, org_id: str = None) -> IncomingPermissions
52
+ ```
53
+
54
+ Retrieve incoming permission settings for a person/entity.
55
+
56
+ - **Scope:** `spark-admin:people_read` (full, user, or read-only admin)
57
+ - **Returns:** `IncomingPermissions`
58
+
59
+ #### `configure`
60
+
61
+ ```python
62
+ def configure(self, entity_id: str, settings: IncomingPermissions, org_id: str = None)
63
+ ```
64
+
65
+ Update incoming permission settings for a person/entity.
66
+
67
+ - **Scope:** `spark-admin:people_write` (admin) or `spark:people_write` (self)
68
+
69
+ ### Raw HTTP
70
+ <!-- Updated by playbook session 2026-03-18 -->
71
+
72
+ **Base URL:** `https://webexapis.com/v1`
73
+
74
+ | Operation | Method | Endpoint |
75
+ |-----------|--------|----------|
76
+ | Read | GET | `people/{personId}/features/incomingPermission` |
77
+ | Update | PUT | `people/{personId}/features/incomingPermission` |
78
+
79
+ ```python
80
+ from wxc_sdk import WebexSimpleApi
81
+ api = WebexSimpleApi()
82
+ BASE = "https://webexapis.com/v1"
83
+
84
+ # Read incoming permissions
85
+ result = api.session.rest_get(f"{BASE}/people/{person_id}/features/incomingPermission")
86
+ # Returns: {"useCustomEnabled": bool, "externalTransfer": str, "internalCallsEnabled": bool, "collectCallsEnabled": bool}
87
+
88
+ # Update incoming permissions
89
+ body = {
90
+ "useCustomEnabled": True,
91
+ "externalTransfer": "ALLOW_ALL_EXTERNAL",
92
+ "internalCallsEnabled": True,
93
+ "collectCallsEnabled": True
94
+ }
95
+ api.session.rest_put(f"{BASE}/people/{person_id}/features/incomingPermission", json=body)
96
+ ```
97
+
98
+ **CLI commands:** `show-incoming-permission`, `update-incoming-permission`
99
+
100
+ ### CLI Examples
101
+
102
+ ```bash
103
+ # Read incoming permission settings for a person
104
+ wxcli user-settings show-incoming-permission Y2lzY29...personId
105
+
106
+ # Enable custom incoming permissions — allow all external, enable internal + collect
107
+ wxcli user-settings update-incoming-permission Y2lzY29...personId \
108
+ --use-custom-enabled \
109
+ --external-transfer ALLOW_ALL_EXTERNAL \
110
+ --internal-calls-enabled \
111
+ --collect-calls-enabled
112
+
113
+ # Block all external call transfers
114
+ wxcli user-settings update-incoming-permission Y2lzY29...personId \
115
+ --use-custom-enabled \
116
+ --external-transfer BLOCK_ALL_EXTERNAL
117
+
118
+ # Reset to org defaults (disable custom permissions)
119
+ wxcli user-settings update-incoming-permission Y2lzY29...personId \
120
+ --no-use-custom-enabled
121
+
122
+ # Use --json-body for full control
123
+ wxcli user-settings update-incoming-permission Y2lzY29...personId \
124
+ --json-body '{"useCustomEnabled": true, "externalTransfer": "ALLOW_ONLY_TRANSFERRED_EXTERNAL", "internalCallsEnabled": true, "collectCallsEnabled": false}'
125
+ ```
126
+
127
+ ---
128
+
129
+ ## 2. Outgoing Permissions
130
+
131
+ Controls what types of outbound calls a person can place, with per-call-type actions, transfer number routing, access codes, and digit pattern overrides.
132
+
133
+ **API class:** `OutgoingPermissionsApi` (extends `PersonSettingsApiChild`)
134
+ - Feature path segment: `outgoingPermission`
135
+ - Also used for: user, workspace, location, virtual line settings
136
+ - Sub-APIs: `transfer_numbers`, `access_codes`, `digit_patterns`
137
+
138
+ > **Note:** `access_codes` is not available for locations. Use the telephony-level access codes API instead.
139
+
140
+ ### Data Models
141
+
142
+ #### `OutgoingPermissionCallType` (enum)
143
+
144
+ | Value | Description |
145
+ |-------|-------------|
146
+ | `INTERNAL_CALL` | Internal calls |
147
+ | `LOCAL` | Local calls (legacy, may be deprecated) |
148
+ | `TOLL_FREE` | Toll-free calls |
149
+ | `TOLL` | Toll calls (legacy, may be deprecated) |
150
+ | `NATIONAL` | National calls |
151
+ | `INTERNATIONAL` | International calls |
152
+ | `OPERATOR_ASSISTED` | Operator-assisted calls |
153
+ | `CHARGEABLE_DIRECTORY_ASSISTED` | Chargeable directory assistance |
154
+ | `SPECIAL_SERVICES_I` | Special services tier I |
155
+ | `SPECIAL_SERVICES_II` | Special services tier II |
156
+ | `PREMIUM_SERVICES_I` | Premium services tier I |
157
+ | `PREMIUM_SERVICES_II` | Premium services tier II |
158
+
159
+ #### `Action` (enum)
160
+
161
+ | Value | Meaning |
162
+ |-------|---------|
163
+ | `ALLOW` | Allow the call type |
164
+ | `BLOCK` | Block the call type |
165
+ | `AUTH_CODE` | Require an authorization code |
166
+ | `TRANSFER_NUMBER_1` | Auto-transfer to transfer number 1 |
167
+ | `TRANSFER_NUMBER_2` | Auto-transfer to transfer number 2 |
168
+ | `TRANSFER_NUMBER_3` | Auto-transfer to transfer number 3 |
169
+
170
+ #### `CallTypePermission` (model)
171
+
172
+ | Field | Type | Description |
173
+ |-------|------|-------------|
174
+ | `action` | `Action` | Action for this call type |
175
+ | `transfer_enabled` | `bool` | Whether transfer/forward is allowed for this call type |
176
+ | `is_call_type_restriction_enabled` | `Optional[bool]` | If `true`, restriction is system-enforced and cannot be changed |
177
+
178
+ #### `CallingPermissions` (model)
179
+
180
+ One `Optional[CallTypePermission]` field for each call type (e.g., `internal_call`, `local`, `toll_free`, `national`, `international`, etc.). Extra/unknown call types are allowed and auto-parsed.
181
+
182
+ **Key methods:**
183
+ - `for_call_type(call_type)` — look up permission by `OutgoingPermissionCallType` enum or string
184
+ - `permissions_dict()` — returns `dict[str, CallTypePermission]`
185
+ - `CallingPermissions.allow_all()` — all call types allowed with transfer enabled
186
+ - `CallingPermissions.default()` — all allowed except `international`, `premium_services_i`, `premium_services_ii` (blocked, transfer disabled)
187
+
188
+ #### `OutgoingPermissions` (model)
189
+
190
+ | Field | Type | Description |
191
+ |-------|------|-------------|
192
+ | `use_custom_enabled` | `Optional[bool]` | Use shared control for all outgoing categories |
193
+ | `use_custom_permissions` | `Optional[bool]` | Use specified outgoing calling permissions |
194
+ | `calling_permissions` | `Optional[CallingPermissions]` | Per-call-type permission settings |
195
+
196
+ > **Serialization note:** The API returns `callingPermissions` as a list of `{callType, action, transferEnabled}` objects. The SDK validator transforms this to/from the dict-based `CallingPermissions` model automatically. On `model_dump`, call types in `{'url_dialing', 'unknown', 'casual'}` are dropped by default.
197
+
198
+ #### `AutoTransferNumbers` (model)
199
+
200
+ | Field | Type | Description |
201
+ |-------|------|-------------|
202
+ | `use_custom_transfer_numbers` | `Optional[bool]` | Use custom transfer number settings |
203
+ | `auto_transfer_number1` | `Optional[str]` | Transfer destination for `TRANSFER_NUMBER_1` action |
204
+ | `auto_transfer_number2` | `Optional[str]` | Transfer destination for `TRANSFER_NUMBER_2` action |
205
+ | `auto_transfer_number3` | `Optional[str]` | Transfer destination for `TRANSFER_NUMBER_3` action |
206
+
207
+ **Property:** `configure_unset_numbers` — returns a copy with `None` numbers replaced by empty strings (required to clear a number via the API).
208
+
209
+ #### `DigitPattern` (model)
210
+
211
+ | Field | Type | Description |
212
+ |-------|------|-------------|
213
+ | `id` | `Optional[str]` | Unique identifier |
214
+ | `name` | `Optional[str]` | Unique name |
215
+ | `pattern` | `Optional[str]` | Digit pattern to match against dialed numbers |
216
+ | `action` | `Optional[Action]` | Action when pattern matches |
217
+ | `transfer_enabled` | `Optional[bool]` | Whether transfer/forward is allowed |
218
+
219
+ #### `DigitPatterns` (model)
220
+
221
+ | Field | Type | Description |
222
+ |-------|------|-------------|
223
+ | `use_custom_digit_patterns` | `Optional[bool]` | Use custom digit pattern settings |
224
+ | `digit_patterns` | `Optional[list[DigitPattern]]` | List of digit patterns |
225
+
226
+ #### `AuthCodes` (model)
227
+
228
+ | Field | Type | Description |
229
+ |-------|------|-------------|
230
+ | `use_custom_access_codes` | `Optional[bool]` | Use custom access code settings |
231
+ | `access_codes` | `Optional[list[AuthCode]]` | List of access codes (from `wxc_sdk.common.AuthCode`) |
232
+
233
+ ### Methods — Main Outgoing Permissions
234
+
235
+ #### `read`
236
+
237
+ ```python
238
+ def read(self, entity_id: str, org_id: str = None) -> OutgoingPermissions
239
+ ```
240
+
241
+ Retrieve outgoing calling permissions.
242
+
243
+ - **Scope:** `spark-admin:people_read` (full, user, or read-only admin)
244
+
245
+ #### `configure`
246
+
247
+ ```python
248
+ def configure(self, entity_id: str, settings: OutgoingPermissions,
249
+ drop_call_types: set[str] = None, org_id: str = None)
250
+ ```
251
+
252
+ Update outgoing calling permissions. The `drop_call_types` parameter excludes specific call type names from the update payload (defaults to `{'url_dialing', 'unknown', 'casual'}`).
253
+
254
+ - **Scope:** `spark-admin:people_write` (admin) or `spark:people_write` (self)
255
+
256
+ ### Methods — Transfer Numbers (`OutgoingPermissionsApi.transfer_numbers`)
257
+
258
+ > **Scope note:** The SDK docstrings list `workspaces_read/write` scopes for Transfer Numbers, but this is only correct for workspace entities. Per the OpenAPI spec, person-level transfer number endpoints use `spark-admin:telephony_config_read/write`.
259
+
260
+ #### `read`
261
+
262
+ ```python
263
+ def read(self, entity_id: str, org_id: str = None) -> AutoTransferNumbers
264
+ ```
265
+
266
+ - **Scope (person):** `spark-admin:telephony_config_read`
267
+ - **Scope (workspace):** `spark-admin:workspaces_read` or `spark:workspaces_read` (self)
268
+
269
+ #### `configure`
270
+
271
+ ```python
272
+ def configure(self, entity_id: str, settings: AutoTransferNumbers, org_id: str = None)
273
+ ```
274
+
275
+ - **Scope (person):** `spark-admin:telephony_config_write`
276
+ - **Scope (workspace):** `spark-admin:workspaces_write` or `spark:workspaces_write` (self)
277
+
278
+ ### Methods — Access Codes (`OutgoingPermissionsApi.access_codes`)
279
+
280
+ > Not available for locations — use the telephony-level access codes API.
281
+
282
+ > **Scope note:** The SDK docstrings list `workspaces_read/write` scopes for Access Codes, but this is only correct for workspace entities. Per the OpenAPI spec, person-level access code endpoints use `spark-admin:telephony_config_read/write`.
283
+
284
+ #### `read`
285
+
286
+ ```python
287
+ def read(self, entity_id: str, org_id: str = None) -> AuthCodes
288
+ ```
289
+
290
+ - **Scope (person):** `spark-admin:telephony_config_read`
291
+ - **Scope (workspace):** `spark-admin:workspaces_read` or `spark:workspaces_read`
292
+
293
+ #### `create`
294
+
295
+ ```python
296
+ def create(self, entity_id: str, code: str, description: str, org_id: str = None)
297
+ ```
298
+
299
+ Create a new access code.
300
+
301
+ - **Scope (person):** `spark-admin:telephony_config_write`
302
+ - **Scope (workspace):** `spark-admin:workspaces_write` or `spark:workspaces_write`
303
+
304
+ #### `modify`
305
+
306
+ ```python
307
+ def modify(self, entity_id: str, use_custom_access_codes: bool = None,
308
+ delete_codes: list[Union[str, AuthCode]] = None, org_id: str = None)
309
+ ```
310
+
311
+ Modify access code settings. Can toggle custom codes on/off and delete specific codes (by code string or `AuthCode` object).
312
+
313
+ - **Scope:** `spark-admin:telephony_config_write`
314
+
315
+ #### `delete`
316
+
317
+ ```python
318
+ def delete(self, entity_id: str, org_id: str = None)
319
+ ```
320
+
321
+ Delete **all** access codes for the entity.
322
+
323
+ - **Scope (person):** `spark-admin:telephony_config_write`
324
+ - **Scope (workspace):** `spark-admin:workspaces_write` or `spark:workspaces_write`
325
+
326
+ ### Methods — Digit Patterns (`OutgoingPermissionsApi.digit_patterns`)
327
+
328
+ #### `get_digit_patterns`
329
+
330
+ ```python
331
+ def get_digit_patterns(self, entity_id: str, org_id: str = None) -> DigitPatterns
332
+ ```
333
+
334
+ - **Scope:** `spark-admin:telephony_config_read`
335
+
336
+ #### `details`
337
+
338
+ ```python
339
+ def details(self, entity_id: str, digit_pattern_id: str, org_id: str = None) -> DigitPattern
340
+ ```
341
+
342
+ - **Scope:** `spark-admin:telephony_config_read`
343
+
344
+ #### `create`
345
+
346
+ ```python
347
+ def create(self, entity_id: str, pattern: DigitPattern, org_id: str = None) -> str
348
+ ```
349
+
350
+ Returns the new digit pattern ID.
351
+
352
+ - **Scope:** `spark-admin:telephony_config_write`
353
+
354
+ #### `update_category_control_settings`
355
+
356
+ ```python
357
+ def update_category_control_settings(self, entity_id: str,
358
+ use_custom_digit_patterns: bool = None,
359
+ org_id: str = None)
360
+ ```
361
+
362
+ Toggle whether custom digit patterns are used.
363
+
364
+ - **Scope:** `spark-admin:telephony_config_write`
365
+
366
+ #### `update`
367
+
368
+ ```python
369
+ def update(self, entity_id: str, settings: DigitPattern, org_id: str = None)
370
+ ```
371
+
372
+ Update an existing digit pattern. Uses `settings.id` to identify which pattern.
373
+
374
+ - **Scope:** `spark-admin:telephony_config_write`
375
+
376
+ #### `delete`
377
+
378
+ ```python
379
+ def delete(self, entity_id: str, digit_pattern_id: str, org_id: str = None)
380
+ ```
381
+
382
+ - **Scope:** `spark-admin:telephony_config_write`
383
+
384
+ #### `delete_all`
385
+
386
+ ```python
387
+ def delete_all(self, entity_id: str, org_id: str = None)
388
+ ```
389
+
390
+ Delete all digit patterns for the entity.
391
+
392
+ - **Scope:** `spark-admin:telephony_config_write`
393
+
394
+ ### Raw HTTP
395
+ <!-- Updated by playbook session 2026-03-18 -->
396
+
397
+ **Base URL:** `https://webexapis.com/v1`
398
+
399
+ | Operation | Method | Endpoint |
400
+ |-----------|--------|----------|
401
+ | Read outgoing permissions | GET | `people/{personId}/features/outgoingPermission` |
402
+ | Update outgoing permissions | PUT | `people/{personId}/features/outgoingPermission` |
403
+ | Read transfer numbers | GET | `people/{personId}/features/outgoingPermission/autoTransferNumbers` |
404
+ | Update transfer numbers | PUT | `people/{personId}/features/outgoingPermission/autoTransferNumbers` |
405
+ | Read access codes | GET | `people/{personId}/features/outgoingPermission/accessCodes` |
406
+ | Create access code | POST | `people/{personId}/features/outgoingPermission/accessCodes` |
407
+ | Modify access codes | PUT | `people/{personId}/features/outgoingPermission/accessCodes` |
408
+ | Delete all access codes | DELETE | `people/{personId}/features/outgoingPermission/accessCodes` |
409
+ | List digit patterns | GET | `telephony/config/people/{personId}/outgoingPermission/digitPatterns` |
410
+ | Create digit pattern | POST | `telephony/config/people/{personId}/outgoingPermission/digitPatterns` |
411
+ | Get digit pattern | GET | `telephony/config/people/{personId}/outgoingPermission/digitPatterns/{digitPatternId}` |
412
+ | Update digit pattern | PUT | `telephony/config/people/{personId}/outgoingPermission/digitPatterns/{digitPatternId}` |
413
+ | Delete digit pattern | DELETE | `telephony/config/people/{personId}/outgoingPermission/digitPatterns/{digitPatternId}` |
414
+ | Delete all digit patterns | DELETE | `telephony/config/people/{personId}/outgoingPermission/digitPatterns` |
415
+ | Update category control | PUT | `telephony/config/people/{personId}/outgoingPermission/digitPatterns` |
416
+
417
+ > **Note:** Main outgoing permissions and transfer numbers/access codes use the `people/{personId}/features/...` base path. Digit patterns use the `telephony/config/people/{personId}/...` base path. The transfer numbers endpoint path is `autoTransferNumbers` (not `transferNumbers`).
418
+
419
+ ```python
420
+ from wxc_sdk import WebexSimpleApi
421
+ api = WebexSimpleApi()
422
+ BASE = "https://webexapis.com/v1"
423
+
424
+ # Read outgoing permissions
425
+ result = api.session.rest_get(f"{BASE}/people/{person_id}/features/outgoingPermission")
426
+ # Returns: {"useCustomEnabled": bool, "useCustomPermissions": bool,
427
+ # "callingPermissions": [{"callType": str, "action": str, "transferEnabled": bool}, ...]}
428
+
429
+ # Update outgoing permissions (callingPermissions is a list, not a dict)
430
+ body = {
431
+ "useCustomEnabled": True,
432
+ "useCustomPermissions": True,
433
+ "callingPermissions": [
434
+ {"callType": "INTERNAL_CALL", "action": "ALLOW", "transferEnabled": True},
435
+ {"callType": "NATIONAL", "action": "ALLOW", "transferEnabled": True},
436
+ {"callType": "INTERNATIONAL", "action": "BLOCK", "transferEnabled": False},
437
+ {"callType": "PREMIUM_SERVICES_I", "action": "BLOCK", "transferEnabled": False},
438
+ {"callType": "PREMIUM_SERVICES_II", "action": "BLOCK", "transferEnabled": False}
439
+ ]
440
+ }
441
+ api.session.rest_put(f"{BASE}/people/{person_id}/features/outgoingPermission", json=body)
442
+
443
+ # Read/update transfer numbers
444
+ xfer = api.session.rest_get(f"{BASE}/people/{person_id}/features/outgoingPermission/autoTransferNumbers")
445
+ api.session.rest_put(f"{BASE}/people/{person_id}/features/outgoingPermission/autoTransferNumbers", json={
446
+ "useCustomTransferNumbers": True,
447
+ "autoTransferNumber1": "+15551234567"
448
+ })
449
+
450
+ # List digit patterns (note: telephony/config path)
451
+ patterns = api.session.rest_get(
452
+ f"{BASE}/telephony/config/people/{person_id}/outgoingPermission/digitPatterns"
453
+ )
454
+
455
+ # Create digit pattern
456
+ api.session.rest_post(
457
+ f"{BASE}/telephony/config/people/{person_id}/outgoingPermission/digitPatterns",
458
+ json={"name": "Block 1900", "pattern": "1900!", "action": "BLOCK", "transferEnabled": False}
459
+ )
460
+ ```
461
+
462
+ **CLI commands:** `show-outgoing-permission`, `update-outgoing-permission`
463
+
464
+ ### CLI Examples
465
+
466
+ ```bash
467
+ # --- Main Outgoing Permissions ---
468
+
469
+ # Read outgoing calling permissions for a person
470
+ wxcli user-settings list-outgoing-permission Y2lzY29...personId
471
+
472
+ # Read as JSON (includes callingPermissions array)
473
+ wxcli user-settings list-outgoing-permission Y2lzY29...personId -o json
474
+
475
+ # Enable custom outgoing permissions
476
+ wxcli user-settings update-outgoing-permission Y2lzY29...personId \
477
+ --use-custom-enabled --use-custom-permissions
478
+
479
+ # Block international and premium calls via --json-body
480
+ wxcli user-settings update-outgoing-permission Y2lzY29...personId \
481
+ --json-body '{"useCustomEnabled": true, "useCustomPermissions": true, "callingPermissions": [{"callType": "INTERNAL_CALL", "action": "ALLOW", "transferEnabled": true}, {"callType": "NATIONAL", "action": "ALLOW", "transferEnabled": true}, {"callType": "INTERNATIONAL", "action": "BLOCK", "transferEnabled": false}, {"callType": "PREMIUM_SERVICES_I", "action": "BLOCK", "transferEnabled": false}, {"callType": "PREMIUM_SERVICES_II", "action": "BLOCK", "transferEnabled": false}]}'
482
+
483
+ # --- Transfer Numbers ---
484
+
485
+ # Read auto-transfer numbers
486
+ wxcli user-settings show-auto-transfer-numbers Y2lzY29...personId
487
+
488
+ # Set transfer number 1
489
+ wxcli user-settings update-auto-transfer-numbers Y2lzY29...personId \
490
+ --use-custom-transfer-numbers \
491
+ --auto-transfer-number1 "+15551234567"
492
+
493
+ # --- Access Codes ---
494
+
495
+ # List access codes for a person
496
+ wxcli user-settings list-access-codes Y2lzY29...personId
497
+
498
+ # Create a new access code
499
+ wxcli user-settings create-access-codes Y2lzY29...personId \
500
+ --code "1234" --description "Conference room auth code"
501
+
502
+ # Modify access codes (e.g., toggle custom codes, delete specific codes)
503
+ wxcli user-settings update-access-codes Y2lzY29...personId \
504
+ --json-body '{"useCustomAccessCodes": true, "deleteCodes": ["1234"]}'
505
+
506
+ # Delete all access codes for a person
507
+ wxcli user-settings delete-access-codes Y2lzY29...personId --force
508
+
509
+ # --- Digit Patterns ---
510
+
511
+ # List all digit patterns
512
+ wxcli user-settings list-digit-patterns Y2lzY29...personId
513
+
514
+ # Create a digit pattern to block 1-900 numbers
515
+ wxcli user-settings create-digit-patterns Y2lzY29...personId \
516
+ --name "Block 1900" --pattern "1900!" --action BLOCK --transfer-enabled
517
+
518
+ # View a specific digit pattern
519
+ wxcli user-settings show-digit-patterns Y2lzY29...personId Y2lzY29...patternId
520
+
521
+ # Delete a specific digit pattern
522
+ wxcli user-settings delete-digit-patterns-outgoing-permission-1 Y2lzY29...personId Y2lzY29...patternId --force
523
+
524
+ # Delete all digit patterns
525
+ wxcli user-settings delete-digit-patterns-outgoing-permission Y2lzY29...personId --force
526
+ ```
527
+
528
+ ---
529
+
530
+ ## 3. Feature Access Controls
531
+
532
+ Controls which Webex Calling features end users can modify via User Hub, Webex client, or IP phone.
533
+
534
+ **API class:** `FeatureAccessApi` (extends `ApiChild`, base=`'telephony'`)
535
+
536
+ ### Data Models
537
+
538
+ #### `FeatureAccessLevel` (enum)
539
+
540
+ | Value | Meaning |
541
+ |-------|---------|
542
+ | `FULL_ACCESS` | User can modify this feature |
543
+ | `NO_ACCESS` | User cannot modify this feature |
544
+
545
+ #### `FeatureAccessSettings` (model)
546
+
547
+ All fields are `Optional[FeatureAccessLevel]`:
548
+
549
+ | Field | Controls access to |
550
+ |-------|--------------------|
551
+ | `anonymous_call_rejection` | Anonymous call rejection |
552
+ | `barge_in` | Barge In |
553
+ | `block_caller_id` | Block caller ID |
554
+ | `call_forwarding` | Call forwarding |
555
+ | `call_waiting` | Call waiting |
556
+ | `call_notify` | Call notify |
557
+ | `connected_line_identity` | Connected line identity |
558
+ | `executive` | Executive/Executive assistant |
559
+ | `hoteling` | Hoteling |
560
+ | `priority_alert` | Priority alert |
561
+ | `selectively_accept_calls` | Selectively accept calls |
562
+ | `selectively_reject_calls` | Selectively reject calls |
563
+ | `selectively_forward_calls` | Selectively forward calls |
564
+ | `sequential_ring` | Sequential ring |
565
+ | `simultaneous_ring` | Simultaneous ring |
566
+ | `single_number_reach` | Single number reach |
567
+ | `voicemail` | Voicemail feature |
568
+ | `send_calls_to_voicemail` | Send calls to voicemail |
569
+ | `voicemail_email_copy` | Email a copy of voicemail |
570
+ | `voicemail_fax_messaging` | Fax messaging |
571
+ | `voicemail_message_storage` | Message storage |
572
+ | `voicemail_notifications` | Voicemail notifications |
573
+ | `voicemail_transfer_number` | Transfer on "0" to another number |
574
+ | `generate_activation_code` | Allow end user to generate activation codes and delete phones |
575
+ | `voicemail_download` | Download voicemail via User Hub/Webex |
576
+
577
+ #### `UserFeatureAccessSettings` (model)
578
+
579
+ | Field | Type | Description |
580
+ |-------|------|-------------|
581
+ | `user_org_settings_permission_enabled` | `Optional[bool]` | Whether org-level settings apply to this user |
582
+ | `user_settings_permissions` | `Optional[FeatureAccessSettings]` | Per-user feature access overrides |
583
+
584
+ ### Methods
585
+
586
+ #### `read_default`
587
+
588
+ ```python
589
+ def read_default(self) -> FeatureAccessSettings
590
+ ```
591
+
592
+ Read the org-level default feature access settings applied to new users.
593
+
594
+ - **Scope:** `spark-admin:telephony_config_read`
595
+
596
+ #### `update_default`
597
+
598
+ ```python
599
+ def update_default(self, settings: FeatureAccessSettings)
600
+ ```
601
+
602
+ Update org-level default feature access settings.
603
+
604
+ - **Scope:** `spark-admin:telephony_config_write`
605
+
606
+ #### `read`
607
+
608
+ ```python
609
+ def read(self, person_id: str) -> UserFeatureAccessSettings
610
+ ```
611
+
612
+ Read feature access settings for a specific person.
613
+
614
+ - **Scope:** `spark-admin:telephony_config_read`
615
+
616
+ #### `update`
617
+
618
+ ```python
619
+ def update(self, person_id: str, settings: FeatureAccessSettings)
620
+ ```
621
+
622
+ Update feature access settings for a specific person.
623
+
624
+ - **Scope:** `spark-admin:telephony_config_write`
625
+
626
+ #### `reset`
627
+
628
+ ```python
629
+ def reset(self, person_id: str)
630
+ ```
631
+
632
+ Reset a person's feature access configuration back to org defaults. This is a POST to `.../actions/reset/invoke`.
633
+
634
+ - **Scope:** `spark-admin:telephony_config_write`
635
+
636
+ ### Raw HTTP
637
+ <!-- Updated by playbook session 2026-03-18 -->
638
+
639
+ **Base URL:** `https://webexapis.com/v1`
640
+
641
+ | Operation | Method | Endpoint |
642
+ |-----------|--------|----------|
643
+ | Read org defaults | GET | `telephony/config/featureAccessCodes` |
644
+ | Update org defaults | PUT | `telephony/config/featureAccessCodes` |
645
+ | Read person settings | GET | `telephony/config/people/{personId}/featureAccessCodes` |
646
+ | Update person settings | PUT | `telephony/config/people/{personId}/featureAccessCodes` |
647
+ | Reset to org defaults | POST | `telephony/config/people/{personId}/featureAccessCodes/actions/reset/invoke` |
648
+
649
+ ```python
650
+ from wxc_sdk import WebexSimpleApi
651
+ api = WebexSimpleApi()
652
+ BASE = "https://webexapis.com/v1"
653
+
654
+ # Read org-level default feature access settings
655
+ defaults = api.session.rest_get(f"{BASE}/telephony/config/featureAccessCodes")
656
+
657
+ # Read person-level feature access settings
658
+ result = api.session.rest_get(f"{BASE}/telephony/config/people/{person_id}/featureAccessCodes")
659
+ # Returns: {"userOrgSettingsPermissionEnabled": bool,
660
+ # "userSettingsPermissions": {"callForwarding": "FULL_ACCESS", "voicemail": "NO_ACCESS", ...}}
661
+
662
+ # Update person feature access
663
+ body = {
664
+ "callForwarding": "NO_ACCESS",
665
+ "simultaneousRing": "NO_ACCESS",
666
+ "voicemail": "FULL_ACCESS"
667
+ }
668
+ api.session.rest_put(f"{BASE}/telephony/config/people/{person_id}/featureAccessCodes", json=body)
669
+
670
+ # Reset person to org defaults
671
+ api.session.rest_post(
672
+ f"{BASE}/telephony/config/people/{person_id}/featureAccessCodes/actions/reset/invoke"
673
+ )
674
+ ```
675
+
676
+ ### CLI Examples
677
+
678
+ > **Note:** Feature access controls do not have dedicated `wxcli` commands yet. Use `curl` with the REST endpoints above, or use the wxc_sdk Python methods.
679
+
680
+ ```bash
681
+ # Read org-level default feature access settings
682
+ curl -s -H "Authorization: Bearer $WEBEX_TOKEN" \
683
+ "https://webexapis.com/v1/telephony/config/featureAccessCodes" | python3 -m json.tool
684
+
685
+ # Read feature access settings for a specific person
686
+ curl -s -H "Authorization: Bearer $WEBEX_TOKEN" \
687
+ "https://webexapis.com/v1/telephony/config/people/Y2lzY29...personId/featureAccessCodes" | python3 -m json.tool
688
+
689
+ # Update person feature access — block call forwarding and simultaneous ring
690
+ curl -s -X PUT -H "Authorization: Bearer $WEBEX_TOKEN" \
691
+ -H "Content-Type: application/json" \
692
+ "https://webexapis.com/v1/telephony/config/people/Y2lzY29...personId/featureAccessCodes" \
693
+ -d '{"callForwarding": "NO_ACCESS", "simultaneousRing": "NO_ACCESS", "voicemail": "FULL_ACCESS"}'
694
+
695
+ # Reset a person's feature access back to org defaults
696
+ curl -s -X POST -H "Authorization: Bearer $WEBEX_TOKEN" \
697
+ "https://webexapis.com/v1/telephony/config/people/Y2lzY29...personId/featureAccessCodes/actions/reset/invoke"
698
+ ```
699
+
700
+ ---
701
+
702
+ ## 4. Executive / Assistant Settings
703
+
704
+ Full executive-assistant pairing, alerting, call filtering, and screening configuration.
705
+
706
+ ### 4a. Exec Assistant Type Assignment
707
+
708
+ **API class:** `ExecAssistantApi` (extends `PersonSettingsApiChild`)
709
+ - Feature path segment: `executiveAssistant`
710
+
711
+ Simple API that reads or sets whether a person is an executive, an executive assistant, or unassigned.
712
+
713
+ #### `ExecAssistantType` (enum)
714
+
715
+ | Value | Meaning |
716
+ |-------|---------|
717
+ | `UNASSIGNED` | Feature not enabled |
718
+ | `EXECUTIVE` | Person is an executive |
719
+ | `EXECUTIVE_ASSISTANT` | Person is an executive assistant |
720
+
721
+ #### `read`
722
+
723
+ ```python
724
+ def read(self, person_id: str, org_id: str = None) -> ExecAssistantType
725
+ ```
726
+
727
+ - **Scope:** `spark-admin:people_read`
728
+
729
+ #### `configure`
730
+
731
+ ```python
732
+ def configure(self, person_id: str, setting: ExecAssistantType, org_id: str = None)
733
+ ```
734
+
735
+ - **Scope:** `spark-admin:people_write`
736
+
737
+ ### 4b. Executive Settings (Detailed)
738
+
739
+ **API class:** `ExecutiveSettingsApi` (extends `ApiChild`, base=`''`)
740
+ - All endpoints under: `telephony/config/people/{person_id}/executive/...`
741
+
742
+ #### Data Models — Alerting
743
+
744
+ **`ExecAlertingMode`** (enum): `SEQUENTIAL` | `SIMULTANEOUS`
745
+
746
+ **`ExecAlertRolloverAction`** (enum):
747
+
748
+ | Value | Meaning |
749
+ |-------|---------|
750
+ | `VOICE_MESSAGING` | Send to executive's voicemail |
751
+ | `NO_ANSWER_PROCESSING` | Trigger no-answer processing (may invoke call forwarding/voicemail) |
752
+ | `FORWARD` | Forward to `rollover_forward_to_phone_number` |
753
+
754
+ **`ExecAlertClidNameMode`** (enum):
755
+
756
+ | Value | Display |
757
+ |-------|---------|
758
+ | `EXECUTIVE_ORIGINATOR` | Executive name followed by caller name |
759
+ | `ORIGINATOR_EXECUTIVE` | Caller name followed by executive name |
760
+ | `EXECUTIVE` | Only executive name |
761
+ | `ORIGINATOR` | Only caller name |
762
+ | `CUSTOM` | Custom name |
763
+
764
+ **`ExecAlertClidPhoneNumberMode`** (enum): `EXECUTIVE` | `ORIGINATOR` | `CUSTOM`
765
+
766
+ **`ExecAlert`** (model):
767
+
768
+ | Field | Type | Description |
769
+ |-------|------|-------------|
770
+ | `alerting_mode` | `ExecAlertingMode` | Sequential or simultaneous alerting |
771
+ | `next_assistant_number_of_rings` | `int` | Rings before next assistant (sequential mode) |
772
+ | `rollover_enabled` | `bool` | Whether rollover timer is active |
773
+ | `rollover_action` | `ExecAlertRolloverAction` | What happens on rollover |
774
+ | `rollover_forward_to_phone_number` | `str` | Forward destination (when action=FORWARD) |
775
+ | `rollover_wait_time_in_secs` | `int` | Seconds before rollover triggers |
776
+ | `clid_name_mode` | `ExecAlertClidNameMode` | Caller ID name display mode |
777
+ | `custom_clidname` | `str` | Custom CLID name (deprecated) — alias `customCLIDName` |
778
+ | `custom_clidname_in_unicode` | `str` | Custom CLID name in Unicode — alias `customCLIDNameInUnicode` |
779
+ | `clid_phone_number_mode` | `ExecAlertClidPhoneNumberMode` | Caller ID phone number mode |
780
+ | `custom_clidphone_number` | `str` | Custom CLID phone number — alias `customCLIDPhoneNumber` |
781
+
782
+ #### Data Models — Assistants
783
+
784
+ **`ExecOrAssistant`** (model):
785
+
786
+ | Field | Type | Description |
787
+ |-------|------|-------------|
788
+ | `id` | `str` | Person ID |
789
+ | `first_name` | `str` | First name |
790
+ | `last_name` | `str` | Last name |
791
+ | `direct_number` | `str` | Direct phone number |
792
+ | `extension` | `str` | Extension |
793
+ | `opt_in_enabled` | `bool` | Whether assistant can opt in to the pool |
794
+ | `location` | `IdAndName` | Location ID and name |
795
+
796
+ **`AssistantSettings`** (model):
797
+
798
+ | Field | Type | Description |
799
+ |-------|------|-------------|
800
+ | `forward_filtered_calls_enabled` | `bool` | Forward filtered calls to a number |
801
+ | `forward_to_phone_number` | `str` | Phone number to forward filtered calls to |
802
+ | `executives` | `list[ExecOrAssistant]` | List of assigned executives |
803
+
804
+ #### Data Models — Call Filtering
805
+
806
+ **`ExecCallFilterType`** (enum):
807
+
808
+ | Value | Meaning |
809
+ |-------|---------|
810
+ | `CUSTOM_CALL_FILTERS` | Only specific calls per custom criteria |
811
+ | `ALL_CALLS` | All internal and external calls |
812
+ | `ALL_INTERNAL_CALLS` | All internal calls only |
813
+ | `ALL_EXTERNAL_CALLS` | All external calls only |
814
+
815
+ **`ExecCallFilteringCriteriaItem`** (model) — summary item in filter list:
816
+
817
+ | Field | Type | Description |
818
+ |-------|------|-------------|
819
+ | `id` | `str` | Criteria ID |
820
+ | `filter_name` | `str` | Name |
821
+ | `source` | `SelectiveFrom` | Call source filter |
822
+ | `activation_enabled` | `bool` | Whether criteria is active |
823
+ | `filter_enabled` | `bool` | `true` = matching calls blocked; `false` = matching calls allowed through as exceptions |
824
+
825
+ **`ExecCallFiltering`** (model):
826
+
827
+ | Field | Type | Description |
828
+ |-------|------|-------------|
829
+ | `enabled` | `bool` | Whether executive call filtering is on |
830
+ | `filter_type` | `ExecCallFilterType` | Filter scope |
831
+ | `criteria` | `list[ExecCallFilteringCriteriaItem]` | Configured filter criteria |
832
+
833
+ **`ExecCallFilteringScheduleLevel`** (enum): `PEOPLE` | `LOCATION`
834
+
835
+ **`ExecCallFilteringToNumber`** (model):
836
+
837
+ | Field | Type | Description |
838
+ |-------|------|-------------|
839
+ | `type` | `PrimaryOrSecondary` | Number type |
840
+ | `phone_number` | `str` | Phone number |
841
+
842
+ **`ExecCallFilteringCriteria`** (model) — full criteria detail:
843
+
844
+ | Field | Type | Description |
845
+ |-------|------|-------------|
846
+ | `id` | `str` | Criteria ID |
847
+ | `filter_name` | `str` | Name |
848
+ | `schedule_name` | `str` | Associated schedule name |
849
+ | `schedule_type` | `ScheduleType` | Schedule type (e.g., holidays) |
850
+ | `schedule_level` | `ExecCallFilteringScheduleLevel` | People or location level |
851
+ | `calls_from` | `SelectiveFrom` | Source filter (e.g., `ANY_PHONE_NUMBER`) |
852
+ | `anonymous_callers_enabled` | `bool` | Apply to anonymous callers |
853
+ | `unavailable_callers_enabled` | `bool` | Apply to unavailable callers |
854
+ | `phone_numbers` | `list[str]` | Specific phone numbers this criteria applies to |
855
+ | `filter_enabled` | `bool` | `true` = block matching; `false` = allow matching (exception) |
856
+ | `calls_to_numbers` | `list[ExecCallFilteringToNumber]` | Numbers to route matching calls to |
857
+
858
+ #### Data Models — Screening
859
+
860
+ **`ExecScreeningAlertType`** (enum): `SILENT` | `RING_SPLASH`
861
+
862
+ **`ExecScreening`** (model):
863
+
864
+ | Field | Type | Description |
865
+ |-------|------|-------------|
866
+ | `enabled` | `bool` | Whether screening is on |
867
+ | `alert_type` | `ExecScreeningAlertType` | Alert sound type |
868
+ | `alert_anywhere_location_enabled` | `bool` | Alerts for Single Number Reach |
869
+ | `alert_mobility_location_enabled` | `bool` | Alerts for Webex Go |
870
+ | `alert_shared_call_appearance_location_enabled` | `bool` | Alerts for Shared Call Appearance |
871
+
872
+ ### Executive Settings API Methods
873
+
874
+ All methods use the `ExecutiveSettingsApi` class.
875
+
876
+ **Read scope (all read methods):** `spark-admin:telephony_config_read`
877
+ **Write scope (all write methods):** `spark-admin:telephony_config_write`
878
+
879
+ #### Alert Settings
880
+
881
+ ```python
882
+ def alert_settings(self, person_id: str, org_id: str = None) -> ExecAlert
883
+ def update_alert_settings(self, person_id: str, settings: ExecAlert, org_id: str = None)
884
+ ```
885
+
886
+ #### Assigned Assistants
887
+
888
+ ```python
889
+ def assigned_assistants(self, person_id: str, org_id: str = None) -> list[ExecOrAssistant]
890
+ def update_assigned_assistants(self, person_id: str, assistant_ids: list[str] = None, org_id: str = None)
891
+ ```
892
+
893
+ To remove all assistants, pass `assistant_ids=None` (sends null).
894
+
895
+ #### Available Assistants
896
+
897
+ ```python
898
+ def executive_available_assistants(self, person_id: str, name: str = None,
899
+ phone_number: str = None, org_id: str = None) -> list[ExecOrAssistant]
900
+ ```
901
+
902
+ Search for people available for assignment. Filter by `name` (first+last combo) or `phone_number`.
903
+
904
+ #### Executive Assistant Settings (from assistant's perspective)
905
+
906
+ ```python
907
+ def executive_assistant_settings(self, person_id: str, org_id: str = None) -> AssistantSettings
908
+ def update_executive_assistant_settings(self, person_id: str, settings: AssistantSettings, org_id: str = None)
909
+ ```
910
+
911
+ Read/update settings for a person who is configured **as an executive assistant** — includes the list of executives they serve.
912
+
913
+ #### Call Filtering Settings
914
+
915
+ ```python
916
+ def executive_call_filtering_settings(self, person_id: str, org_id: str = None) -> ExecCallFiltering
917
+ def update_executive_call_filtering_settings(self, person_id: str, settings: ExecCallFiltering, org_id: str = None)
918
+ ```
919
+
920
+ #### Call Filtering Criteria (CRUD)
921
+
922
+ ```python
923
+ def create_call_filtering_criteria(self, person_id: str, settings: ExecCallFilteringCriteria,
924
+ org_id: str = None) -> str # returns criteria ID
925
+
926
+ def get_filtering_criteria(self, person_id: str, id: str,
927
+ org_id: str = None) -> ExecCallFilteringCriteria
928
+
929
+ def update_call_filtering_criteria(self, person_id: str, id: str,
930
+ settings: ExecCallFilteringCriteria, org_id: str = None)
931
+
932
+ def delete_call_filtering_criteria(self, person_id: str, id: str, org_id: str = None)
933
+ ```
934
+
935
+ #### Screening Settings
936
+
937
+ ```python
938
+ def screening_settings(self, person_id: str, org_id: str = None) -> ExecScreening
939
+ def update_screening_settings(self, person_id: str, settings: ExecScreening, org_id: str = None)
940
+ ```
941
+
942
+ ### Raw HTTP
943
+ <!-- Updated by playbook session 2026-03-18 -->
944
+
945
+ **Base URL:** `https://webexapis.com/v1`
946
+
947
+ Two different base paths are used:
948
+
949
+ **Exec/Assistant type assignment** (`people/{personId}/features/...`):
950
+
951
+ | Operation | Method | Endpoint |
952
+ |-----------|--------|----------|
953
+ | Read type | GET | `people/{personId}/features/executiveAssistant` |
954
+ | Set type | PUT | `people/{personId}/features/executiveAssistant` |
955
+
956
+ **Executive detailed settings** (`telephony/config/people/{personId}/executive/...`):
957
+
958
+ | Operation | Method | Endpoint |
959
+ |-----------|--------|----------|
960
+ | Read alert settings | GET | `telephony/config/people/{personId}/executive/alertSettings` |
961
+ | Update alert settings | PUT | `telephony/config/people/{personId}/executive/alertSettings` |
962
+ | List assigned assistants | GET | `telephony/config/people/{personId}/executive/assignedAssistants` |
963
+ | Update assigned assistants | PUT | `telephony/config/people/{personId}/executive/assignedAssistants` |
964
+ | List available assistants | GET | `telephony/config/people/{personId}/executive/availableAssistants` |
965
+ | Read assistant settings | GET | `telephony/config/people/{personId}/executive/assistant` |
966
+ | Update assistant settings | PUT | `telephony/config/people/{personId}/executive/assistant` |
967
+ | Read call filtering | GET | `telephony/config/people/{personId}/executive/callFiltering` |
968
+ | Update call filtering | PUT | `telephony/config/people/{personId}/executive/callFiltering` |
969
+ | Create filter criteria | POST | `telephony/config/people/{personId}/executive/callFiltering/criteria` |
970
+ | Get filter criteria | GET | `telephony/config/people/{personId}/executive/callFiltering/criteria/{criteriaId}` |
971
+ | Update filter criteria | PUT | `telephony/config/people/{personId}/executive/callFiltering/criteria/{criteriaId}` |
972
+ | Delete filter criteria | DELETE | `telephony/config/people/{personId}/executive/callFiltering/criteria/{criteriaId}` |
973
+ | Read screening | GET | `telephony/config/people/{personId}/executive/screening` |
974
+ | Update screening | PUT | `telephony/config/people/{personId}/executive/screening` |
975
+
976
+ ```python
977
+ from wxc_sdk import WebexSimpleApi
978
+ api = WebexSimpleApi()
979
+ BASE = "https://webexapis.com/v1"
980
+
981
+ # --- Exec/Assistant Type Assignment ---
982
+ # Read type (returns {"type": "UNASSIGNED"|"EXECUTIVE"|"EXECUTIVE_ASSISTANT"})
983
+ result = api.session.rest_get(f"{BASE}/people/{person_id}/features/executiveAssistant")
984
+
985
+ # Assign as executive
986
+ api.session.rest_put(f"{BASE}/people/{person_id}/features/executiveAssistant",
987
+ json={"type": "EXECUTIVE"})
988
+
989
+ # --- Executive Detailed Settings (telephony/config path) ---
990
+ # Read alert settings
991
+ alert = api.session.rest_get(
992
+ f"{BASE}/telephony/config/people/{person_id}/executive/alertSettings"
993
+ )
994
+
995
+ # Update alert settings
996
+ api.session.rest_put(
997
+ f"{BASE}/telephony/config/people/{person_id}/executive/alertSettings",
998
+ json={
999
+ "alertingMode": "SEQUENTIAL",
1000
+ "nextAssistantNumberOfRings": 4,
1001
+ "rolloverEnabled": True,
1002
+ "rolloverAction": "VOICE_MESSAGING",
1003
+ "rolloverWaitTimeInSecs": 20
1004
+ }
1005
+ )
1006
+
1007
+ # Assign assistants to executive
1008
+ api.session.rest_put(
1009
+ f"{BASE}/telephony/config/people/{person_id}/executive/assignedAssistants",
1010
+ json={"assistants": [{"id": assistant_person_id}]}
1011
+ )
1012
+
1013
+ # Read assistant settings (from assistant's perspective)
1014
+ asst = api.session.rest_get(
1015
+ f"{BASE}/telephony/config/people/{assistant_id}/executive/assistant"
1016
+ )
1017
+
1018
+ # Read screening settings
1019
+ screening = api.session.rest_get(
1020
+ f"{BASE}/telephony/config/people/{person_id}/executive/screening"
1021
+ )
1022
+ ```
1023
+
1024
+ **CLI commands:** `show-executive-assistant`, `update-executive-assistant`
1025
+ **CLI commands (self):** `list-assigned-assistants`, `update-assigned-assistants`, `list-available-assistants`, `show-assistant`, `update-assistant`
1026
+
1027
+ ### CLI Examples
1028
+
1029
+ ```bash
1030
+ # --- Exec/Assistant Type Assignment ---
1031
+
1032
+ # Read executive/assistant type for a person
1033
+ wxcli user-settings show-executive-assistant Y2lzY29...personId
1034
+
1035
+ # Assign a person as an executive
1036
+ wxcli user-settings update-executive-assistant Y2lzY29...execPersonId \
1037
+ --type EXECUTIVE
1038
+
1039
+ # Assign a person as an executive assistant
1040
+ wxcli user-settings update-executive-assistant Y2lzY29...asstPersonId \
1041
+ --type EXECUTIVE_ASSISTANT
1042
+
1043
+ # Remove executive/assistant assignment
1044
+ wxcli user-settings update-executive-assistant Y2lzY29...personId \
1045
+ --type UNASSIGNED
1046
+
1047
+ # --- Executive Alert Settings ---
1048
+
1049
+ # Read executive alert settings
1050
+ wxcli user-settings show-alert Y2lzY29...execPersonId
1051
+
1052
+ # Configure sequential alerting with rollover to voicemail after 20 seconds
1053
+ wxcli user-settings update-alert Y2lzY29...execPersonId \
1054
+ --alerting-mode SEQUENTIAL \
1055
+ --next-assistant-number-of-rings 4 \
1056
+ --rollover-enabled \
1057
+ --rollover-action VOICE_MESSAGING \
1058
+ --rollover-wait-time-in-secs 20
1059
+
1060
+ # Configure simultaneous alerting with forward rollover
1061
+ wxcli user-settings update-alert Y2lzY29...execPersonId \
1062
+ --alerting-mode SIMULTANEOUS \
1063
+ --rollover-enabled \
1064
+ --rollover-action FORWARD \
1065
+ --rollover-forward-to-phone-number "+15559876543" \
1066
+ --rollover-wait-time-in-secs 30
1067
+
1068
+ # --- Assistant Assignment ---
1069
+
1070
+ # List assistants assigned to an executive
1071
+ wxcli user-settings list-assigned-assistants Y2lzY29...execPersonId
1072
+
1073
+ # Search for available assistants by name
1074
+ wxcli user-settings list-available-assistants Y2lzY29...execPersonId \
1075
+ --name "Jane Smith"
1076
+
1077
+ # Assign assistants to an executive (requires --json-body for the array)
1078
+ wxcli user-settings update-assigned-assistants Y2lzY29...execPersonId \
1079
+ --json-body '{"assistants": [{"id": "Y2lzY29...asstPersonId"}]}'
1080
+
1081
+ # Remove all assistants (send null)
1082
+ wxcli user-settings update-assigned-assistants Y2lzY29...execPersonId \
1083
+ --json-body '{"assistants": null}'
1084
+
1085
+ # --- Assistant Settings (from assistant's perspective) ---
1086
+
1087
+ # Read assistant settings (which executives they serve)
1088
+ wxcli user-settings list-assistant Y2lzY29...asstPersonId
1089
+
1090
+ # --- Call Filtering ---
1091
+
1092
+ # Read executive call filtering settings
1093
+ wxcli user-settings list-call-filtering Y2lzY29...execPersonId
1094
+
1095
+ # --- Screening ---
1096
+
1097
+ # Read screening settings for an executive
1098
+ wxcli user-settings show-screening Y2lzY29...execPersonId
1099
+
1100
+ # Enable screening with ring splash alerts
1101
+ wxcli user-settings update-screening Y2lzY29...execPersonId \
1102
+ --enabled --alert-type RING_SPLASH
1103
+
1104
+ # Disable screening
1105
+ wxcli user-settings update-screening Y2lzY29...execPersonId --no-enabled
1106
+ ```
1107
+
1108
+ ---
1109
+
1110
+ ## 5. Call Policy
1111
+
1112
+ Controls Connected Line Identification Privacy on redirected calls.
1113
+
1114
+ **API class:** `CallPolicyApi` (extends `PersonSettingsApiChild`)
1115
+ - Feature path segment: `callPolicies`
1116
+
1117
+ > **Important:** This API is only available for **professional licensed workspaces** when accessed via admin tokens. The scopes shown (`workspaces_read/write`) are workspace-specific. There is no admin-level `people/{personId}` callPolicies endpoint. However, calling-licensed users can access their own call policy via the self-access endpoint (`/telephony/config/people/me/settings/callPolicies`) with the `spark:telephony_config_read/write` scope. The wxc_sdk only wires `CallPolicyApi` into `workspace_settings`, not `person_settings`.
1118
+
1119
+ ### Data Models
1120
+
1121
+ #### `PrivacyOnRedirectedCalls` (enum)
1122
+
1123
+ | Value | Meaning |
1124
+ |-------|---------|
1125
+ | `NO_PRIVACY` | Connected line identification is not blocked on redirected calls |
1126
+ | `PRIVACY_FOR_EXTERNAL_CALLS` | Blocked on redirected calls to external numbers only |
1127
+ | `PRIVACY_FOR_ALL_CALLS` | Blocked on all redirected calls |
1128
+
1129
+ ### Methods
1130
+
1131
+ #### `read`
1132
+
1133
+ ```python
1134
+ def read(self, entity_id: str, org_id: str = None) -> PrivacyOnRedirectedCalls
1135
+ ```
1136
+
1137
+ - **Scope:** `spark-admin:workspaces_read`
1138
+
1139
+ #### `configure`
1140
+
1141
+ ```python
1142
+ def configure(self, entity_id: str,
1143
+ connected_line_id_privacy_on_redirected_calls: PrivacyOnRedirectedCalls,
1144
+ org_id: str = None)
1145
+ ```
1146
+
1147
+ - **Scope:** `spark-admin:workspaces_write`
1148
+
1149
+ ### Raw HTTP
1150
+ <!-- Updated by playbook session 2026-03-18 -->
1151
+
1152
+ > **WARNING: No admin-level person endpoint exists.** The path `people/{personId}/features/callPolicies` returns 404 for persons. Only the workspace admin path and the self-service `/me` path work.
1153
+
1154
+ **Base URL:** `https://webexapis.com/v1`
1155
+
1156
+ | Operation | Method | Endpoint | Token Type |
1157
+ |-----------|--------|----------|------------|
1158
+ | Read (workspace) | GET | `workspaces/{workspaceId}/features/callPolicies` | Admin |
1159
+ | Update (workspace) | PUT | `workspaces/{workspaceId}/features/callPolicies` | Admin |
1160
+ | Read (self) | GET | `telephony/config/people/me/settings/callPolicies` | User (calling-licensed) |
1161
+ | Update (self) | PUT | `telephony/config/people/me/settings/callPolicies` | User (calling-licensed) |
1162
+
1163
+ ```python
1164
+ from wxc_sdk import WebexSimpleApi
1165
+ api = WebexSimpleApi()
1166
+ BASE = "https://webexapis.com/v1"
1167
+
1168
+ # Read call policy for a workspace (admin token)
1169
+ result = api.session.rest_get(f"{BASE}/workspaces/{workspace_id}/features/callPolicies")
1170
+ # Returns: {"connectedLineIdPrivacyOnRedirectedCalls": "NO_PRIVACY"|"PRIVACY_FOR_EXTERNAL_CALLS"|"PRIVACY_FOR_ALL_CALLS"}
1171
+
1172
+ # Update call policy for a workspace (admin token)
1173
+ api.session.rest_put(f"{BASE}/workspaces/{workspace_id}/features/callPolicies",
1174
+ json={"connectedLineIdPrivacyOnRedirectedCalls": "PRIVACY_FOR_EXTERNAL_CALLS"})
1175
+
1176
+ # Read call policy for self (calling-licensed user token, spark:telephony_config_read scope)
1177
+ result = api.session.rest_get(f"{BASE}/telephony/config/people/me/settings/callPolicies")
1178
+
1179
+ # Update call policy for self (calling-licensed user token, spark:telephony_config_write scope)
1180
+ api.session.rest_put(f"{BASE}/telephony/config/people/me/settings/callPolicies",
1181
+ json={"connectedLineIdPrivacyOnRedirectedCalls": "PRIVACY_FOR_EXTERNAL_CALLS"})
1182
+ ```
1183
+
1184
+ ### CLI Examples
1185
+
1186
+ > **Note:** Call Policy is only available for **workspaces** via admin CLI commands (`workspace-settings show-call-policies`, `update-call-policies`). There is no admin-level `people/{personId}` endpoint for call policy. Calling-licensed users can read/update their own call policy via the self-access endpoint (`/telephony/config/people/me/settings/callPolicies` with `spark:telephony_config_read/write` scope), but this requires user-level OAuth, not admin tokens.
1187
+
1188
+ ```bash
1189
+ # Read call policy for a workspace
1190
+ wxcli workspace-settings show-call-policies Y2lzY29...workspaceId
1191
+
1192
+ # Set privacy for external calls only
1193
+ wxcli workspace-settings update-call-policies Y2lzY29...workspaceId \
1194
+ --connected-line-id-privacy-on-redirected-calls PRIVACY_FOR_EXTERNAL_CALLS
1195
+
1196
+ # Set privacy for all redirected calls
1197
+ wxcli workspace-settings update-call-policies Y2lzY29...workspaceId \
1198
+ --connected-line-id-privacy-on-redirected-calls PRIVACY_FOR_ALL_CALLS
1199
+
1200
+ # Remove privacy on redirected calls
1201
+ wxcli workspace-settings update-call-policies Y2lzY29...workspaceId \
1202
+ --connected-line-id-privacy-on-redirected-calls NO_PRIVACY
1203
+
1204
+ # For person-level call policy, use the /me self-service endpoint (requires calling-licensed user token)
1205
+ # NOTE: The admin path people/{personId}/features/callPolicies returns 404 for persons
1206
+ curl -s -H "Authorization: Bearer $USER_TOKEN" \
1207
+ "https://webexapis.com/v1/telephony/config/people/me/settings/callPolicies" | python3 -m json.tool
1208
+ ```
1209
+
1210
+ ---
1211
+
1212
+ ## Scope Summary
1213
+
1214
+ | API Area | Read Scope | Write Scope |
1215
+ |----------|-----------|-------------|
1216
+ | Incoming Permissions | `spark-admin:people_read` | `spark-admin:people_write` or `spark:people_write` (self) |
1217
+ | Outgoing Permissions (main) | `spark-admin:people_read` | `spark-admin:people_write` or `spark:people_write` (self) |
1218
+ | Outgoing — Transfer Numbers (person) | `spark-admin:telephony_config_read` | `spark-admin:telephony_config_write` |
1219
+ | Outgoing — Transfer Numbers (workspace) | `spark-admin:workspaces_read` | `spark-admin:workspaces_write` |
1220
+ | Outgoing — Access Codes (person) | `spark-admin:telephony_config_read` | `spark-admin:telephony_config_write` |
1221
+ | Outgoing — Access Codes (workspace) | `spark-admin:workspaces_read` | `spark-admin:workspaces_write` |
1222
+ | Outgoing — Digit Patterns | `spark-admin:telephony_config_read` | `spark-admin:telephony_config_write` |
1223
+ | Feature Access | `spark-admin:telephony_config_read` | `spark-admin:telephony_config_write` |
1224
+ | Exec Assistant Type | `spark-admin:people_read` | `spark-admin:people_write` |
1225
+ | Executive Settings (alert, filtering, screening, assistants) | `spark-admin:telephony_config_read` | `spark-admin:telephony_config_write` |
1226
+ | Call Policy (workspace, admin) | `spark-admin:workspaces_read` | `spark-admin:workspaces_write` |
1227
+ | Call Policy (self, user token) | `spark:telephony_config_read` | `spark:telephony_config_write` |
1228
+
1229
+ ---
1230
+
1231
+ ## Usage Patterns
1232
+
1233
+ ### Setting per-call-type outgoing permissions
1234
+
1235
+ ```python
1236
+ from wxc_sdk.person_settings.permissions_out import (
1237
+ OutgoingPermissions, CallingPermissions, Action, OutgoingPermissionCallType
1238
+ )
1239
+
1240
+ # Start with defaults (blocks international + premium)
1241
+ perms = CallingPermissions.default()
1242
+
1243
+ # Also block operator-assisted
1244
+ op = perms.for_call_type(OutgoingPermissionCallType.operator_assisted)
1245
+ op.action = Action.block
1246
+ op.transfer_enabled = False
1247
+
1248
+ settings = OutgoingPermissions(
1249
+ use_custom_enabled=True,
1250
+ use_custom_permissions=True,
1251
+ calling_permissions=perms
1252
+ )
1253
+
1254
+ api.person_settings.permissions_out.configure(person_id, settings)
1255
+ ```
1256
+
1257
+ ### Assigning an executive and assistant
1258
+
1259
+ ```python
1260
+ from wxc_sdk.person_settings.exec_assistant import ExecAssistantType
1261
+
1262
+ # Mark person as executive
1263
+ api.person_settings.exec_assistant.configure(exec_person_id, ExecAssistantType.executive)
1264
+
1265
+ # Mark another person as assistant
1266
+ api.person_settings.exec_assistant.configure(asst_person_id, ExecAssistantType.executive_assistant)
1267
+
1268
+ # Assign assistant to executive
1269
+ api.person_settings.executive.update_assigned_assistants(exec_person_id, assistant_ids=[asst_person_id])
1270
+ ```
1271
+
1272
+ ### Configuring executive alerting
1273
+
1274
+ ```python
1275
+ from wxc_sdk.person_settings.executive import (
1276
+ ExecAlert, ExecAlertingMode, ExecAlertRolloverAction
1277
+ )
1278
+
1279
+ alert = ExecAlert(
1280
+ alerting_mode=ExecAlertingMode.sequential,
1281
+ next_assistant_number_of_rings=4,
1282
+ rollover_enabled=True,
1283
+ rollover_action=ExecAlertRolloverAction.voice_messaging,
1284
+ rollover_wait_time_in_secs=20
1285
+ )
1286
+
1287
+ api.person_settings.executive.update_alert_settings(exec_person_id, alert)
1288
+ ```
1289
+
1290
+ ### Restricting feature access for a user
1291
+
1292
+ ```python
1293
+ from wxc_sdk.person_settings.feature_access import FeatureAccessSettings, FeatureAccessLevel
1294
+
1295
+ settings = FeatureAccessSettings(
1296
+ call_forwarding=FeatureAccessLevel.no_access,
1297
+ simultaneous_ring=FeatureAccessLevel.no_access,
1298
+ voicemail=FeatureAccessLevel.full_access
1299
+ )
1300
+
1301
+ api.person_settings.feature_access.update(person_id, settings)
1302
+ ```
1303
+
1304
+ ---
1305
+
1306
+ ## Gotchas (Cross-Cutting)
1307
+
1308
+ 1. **Outgoing permissions `callingPermissions` is a list, not a dict.** The API returns and expects `callingPermissions` as an array of `{callType, action, transferEnabled}` objects. The wxc_sdk model transforms this to a dict internally, but when using `--json-body` or raw HTTP, always send an array.
1309
+
1310
+ 2. **Three different base paths across this doc.** Incoming/outgoing permissions and exec-assistant type use `people/{personId}/features/...`. Digit patterns and feature access use `telephony/config/people/{personId}/...`. Executive detailed settings use `telephony/config/people/{personId}/executive/...`. Mixing up the base path returns 404.
1311
+
1312
+ 3. **Access codes `modify` uses a different scope.** Read/create/delete access codes require `workspaces_read/write`, but the modify (PUT) endpoint requires `telephony_config_write`. A service app with only workspace scopes can create and delete codes but cannot modify them.
1313
+
1314
+ 4. **Executive assistant assignment is two steps.** You must first set both persons' types (one as `EXECUTIVE`, one as `EXECUTIVE_ASSISTANT`) via the type assignment API, then assign the assistant to the executive via `update-assigned-assistants`. Setting the type alone does not create the pairing.
1315
+
1316
+ 5. **`drop_call_types` matters for outgoing permission updates.** By default, the SDK drops `url_dialing`, `unknown`, and `casual` call types from the update payload. If you see unexpected call types in the API response, they may be auto-excluded during writes. When using `--json-body`, only include call types you want to set.
1317
+
1318
+ 6. **Feature access `reset` is a POST, not a DELETE.** Resetting a person's feature access to org defaults uses `POST .../actions/reset/invoke`, not a DELETE. Sending DELETE to this endpoint returns 405.
1319
+
1320
+ 7. **Call Policy has NO admin-level person endpoint.** Live API testing confirms that `people/{personId}/features/callPolicies` returns 404 for persons. The only working paths are: (1) workspace admin: `workspaces/{workspaceId}/features/callPolicies`, and (2) self-service: `telephony/config/people/me/settings/callPolicies` (requires calling-licensed user token with `spark:telephony_config_read/write`). The `wxcli` commands (`show-call-policies`, `update-call-policies`) are under `workspace-settings` only.
1321
+
1322
+ 8. **Transfer numbers and access codes scopes differ by entity type.** The SDK docstrings for `TransferNumbersApi` and `AccessCodesApi` incorrectly list `workspaces_read/write` scopes for all entities. Per the OpenAPI spec, person-level transfer numbers and access codes endpoints (at `telephony/config/people/{personId}/outgoingPermission/...`) require `spark-admin:telephony_config_read/write`, not `workspaces_read/write`. The workspace scopes only apply to workspace-level endpoints.
1323
+
1324
+ ---
1325
+
1326
+ ## See Also
1327
+
1328
+ - **[Location Recording — Advanced](location-recording-advanced.md)** — Location-level supervisor settings and related administrative controls
1329
+ - **[self-service-call-settings.md](self-service-call-settings.md)** -- User-level `/people/me/` endpoints for self-service call settings, including 6 user-only settings with no admin path.