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,849 @@
1
+ <!-- Not directly verified via CLI — documents wxcadm library (not generated CLI commands) -->
2
+ <!-- wxcadm v4.6.1 review 2026-03-27: All v4.5.0–v4.6.1 changes verified present. AutoAttendantList(org, location), CallQueueList(org, location), HuntGroupList(org, location) signatures, RecordingList.reassign_owner(), Recording.metadata property, ComplianceAnnouncementSettings.push() implementation, OrgRecordingVendorSelection.set_failure_behavior still unimplemented — all accurately documented. No discrepancies found. -->
3
+ # wxcadm Call Features Reference
4
+
5
+ Reference document covering wxcadm's call feature modules: Auto Attendant, Call Queue, Hunt Group, Pickup Group, Announcements (including Playlists), and Recording.
6
+
7
+ All source paths are relative to the `wxcadm` package root.
8
+
9
+ ---
10
+
11
+ <!-- Updated by playbook session 2026-03-18 -->
12
+ ## When to Use wxcadm vs Raw HTTP
13
+
14
+ | Use wxcadm when | Use raw HTTP when |
15
+ |---|---|
16
+ | You want **convenience wrappers** for Auto Attendant, Call Queue, or Hunt Group creation with sensible defaults | You need full control over the request payload (e.g., setting fields wxcadm doesn't expose) |
17
+ | You want **list-based discovery** — `org.auto_attendants`, `org.call_queues`, etc. with cached lookup by name/ID | You're doing targeted CRUD on a known feature ID |
18
+ | You need **announcement upload** convenience (`upload_greeting()` methods) | You need to configure advanced settings that wxcadm methods don't cover |
19
+
20
+ > **Note:** The playbook uses raw HTTP via `api.session.rest_*()` for all feature CRUD (Auto Attendant, Call Queue, Hunt Group, Pickup Group, etc.). wxcadm provides no unique capability here that raw HTTP cannot replicate — the same REST endpoints back both approaches. wxcadm's value in this area is convenience (simpler method signatures, cached lists), not exclusivity. Prefer raw HTTP for predictability and full payload control.
21
+
22
+ ---
23
+
24
+ ## Table of Contents
25
+
26
+ 1. [Auto Attendant](#auto-attendant)
27
+ 2. [Call Queue](#call-queue)
28
+ 3. [Hunt Group](#hunt-group)
29
+ 4. [Pickup Group](#pickup-group)
30
+ 5. [Announcements](#announcements)
31
+ 6. [Playlists](#playlists)
32
+ 7. [Recording](#recording)
33
+ 8. [wxcadm vs wxc_sdk Comparison](#wxcadm-vs-wxc_sdk-comparison)
34
+
35
+ ---
36
+
37
+ ## Auto Attendant
38
+
39
+ **Source:** `wxcadm/auto_attendant.py`
40
+
41
+ ### Overview
42
+
43
+ Auto Attendants provide IVR menus that route callers based on key presses, extension dialing, or name dialing. wxcadm models them as an `AutoAttendantList` (a `UserList` subclass) containing `AutoAttendant` dataclass instances. The list can be scoped to the whole Org or to a single Location.
44
+
45
+ ### AutoAttendantList
46
+
47
+ Collection class. Inherits `UserList`.
48
+
49
+ **Constructor:**
50
+
51
+ ```python
52
+ AutoAttendantList(org: Org, location: Optional[Location] = None)
53
+ ```
54
+
55
+ - When `location` is provided, only Auto Attendants at that Location are fetched.
56
+ - API endpoint: `GET v1/telephony/config/autoAttendants` (with optional `locationId` param).
57
+
58
+ **Methods:**
59
+
60
+ | Method | Signature | Returns | Description |
61
+ |--------|-----------|---------|-------------|
62
+ | `refresh` | `refresh() -> bool` | `True` | Re-fetches the list from Webex |
63
+ | `get` | `get(id=None, name=None, spark_id=None, uuid=None) -> AutoAttendant \| None` | `AutoAttendant` or `None` | Looks up by ID, Name, UUID, or Spark ID (searched in that order). Raises `ValueError` if no argument provided. |
64
+ | `create` | See full signature below | `AutoAttendant` | Creates a new Auto Attendant at a Location |
65
+
66
+ **`create` full signature:**
67
+
68
+ ```python
69
+ def create(self,
70
+ name: str,
71
+ first_name: str,
72
+ last_name: str,
73
+ phone_number: Optional[str],
74
+ extension: Optional[str],
75
+ business_hours_schedule: str,
76
+ holiday_schedule: Optional[str],
77
+ business_hours_menu: Optional[dict] = None,
78
+ after_hours_menu: Optional[dict] = None,
79
+ extension_dialing_scope: str = "GROUP",
80
+ name_dialing_scope: str = "GROUP",
81
+ language: Optional[str] = None,
82
+ time_zone: Optional[str] = None,
83
+ location: Optional[Location] = None
84
+ ) -> AutoAttendant
85
+ ```
86
+
87
+ - `phone_number` and/or `extension` must be provided (at least one).
88
+ - `business_hours_menu` / `after_hours_menu` default to a simple menu with key `0` = EXIT and extension dialing enabled.
89
+ - `language` and `time_zone` default to the Location's `announcement_language` and `time_zone`.
90
+ - `extension_dialing_scope` / `name_dialing_scope` accept `"GROUP"` or `"ENTERPRISE"`.
91
+ - `location` is required when the list is at the Org level; optional at the Location level.
92
+ - API endpoint: `POST v1/telephony/config/locations/{locationId}/autoAttendants`
93
+
94
+ ### AutoAttendant
95
+
96
+ Dataclass representing a single Auto Attendant.
97
+
98
+ **Constructor fields:**
99
+
100
+ | Field | Type | Description |
101
+ |-------|------|-------------|
102
+ | `org` | `Org` | Parent Org (not shown in repr) |
103
+ | `id` | `str` | Webex ID |
104
+ | `data` | `dict` | Raw API response dict |
105
+
106
+ **Attributes set from list-level data (available immediately):**
107
+
108
+ | Attribute | Type | Description |
109
+ |-----------|------|-------------|
110
+ | `name` | `str` | AA name |
111
+ | `location_id` | `str` | Owning Location ID |
112
+ | `phone_number` | `Optional[str]` | DID |
113
+ | `extension` | `Optional[str]` | Extension |
114
+ | `routing_prefix` | `Optional[str]` | Routing prefix |
115
+ | `esn` | `Optional[str]` | ESN |
116
+ | `toll_free_number` | `bool` | Whether the number is toll-free |
117
+
118
+ **Lazy-loaded properties (trigger a detail API call on first access):**
119
+
120
+ | Property | Type | Description |
121
+ |----------|------|-------------|
122
+ | `enabled` | `bool` | Whether the AA is enabled |
123
+ | `first_name` | `str` | Directory first name |
124
+ | `last_name` | `str` | Directory last name |
125
+ | `alternate_numbers` | `list` | Alternate numbers |
126
+ | `language` | `str` | Language display name |
127
+ | `language_code` | `str` | Language code (e.g. `en_us`) |
128
+ | `business_schedule` | `str` | Business hours schedule name |
129
+ | `holiday_schedule` | `str` | Holiday schedule name |
130
+ | `extension_dialing` | `str` | `GROUP` or `ENTERPRISE` |
131
+ | `name_dialing` | `str` | `GROUP` or `ENTERPRISE` |
132
+ | `time_zone` | `str` | Time zone string |
133
+ | `business_hours_menu` | `dict` | Business hours menu config |
134
+ | `after_hours_menu` | `dict` | After hours menu config |
135
+ | `spark_id` | `str` | Decoded Spark ID |
136
+ | `config` | `dict` | Full JSON config (always fetches fresh) |
137
+
138
+ **Additional properties and methods:**
139
+
140
+ | Member | Signature | Returns | Description |
141
+ |--------|-----------|---------|-------------|
142
+ | `call_forwarding` | `@property -> dict` | `dict` | Call Forwarding settings (GET `.../callForwarding`) |
143
+ | `copy_menu_from_template` | `copy_menu_from_template(source: AutoAttendant, menu_type: str = "both") -> bool` | `bool` | Copies business hours, after hours, or both menus from another AA. **Limitation:** does not work with CUSTOM announcements (only DEFAULT greetings). Accepts `"business_hours"`, `"after_hours"`, or `"both"`. |
144
+
145
+ **Detail API endpoint:** `GET v1/telephony/config/locations/{locationId}/autoAttendants/{id}`
146
+
147
+ ---
148
+
149
+ ## Call Queue
150
+
151
+ **Source:** `wxcadm/call_queue.py`
152
+
153
+ ### Overview
154
+
155
+ Call Queues distribute incoming calls to a pool of agents with configurable routing policies, queue behavior, and overflow handling. wxcadm provides `CallQueueList`, `CallQueue`, and `OrgQueueSettings`.
156
+
157
+ ### OrgQueueSettings
158
+
159
+ Dataclass (decorated with `@dataclass_json`) for org-wide queue settings. Related to Customer Assist (formerly CX Essentials) features.
160
+
161
+ **Attributes:**
162
+
163
+ | Attribute | API Field | Type | Description |
164
+ |-----------|-----------|------|-------------|
165
+ | `maintain_queue_position_for_sim_ring` | `maintainQueuePositionForSimRingEnabled` | `bool` | Maintain queue position for Simultaneous routing |
166
+ | `agent_unavailable_on_bounce` | `forceAgentUnavailableOnBouncedEnabled` | `bool` | Mark agent unavailable when calls bounce |
167
+ | `play_barge_in_tone` | `playToneToAgentForBargeInEnabled` | `bool` | Notification tone for Supervisor Barge-In |
168
+ | `play_monitoring_tone` | `playToneToAgentForSilentMonitoringEnabled` | `bool` | Notification tone for Supervisor Silent Monitoring |
169
+ | `play_whisper_tone` | `playToneToAgentForSupervisorCoachingEnabled` | `bool` | Notification tone for Supervisor Coaching (whisper) |
170
+
171
+ **Methods:**
172
+
173
+ ```python
174
+ def set(self,
175
+ maintain_queue_position_for_sim_ring: Optional[bool] = None,
176
+ agent_unavailable_on_bounce: Optional[bool] = None,
177
+ play_barge_in_tone: Optional[bool] = None,
178
+ play_monitoring_tone: Optional[bool] = None,
179
+ play_whisper_tone: Optional[bool] = None
180
+ ) -> bool
181
+ ```
182
+
183
+ Sets one or more attributes and pushes to Webex via `PUT v1/telephony/config/queues/settings`.
184
+
185
+ ### CallQueueList
186
+
187
+ Collection class. Inherits `UserList`.
188
+
189
+ **Constructor:**
190
+
191
+ ```python
192
+ CallQueueList(org: Org, location: Optional[Location] = None)
193
+ ```
194
+
195
+ - API endpoint: `GET v1/telephony/config/queues` (with optional `locationId` param).
196
+
197
+ **Methods:**
198
+
199
+ | Method | Signature | Returns | Description |
200
+ |--------|-----------|---------|-------------|
201
+ | `refresh` | `refresh() -> bool` | `True` | Re-fetches the list from Webex |
202
+ | `get` | `get(id=None, name=None, spark_id=None, uuid=None) -> CallQueue \| None` | `CallQueue` or `None` | Looks up by ID, Name (case-insensitive), UUID, or Spark ID. Raises `ValueError` if no argument. |
203
+ | `create` | See full signature below | `CallQueue` | Creates a new Call Queue at a Location |
204
+
205
+ **`create` full signature:**
206
+
207
+ ```python
208
+ def create(self,
209
+ name: str,
210
+ first_name: str,
211
+ last_name: str,
212
+ phone_number: Optional[str],
213
+ extension: Optional[str],
214
+ call_policies: dict,
215
+ queue_settings: dict,
216
+ language: Optional[str] = None,
217
+ time_zone: Optional[str] = None,
218
+ allow_agent_join: Optional[bool] = False,
219
+ allow_did_for_outgoing_calls: Optional[bool] = False,
220
+ location: Optional[Location] = None
221
+ ) -> CallQueue
222
+ ```
223
+
224
+ - `call_policies` and `queue_settings` are required dicts; their formats change frequently so consult developer.webex.com.
225
+ - `language` / `time_zone` default to the Location values.
226
+ - `location` required at Org level, implied at Location level.
227
+ - API endpoint: `POST v1/telephony/config/locations/{locationId}/queues`
228
+
229
+ ### CallQueue
230
+
231
+ Represents a single Call Queue.
232
+
233
+ **Attributes (set on init from list data):**
234
+
235
+ | Attribute | Type | Description |
236
+ |-----------|------|-------------|
237
+ | `org` | `Org` | Parent Org |
238
+ | `id` | `str` | Webex ID |
239
+ | `name` | `str` | Queue name |
240
+ | `location_id` | `str` | Location ID |
241
+ | `phone_number` | `str` | DID |
242
+ | `extension` | `str` | Extension |
243
+ | `enabled` | `bool` | Whether the queue is enabled |
244
+
245
+ **Properties and methods:**
246
+
247
+ | Member | Signature | Returns | Description |
248
+ |--------|-----------|---------|-------------|
249
+ | `spark_id` | `@property -> str` | `str` | Decoded Spark ID |
250
+ | `config` | `@property -> dict` | `dict` | Full queue config (fetches fresh each time) |
251
+ | `call_forwarding` | `@property -> dict` | `dict` | Call Forwarding settings |
252
+ | `agents` | `@property -> list` | `list` | List of agents from the config |
253
+ | `add_agent` | `add_agent(agent: Person \| Workspace, weight=None, skill=None, joined=True) -> bool` | `bool` | **Not implemented** (`pass` in source, with `# TODO: Fix this` comment) |
254
+ | `push` | `push() -> dict` | `dict` | Pushes `self.config` back to Webex via PUT |
255
+
256
+ **Method aliases:**
257
+
258
+ - `get_queue_config` = `config`
259
+ - `get_queue_forwarding` = `call_forwarding`
260
+
261
+ ---
262
+
263
+ ## Hunt Group
264
+
265
+ **Source:** `wxcadm/hunt_group.py`
266
+
267
+ ### Overview
268
+
269
+ Hunt Groups route calls to a list of agents according to a call policy (simultaneous, regular/sequential, circular, weighted). wxcadm provides `HuntGroupList` and `HuntGroup`.
270
+
271
+ ### HuntGroupList
272
+
273
+ Collection class. Inherits `UserList`.
274
+
275
+ **Constructor:**
276
+
277
+ ```python
278
+ HuntGroupList(org: Org, location: Optional[Location] = None)
279
+ ```
280
+
281
+ - API endpoint: `GET v1/telephony/config/huntGroups` (with optional `locationId` param).
282
+
283
+ **Methods:**
284
+
285
+ | Method | Signature | Returns | Description |
286
+ |--------|-----------|---------|-------------|
287
+ | `refresh` | `refresh() -> bool` | `True` | Re-fetches from Webex |
288
+ | `get` | `get(id=None, name=None, spark_id=None, uuid=None) -> HuntGroup \| None` | `HuntGroup` or `None` | Case-insensitive name match. Raises `ValueError` if no argument. |
289
+ | `create` | See full signature below | `HuntGroup` | Creates a new Hunt Group |
290
+
291
+ > **Bug note:** The `get` method contains a typo on the `uuid` branch -- `item.spark_id.split('/')[-1].uppper()` should be `.upper()`. This will raise `AttributeError` at runtime when searching by UUID.
292
+
293
+ **`create` full signature:**
294
+
295
+ ```python
296
+ def create(self,
297
+ name: str,
298
+ first_name: str,
299
+ last_name: str,
300
+ phone_number: Optional[str] = None,
301
+ extension: Optional[str] = None,
302
+ call_policies: Optional[dict] = None,
303
+ enabled: bool = True,
304
+ language: Optional[str] = None,
305
+ time_zone: Optional[str] = None,
306
+ location: Optional[Location] = None,
307
+ agents: Optional[list] = None,
308
+ allow_as_agent_caller_id: bool = False
309
+ ) -> HuntGroup
310
+ ```
311
+
312
+ - `call_policies` defaults to a SIMULTANEOUS policy with no forwarding if not provided. Example structure:
313
+
314
+ ```python
315
+ {
316
+ 'policy': 'SIMULTANEOUS', # or 'REGULAR', 'CIRCULAR', 'WEIGHTED'
317
+ 'waitingEnabled': False,
318
+ 'groupBusyEnabled': False,
319
+ 'allowMembersToControlGroupBusyEnabled': False,
320
+ 'noAnswer': {
321
+ 'nextAgentEnabled': False,
322
+ 'nextAgentRings': 5,
323
+ 'forwardEnabled': False,
324
+ 'numberOfRings': 15,
325
+ 'systemMaxNumberOfRings': 20,
326
+ 'destinationVoicemailEnabled': False
327
+ },
328
+ 'busyRedirect': {
329
+ 'enabled': False,
330
+ 'destinationVoicemailEnabled': False,
331
+ },
332
+ 'businessContinuityRedirect': {
333
+ 'enabled': False,
334
+ 'destinationVoicemailEnabled': False
335
+ }
336
+ }
337
+ ```
338
+
339
+ - `agents` accepts a list of `Person`, `Workspace`, or `VirtualLine` instances.
340
+ - `allow_as_agent_caller_id` maps to `huntGroupCallerIdForOutgoingCallsEnabled` in the API.
341
+ - API endpoint: `POST v1/telephony/config/locations/{locationId}/huntGroups`
342
+
343
+ ### HuntGroup
344
+
345
+ Represents a single Hunt Group.
346
+
347
+ **Attributes (set on init):**
348
+
349
+ | Attribute | Type | Description |
350
+ |-----------|------|-------------|
351
+ | `org` | `Org` | Parent Org |
352
+ | `id` | `str` | Webex ID |
353
+ | `name` | `str` | Hunt Group name |
354
+ | `location_id` | `str` | Location ID |
355
+ | `enabled` | `bool` | Whether enabled |
356
+ | `phone_number` | `str` | DID |
357
+ | `extension` | `str` | Extension |
358
+
359
+ **Properties and methods:**
360
+
361
+ | Member | Signature | Returns | Description |
362
+ |--------|-----------|---------|-------------|
363
+ | `config` | `@property -> dict` | `dict` | Full config (fresh fetch) |
364
+ | `agents` | `@property -> list` | `list` | Agent list from config |
365
+ | `spark_id` | `@property -> str` | `str` | Decoded Spark ID |
366
+ | `add_agent` | `add_agent(agent: Person \| Workspace \| VirtualLine, weight: Optional[str] = None) -> bool` | `True` | Adds an agent. `weight` required only for WEIGHTED policy. Fetches current config, appends agent, PUTs the whole config back. |
367
+
368
+ ---
369
+
370
+ ## Pickup Group
371
+
372
+ **Source:** `wxcadm/pickup_group.py`
373
+
374
+ ### Overview
375
+
376
+ Pickup Groups (Call Pickup) allow users in the same group to answer each other's ringing calls. wxcadm provides `PickupGroupList` and `PickupGroup`.
377
+
378
+ **Important:** Unlike the other features, `PickupGroupList` is Location-scoped only -- there is no Org-level constructor.
379
+
380
+ ### PickupGroupList
381
+
382
+ Collection class. Inherits `UserList`.
383
+
384
+ **Constructor:**
385
+
386
+ ```python
387
+ PickupGroupList(location: Location)
388
+ ```
389
+
390
+ - Raises `ValueError` if `location` is not a `Location` instance.
391
+ - API endpoint: `GET v1/telephony/config/locations/{locationId}/callPickups`
392
+
393
+ **Methods:**
394
+
395
+ | Method | Signature | Returns | Description |
396
+ |--------|-----------|---------|-------------|
397
+ | `get` | `get(id=None, name=None, spark_id=None) -> PickupGroup \| None` | `PickupGroup` or `None` | Looks up by ID, Name, or Spark ID. Raises `ValueError` if no argument. |
398
+
399
+ > **Note:** There is no `refresh`, `create`, or `delete` method on `PickupGroupList`. Only `get()` and `_get_items()` are defined.
400
+
401
+ ### PickupGroup
402
+
403
+ Represents a single Pickup Group.
404
+
405
+ **Attributes:**
406
+
407
+ | Attribute | Type | Description |
408
+ |-----------|------|-------------|
409
+ | `location` | `Location` | Parent Location |
410
+ | `id` | `str` | Webex ID |
411
+ | `name` | `str` | Group name |
412
+ | `config` | `dict` | Raw JSON config from list response |
413
+
414
+ **Properties:**
415
+
416
+ | Property | Signature | Returns | Description |
417
+ |----------|-----------|---------|-------------|
418
+ | `users` | `@property -> list` | `list` | All agents in the group. Fetches detail via `GET .../callPickups/{id}`, then resolves each agent to a `Person`, `Workspace`, or `VirtualLine` instance by type (`PEOPLE`, `PLACE`, `VIRTUAL_LINE`). Falls back to raw dict for unknown types. |
419
+
420
+ ---
421
+
422
+ ## Announcements
423
+
424
+ **Source:** `wxcadm/announcements.py`
425
+
426
+ ### Overview
427
+
428
+ Announcements are audio files (WAV) uploaded to Webex for use in Auto Attendants, Call Queues, and other call features. They can exist at the Organization level or at a specific Location level. wxcadm provides `AnnouncementList` and the `Announcement` dataclass.
429
+
430
+ ### AnnouncementList
431
+
432
+ Collection class. Inherits `UserList`.
433
+
434
+ **Constructor:**
435
+
436
+ ```python
437
+ AnnouncementList(org: Org)
438
+ ```
439
+
440
+ - Always fetches all announcements (both Org-level and Location-level) by passing `locationId=all`.
441
+ - API endpoint: `GET v1/telephony/config/announcements?locationId=all`
442
+
443
+ **Methods:**
444
+
445
+ | Method | Signature | Returns | Description |
446
+ |--------|-----------|---------|-------------|
447
+ | `get` | `get(id=None, name=None, file_name=None, level=None, location=None) -> Announcement \| list[Announcement] \| None` | Single, list, or `None` | Filters announcements by any combination of criteria. `name` uses substring match (`in`). Returns a single `Announcement` if exactly one match, a list if multiple, `None` if zero. |
448
+ | `get_by_location_id` | `get_by_location_id(location_id: str) -> list[Announcement]` | `list` | Returns Location-level announcements for a given Location ID. Does not include Org-level announcements. |
449
+ | `get_by_id` | `get_by_id(id: str) -> Announcement \| None` | `Announcement` or `None` | Exact ID match |
450
+ | `upload` | `upload(name: str, filename: str, location: str \| Location = None) -> str` | `str` (new ID) | Uploads a WAV file. If `location` is provided (as ID string or `Location` instance), uploads at Location level; otherwise uploads at Org level. Uses `MultipartEncoder` from `requests_toolbelt`. |
451
+
452
+ **Properties:**
453
+
454
+ | Property | Signature | Returns | Description |
455
+ |----------|-----------|---------|-------------|
456
+ | `stats` | `@property -> dict` | `dict` | Repository usage stats (`GET v1/telephony/config/announcements/usage`) |
457
+
458
+ ### Announcement
459
+
460
+ Dataclass for a single announcement.
461
+
462
+ **Fields:**
463
+
464
+ | Field | Type | Description |
465
+ |-------|------|-------------|
466
+ | `org` | `Org` | Parent Org (not in repr) |
467
+ | `id` | `str` | Announcement ID |
468
+ | `name` | `str` | Display name |
469
+ | `fileName` | `str` | Name of the uploaded file |
470
+ | `fileSize` | `str` | File size in bytes (note: stored as `str`) |
471
+ | `mediaFileType` | `str` | File type (e.g. `WAV`) |
472
+ | `lastUpdated` | `str` | Timestamp of last update |
473
+ | `level` | `str` | `ORGANIZATION` or `LOCATION` |
474
+ | `location` | `dict \| None` | Location dict (only for `LOCATION`-level) |
475
+
476
+ **Properties:**
477
+
478
+ | Property | Signature | Returns | Description |
479
+ |----------|-----------|---------|-------------|
480
+ | `used_by` | `@property -> list` | `list[dict]` | List of call features using this announcement. Each dict has `id`, `name`, `type`, `location` (resolved to `Location` instance). For Call Queue type, also includes an `instance` key with the `CallQueue` object. |
481
+ | `in_use` | `@property -> bool` | `bool` | Whether the announcement is assigned to any feature |
482
+
483
+ **Methods:**
484
+
485
+ | Method | Signature | Returns | Description |
486
+ |--------|-----------|---------|-------------|
487
+ | `replace_file` | `replace_file(filename: str) -> bool` | `True` | Replaces the audio file with a new WAV. Uses `PUT` with `MultipartEncoder`. Works for both Org and Location level. |
488
+ | `delete` | `delete() -> bool` | `True` or `False` | Deletes the announcement. Returns `False` immediately if `in_use` is True (does not attempt the API call). |
489
+
490
+ ---
491
+
492
+ ## Playlists
493
+
494
+ **Source:** `wxcadm/announcements.py` (same file as Announcements)
495
+
496
+ ### Overview
497
+
498
+ Playlists are ordered collections of Announcements that can be assigned to Locations for music-on-hold or similar use. wxcadm provides `PlaylistList` and the `Playlist` dataclass (decorated with `@dataclass_json`).
499
+
500
+ ### PlaylistList
501
+
502
+ Collection class. Inherits `UserList`.
503
+
504
+ **Constructor:**
505
+
506
+ ```python
507
+ PlaylistList(parent: Org)
508
+ ```
509
+
510
+ - API endpoint: `GET v1/telephony/config/announcements/playlists`
511
+
512
+ **Methods:**
513
+
514
+ | Method | Signature | Returns | Description |
515
+ |--------|-----------|---------|-------------|
516
+ | `get` | `get(id='', name='') -> Playlist \| None` | `Playlist` or `None` | Looks up by ID or Name |
517
+ | `create` | `create(name: str, announcements: list[Announcement]) -> Playlist` | `Playlist` | Creates a new Playlist from a list of Announcement instances |
518
+
519
+ ### Playlist
520
+
521
+ Dataclass (with `@dataclass_json`) for a single playlist.
522
+
523
+ **Init fields:**
524
+
525
+ | Field | API Field | Type | Description |
526
+ |-------|-----------|------|-------------|
527
+ | `org` | -- | `Org` | Parent Org (not in repr) |
528
+ | `id` | `id` | `str` | Playlist ID |
529
+ | `name` | `name` | `str` | Playlist name |
530
+ | `file_count` | `fileCount` | `int` | Number of files in the playlist |
531
+ | `last_updated` | `lastUpdated` | `str` | Last update timestamp |
532
+ | `in_use` | `isInUse` | `bool` | Whether the playlist is in use (default `False`) |
533
+ | `location_count` | `locationCount` | `int` | Number of assigned Locations (default `0`) |
534
+
535
+ **Lazy-loaded fields (fetched via `__getattr__` on first access):**
536
+
537
+ | Field | Type | Description |
538
+ |-------|------|-------------|
539
+ | `file_size` | `int` | Total file size in bytes |
540
+ | `announcements` | `list` | List of `Announcement` instances in the playlist |
541
+
542
+ > **Bug note:** The `__getattr__` method uses `"fv1/telephony/config/announcements/playlists/{self.id}"` as the URL -- this is a regular string (not an f-string), so `{self.id}` is literal text and the path starts with `fv1/` instead of `v1/`. The `refresh()` method uses the correct f-string `f"v1/telephony/config/announcements/playlists/{self.id}"`. The lazy-load will fail with an API error.
543
+
544
+ **Methods:**
545
+
546
+ | Method | Signature | Returns | Description |
547
+ |--------|-----------|---------|-------------|
548
+ | `refresh` | `refresh() -> bool` | `True` | Refreshes all playlist details from the API |
549
+ | `delete` | `delete() -> bool` | `True` | Deletes the playlist |
550
+ | `replace_announcements` | `replace_announcements(announcements: list[Announcement]) -> bool` | `True` | Replaces all announcements in the playlist |
551
+
552
+ **Properties:**
553
+
554
+ | Property | Signature | Returns | Description |
555
+ |----------|-----------|---------|-------------|
556
+ | `locations` | `@property -> list[Location]` | `list[Location]` | Locations the playlist is assigned to |
557
+
558
+ **Additional methods:**
559
+
560
+ | Method | Signature | Returns | Description |
561
+ |--------|-----------|---------|-------------|
562
+ | `assign_to_location` | `assign_to_location(location: Location) -> bool` | `True` | Assigns the playlist to a Location (preserves existing Location assignments and appends the new one) |
563
+
564
+ ---
565
+
566
+ ## Recording
567
+
568
+ **Source:** `wxcadm/recording.py`
569
+
570
+ ### Overview
571
+
572
+ The recording module covers three concerns:
573
+
574
+ 1. **Recording vendor selection** (Org and Location level) -- which provider records calls and what happens on failure.
575
+ 2. **Compliance announcements** -- the tone/announcement played to inform parties that a call is being recorded.
576
+ 3. **Converged Recordings** -- accessing, downloading, transcribing, and managing actual recording files.
577
+
578
+ ### RecordingVendor / RecordingVendorsList
579
+
580
+ **`RecordingVendor`** is a `@dataclass_json` dataclass.
581
+
582
+ | Field | API Field | Type | Description |
583
+ |-------|-----------|------|-------------|
584
+ | `id` | `id` | `str` | Vendor ID |
585
+ | `name` | `name` | `str` | Vendor name |
586
+ | `description` | `description` | `str` | Vendor description |
587
+ | `auto_user_account_creation` | `migrateUserCreationEnabled` | `bool` | Auto user account provisioning |
588
+ | `login_url` | `loginUrl` | `str` | Vendor login URL |
589
+ | `tos_url` | `termsOfServiceUrl` | `str` | Terms of Service URL |
590
+
591
+ **`RecordingVendorsList`** (`UserList`) wraps a list of `RecordingVendor` instances.
592
+
593
+ | Method | Signature | Returns | Description |
594
+ |--------|-----------|---------|-------------|
595
+ | `get` | `get(id='', name='') -> RecordingVendor \| None` | Match or `None` | Looks up by ID or name |
596
+
597
+ ### OrgRecordingVendorSelection
598
+
599
+ Manages the Org-level recording vendor configuration.
600
+
601
+ **Constructor:**
602
+
603
+ ```python
604
+ OrgRecordingVendorSelection(org: Org)
605
+ ```
606
+
607
+ - API endpoint: `GET v1/telephony/config/callRecording/vendors`
608
+
609
+ **Attributes:**
610
+
611
+ | Attribute | Type | Description |
612
+ |-----------|------|-------------|
613
+ | `available_vendors` | `RecordingVendorsList` | All vendors available to the Org |
614
+ | `selected_vendor` | `RecordingVendor` | Currently selected vendor |
615
+ | `storage_region` | `Optional[str]` | Storage region (Webex recording only) |
616
+ | `failure_behavior` | `Optional[str]` | Behavior when recording session fails |
617
+
618
+ **Methods:**
619
+
620
+ | Method | Signature | Returns | Description |
621
+ |--------|-----------|---------|-------------|
622
+ | `change_vendor` | `change_vendor(new_vendor: RecordingVendor) -> bool` | `True` | Switches the Org recording vendor |
623
+ | `set_failure_behavior` | `set_failure_behavior(failure_behavior: str) -> bool` | `False` | **Not implemented** (returns `False`, with `#TODO: Fix this` comment). Valid values would be `PROCEED_WITH_CALL_NO_ANNOUNCEMENT`, `PROCEED_CALL_WITH_ANNOUNCEMENT`, `END_CALL_WITH_ANNOUNCEMENT`. |
624
+
625
+ ### LocationRecordingVendorSelection
626
+
627
+ Manages Location-level recording vendor configuration with the ability to override or inherit Org-level settings.
628
+
629
+ **Constructor:**
630
+
631
+ ```python
632
+ LocationRecordingVendorSelection(location: Location)
633
+ ```
634
+
635
+ - API endpoint: `GET v1/telephony/config/locations/{locationId}/callRecording/vendors`
636
+
637
+ **Attributes:**
638
+
639
+ | Attribute | Type | Description |
640
+ |-----------|------|-------------|
641
+ | `available_vendors` | `RecordingVendorsList` | Available vendors |
642
+ | `use_org_vendor` | `bool` | Whether Location uses the Org vendor |
643
+ | `org_vendor` | `RecordingVendor` | The Org-level vendor |
644
+ | `location_vendor` | `RecordingVendor` | The Location-level vendor |
645
+ | `use_org_storage_region` | `Optional[bool]` | Whether to use Org storage region |
646
+ | `org_storage_region` | `Optional[str]` | Org storage region |
647
+ | `location_storage_region` | `Optional[str]` | Location storage region |
648
+ | `use_org_failure_behavior` | `bool` | Whether to use Org failure behavior |
649
+ | `org_failure_behavior` | `str` | Org failure behavior |
650
+ | `location_failure_behavior` | `str` | Location failure behavior |
651
+
652
+ **Methods:**
653
+
654
+ | Method | Signature | Returns | Description |
655
+ |--------|-----------|---------|-------------|
656
+ | `change_vendor` | `change_vendor(new_vendor: RecordingVendor) -> bool` | `True` | Sets a Location-specific vendor (disables Org default) |
657
+ | `set_storage_region` | `set_storage_region(region: str) -> bool` | `True` | Sets a Location-specific storage region (2-char code) |
658
+ | `set_failure_behavior` | `set_failure_behavior(failure_behavior: str) -> bool` | `True` | Sets Location-specific failure behavior. Valid: `PROCEED_WITH_CALL_NO_ANNOUNCEMENT`, `PROCEED_CALL_WITH_ANNOUNCEMENT`, `END_CALL_WITH_ANNOUNCEMENT` |
659
+ | `clear_vendor_override` | `clear_vendor_override() -> bool` | `True` | Reverts to Org default vendor |
660
+ | `clear_region_override` | `clear_region_override() -> bool` | `True` | Reverts to Org default storage region |
661
+ | `clear_failure_override` | `clear_failure_override() -> bool` | `True` | Reverts to Org default failure behavior |
662
+
663
+ ### ComplianceAnnouncementSettings
664
+
665
+ Manages compliance announcement settings (the recording notification played to callers) at Org or Location level.
666
+
667
+ **Constructor:**
668
+
669
+ ```python
670
+ ComplianceAnnouncementSettings(
671
+ org: Org,
672
+ inboundPSTNCallsEnabled: bool,
673
+ outboundPSTNCallsEnabled: bool,
674
+ outboundPSTNCallsDelayEnabled: bool,
675
+ delayInSeconds: int,
676
+ useOrgSettingsEnabled: Optional[bool] = None,
677
+ location: Optional[Location] = None
678
+ )
679
+ ```
680
+
681
+ **Attributes:**
682
+
683
+ | Attribute | Type | Description |
684
+ |-----------|------|-------------|
685
+ | `inbound_pstn_calls_enabled` | `bool` | Play compliance announcement for inbound PSTN calls |
686
+ | `outbound_pstn_calls_enabled` | `bool` | Play compliance announcement for outbound PSTN calls |
687
+ | `outbound_pstn_calls_delay_enabled` | `bool` | Delay the announcement on outbound calls |
688
+ | `delay` | `int` | Seconds to delay |
689
+ | `use_org_settings` | `Optional[bool]` | For Location-level: `False` means overriding Org settings |
690
+
691
+ **Methods:**
692
+
693
+ | Method | Signature | Returns | Description |
694
+ |--------|-----------|---------|-------------|
695
+ | `to_webex` | `to_webex() -> dict` | `dict` | Returns dict with Webex API field names |
696
+ | `to_json` | `to_json() -> str` | `str` | JSON string representation |
697
+ | `push` | `push() -> bool` | `True` | Pushes settings to Webex. Uses Location endpoint if `self.location` is set, otherwise Org endpoint. |
698
+
699
+ > **Bug note:** The Location-level endpoint in `push()` has a double slash: `f"v1//telephony/config/locations/{self.location.id}/callRecording/complianceAnnouncement"`. This may cause API failures depending on how the HTTP client normalizes paths.
700
+
701
+ ### RecordingList
702
+
703
+ Collection class for converged recordings. Inherits `UserList`.
704
+
705
+ **Constructor:**
706
+
707
+ ```python
708
+ RecordingList(
709
+ org: Org,
710
+ from_date_time: Optional[str] = None,
711
+ to_date_time: Optional[str] = None,
712
+ status: Optional[str] = None,
713
+ service: Optional[str] = None,
714
+ owner: Optional[Person | Workspace | VirtualLine] = None,
715
+ region: Optional[str] = None,
716
+ location: Optional[Location] = None
717
+ )
718
+ ```
719
+
720
+ - All filter parameters are optional. `max` is hardcoded to 100.
721
+ - API endpoint: `GET v1/admin/convergedRecordings`
722
+
723
+ **Methods:**
724
+
725
+ | Method | Signature | Returns | Description |
726
+ |--------|-----------|---------|-------------|
727
+ | `refresh` | `refresh() -> bool` | `True` | Re-fetches with same params |
728
+ | `get` | `get(id=None, call_id=None) -> Recording \| list[Recording]` | Single `Recording` by ID, `list` by call_id | When using `call_id`, always returns a list (may be empty). Raises `ValueError` if neither argument provided. |
729
+ | `reassign_owner` | `reassign_owner(current_owner, new_owner: Person, recording_list=None) -> bool` | `True` | Reassigns recordings from one owner to another. `new_owner` must be a `Person`. If `recording_list` is None, reassigns all. |
730
+
731
+ ### Recording
732
+
733
+ Represents a single converged recording.
734
+
735
+ **Constructor:**
736
+
737
+ ```python
738
+ Recording(org: Org, id: str, details: Optional[dict] = None, timezone: Optional[str] = None)
739
+ ```
740
+
741
+ - If `details` is `None`, fetches from API on init.
742
+ - API endpoint: `GET v1/convergedRecordings/{id}`
743
+
744
+ **Properties:**
745
+
746
+ | Property | Type | Description |
747
+ |----------|------|-------------|
748
+ | `metadata` | `dict` | Recording metadata (lazy-loaded from `/metadata` endpoint) |
749
+ | `status` | `str` | Recording status |
750
+ | `temporary_download_links` | `dict` | Dict of temporary download URLs |
751
+ | `url` | `Optional[str]` | Audio download URL |
752
+ | `transcript_url` | `Optional[str]` | Transcript download URL |
753
+ | `suggested_notes_url` | `Optional[str]` | Suggested notes download URL |
754
+ | `action_items_url` | `Optional[str]` | Action items download URL |
755
+ | `short_notes_url` | `str` | Short notes download URL |
756
+ | `download_expires` | `str` | Expiration timestamp for download links |
757
+ | `file_format` | `str` | Recording file format |
758
+ | `duration` | `int` | Duration in seconds |
759
+ | `file_size` | `int` | Size in bytes |
760
+ | `topic` | `str` | Topic/description |
761
+ | `service_type` | `str` | Service type (e.g. `calling`) |
762
+ | `storage_region` | `str` | Storage region |
763
+ | `created` | `str` | File creation timestamp |
764
+ | `recorded` | `str` | Call recording timestamp |
765
+ | `owner_id` | `str` | Owner UUID |
766
+ | `owner_type` | `str` | Owner type (user, workspace, virtual line) |
767
+ | `owner_email` | `str` | Owner email |
768
+ | `location_id` | `Optional[str]` | Location ID (Calling service only; returns `None` for non-calling) |
769
+ | `call_session_id` | `Optional[str]` | Call Session ID (Calling service only) |
770
+
771
+ **Methods:**
772
+
773
+ | Method | Signature | Returns | Description |
774
+ |--------|-----------|---------|-------------|
775
+ | `refresh` | `refresh() -> None` | -- | Refreshes details from API |
776
+ | `download` | `download(filename: str) -> bool` | `True` | Downloads the audio file to a local path (uses `requests.get` directly, not the Org API client) |
777
+ | `get_transcript` | `get_transcript(text_only: bool = False) -> str` | `str` | Gets the transcript. If `text_only=True`, strips timestamps and WEBVTT headers, returning just the spoken text joined by spaces. |
778
+ | `get_suggested_notes` | `get_suggested_notes() -> str` | `str` | Downloads suggested notes text |
779
+ | `get_action_items` | `get_action_items() -> str` | `str` | Downloads action items text |
780
+ | `get_short_notes` | `get_short_notes() -> str` | `str` | Downloads short notes text |
781
+
782
+ ---
783
+
784
+ ## wxcadm vs wxc_sdk Comparison
785
+
786
+ | Aspect | wxcadm | wxc_sdk |
787
+ |--------|--------|---------|
788
+ | **Architecture** | List classes (UserList subclasses) own data fetching; item classes are plain classes or dataclasses. Lazy-loaded properties on items. | Strongly typed Pydantic models (`ApiModel(BaseModel)`) with a central API client. Separate API method classes (e.g. `AutoAttendantApi(ApiChild)`). |
789
+ | **Data fetching** | Automatic on list init; manual `refresh()` to update. Detail calls are lazy (triggered on first property access). | Explicit method calls on API objects (e.g. `AutoAttendantApi.list()`, `.details()`, `.create()`). Returns generators for list operations. |
790
+ | **Scoping** | List classes accept `org` + optional `location` in constructor (except `PickupGroupList` which is Location-only). | Location filtering via `location_id` parameter on API methods (e.g. `list(location_id=...)`, `create(location_id=...)`). |
791
+ | **Lookup pattern** | `.get(id=, name=, spark_id=, uuid=)` on every list class. Search order: ID, Name, UUID, Spark ID. | `.details(location_id, feature_id)` for single-item fetch; `.list()` with filter params for discovery. |
792
+ | **Create pattern** | `.create(...)` on list class; returns the new item instance. Location defaults from parent if scoped. | `<FeatureApi>.create(location_id, settings)` methods; returns new ID as string. |
793
+ | **Update pattern** | Modify `config` dict, then call `push()` (Call Queue) or use dedicated methods (Hunt Group `add_agent`). No universal update pattern. | `<FeatureApi>.update(location_id, feature_id, settings)` methods with typed `ApiModel` settings objects. |
794
+ | **Serialization** | Mix of plain dicts, `@dataclass`, and `@dataclass_json`. No unified serialization layer. | Pydantic `ApiModel(BaseModel)` with camelCase alias generation, `model_dump_json()`, and `model_validate()`. |
795
+ | **Recordings** | Full converged recordings support: list, download, transcript, reassign, compliance settings, vendor selection at Org and Location level. | `ConvergedRecordingsApi` with list, get, delete, reassign, download, and transcript support. Also has in-call recording controls (start/stop/pause/resume) via `CallsApi`. |
796
+ | **Announcements** | Full support including upload, delete, replace, Playlists with Location assignment. | Full announcement repo support via `announcements_repo/`: list, upload (`upload_announcement`), modify, delete. Supports both Org and Location level. |
797
+ | **Pickup Groups** | Location-only; read-only (no create/delete). | Full CRUD via `CallPickupApi`: `list()`, `create()`, `details()`, `update()`. No explicit `delete()` method found. |
798
+ | **Known gaps in wxcadm** | `CallQueue.add_agent` not implemented. `OrgRecordingVendorSelection.set_failure_behavior` not implemented. Several typos in API URLs (see bug notes above). | N/A |
799
+
800
+ ---
801
+
802
+ ## Common Patterns
803
+
804
+ ### Shared List Class Interface
805
+
806
+ All list classes (`AutoAttendantList`, `CallQueueList`, `HuntGroupList`, `PickupGroupList`, `AnnouncementList`, `PlaylistList`, `RecordingList`) inherit from `UserList` and share these patterns:
807
+
808
+ - Data is fetched automatically in `__init__`.
809
+ - Most have `refresh()` to re-fetch.
810
+ - Most have `get(...)` with various lookup keys.
811
+ - Most have `create(...)` for provisioning new items.
812
+
813
+ ### Lazy-Loaded Detail Properties
814
+
815
+ `AutoAttendant` uses private `_field` attributes initialized to `None`, with `@property` accessors that call `_get_details()` on first access. Other classes (like `CallQueue`, `HuntGroup`) use the `config` property which fetches the full config dict fresh on every access.
816
+
817
+ ### API URL Patterns
818
+
819
+ | Feature | List Endpoint | Detail Endpoint |
820
+ |---------|--------------|-----------------|
821
+ | Auto Attendant | `v1/telephony/config/autoAttendants` | `v1/telephony/config/locations/{locId}/autoAttendants/{id}` |
822
+ | Call Queue | `v1/telephony/config/queues` | `v1/telephony/config/locations/{locId}/queues/{id}` |
823
+ | Hunt Group | `v1/telephony/config/huntGroups` | `v1/telephony/config/locations/{locId}/huntGroups/{id}` |
824
+ | Pickup Group | `v1/telephony/config/locations/{locId}/callPickups` | `v1/telephony/config/locations/{locId}/callPickups/{id}` |
825
+ | Announcements | `v1/telephony/config/announcements` | `v1/telephony/config/announcements/{id}` or `v1/telephony/config/locations/{locId}/announcements/{id}` |
826
+ | Playlists | `v1/telephony/config/announcements/playlists` | `v1/telephony/config/announcements/playlists/{id}` |
827
+ | Recordings | `v1/admin/convergedRecordings` | `v1/convergedRecordings/{id}` |
828
+ | Recording Vendors (Org) | `v1/telephony/config/callRecording/vendors` | -- |
829
+ | Recording Vendors (Location) | `v1/telephony/config/locations/{locId}/callRecording/vendors` | -- |
830
+ | Compliance Announcement (Org) | `v1/telephony/config/callRecording/complianceAnnouncement` | -- |
831
+ | Compliance Announcement (Location) | `v1/telephony/config/locations/{locId}/callRecording/complianceAnnouncement` | -- |
832
+
833
+ ---
834
+
835
+ ## Known Bugs and Incomplete Features
836
+
837
+ 1. **`CallQueue.add_agent`** -- method body is `pass`; not implemented.
838
+ 2. **`OrgRecordingVendorSelection.set_failure_behavior`** -- returns `False` immediately; not implemented.
839
+ 3. **`HuntGroupList.get` uuid branch** -- typo `.uppper()` instead of `.upper()` will raise `AttributeError`.
840
+ 4. **`Playlist.__getattr__`** -- URL string `"fv1/telephony/..."` is not an f-string; the literal `f` is prepended to the path, causing the API call to fail. The `refresh()` method has the correct URL.
841
+ 5. **`ComplianceAnnouncementSettings.push`** -- Location-level endpoint has a double slash: `v1//telephony/config/locations/...`.
842
+ 6. **`PickupGroupList`** -- no `refresh()`, `create()`, or `delete()` methods.
843
+
844
+ ---
845
+
846
+ ## See Also
847
+
848
+ - [call-features-major.md](call-features-major.md) — wxc_sdk auto attendant, call queue, and hunt group APIs for comparison
849
+ - [call-features-additional.md](call-features-additional.md) — wxc_sdk pickup group, paging group, call park, announcements, and recording APIs