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,1007 @@
1
+ # Admin: Identity & SCIM
2
+
3
+ SCIM 2.0 user/group provisioning, Webex People/Groups APIs, identity org settings, and directory management.
4
+
5
+ ## Sources
6
+
7
+ - [SCIM 2.0 Protocol (RFC 7644)](https://datatracker.ietf.org/doc/html/rfc7644) -- Standard protocol for cross-domain identity management
8
+ - [Webex SCIM 2.0 Users API](https://developer.webex.com/docs/api/v1/scim2-user) -- Official API docs
9
+ - [Webex People API](https://developer.webex.com/docs/api/v1/people) -- Official API docs
10
+ - [Webex Groups API](https://developer.webex.com/docs/api/v1/groups) -- Official API docs
11
+ - OpenAPI spec: `specs/webex-admin.json` -- Tags: SCIM 2 Users, SCIM 2 Groups, SCIM 2 Schemas, Bulk Manage SCIM 2 Users and Groups, Identity Organization, Groups, People
12
+
13
+ ---
14
+
15
+ ## Key Concepts
16
+
17
+ ### SCIM 2.0 Protocol
18
+
19
+ SCIM (System for Cross-domain Identity Management) is a standardized REST protocol for provisioning and managing user identities across systems. Webex implements SCIM 2.0 at `/identity/scim/{orgId}/v2/` endpoints. Key SCIM concepts:
20
+
21
+ - **Resources** are Users and Groups, represented as JSON objects with standard schemas.
22
+ - **Schemas** define the attributes available on each resource type. Webex extends the core SCIM schemas with `urn:scim:schemas:extension:cisco:webexidentity:2.0:User` and `urn:scim:schemas:extension:cisco:webexidentity:2.0:Group`.
23
+ - **Filters** use SCIM filter syntax for search: `filter=userName eq "user@example.com"` or `filter=displayName co "Engineering"`. Operators: `eq`, `ne`, `co` (contains), `sw` (starts with), `pr` (present), `gt`, `ge`, `lt`, `le`.
24
+ - **Bulk operations** allow multiple create/update/delete operations in a single HTTP request via the `/Bulk` endpoint.
25
+
26
+ ### PUT vs PATCH
27
+
28
+ Both SCIM user and group endpoints support two update methods:
29
+
30
+ - **PUT** (`update` commands) -- Replaces the entire resource. Any attribute not included in the PUT body is removed. Always GET the resource first, modify the JSON, then PUT the full object back.
31
+ - **PATCH** (`update-users` / `update-groups` commands) -- Partial update. Only the specified attributes are changed; all other attributes are left intact. Uses SCIM patch operations: `add`, `replace`, `remove`.
32
+
33
+ ### scim-users vs people
34
+
35
+ Both manage user accounts, but serve different purposes:
36
+
37
+ | Aspect | `scim-users` | `people` |
38
+ |--------|-------------|----------|
39
+ | Protocol | SCIM 2.0 (RFC 7644) | Webex REST API |
40
+ | Base path | `/identity/scim/{orgId}/v2/Users` | `/v1/people` |
41
+ | Primary use | IdP sync, automated provisioning, directory integration | Webex-native user management, manual CRUD |
42
+ | Requires `orgId` arg | Yes | No (uses token's org) |
43
+ | Update methods | PUT (full replace) + PATCH (partial) | PUT only |
44
+ | Scopes | `identity:people_rw` / `identity:people_read` | `spark-admin:people_write` / `spark-admin:people_read` |
45
+ | Calling data | Not returned | Optional via `--calling-data true` |
46
+
47
+ Use `scim-users` when integrating with an external IdP (Okta, Azure AD, etc.) or doing bulk provisioning. Use `people` for Webex-native user management and when you need calling-specific data.
48
+
49
+ ### scim-groups vs groups
50
+
51
+ | Aspect | `scim-groups` | `groups` |
52
+ |--------|--------------|----------|
53
+ | Protocol | SCIM 2.0 | Webex REST API |
54
+ | Base path | `/identity/scim/{orgId}/v2/Groups` | `/v1/groups` |
55
+ | Primary use | IdP group sync, directory groups | Webex-native group management |
56
+ | Requires `orgId` arg | Yes | No (uses token's org) |
57
+ | Update methods | PUT + PATCH | PATCH only |
58
+ | Member listing | Via `--include-members` on list/show, or dedicated `GET /Groups/{groupId}/Members` sub-endpoint (paginated, up to 500/page) | Separate `list-members` command |
59
+
60
+ ---
61
+
62
+ ## Required Scopes
63
+
64
+ | Scope | Purpose |
65
+ |-------|---------|
66
+ | `identity:people_rw` | Read and write SCIM users, SCIM groups, and SCIM bulk operations. |
67
+ | `identity:people_read` | Read-only access to SCIM users and SCIM groups. |
68
+ | `identity:organizations_rw` | Read and write identity organization settings. |
69
+ | `identity:organizations_read` | Read-only access to identity organization settings. |
70
+ | `Identity:one_time_password` | Generate OTP for a user. |
71
+ | `spark-admin:people_write` | Create, update, and delete people (Webex REST API). |
72
+ | `spark-admin:people_read` | List and get people (Webex REST API). |
73
+
74
+ **Note:** SCIM endpoints (`scim-users`, `scim-groups`, `scim-bulk`) use `identity:*` scopes. Webex REST endpoints (`people`, `groups`) use `spark-admin:*` scopes. Mixing them up produces 403 errors.
75
+
76
+ ---
77
+
78
+ ## Table of Contents
79
+
80
+ 1. [SCIM Users (`scim-users`)](#1-scim-users-scim-users)
81
+ 2. [SCIM Groups (`scim-groups`)](#2-scim-groups-scim-groups)
82
+ 3. [SCIM Schemas (`scim-schemas`)](#3-scim-schemas-scim-schemas)
83
+ 4. [SCIM Bulk Operations (`scim-bulk`)](#4-scim-bulk-operations-scim-bulk)
84
+ 5. [Identity Organization (`identity-org`)](#5-identity-organization-identity-org)
85
+ 6. [Groups (Webex REST API) (`groups`)](#6-groups-webex-rest-api-groups)
86
+ 7. [People (Webex REST API) (`people`)](#7-people-webex-rest-api-people)
87
+ 8. [Recipes](#recipes)
88
+ 9. [Gotchas](#gotchas)
89
+ 10. [See Also](#see-also)
90
+
91
+ ---
92
+
93
+ ## 1. SCIM Users (`scim-users`)
94
+
95
+ SCIM 2.0 user provisioning and management. All commands require an `org-id` positional argument.
96
+
97
+ ### Endpoints
98
+
99
+ | Method | Path | CLI Command |
100
+ |--------|------|-------------|
101
+ | GET | `/identity/scim/{orgId}/v2/Users` | `scim-users list` |
102
+ | POST | `/identity/scim/{orgId}/v2/Users` | `scim-users create` |
103
+ | GET | `/identity/scim/{orgId}/v2/Users/{userId}` | `scim-users show` |
104
+ | PUT | `/identity/scim/{orgId}/v2/Users/{userId}` | `scim-users update` |
105
+ | PATCH | `/identity/scim/{orgId}/v2/Users/{userId}` | `scim-users update-users` |
106
+ | DELETE | `/identity/scim/{orgId}/v2/Users/{userId}` | `scim-users delete` |
107
+ | GET | `/identity/scim/v2/Users/me` | `scim-users show-me` |
108
+
109
+ ### Command Reference
110
+
111
+ | Command | Description | Key Options |
112
+ |---------|-------------|-------------|
113
+ | `list` | Search users with SCIM filters | `--filter`, `--attributes`, `--excluded-attributes`, `--sort-by`, `--sort-order`, `--start-index`, `--count`, `--return-groups`, `--include-group-details`, `--group-usage-types` |
114
+ | `create` | Create a SCIM user | `--user-name` (required), `--display-name`, `--title`, `--active/--no-active`, `--preferred-language`, `--locale`, `--timezone`, `--external-id`, `--nick-name`, `--profile-url`, `--json-body` |
115
+ | `show` | Get a single user by ID | `ORG_ID`, `USER_ID` (positional) |
116
+ | `update` | Full replace (PUT) of user | Same options as `create` plus `USER_ID` positional. **Replaces entire resource.** |
117
+ | `update-users` | Partial update (PATCH) of user | `--json-body` only (SCIM patch operations) |
118
+ | `delete` | Delete a user | `--force` to skip confirmation |
119
+ | `show-me` | Get authenticated user's own SCIM record | No `org-id` required. Requires user-level token. |
120
+
121
+ ### CLI Examples
122
+
123
+ ```bash
124
+ # List all SCIM users in the org
125
+ wxcli scim-users list YOUR_ORG_ID
126
+
127
+ # Search for a specific user by email
128
+ wxcli scim-users list YOUR_ORG_ID --filter 'userName eq "jsmith@example.com"'
129
+
130
+ # Search users by display name (contains)
131
+ wxcli scim-users list YOUR_ORG_ID --filter 'displayName co "Smith"'
132
+
133
+ # Get specific user attributes only
134
+ wxcli scim-users list YOUR_ORG_ID --filter 'userName sw "j"' --attributes "userName,displayName,emails"
135
+
136
+ # Create a new SCIM user
137
+ wxcli scim-users create YOUR_ORG_ID --user-name "newuser@example.com" --display-name "New User" --active
138
+
139
+ # Create user with full JSON body (for nested fields like name, emails, addresses)
140
+ wxcli scim-users create YOUR_ORG_ID --json-body '{
141
+ "userName": "jdoe@example.com",
142
+ "displayName": "Jane Doe",
143
+ "name": {"givenName": "Jane", "familyName": "Doe"},
144
+ "emails": [{"value": "jdoe@example.com", "type": "work", "primary": true}],
145
+ "active": true
146
+ }'
147
+
148
+ # Get a specific user
149
+ wxcli scim-users show YOUR_ORG_ID USER_ID -o json
150
+
151
+ # Full replace a user (PUT) -- always GET first to avoid data loss
152
+ wxcli scim-users update YOUR_ORG_ID USER_ID --json-body '{ ... full user JSON ... }'
153
+
154
+ # Partial update a user (PATCH) -- change only specific fields
155
+ wxcli scim-users update-users YOUR_ORG_ID USER_ID --json-body '{
156
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
157
+ "Operations": [
158
+ {"op": "replace", "path": "displayName", "value": "Jane M. Doe"},
159
+ {"op": "replace", "path": "title", "value": "Senior Engineer"}
160
+ ]
161
+ }'
162
+
163
+ # Deactivate a user via PATCH
164
+ wxcli scim-users update-users YOUR_ORG_ID USER_ID --json-body '{
165
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
166
+ "Operations": [{"op": "replace", "path": "active", "value": false}]
167
+ }'
168
+
169
+ # Delete a user (with confirmation skip)
170
+ wxcli scim-users delete YOUR_ORG_ID USER_ID --force
171
+
172
+ # Get your own SCIM identity (user-level token required)
173
+ wxcli scim-users show-me -o json
174
+ ```
175
+
176
+ ### Raw HTTP Fallback
177
+
178
+ ```bash
179
+ # List SCIM users
180
+ curl -s -H "Authorization: Bearer $TOKEN" \
181
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Users?filter=userName%20eq%20%22user%40example.com%22"
182
+
183
+ # Create a SCIM user
184
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" \
185
+ -H "Content-Type: application/json" \
186
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Users" \
187
+ -d '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:User"],"userName":"user@example.com","displayName":"New User","active":true}'
188
+
189
+ # PATCH a SCIM user (partial update)
190
+ curl -s -X PATCH -H "Authorization: Bearer $TOKEN" \
191
+ -H "Content-Type: application/json" \
192
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Users/USER_ID" \
193
+ -d '{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],"Operations":[{"op":"replace","path":"active","value":false}]}'
194
+ ```
195
+
196
+ > **Gotcha — PUT Replaces the Entire Resource:**
197
+ > The `scim-users update` and `scim-groups update` commands use HTTP PUT, which replaces the entire resource. If you PUT a user without including their `emails`, `phoneNumbers`, or `addresses`, those fields are removed.
198
+ >
199
+ > **Safe pattern:** Always GET the current resource first, modify the JSON, then PUT the full object back:
200
+ > ```bash
201
+ > # Step 1: GET current state
202
+ > wxcli scim-users show YOUR_ORG_ID USER_ID -o json > user.json
203
+ > # Step 2: Edit user.json to change what you need
204
+ > # Step 3: PUT the modified full object
205
+ > wxcli scim-users update YOUR_ORG_ID USER_ID --json-body "$(cat user.json)"
206
+ > ```
207
+ > **Better alternative:** Use PATCH (`update-users` / `update-groups`) for partial updates whenever possible.
208
+
209
+ ---
210
+
211
+ ## 2. SCIM Groups (`scim-groups`)
212
+
213
+ SCIM 2.0 group provisioning and management. All commands require an `org-id` positional argument.
214
+
215
+ ### Endpoints
216
+
217
+ | Method | Path | CLI Command |
218
+ |--------|------|-------------|
219
+ | GET | `/identity/scim/{orgId}/v2/Groups` | `scim-groups list` |
220
+ | POST | `/identity/scim/{orgId}/v2/Groups` | `scim-groups create` |
221
+ | GET | `/identity/scim/{orgId}/v2/Groups/{groupId}` | `scim-groups show` |
222
+ | GET | `/identity/scim/{orgId}/v2/Groups/{groupId}/Members` | *(raw HTTP only — no CLI command)* |
223
+ | PUT | `/identity/scim/{orgId}/v2/Groups/{groupId}` | `scim-groups update` |
224
+ | PATCH | `/identity/scim/{orgId}/v2/Groups/{groupId}` | `scim-groups update-groups` |
225
+ | DELETE | `/identity/scim/{orgId}/v2/Groups/{groupId}` | `scim-groups delete` |
226
+
227
+ > **Note — `GET /Groups/{groupId}/Members`:** This sub-endpoint returns members of a specific group with pagination support. Query params: `startIndex`, `count`, `memberType` (values: `user`, `machine`, `group`). Returns up to **500 members per page**. Preferred over `--include-members` on `list`/`show` when paginating large groups, since `--include-members` returns all members in a single response and can be slow or truncated for large groups.
228
+ >
229
+ > ```bash
230
+ > # Raw HTTP: get members of a SCIM group (first page)
231
+ > curl -s -H "Authorization: Bearer $TOKEN" \
232
+ > "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups/GROUP_ID/Members?count=500&startIndex=1"
233
+ >
234
+ > # Filter by member type
235
+ > curl -s -H "Authorization: Bearer $TOKEN" \
236
+ > "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups/GROUP_ID/Members?memberType=user&count=500"
237
+ > ```
238
+
239
+ ### Command Reference
240
+
241
+ | Command | Description | Key Options |
242
+ |---------|-------------|-------------|
243
+ | `list` | Search groups with SCIM filters | `--filter`, `--attributes`, `--excluded-attributes`, `--sort-by`, `--sort-order`, `--start-index`, `--count`, `--include-members`, `--member-type` |
244
+ | `create` | Create a SCIM group | `--display-name` (required), `--external-id`, `--json-body` |
245
+ | `show` | Get a single group by ID | `--excluded-attributes` |
246
+ | `update` | Full replace (PUT) of group | `--display-name`, `--external-id`, `--json-body`. **Replaces entire resource.** |
247
+ | `update-groups` | Partial update (PATCH) of group | `--json-body` only (SCIM patch operations) |
248
+ | `delete` | Delete a group | `--force` to skip confirmation |
249
+
250
+ ### CLI Examples
251
+
252
+ ```bash
253
+ # List all SCIM groups
254
+ wxcli scim-groups list YOUR_ORG_ID
255
+
256
+ # Search for a group by name
257
+ wxcli scim-groups list YOUR_ORG_ID --filter 'displayName eq "Engineering"'
258
+
259
+ # List groups with member details
260
+ wxcli scim-groups list YOUR_ORG_ID --include-members true --member-type user
261
+
262
+ # Create a SCIM group
263
+ wxcli scim-groups create YOUR_ORG_ID --display-name "DevOps Team"
264
+
265
+ # Create a group with members via JSON body
266
+ wxcli scim-groups create YOUR_ORG_ID --json-body '{
267
+ "displayName": "DevOps Team",
268
+ "members": [
269
+ {"value": "USER_ID_1", "type": "user"},
270
+ {"value": "USER_ID_2", "type": "user"}
271
+ ]
272
+ }'
273
+
274
+ # Add a member to a group via PATCH
275
+ wxcli scim-groups update-groups YOUR_ORG_ID GROUP_ID --json-body '{
276
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
277
+ "Operations": [
278
+ {"op": "add", "path": "members", "value": [{"value": "USER_ID", "type": "user"}]}
279
+ ]
280
+ }'
281
+
282
+ # Remove a member from a group via PATCH
283
+ wxcli scim-groups update-groups YOUR_ORG_ID GROUP_ID --json-body '{
284
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
285
+ "Operations": [
286
+ {"op": "remove", "path": "members[value eq \"USER_ID\"]"}
287
+ ]
288
+ }'
289
+
290
+ # Delete a group
291
+ wxcli scim-groups delete YOUR_ORG_ID GROUP_ID --force
292
+ ```
293
+
294
+ ### Raw HTTP Fallback
295
+
296
+ ```bash
297
+ # List SCIM groups
298
+ curl -s -H "Authorization: Bearer $TOKEN" \
299
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups"
300
+
301
+ # Search SCIM groups by name
302
+ curl -s -H "Authorization: Bearer $TOKEN" \
303
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups?filter=displayName%20eq%20%22Engineering%22"
304
+
305
+ # Create a SCIM group
306
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" \
307
+ -H "Content-Type: application/json" \
308
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups" \
309
+ -d '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],"displayName":"DevOps Team"}'
310
+
311
+ # Get a SCIM group by ID
312
+ curl -s -H "Authorization: Bearer $TOKEN" \
313
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups/GROUP_ID"
314
+
315
+ # PUT (full replace) a SCIM group
316
+ curl -s -X PUT -H "Authorization: Bearer $TOKEN" \
317
+ -H "Content-Type: application/json" \
318
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups/GROUP_ID" \
319
+ -d '{"schemas":["urn:ietf:params:scim:schemas:core:2.0:Group"],"displayName":"DevOps Team","members":[{"value":"USER_ID","type":"user"}]}'
320
+
321
+ # PATCH a SCIM group (add member)
322
+ curl -s -X PATCH -H "Authorization: Bearer $TOKEN" \
323
+ -H "Content-Type: application/json" \
324
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups/GROUP_ID" \
325
+ -d '{"schemas":["urn:ietf:params:scim:api:messages:2.0:PatchOp"],"Operations":[{"op":"add","path":"members","value":[{"value":"USER_ID","type":"user"}]}]}'
326
+
327
+ # Delete a SCIM group
328
+ curl -s -X DELETE -H "Authorization: Bearer $TOKEN" \
329
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Groups/GROUP_ID"
330
+ ```
331
+
332
+ ---
333
+
334
+ ## 3. SCIM Schemas (`scim-schemas`)
335
+
336
+ Retrieve the SCIM schema definitions that describe available attributes for Users and Groups. Useful for discovering which fields are available and their types before creating or updating resources.
337
+
338
+ ### Endpoints
339
+
340
+ | Method | Path | CLI Command |
341
+ |--------|------|-------------|
342
+ | GET | `/Schemas/SCIM2/Group` | `scim-schemas show` |
343
+ | GET | `/Schemas/SCIM2/User` | `scim-schemas show-user` |
344
+ | GET | `/Schemas/SCIM2/{schemaId}` | `scim-schemas show-scim2` |
345
+
346
+ ### Command Reference
347
+
348
+ | Command | Description | Key Options |
349
+ |---------|-------------|-------------|
350
+ | `show` | Get the Group schema definition | `-o json` |
351
+ | `show-user` | Get the User schema definition | `-o json` |
352
+ | `show-scim2` | Get a schema by its schema ID | `SCHEMA_ID` (positional), `-o json` |
353
+
354
+ ### CLI Examples
355
+
356
+ ```bash
357
+ # Get the SCIM User schema (discover all available user attributes)
358
+ wxcli scim-schemas show-user -o json
359
+
360
+ # Get the SCIM Group schema
361
+ wxcli scim-schemas show -o json
362
+
363
+ # Get a specific schema by ID (e.g., the Cisco extension schema)
364
+ wxcli scim-schemas show-scim2 "urn:scim:schemas:extension:cisco:webexidentity:2.0:User" -o json
365
+ ```
366
+
367
+ ### Key Schema URNs
368
+
369
+ | Schema URN | Description |
370
+ |------------|-------------|
371
+ | `urn:ietf:params:scim:schemas:core:2.0:User` | Core SCIM user attributes |
372
+ | `urn:ietf:params:scim:schemas:core:2.0:Group` | Core SCIM group attributes |
373
+ | `urn:ietf:params:scim:schemas:extension:enterprise:2.0:User` | IETF Enterprise User Extension — carries `costCenter`, `organization`, `division`, `department`, `employeeNumber`, `manager`. Required for provisioning flows that map org-chart attributes from IdPs like Azure AD or Okta; also the source of the `department` attribute used in SCIM search recipes. |
374
+ | `urn:scim:schemas:extension:cisco:webexidentity:2.0:User` | Cisco/Webex extension attributes for users |
375
+ | `urn:scim:schemas:extension:cisco:webexidentity:2.0:Group` | Cisco/Webex extension attributes for groups |
376
+ | `urn:ietf:params:scim:api:messages:2.0:PatchOp` | Schema for PATCH operation payloads |
377
+ | `urn:ietf:params:scim:api:messages:2.0:BulkRequest` | Schema for bulk operation request payloads |
378
+
379
+ ### Raw HTTP Fallback
380
+
381
+ ```bash
382
+ # Get the SCIM User schema
383
+ curl -s -H "Authorization: Bearer $TOKEN" \
384
+ "https://webexapis.com/Schemas/SCIM2/User"
385
+
386
+ # Get the SCIM Group schema
387
+ curl -s -H "Authorization: Bearer $TOKEN" \
388
+ "https://webexapis.com/Schemas/SCIM2/Group"
389
+
390
+ # Get a schema by ID (e.g., Cisco extension schema)
391
+ curl -s -H "Authorization: Bearer $TOKEN" \
392
+ "https://webexapis.com/Schemas/SCIM2/urn:scim:schemas:extension:cisco:webexidentity:2.0:User"
393
+ ```
394
+
395
+ ---
396
+
397
+ ## 4. SCIM Bulk Operations (`scim-bulk`)
398
+
399
+ Execute multiple SCIM user/group operations in a single HTTP request. Supports creating, updating, and deleting users and groups in bulk.
400
+
401
+ ### Endpoint
402
+
403
+ | Method | Path | CLI Command |
404
+ |--------|------|-------------|
405
+ | POST | `/identity/scim/{orgId}/v2/Bulk` | `scim-bulk create` |
406
+
407
+ ### Command Reference
408
+
409
+ | Command | Description | Key Options |
410
+ |---------|-------------|-------------|
411
+ | `create` | Execute a bulk SCIM operation | `ORG_ID` (positional), `--fail-on-errors` (required), `--json-body` |
412
+
413
+ The `--fail-on-errors` parameter specifies the maximum number of individual operation failures before the entire bulk request is aborted.
414
+
415
+ ### CLI Examples
416
+
417
+ ```bash
418
+ # Bulk create multiple users
419
+ wxcli scim-bulk create YOUR_ORG_ID --fail-on-errors 5 --json-body '{
420
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"],
421
+ "failOnErrors": 5,
422
+ "Operations": [
423
+ {
424
+ "method": "POST",
425
+ "path": "/Users",
426
+ "data": {
427
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
428
+ "userName": "alice@example.com",
429
+ "displayName": "Alice Smith",
430
+ "name": {"givenName": "Alice", "familyName": "Smith"},
431
+ "emails": [{"value": "alice@example.com", "type": "work", "primary": true}],
432
+ "active": true
433
+ }
434
+ },
435
+ {
436
+ "method": "POST",
437
+ "path": "/Users",
438
+ "data": {
439
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
440
+ "userName": "bob@example.com",
441
+ "displayName": "Bob Jones",
442
+ "name": {"givenName": "Bob", "familyName": "Jones"},
443
+ "emails": [{"value": "bob@example.com", "type": "work", "primary": true}],
444
+ "active": true
445
+ }
446
+ }
447
+ ]
448
+ }'
449
+
450
+ # Bulk deactivate users
451
+ wxcli scim-bulk create YOUR_ORG_ID --fail-on-errors 10 --json-body '{
452
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"],
453
+ "failOnErrors": 10,
454
+ "Operations": [
455
+ {
456
+ "method": "PATCH",
457
+ "path": "/Users/USER_ID_1",
458
+ "data": {
459
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
460
+ "Operations": [{"op": "replace", "path": "active", "value": false}]
461
+ }
462
+ },
463
+ {
464
+ "method": "PATCH",
465
+ "path": "/Users/USER_ID_2",
466
+ "data": {
467
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
468
+ "Operations": [{"op": "replace", "path": "active", "value": false}]
469
+ }
470
+ }
471
+ ]
472
+ }'
473
+
474
+ # Bulk delete users
475
+ wxcli scim-bulk create YOUR_ORG_ID --fail-on-errors 0 --json-body '{
476
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"],
477
+ "failOnErrors": 0,
478
+ "Operations": [
479
+ {"method": "DELETE", "path": "/Users/USER_ID_1"},
480
+ {"method": "DELETE", "path": "/Users/USER_ID_2"}
481
+ ]
482
+ }'
483
+ ```
484
+
485
+ ### Raw HTTP Fallback
486
+
487
+ ```bash
488
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" \
489
+ -H "Content-Type: application/json" \
490
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Bulk" \
491
+ -d '{"schemas":["urn:ietf:params:scim:api:messages:2.0:BulkRequest"],"failOnErrors":5,"Operations":[...]}'
492
+ ```
493
+
494
+ > **Gotcha — Bulk Operations Can Partially Fail:**
495
+ > A `scim-bulk create` request can succeed for some operations and fail for others. The `--fail-on-errors` parameter controls the threshold: if the number of failed operations exceeds this value, the remaining operations are not attempted. Always check the response body, which contains per-operation `status` codes.
496
+ >
497
+ > Example partial failure response (abridged):
498
+ > ```json
499
+ > {
500
+ > "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkResponse"],
501
+ > "Operations": [
502
+ > {"method": "POST", "location": "/Users/NEW_ID_1", "status": "201"},
503
+ > {"method": "POST", "status": "409", "response": {"detail": "User already exists"}}
504
+ > ]
505
+ > }
506
+ > ```
507
+
508
+ > **Gotcha — 100-Operation Limit Per Bulk Request:**
509
+ > A single bulk request may contain a maximum of **100 operations**. If you need to process more than 100 users or groups, split the work into multiple `scim-bulk create` calls.
510
+
511
+ > **Warning — Bulk DELETE Is Irreversible:**
512
+ > Bulk DELETE operations on users cannot be undone. There is no recycle bin or undo for SCIM deletes — once a user is deleted, their Webex identity, messages, and associated data are gone. Always verify your target user IDs against a dry-run list before issuing bulk DELETE operations.
513
+
514
+ ---
515
+
516
+ ## 5. Identity Organization (`identity-org`)
517
+
518
+ Manage identity-level organization settings and generate one-time passwords for users. All commands require an `org-id` positional argument.
519
+
520
+ ### Endpoints
521
+
522
+ | Method | Path | CLI Command |
523
+ |--------|------|-------------|
524
+ | GET | `/identity/organizations/{orgId}` | `identity-org show` |
525
+ | PATCH | `/identity/organizations/{orgId}` | `identity-org update` |
526
+ | POST | `/identity/organizations/{orgId}/users/{userId}/actions/generateOtp` | `identity-org generate-otp` |
527
+
528
+ ### Command Reference
529
+
530
+ | Command | Description | Key Options |
531
+ |---------|-------------|-------------|
532
+ | `show` | Get identity organization details | `ORG_ID` (positional) |
533
+ | `update` | Update organization settings | `--display-name`, `--preferred-language`, `--json-body` |
534
+ | `generate-otp` | Generate a one-time password for a user | `ORG_ID`, `USER_ID` (positional), `--json-body` |
535
+
536
+ ### CLI Examples
537
+
538
+ ```bash
539
+ # Get identity org details
540
+ wxcli identity-org show YOUR_ORG_ID -o json
541
+
542
+ # Update the org display name
543
+ wxcli identity-org update YOUR_ORG_ID --display-name "Acme Corp"
544
+
545
+ # Set default language for new users
546
+ wxcli identity-org update YOUR_ORG_ID --preferred-language "en_US"
547
+
548
+ # Generate OTP for a user (for first-time login or password reset)
549
+ wxcli identity-org generate-otp YOUR_ORG_ID USER_ID
550
+ ```
551
+
552
+ ### Raw HTTP Fallback
553
+
554
+ ```bash
555
+ # Get identity org
556
+ curl -s -H "Authorization: Bearer $TOKEN" \
557
+ "https://webexapis.com/identity/organizations/YOUR_ORG_ID"
558
+
559
+ # Update identity org
560
+ curl -s -X PATCH -H "Authorization: Bearer $TOKEN" \
561
+ -H "Content-Type: application/json" \
562
+ "https://webexapis.com/identity/organizations/YOUR_ORG_ID" \
563
+ -d '{"displayName": "Acme Corp", "preferredLanguage": "en_US"}'
564
+
565
+ # Generate OTP
566
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" \
567
+ "https://webexapis.com/identity/organizations/YOUR_ORG_ID/users/USER_ID/actions/generateOtp"
568
+ ```
569
+
570
+ ---
571
+
572
+ ## 6. Groups (Webex REST API) (`groups`)
573
+
574
+ Webex-native group management. Does not require `org-id` -- uses the authenticated token's organization.
575
+
576
+ ### Endpoints
577
+
578
+ | Method | Path | CLI Command |
579
+ |--------|------|-------------|
580
+ | GET | `/v1/groups` | `groups list` |
581
+ | POST | `/v1/groups` | `groups create` |
582
+ | GET | `/v1/groups/{groupId}` | `groups show` |
583
+ | PATCH | `/v1/groups/{groupId}` | `groups update` |
584
+ | DELETE | `/v1/groups/{groupId}` | `groups delete` |
585
+ | GET | `/v1/groups/{groupId}/members` | `groups list-members` |
586
+
587
+ ### Command Reference
588
+
589
+ | Command | Description | Key Options |
590
+ |---------|-------------|-------------|
591
+ | `list` | List and search groups | `--filter`, `--attributes`, `--sort-by`, `--sort-order`, `--include-members`, `--start-index`, `--count` |
592
+ | `create` | Create a group | `--display-name` (required), `--external-id`, `--json-body` |
593
+ | `show` | Get group details | `GROUP_ID` (positional), `--include-members` |
594
+ | `update` | Update a group (PATCH) | `GROUP_ID` (positional), `--json-body` |
595
+ | `delete` | Delete a group | `GROUP_ID` (positional), `--force` |
596
+ | `list-members` | Get group members with pagination | `GROUP_ID` (positional), `--start-index`, `--count` |
597
+
598
+ ### CLI Examples
599
+
600
+ ```bash
601
+ # List all groups
602
+ wxcli groups list
603
+
604
+ # Search groups by name
605
+ wxcli groups list --filter 'displayName eq "Sales Team"'
606
+
607
+ # List groups with members included
608
+ wxcli groups list --include-members true
609
+
610
+ # Create a group
611
+ wxcli groups create --display-name "Support Team"
612
+
613
+ # Create a group with members via JSON body
614
+ wxcli groups create --json-body '{
615
+ "displayName": "Support Team",
616
+ "members": [
617
+ {"id": "PERSON_ID_1", "type": "user"},
618
+ {"id": "PERSON_ID_2", "type": "user"}
619
+ ]
620
+ }'
621
+
622
+ # Get group details with members
623
+ wxcli groups show GROUP_ID --include-members true -o json
624
+
625
+ # List group members (paginated)
626
+ wxcli groups list-members GROUP_ID --count 100
627
+
628
+ # Update a group (add/remove members)
629
+ wxcli groups update GROUP_ID --json-body '{
630
+ "members": [
631
+ {"id": "PERSON_ID_1", "type": "user", "operation": "add"},
632
+ {"id": "PERSON_ID_3", "type": "user", "operation": "delete"}
633
+ ]
634
+ }'
635
+
636
+ # Delete a group
637
+ wxcli groups delete GROUP_ID --force
638
+ ```
639
+
640
+ ### Raw HTTP Fallback
641
+
642
+ ```bash
643
+ # List groups
644
+ curl -s -H "Authorization: Bearer $TOKEN" \
645
+ "https://webexapis.com/v1/groups?includeMembers=true"
646
+
647
+ # Get group members
648
+ curl -s -H "Authorization: Bearer $TOKEN" \
649
+ "https://webexapis.com/v1/groups/GROUP_ID/members?startIndex=1&count=100"
650
+
651
+ # Create a group
652
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" \
653
+ -H "Content-Type: application/json" \
654
+ "https://webexapis.com/v1/groups" \
655
+ -d '{"displayName": "Support Team"}'
656
+ ```
657
+
658
+ ---
659
+
660
+ ## 7. People (Webex REST API) (`people`)
661
+
662
+ Webex-native user management. Does not require `org-id` -- uses the authenticated token's organization. Supports Webex Calling data inclusion via `--calling-data`.
663
+
664
+ ### Endpoints
665
+
666
+ | Method | Path | CLI Command |
667
+ |--------|------|-------------|
668
+ | GET | `/v1/people` | `people list` |
669
+ | POST | `/v1/people` | `people create` |
670
+ | GET | `/v1/people/{personId}` | `people show` |
671
+ | PUT | `/v1/people/{personId}` | `people update` |
672
+ | DELETE | `/v1/people/{personId}` | `people delete` |
673
+ | GET | `/v1/people/me` | `people list-me` |
674
+
675
+ ### Command Reference
676
+
677
+ | Command | Description | Key Options |
678
+ |---------|-------------|-------------|
679
+ | `list` | List people in the org | `--email`, `--display-name`, `--id` (up to 85 IDs), `--roles`, `--calling-data`, `--location-id`, `--max`, `--exclude-status` |
680
+ | `create` | Create a person | `--display-name`, `--first-name`, `--last-name`, `--extension`, `--location-id`, `--org-id`, `--department`, `--manager`, `--manager-id`, `--title`, `--avatar`, `--json-body` |
681
+ | `show` | Get person details | `PERSON_ID` (positional) |
682
+ | `update` | Update a person (PUT) | `PERSON_ID` (positional), `--display-name`, `--first-name`, `--last-name`, `--nick-name`, `--extension`, `--location-id`, `--department`, `--manager`, `--manager-id`, `--title`, `--avatar`, `--login-enabled/--no-login-enabled`, `--json-body` |
683
+ | `delete` | Delete a person | `PERSON_ID` (positional), `--force` |
684
+ | `list-me` | Get your own details | `--calling-data` |
685
+
686
+ ### CLI Examples
687
+
688
+ ```bash
689
+ # List all people in the org
690
+ wxcli people list
691
+
692
+ # Search by email
693
+ wxcli people list --email "jsmith@example.com"
694
+
695
+ # Search by display name prefix
696
+ wxcli people list --display-name "John"
697
+
698
+ # List people with Webex Calling details
699
+ wxcli people list --calling-data true --location-id LOCATION_ID
700
+
701
+ # List people by multiple IDs
702
+ wxcli people list --id "ID1,ID2,ID3"
703
+
704
+ # Get a specific person
705
+ wxcli people show PERSON_ID -o json
706
+
707
+ # Create a new person (emails must be passed via --json-body)
708
+ wxcli people create --json-body '{
709
+ "emails": ["newuser@example.com"],
710
+ "displayName": "New User",
711
+ "firstName": "New",
712
+ "lastName": "User",
713
+ "orgId": "YOUR_ORG_ID"
714
+ }'
715
+
716
+ # Update a person's department and title
717
+ wxcli people update PERSON_ID --department "Engineering" --title "Staff Engineer"
718
+
719
+ # Disable a person's login
720
+ wxcli people update PERSON_ID --no-login-enabled
721
+
722
+ # Delete a person
723
+ wxcli people delete PERSON_ID --force
724
+
725
+ # Get your own details (with calling data)
726
+ wxcli people list-me --calling-data true -o json
727
+ ```
728
+
729
+ ### Raw HTTP Fallback
730
+
731
+ ```bash
732
+ # List people by email
733
+ curl -s -H "Authorization: Bearer $TOKEN" \
734
+ "https://webexapis.com/v1/people?email=jsmith%40example.com"
735
+
736
+ # Get person with calling data
737
+ curl -s -H "Authorization: Bearer $TOKEN" \
738
+ "https://webexapis.com/v1/people/PERSON_ID?callingData=true"
739
+
740
+ # Create a person
741
+ curl -s -X POST -H "Authorization: Bearer $TOKEN" \
742
+ -H "Content-Type: application/json" \
743
+ "https://webexapis.com/v1/people" \
744
+ -d '{"emails":["user@example.com"],"displayName":"New User","firstName":"New","lastName":"User"}'
745
+
746
+ # Update a person (PUT -- sends full replacement)
747
+ curl -s -X PUT -H "Authorization: Bearer $TOKEN" \
748
+ -H "Content-Type: application/json" \
749
+ "https://webexapis.com/v1/people/PERSON_ID" \
750
+ -d '{ ... full person JSON ... }'
751
+
752
+ # Get my own details
753
+ curl -s -H "Authorization: Bearer $TOKEN" \
754
+ "https://webexapis.com/v1/people/me?callingData=true"
755
+ ```
756
+
757
+ > **Gotcha — People API: emails Must Use --json-body:**
758
+ > The `people create` command does not have a `--emails` CLI option. The `emails` field (an array of objects) is too complex for a simple CLI flag. Use `--json-body` to pass the emails array:
759
+ > ```bash
760
+ > wxcli people create --json-body '{"emails": ["user@example.com"], "displayName": "User Name"}'
761
+ > ```
762
+
763
+ > **Gotcha — People API: update is PUT (Full Replace):**
764
+ > Like the SCIM PUT, `people update` uses HTTP PUT. It replaces the entire person record. The CLI does **not** do a GET-merge-PUT for flag-based options -- it sends only the specified fields in the PUT body, which means unspecified fields may be cleared by the API. Always use `--json-body` with the full person record for safe updates, or use the GET-modify-PUT pattern shown in the SCIM section above.
765
+
766
+ > **Gotcha — `callingData=true` Caps Results at 100 Per Page:**
767
+ > When `--calling-data true` is specified on `people list`, the API limits results to **100 per page** (down from the normal 1000). If `--location-id` is also specified alongside `--calling-data true`, the cap drops further to **50 per page**. Paginate using `--start-index` (or the `@odata.nextLink` in the raw response) to retrieve the full result set.
768
+
769
+ ---
770
+
771
+ ## Recipes
772
+
773
+ ### SCIM Bulk User Import
774
+
775
+ Import multiple users from a CSV/list in a single API call:
776
+
777
+ ```bash
778
+ # Build a bulk request JSON file, then submit
779
+ wxcli scim-bulk create YOUR_ORG_ID --fail-on-errors 5 --json-body '{
780
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"],
781
+ "failOnErrors": 5,
782
+ "Operations": [
783
+ {
784
+ "method": "POST",
785
+ "path": "/Users",
786
+ "data": {
787
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
788
+ "userName": "user1@example.com",
789
+ "displayName": "User One",
790
+ "name": {"givenName": "User", "familyName": "One"},
791
+ "emails": [{"value": "user1@example.com", "type": "work", "primary": true}],
792
+ "active": true
793
+ }
794
+ },
795
+ {
796
+ "method": "POST",
797
+ "path": "/Users",
798
+ "data": {
799
+ "schemas": ["urn:ietf:params:scim:schemas:core:2.0:User"],
800
+ "userName": "user2@example.com",
801
+ "displayName": "User Two",
802
+ "name": {"givenName": "User", "familyName": "Two"},
803
+ "emails": [{"value": "user2@example.com", "type": "work", "primary": true}],
804
+ "active": true
805
+ }
806
+ }
807
+ ]
808
+ }'
809
+ ```
810
+
811
+ Check the response for per-operation status. Each operation in the response has its own `status` code (e.g., `201` for created, `409` for conflict/duplicate).
812
+
813
+ ### Search Users by Email or Department
814
+
815
+ ```bash
816
+ # SCIM: exact email match
817
+ wxcli scim-users list YOUR_ORG_ID --filter 'userName eq "target@example.com"'
818
+
819
+ # SCIM: users whose email contains a domain
820
+ wxcli scim-users list YOUR_ORG_ID --filter 'userName co "@acme.com"'
821
+
822
+ # People API: search by email
823
+ wxcli people list --email "target@example.com"
824
+
825
+ # People API: search by name prefix
826
+ wxcli people list --display-name "John"
827
+
828
+ # SCIM: search users by department (Enterprise Extension attribute)
829
+ wxcli scim-users list YOUR_ORG_ID --filter 'department eq "Engineering"'
830
+
831
+ # SCIM: search users whose department starts with "Eng"
832
+ wxcli scim-users list YOUR_ORG_ID --filter 'department sw "Eng"'
833
+ ```
834
+
835
+ ### Bulk Deactivate Stale Users
836
+
837
+ Deactivate users who should no longer have Webex access. Use PATCH for efficiency (no need to send the full user record):
838
+
839
+ ```bash
840
+ # Step 1: Identify users to deactivate (list and filter externally)
841
+ wxcli scim-users list YOUR_ORG_ID --filter 'active eq true' -o json > active_users.json
842
+
843
+ # Step 2: For each user to deactivate, PATCH their active status
844
+ wxcli scim-users update-users YOUR_ORG_ID USER_ID --json-body '{
845
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
846
+ "Operations": [{"op": "replace", "path": "active", "value": false}]
847
+ }'
848
+
849
+ # Or use bulk operations for many users at once
850
+ wxcli scim-bulk create YOUR_ORG_ID --fail-on-errors 10 --json-body '{
851
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:BulkRequest"],
852
+ "failOnErrors": 10,
853
+ "Operations": [
854
+ {"method": "PATCH", "path": "/Users/USER_ID_1", "data": {"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [{"op": "replace", "path": "active", "value": false}]}},
855
+ {"method": "PATCH", "path": "/Users/USER_ID_2", "data": {"schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"], "Operations": [{"op": "replace", "path": "active", "value": false}]}}
856
+ ]
857
+ }'
858
+ ```
859
+
860
+ ### Group Membership Management
861
+
862
+ ```bash
863
+ # Webex Groups API: list members of a group
864
+ wxcli groups list-members GROUP_ID
865
+
866
+ # Webex Groups API: add a member
867
+ wxcli groups update GROUP_ID --json-body '{
868
+ "members": [{"id": "PERSON_ID", "type": "user", "operation": "add"}]
869
+ }'
870
+
871
+ # SCIM Groups: add members via PATCH
872
+ wxcli scim-groups update-groups YOUR_ORG_ID SCIM_GROUP_ID --json-body '{
873
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
874
+ "Operations": [
875
+ {"op": "add", "path": "members", "value": [{"value": "SCIM_USER_ID", "type": "user"}]}
876
+ ]
877
+ }'
878
+
879
+ # SCIM Groups: remove a specific member
880
+ wxcli scim-groups update-groups YOUR_ORG_ID SCIM_GROUP_ID --json-body '{
881
+ "schemas": ["urn:ietf:params:scim:api:messages:2.0:PatchOp"],
882
+ "Operations": [
883
+ {"op": "remove", "path": "members[value eq \"SCIM_USER_ID\"]"}
884
+ ]
885
+ }'
886
+ ```
887
+
888
+ ### OTP Generation
889
+
890
+ Generate a one-time password for a user who needs to sign in for the first time or has been locked out:
891
+
892
+ ```bash
893
+ # Generate OTP for a user
894
+ wxcli identity-org generate-otp YOUR_ORG_ID USER_ID
895
+
896
+ # The response contains the OTP value -- share it securely with the user
897
+ ```
898
+
899
+ ---
900
+
901
+ ## Gotchas
902
+
903
+ ### /me Endpoints Require User-Level Tokens
904
+
905
+ `scim-users show-me` and `people list-me` hit the `/me` endpoint, which returns the identity of the authenticated user. These commands fail with admin service-app tokens because service apps do not represent a person. Use a user-level OAuth token (authorization code grant flow) instead.
906
+
907
+ ### orgId Requirement on SCIM Commands
908
+
909
+ All SCIM commands (`scim-users`, `scim-groups`, `scim-bulk`) require `ORG_ID` as a positional argument because the org ID is part of the URL path (`/identity/scim/{orgId}/v2/...`). It cannot be omitted or inferred from the token. The Webex REST API commands (`people`, `groups`) do not require it -- they use the org implied by the token.
910
+
911
+ ### Scope Troubleshooting for Identity Scopes
912
+
913
+ SCIM endpoints use `identity:*` scopes, not the `spark-admin:*` scopes used by People and Groups. If you get a 403 on SCIM endpoints, check:
914
+
915
+ 1. Your integration/service-app has `identity:people_rw` or `identity:people_read` granted.
916
+ 2. For `identity-org` endpoints, you need `identity:organizations_rw` or `identity:organizations_read`.
917
+ 3. For OTP generation, you need `Identity:one_time_password` (note the capital "I" in `Identity`). An alternative scope is `Identity:Config`.
918
+ 4. These identity scopes must be explicitly requested during OAuth authorization. They are separate from the `spark-admin:people_*` scopes.
919
+
920
+ ### SCIM Filter URL Encoding
921
+
922
+ SCIM filter values must be URL-encoded when used in raw HTTP requests. The CLI handles this automatically for the `--filter` parameter, but if you are using `curl` directly, you must encode the filter:
923
+
924
+ ```bash
925
+ # CLI handles encoding automatically
926
+ wxcli scim-users list YOUR_ORG_ID --filter 'userName eq "user@example.com"'
927
+
928
+ # Raw curl requires manual encoding
929
+ curl -s -H "Authorization: Bearer $TOKEN" \
930
+ "https://webexapis.com/identity/scim/YOUR_ORG_ID/v2/Users?filter=userName%20eq%20%22user%40example.com%22"
931
+ ```
932
+
933
+ ### Bracket Filter Syntax — No Space Before `[`
934
+
935
+ The official docs show `phoneNumbers [ type eq "mobile" and value eq "..." ]` with a space before `[`. This does not parse correctly. The working syntax has no space:
936
+
937
+ ```
938
+ phoneNumbers[type eq "alternate1" and value eq "+19197010928"]
939
+ ```
940
+
941
+ URL encoded:
942
+ ```
943
+ phoneNumbers%5Btype%20eq%20%22alternate1%22%20and%20value%20eq%20%22%2B19197010928%22%5D
944
+ ```
945
+
946
+ ### `phoneNumbers.value` Dot Notation Not Implemented
947
+
948
+ The supported attributes table lists `phoneNumbers.value` with `eq`, `sw`, `ew` operators. In practice this returns:
949
+
950
+ ```json
951
+ {"status": "400", "scimType": "invalidFilter", "details": "The user's attribute phoneNumbers.value in request can not find correspond table name."}
952
+ ```
953
+
954
+ Use the bracket filter syntax instead: `phoneNumbers[type eq "alternate1" and value eq "..."]`.
955
+
956
+ ### `+` in Phone Number Filter Values Must Be Encoded as `%2B`
957
+
958
+ The SCIM server decodes `+` in query strings as a space (form encoding). A filter like `value eq "+19197010928"` with a literal `+` in the URL will be received by the server as `value eq " 19197010928"` and return zero results.
959
+
960
+ Always encode `+` as `%2B` in filter values:
961
+
962
+ ```
963
+ # Wrong — + decoded as space, zero results
964
+ filter=phoneNumbers%5Btype%20eq%20%22alternate1%22%20and%20value%20eq%20%22+19197010928%22%5D
965
+
966
+ # Correct — %2B preserved as literal +
967
+ filter=phoneNumbers%5Btype%20eq%20%22alternate1%22%20and%20value%20eq%20%22%2B19197010928%22%5D
968
+ ```
969
+
970
+ ### SCIM from WxCC Flow Designer HTTP Request Nodes
971
+
972
+ The SCIM API requires `identity:people_read` scope — separate from `spark-admin:people_read`. A PAT from developer.webex.com works for testing but expires after 12 hours. For production, use an OAuth Integration or Service App with `identity:people_read` explicitly selected.
973
+
974
+ **Two-node pattern to look up a user by alternate1 phone number and retrieve their profile:**
975
+
976
+ **Node 1 — Search by phone number:**
977
+ - URL: `https://webexapis.com/identity/scim/{orgId}/v2/Users`
978
+ - Query param key: `filter`
979
+ - Query param value (with `DNIS` variable containing digits only, no `+`): `phoneNumbers%5Btype%20eq%20%22alternate1%22%20and%20value%20eq%20%22%2B{{DNIS}}%22%5D`
980
+ - JSONPath to extract user ID: `$.Resources[0].id` → store in e.g. `StoreUserPersonId`
981
+
982
+ **Node 2 — Get full profile by ID:**
983
+ - URL: `https://webexapis.com/identity/scim/{orgId}/v2/Users/{{StoreUserPersonId}}`
984
+ - No filter needed
985
+ - JSONPath to extract alternate1 value: `$.phoneNumbers[?(@.type=='alternate1')].value`
986
+
987
+ **Stripping `+` from DNIS in Flow Designer:**
988
+
989
+ DNIS arrives in E.164 format (e.g. `+19197010928`). Strip the `+` using a Set Variable node before the HTTP node:
990
+
991
+ ```
992
+ {{NewContact.DNIS | slice(1)}}
993
+ ```
994
+
995
+ - `| slice(1)` works in WxCC Flow Designer (Pebble)
996
+ - `| replace("+", "%2B")` does NOT work — `+` is a regex special character and fails silently
997
+ - `.substring(1)` does NOT work in Flow Designer expression context
998
+ - Hardcode `%2B` in the filter template and substitute only the digits via `{{DNIS}}`
999
+
1000
+ ---
1001
+
1002
+ ## See Also
1003
+
1004
+ - [provisioning.md](provisioning.md) -- For Webex Calling user provisioning (licenses, extensions, locations)
1005
+ - [person-call-settings-handling.md](person-call-settings-handling.md) -- For calling-specific person settings (forwarding, DND, sim ring)
1006
+ - [person-call-settings-behavior.md](person-call-settings-behavior.md) -- For calling behavior, hoteling, numbers
1007
+ - [authentication.md](authentication.md) -- OAuth flows, token types, scope management