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.
- wxcli/__init__.py +4 -0
- wxcli/_playbook/.claude/agents/migration-advisor.md +239 -0
- wxcli/_playbook/.claude/agents/wxc-calling-builder.md +946 -0
- wxcli/_playbook/.claude/rules/cleanup.md +29 -0
- wxcli/_playbook/.claude/rules/cucm-migration.md +58 -0
- wxcli/_playbook/.claude/rules/org-health.md +14 -0
- wxcli/_playbook/.claude/settings.json +8 -0
- wxcli/_playbook/.claude/skills/audit-compliance/SKILL.md +515 -0
- wxcli/_playbook/.claude/skills/call-control/SKILL.md +747 -0
- wxcli/_playbook/.claude/skills/configure-features/SKILL.md +623 -0
- wxcli/_playbook/.claude/skills/configure-routing/SKILL.md +627 -0
- wxcli/_playbook/.claude/skills/contact-center/SKILL.md +1181 -0
- wxcli/_playbook/.claude/skills/cucm-migrate/SKILL.md +820 -0
- wxcli/_playbook/.claude/skills/customer-assist/SKILL.md +443 -0
- wxcli/_playbook/.claude/skills/device-platform/SKILL.md +407 -0
- wxcli/_playbook/.claude/skills/manage-call-settings/SKILL.md +757 -0
- wxcli/_playbook/.claude/skills/manage-devices/SKILL.md +790 -0
- wxcli/_playbook/.claude/skills/manage-identity/SKILL.md +638 -0
- wxcli/_playbook/.claude/skills/manage-licensing/SKILL.md +528 -0
- wxcli/_playbook/.claude/skills/manage-meetings/SKILL.md +708 -0
- wxcli/_playbook/.claude/skills/messaging-bots/SKILL.md +365 -0
- wxcli/_playbook/.claude/skills/messaging-spaces/SKILL.md +520 -0
- wxcli/_playbook/.claude/skills/org-health/SKILL.md +159 -0
- wxcli/_playbook/.claude/skills/provision-calling/SKILL.md +421 -0
- wxcli/_playbook/.claude/skills/query-live/SKILL.md +183 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-flow-trace.md +223 -0
- wxcli/_playbook/.claude/skills/query-live/domains/call-history.md +44 -0
- wxcli/_playbook/.claude/skills/query-live/domains/features.md +169 -0
- wxcli/_playbook/.claude/skills/query-live/domains/numbers.md +93 -0
- wxcli/_playbook/.claude/skills/query-live/domains/people-and-settings.md +146 -0
- wxcli/_playbook/.claude/skills/query-live/domains/routing.md +124 -0
- wxcli/_playbook/.claude/skills/reporting/SKILL.md +501 -0
- wxcli/_playbook/.claude/skills/reporting/references/cdr-recipes.md +1628 -0
- wxcli/_playbook/.claude/skills/reporting-cc/SKILL.md +251 -0
- wxcli/_playbook/.claude/skills/reporting-meetings/SKILL.md +290 -0
- wxcli/_playbook/.claude/skills/teardown/SKILL.md +214 -0
- wxcli/_playbook/.claude/skills/video-mesh/SKILL.md +379 -0
- wxcli/_playbook/.claude/skills/wxc-calling-debug/SKILL.md +475 -0
- wxcli/_playbook/CLAUDE.md +373 -0
- wxcli/_playbook/docs/reference/CLAUDE.md +25 -0
- wxcli/_playbook/docs/reference/admin-apps-data.md +643 -0
- wxcli/_playbook/docs/reference/admin-audit-security.md +322 -0
- wxcli/_playbook/docs/reference/admin-hybrid.md +383 -0
- wxcli/_playbook/docs/reference/admin-identity-scim.md +1007 -0
- wxcli/_playbook/docs/reference/admin-licensing.md +414 -0
- wxcli/_playbook/docs/reference/admin-org-management.md +586 -0
- wxcli/_playbook/docs/reference/admin-partner.md +357 -0
- wxcli/_playbook/docs/reference/archive/wxc-sdk-patterns.md +1229 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-advanced.md +835 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-core.md +743 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-devices-workspaces.md +1305 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-features.md +849 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-locations.md +938 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-person.md +1255 -0
- wxcli/_playbook/docs/reference/archive/wxcadm-routing.md +1262 -0
- wxcli/_playbook/docs/reference/authentication.md +965 -0
- wxcli/_playbook/docs/reference/call-control.md +1205 -0
- wxcli/_playbook/docs/reference/call-features-additional.md +2541 -0
- wxcli/_playbook/docs/reference/call-features-major.md +1320 -0
- wxcli/_playbook/docs/reference/call-routing.md +2304 -0
- wxcli/_playbook/docs/reference/contact-center-analytics.md +1049 -0
- wxcli/_playbook/docs/reference/contact-center-core.md +1614 -0
- wxcli/_playbook/docs/reference/contact-center-journey.md +457 -0
- wxcli/_playbook/docs/reference/contact-center-routing.md +1138 -0
- wxcli/_playbook/docs/reference/devices-core.md +1869 -0
- wxcli/_playbook/docs/reference/devices-dect.md +1150 -0
- wxcli/_playbook/docs/reference/devices-platform.md +467 -0
- wxcli/_playbook/docs/reference/devices-workspaces.md +1426 -0
- wxcli/_playbook/docs/reference/emergency-services.md +1122 -0
- wxcli/_playbook/docs/reference/location-calling-core.md +2037 -0
- wxcli/_playbook/docs/reference/location-calling-media.md +1334 -0
- wxcli/_playbook/docs/reference/location-recording-advanced.md +1482 -0
- wxcli/_playbook/docs/reference/meetings-content.md +473 -0
- wxcli/_playbook/docs/reference/meetings-core.md +903 -0
- wxcli/_playbook/docs/reference/meetings-infrastructure.md +899 -0
- wxcli/_playbook/docs/reference/meetings-settings.md +850 -0
- wxcli/_playbook/docs/reference/messaging-bots.md +1091 -0
- wxcli/_playbook/docs/reference/messaging-spaces.md +695 -0
- wxcli/_playbook/docs/reference/person-call-settings-behavior.md +1639 -0
- wxcli/_playbook/docs/reference/person-call-settings-handling.md +1394 -0
- wxcli/_playbook/docs/reference/person-call-settings-media.md +1898 -0
- wxcli/_playbook/docs/reference/person-call-settings-permissions.md +1329 -0
- wxcli/_playbook/docs/reference/provisioning.md +1366 -0
- wxcli/_playbook/docs/reference/reporting-analytics.md +1318 -0
- wxcli/_playbook/docs/reference/self-service-call-settings.md +1020 -0
- wxcli/_playbook/docs/reference/virtual-lines.md +1132 -0
- wxcli/_playbook/docs/reference/webhooks-events.md +1444 -0
- wxcli/_playbook/docs/reference/wxcadm-xsi-realtime.md +953 -0
- wxcli/_version.py +24 -0
- wxcli/auth.py +137 -0
- wxcli/commands/__init__.py +0 -0
- wxcli/commands/_registry.py +181 -0
- wxcli/commands/activation_email.py +103 -0
- wxcli/commands/admin_recordings.py +585 -0
- wxcli/commands/analytics.py +105 -0
- wxcli/commands/announcement_playlists.py +219 -0
- wxcli/commands/announcements.py +519 -0
- wxcli/commands/archive_users.py +36 -0
- wxcli/commands/attachment_actions.py +60 -0
- wxcli/commands/audit_events.py +83 -0
- wxcli/commands/authorizations.py +113 -0
- wxcli/commands/auto_attendant.py +642 -0
- wxcli/commands/broadworks_billing_reports.py +126 -0
- wxcli/commands/broadworks_enterprises.py +160 -0
- wxcli/commands/broadworks_subscribers.py +319 -0
- wxcli/commands/broadworks_workspaces.py +108 -0
- wxcli/commands/call_controls.py +1304 -0
- wxcli/commands/call_park.py +494 -0
- wxcli/commands/call_pickup.py +229 -0
- wxcli/commands/call_queue.py +1878 -0
- wxcli/commands/call_recording.py +707 -0
- wxcli/commands/call_routing.py +1610 -0
- wxcli/commands/call_settings_for_me_phase_5.py +212 -0
- wxcli/commands/caller_reputation.py +169 -0
- wxcli/commands/calling_service.py +305 -0
- wxcli/commands/cc_address_book.py +770 -0
- wxcli/commands/cc_agent_greetings.py +242 -0
- wxcli/commands/cc_agent_summaries.py +39 -0
- wxcli/commands/cc_agent_wellbeing.py +216 -0
- wxcli/commands/cc_agents.py +425 -0
- wxcli/commands/cc_ai_assistant.py +55 -0
- wxcli/commands/cc_ai_feature.py +294 -0
- wxcli/commands/cc_audio_files.py +149 -0
- wxcli/commands/cc_auto_csat.py +311 -0
- wxcli/commands/cc_aux_code.py +458 -0
- wxcli/commands/cc_business_hour.py +353 -0
- wxcli/commands/cc_call_monitoring.py +228 -0
- wxcli/commands/cc_callbacks.py +194 -0
- wxcli/commands/cc_campaign.py +212 -0
- wxcli/commands/cc_captures.py +39 -0
- wxcli/commands/cc_contact_list.py +169 -0
- wxcli/commands/cc_contact_number.py +295 -0
- wxcli/commands/cc_data_sources.py +235 -0
- wxcli/commands/cc_desktop_layout.py +380 -0
- wxcli/commands/cc_desktop_profile.py +322 -0
- wxcli/commands/cc_dial_number.py +511 -0
- wxcli/commands/cc_dial_plan.py +347 -0
- wxcli/commands/cc_dnc.py +101 -0
- wxcli/commands/cc_entry_point.py +545 -0
- wxcli/commands/cc_ewt.py +51 -0
- wxcli/commands/cc_flow.py +477 -0
- wxcli/commands/cc_global_vars.py +430 -0
- wxcli/commands/cc_holiday_list.py +335 -0
- wxcli/commands/cc_journey.py +1261 -0
- wxcli/commands/cc_legacy_flows.py +49 -0
- wxcli/commands/cc_multimedia_profile.py +436 -0
- wxcli/commands/cc_notification.py +51 -0
- wxcli/commands/cc_outdial_ani.py +604 -0
- wxcli/commands/cc_overrides.py +341 -0
- wxcli/commands/cc_queue.py +1083 -0
- wxcli/commands/cc_queue_stats.py +55 -0
- wxcli/commands/cc_realtime.py +51 -0
- wxcli/commands/cc_resource_collection.py +312 -0
- wxcli/commands/cc_search.py +46 -0
- wxcli/commands/cc_site.py +400 -0
- wxcli/commands/cc_skill.py +350 -0
- wxcli/commands/cc_skill_profile.py +289 -0
- wxcli/commands/cc_subscriptions.py +426 -0
- wxcli/commands/cc_summaries.py +130 -0
- wxcli/commands/cc_tasks.py +844 -0
- wxcli/commands/cc_team.py +325 -0
- wxcli/commands/cc_user_profiles.py +349 -0
- wxcli/commands/cc_users.py +701 -0
- wxcli/commands/cc_work_types.py +363 -0
- wxcli/commands/cdr.py +89 -0
- wxcli/commands/classifications.py +38 -0
- wxcli/commands/cleanup.py +1427 -0
- wxcli/commands/client_settings.py +72 -0
- wxcli/commands/conference.py +328 -0
- wxcli/commands/configure.py +72 -0
- wxcli/commands/converged_recordings.py +347 -0
- wxcli/commands/converged_recordings_export.py +310 -0
- wxcli/commands/cq_playlists.py +42 -0
- wxcli/commands/cucm.py +2794 -0
- wxcli/commands/cucm_config.py +129 -0
- wxcli/commands/customer_assist.py +373 -0
- wxcli/commands/data_sources.py +227 -0
- wxcli/commands/dect_devices.py +787 -0
- wxcli/commands/device_configurations.py +77 -0
- wxcli/commands/device_dynamic_settings.py +320 -0
- wxcli/commands/device_settings.py +1489 -0
- wxcli/commands/devices.py +280 -0
- wxcli/commands/domains.py +142 -0
- wxcli/commands/ecm.py +178 -0
- wxcli/commands/emergency_services.py +827 -0
- wxcli/commands/events.py +83 -0
- wxcli/commands/external_voicemail.py +52 -0
- wxcli/commands/groups.py +206 -0
- wxcli/commands/guest_management.py +76 -0
- wxcli/commands/hds.py +340 -0
- wxcli/commands/hot_desk.py +67 -0
- wxcli/commands/hot_desking_members.py +118 -0
- wxcli/commands/hot_desking_portal.py +124 -0
- wxcli/commands/hunt_group.py +577 -0
- wxcli/commands/hybrid_clusters.py +71 -0
- wxcli/commands/hybrid_connectors.py +67 -0
- wxcli/commands/identity_org.py +159 -0
- wxcli/commands/init_playbook.py +155 -0
- wxcli/commands/licenses.py +106 -0
- wxcli/commands/live_monitoring.py +40 -0
- wxcli/commands/location_call_handling.py +577 -0
- wxcli/commands/location_schedules.py +341 -0
- wxcli/commands/location_settings.py +1297 -0
- wxcli/commands/location_voicemail.py +494 -0
- wxcli/commands/locations.py +336 -0
- wxcli/commands/meeting_captions.py +110 -0
- wxcli/commands/meeting_chats.py +63 -0
- wxcli/commands/meeting_invitees.py +234 -0
- wxcli/commands/meeting_messages.py +28 -0
- wxcli/commands/meeting_participants.py +278 -0
- wxcli/commands/meeting_polls.py +111 -0
- wxcli/commands/meeting_preferences.py +515 -0
- wxcli/commands/meeting_qa.py +78 -0
- wxcli/commands/meeting_qualities.py +43 -0
- wxcli/commands/meeting_reports.py +101 -0
- wxcli/commands/meeting_session_types.py +105 -0
- wxcli/commands/meeting_site.py +57 -0
- wxcli/commands/meeting_slido.py +44 -0
- wxcli/commands/meeting_summaries.py +92 -0
- wxcli/commands/meeting_tracking_codes.py +233 -0
- wxcli/commands/meeting_transcripts.py +230 -0
- wxcli/commands/meetings.py +1997 -0
- wxcli/commands/memberships.py +164 -0
- wxcli/commands/messages.py +213 -0
- wxcli/commands/mode_management.py +244 -0
- wxcli/commands/my_call_settings.py +3577 -0
- wxcli/commands/numbers.py +405 -0
- wxcli/commands/operating_modes.py +410 -0
- wxcli/commands/org_contacts.py +284 -0
- wxcli/commands/org_health_cli.py +55 -0
- wxcli/commands/org_settings.py +71 -0
- wxcli/commands/organizations.py +83 -0
- wxcli/commands/paging_group.py +257 -0
- wxcli/commands/partner_admins.py +141 -0
- wxcli/commands/partner_reports.py +188 -0
- wxcli/commands/partner_tags.py +216 -0
- wxcli/commands/people.py +279 -0
- wxcli/commands/person_call_settings.py +71 -0
- wxcli/commands/pstn.py +280 -0
- wxcli/commands/recording_report.py +154 -0
- wxcli/commands/report_templates.py +38 -0
- wxcli/commands/reports.py +144 -0
- wxcli/commands/resource_group_memberships.py +160 -0
- wxcli/commands/resource_groups.py +67 -0
- wxcli/commands/roles.py +63 -0
- wxcli/commands/room_tabs.py +160 -0
- wxcli/commands/rooms.py +225 -0
- wxcli/commands/scim_bulk.py +46 -0
- wxcli/commands/scim_groups.py +246 -0
- wxcli/commands/scim_schemas.py +82 -0
- wxcli/commands/scim_users.py +283 -0
- wxcli/commands/security_audit.py +54 -0
- wxcli/commands/service_apps.py +51 -0
- wxcli/commands/single_number_reach.py +209 -0
- wxcli/commands/team_memberships.py +155 -0
- wxcli/commands/teams.py +153 -0
- wxcli/commands/ucm_profile.py +42 -0
- wxcli/commands/update.py +219 -0
- wxcli/commands/user_settings.py +5116 -0
- wxcli/commands/video_mesh.py +1090 -0
- wxcli/commands/virtual_extensions.py +502 -0
- wxcli/commands/virtual_line_settings.py +2072 -0
- wxcli/commands/webhooks.py +176 -0
- wxcli/commands/wholesale_billing_reports.py +147 -0
- wxcli/commands/wholesale_provisioning.py +523 -0
- wxcli/commands/workspace_locations.py +339 -0
- wxcli/commands/workspace_metrics.py +103 -0
- wxcli/commands/workspace_personalization.py +70 -0
- wxcli/commands/workspace_settings.py +3347 -0
- wxcli/commands/workspaces.py +279 -0
- wxcli/commands/xapi.py +114 -0
- wxcli/config.py +139 -0
- wxcli/errors.py +77 -0
- wxcli/main.py +210 -0
- wxcli/migration/CLAUDE.md +106 -0
- wxcli/migration/__init__.py +1 -0
- wxcli/migration/advisory/CLAUDE.md +196 -0
- wxcli/migration/advisory/__init__.py +46 -0
- wxcli/migration/advisory/advisor.py +107 -0
- wxcli/migration/advisory/advisory_patterns.py +2552 -0
- wxcli/migration/advisory/recommendation_rules.py +835 -0
- wxcli/migration/cucm/CLAUDE.md +74 -0
- wxcli/migration/cucm/__init__.py +5 -0
- wxcli/migration/cucm/connection.py +265 -0
- wxcli/migration/cucm/discovery.py +225 -0
- wxcli/migration/cucm/extractors/__init__.py +1 -0
- wxcli/migration/cucm/extractors/announcements.py +92 -0
- wxcli/migration/cucm/extractors/base.py +90 -0
- wxcli/migration/cucm/extractors/device_profiles.py +98 -0
- wxcli/migration/cucm/extractors/devices.py +193 -0
- wxcli/migration/cucm/extractors/e911.py +103 -0
- wxcli/migration/cucm/extractors/features.py +309 -0
- wxcli/migration/cucm/extractors/helpers.py +73 -0
- wxcli/migration/cucm/extractors/informational.py +295 -0
- wxcli/migration/cucm/extractors/locations.py +221 -0
- wxcli/migration/cucm/extractors/moh.py +100 -0
- wxcli/migration/cucm/extractors/remote_destinations.py +96 -0
- wxcli/migration/cucm/extractors/routing.py +493 -0
- wxcli/migration/cucm/extractors/shared_lines.py +146 -0
- wxcli/migration/cucm/extractors/templates.py +229 -0
- wxcli/migration/cucm/extractors/tier4.py +173 -0
- wxcli/migration/cucm/extractors/users.py +240 -0
- wxcli/migration/cucm/extractors/voicemail.py +243 -0
- wxcli/migration/cucm/extractors/workspaces.py +88 -0
- wxcli/migration/cucm/unity_connection.py +304 -0
- wxcli/migration/execute/CLAUDE.md +372 -0
- wxcli/migration/execute/__init__.py +303 -0
- wxcli/migration/execute/batch.py +277 -0
- wxcli/migration/execute/dependency.py +483 -0
- wxcli/migration/execute/engine.py +964 -0
- wxcli/migration/execute/handlers.py +2232 -0
- wxcli/migration/execute/planner.py +1939 -0
- wxcli/migration/execute/runtime.py +571 -0
- wxcli/migration/export/CLAUDE.md +49 -0
- wxcli/migration/export/__init__.py +8 -0
- wxcli/migration/export/csv_export.py +126 -0
- wxcli/migration/export/deployment_plan.py +479 -0
- wxcli/migration/export/json_export.py +60 -0
- wxcli/migration/models.py +941 -0
- wxcli/migration/phone_models.py +50 -0
- wxcli/migration/preflight/CLAUDE.md +52 -0
- wxcli/migration/preflight/__init__.py +89 -0
- wxcli/migration/preflight/checks.py +911 -0
- wxcli/migration/preflight/runner.py +293 -0
- wxcli/migration/rate_limiter.py +144 -0
- wxcli/migration/report/CLAUDE.md +245 -0
- wxcli/migration/report/__init__.py +7 -0
- wxcli/migration/report/appendix.py +2437 -0
- wxcli/migration/report/assembler.py +183 -0
- wxcli/migration/report/charts.py +263 -0
- wxcli/migration/report/executive.py +776 -0
- wxcli/migration/report/explainer.py +704 -0
- wxcli/migration/report/helpers.py +74 -0
- wxcli/migration/report/ingest.py +152 -0
- wxcli/migration/report/notice_templates.py +192 -0
- wxcli/migration/report/score.py +375 -0
- wxcli/migration/report/styles.py +1052 -0
- wxcli/migration/report/user_diff.py +1052 -0
- wxcli/migration/report/user_notice.py +425 -0
- wxcli/migration/state.py +139 -0
- wxcli/migration/store.py +860 -0
- wxcli/migration/transform/CLAUDE.md +107 -0
- wxcli/migration/transform/__init__.py +12 -0
- wxcli/migration/transform/analysis_pipeline.py +453 -0
- wxcli/migration/transform/analyzers/__init__.py +142 -0
- wxcli/migration/transform/analyzers/css_permission.py +189 -0
- wxcli/migration/transform/analyzers/css_routing.py +335 -0
- wxcli/migration/transform/analyzers/device_compatibility.py +122 -0
- wxcli/migration/transform/analyzers/dn_ambiguity.py +131 -0
- wxcli/migration/transform/analyzers/duplicate_user.py +221 -0
- wxcli/migration/transform/analyzers/extension_conflict.py +173 -0
- wxcli/migration/transform/analyzers/feature_approximation.py +227 -0
- wxcli/migration/transform/analyzers/layout_overflow.py +174 -0
- wxcli/migration/transform/analyzers/location_ambiguity.py +184 -0
- wxcli/migration/transform/analyzers/missing_data.py +300 -0
- wxcli/migration/transform/analyzers/selective_call_handling.py +394 -0
- wxcli/migration/transform/analyzers/shared_line.py +170 -0
- wxcli/migration/transform/analyzers/voicemail_compatibility.py +267 -0
- wxcli/migration/transform/analyzers/workspace_license.py +212 -0
- wxcli/migration/transform/cross_reference.py +1136 -0
- wxcli/migration/transform/cucm_pattern.py +246 -0
- wxcli/migration/transform/decisions.py +301 -0
- wxcli/migration/transform/e164.py +145 -0
- wxcli/migration/transform/engine.py +256 -0
- wxcli/migration/transform/mappers/CLAUDE.md +123 -0
- wxcli/migration/transform/mappers/__init__.py +76 -0
- wxcli/migration/transform/mappers/announcement_mapper.py +122 -0
- wxcli/migration/transform/mappers/base.py +190 -0
- wxcli/migration/transform/mappers/button_template_mapper.py +186 -0
- wxcli/migration/transform/mappers/call_forwarding_mapper.py +228 -0
- wxcli/migration/transform/mappers/call_settings_mapper.py +144 -0
- wxcli/migration/transform/mappers/css_mapper.py +868 -0
- wxcli/migration/transform/mappers/dect_mapper.py +367 -0
- wxcli/migration/transform/mappers/device_layout_mapper.py +289 -0
- wxcli/migration/transform/mappers/device_mapper.py +227 -0
- wxcli/migration/transform/mappers/device_profile_mapper.py +190 -0
- wxcli/migration/transform/mappers/device_settings_mapper.py +464 -0
- wxcli/migration/transform/mappers/e911_mapper.py +129 -0
- wxcli/migration/transform/mappers/ecbn_mapper.py +263 -0
- wxcli/migration/transform/mappers/executive_assistant_mapper.py +156 -0
- wxcli/migration/transform/mappers/feature_mapper.py +1179 -0
- wxcli/migration/transform/mappers/line_mapper.py +310 -0
- wxcli/migration/transform/mappers/location_mapper.py +235 -0
- wxcli/migration/transform/mappers/moh_mapper.py +114 -0
- wxcli/migration/transform/mappers/monitoring_mapper.py +221 -0
- wxcli/migration/transform/mappers/receptionist_mapper.py +245 -0
- wxcli/migration/transform/mappers/routing_mapper.py +821 -0
- wxcli/migration/transform/mappers/snr_mapper.py +201 -0
- wxcli/migration/transform/mappers/softkey_mapper.py +205 -0
- wxcli/migration/transform/mappers/user_mapper.py +264 -0
- wxcli/migration/transform/mappers/voicemail_group_mapper.py +286 -0
- wxcli/migration/transform/mappers/voicemail_mapper.py +514 -0
- wxcli/migration/transform/mappers/workspace_mapper.py +464 -0
- wxcli/migration/transform/normalizers.py +2008 -0
- wxcli/migration/transform/pattern_converter.py +106 -0
- wxcli/migration/transform/pipeline.py +271 -0
- wxcli/migration/transform/rules.py +255 -0
- wxcli/org_health/CLAUDE.md +63 -0
- wxcli/org_health/__init__.py +7 -0
- wxcli/org_health/analyze.py +93 -0
- wxcli/org_health/checks.py +458 -0
- wxcli/org_health/collector.py +62 -0
- wxcli/org_health/models.py +78 -0
- wxcli/org_health/report.py +300 -0
- wxcli/output.py +101 -0
- wxcli-1.2.0.dist-info/METADATA +505 -0
- wxcli-1.2.0.dist-info/RECORD +413 -0
- wxcli-1.2.0.dist-info/WHEEL +5 -0
- wxcli-1.2.0.dist-info/entry_points.txt +2 -0
- wxcli-1.2.0.dist-info/licenses/LICENSE +191 -0
- wxcli-1.2.0.dist-info/scm_file_list.json +751 -0
- wxcli-1.2.0.dist-info/scm_version.json +8 -0
- wxcli-1.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,747 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: call-control
|
|
3
|
+
description: |
|
|
4
|
+
Real-time Webex Calling call control, telephony webhook/event monitoring, conference controls,
|
|
5
|
+
and XSI real-time event streaming. Covers the Call Control API (user-level and Service App),
|
|
6
|
+
telephony webhook subscriptions and event parsing, conference controls, and wxcadm XSI for
|
|
7
|
+
real-time call monitoring and programmatic call control via BroadWorks.
|
|
8
|
+
NOT for: messaging webhooks/bot events (use messaging-bots skill), call settings/forwarding
|
|
9
|
+
configuration (use manage-call-settings skill), or CDR/call history queries (use reporting skill).
|
|
10
|
+
allowed-tools: Read, Grep, Glob, Bash
|
|
11
|
+
argument-hint: [call-control | webhooks | xsi-events | conference]
|
|
12
|
+
---
|
|
13
|
+
|
|
14
|
+
<!-- Created 2026-03-19 -->
|
|
15
|
+
|
|
16
|
+
# Call Control & Real-time Events Workflow
|
|
17
|
+
|
|
18
|
+
> **CRITICAL WARNING: USER-LEVEL OAUTH TOKEN REQUIRED**
|
|
19
|
+
>
|
|
20
|
+
> The Call Control API (`/v1/telephony/calls/*`) requires a **user-level OAuth token** with `spark:calls_read` / `spark:calls_write` scopes. Admin tokens get **400 "Target user not authorized"**. This is the #1 gotcha.
|
|
21
|
+
>
|
|
22
|
+
> **Service Apps** (with `spark-admin:calls_read` / `spark-admin:calls_write`) must use the **Members API** (`/v1/telephony/calls/members/{memberId}/*`) instead of the user-level endpoints.
|
|
23
|
+
>
|
|
24
|
+
> `wxcli call-controls` commands use user-level endpoints by default. Do NOT use them with admin/service-app tokens.
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
**Checkpoint — do NOT proceed until you can answer these:**
|
|
29
|
+
1. What token type does the Call Control API require, and what error do admin tokens get? (Answer: User-level OAuth with `spark:calls_read`/`spark:calls_write`. Admin tokens get 400 "Target user not authorized".)
|
|
30
|
+
2. What API path must Service Apps use instead of user-level endpoints? (Answer: Members API — `/v1/telephony/calls/members/{memberId}/*` with `spark-admin:calls_read`/`spark-admin:calls_write`.)
|
|
31
|
+
|
|
32
|
+
If you cannot answer both, you skipped reading this skill. Go back and read it.
|
|
33
|
+
|
|
34
|
+
## Step 1: Load references
|
|
35
|
+
|
|
36
|
+
Load the reference docs needed for the requested operation. Load all three if the user hasn't specified which approach they need yet; otherwise load only the relevant one(s).
|
|
37
|
+
|
|
38
|
+
| Reference doc | When to load |
|
|
39
|
+
|---------------|-------------|
|
|
40
|
+
| `docs/reference/call-control.md` | Call Control API operations, conference controls |
|
|
41
|
+
| `docs/reference/webhooks-events.md` | Webhook setup, telephony event subscriptions |
|
|
42
|
+
| `docs/reference/wxcadm-xsi-realtime.md` | XSI real-time event streaming (wxcadm only) |
|
|
43
|
+
|
|
44
|
+
**Mandatory --help verification:** Before constructing any wxcli command, run `wxcli <group> --help` to verify the subcommand exists, then `wxcli <group> <subcommand> --help` to verify the exact flags. Do NOT rely on examples in this skill or reference docs — the CLI is auto-generated and flag names may differ from what documentation suggests.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Step 2: Verify authentication
|
|
49
|
+
|
|
50
|
+
Before any call control or webhook operations, confirm the user has a working token:
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
wxcli whoami
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
If this fails, resolve authentication first (`wxcli configure`).
|
|
57
|
+
|
|
58
|
+
### Scope verification
|
|
59
|
+
|
|
60
|
+
After confirming a valid token, verify the token has the scopes required for the user's intended approach:
|
|
61
|
+
|
|
62
|
+
| Approach | Required Scopes | Token Type |
|
|
63
|
+
|----------|----------------|------------|
|
|
64
|
+
| **Call Control (user)** | `spark:calls_read`, `spark:calls_write` | User-level OAuth (Integration flow) |
|
|
65
|
+
| **Call Control (Service App)** | `spark-admin:calls_read`, `spark-admin:calls_write` | Service App token |
|
|
66
|
+
| **Webhooks** | `spark:calls_read` (to create telephony_calls webhook) | User-level OAuth |
|
|
67
|
+
| **XSI Events (wxcadm)** | `spark:xsi` (user) or `spark-admin:xsi` (admin) | User or admin |
|
|
68
|
+
| **WebRTC Calling** | `spark:webrtc_calling` | User-level OAuth |
|
|
69
|
+
| **Firehose webhook** | `spark:all` | User-level OAuth |
|
|
70
|
+
|
|
71
|
+
**Scope-checking logic:**
|
|
72
|
+
|
|
73
|
+
1. Run `wxcli whoami` — confirm the token is valid and note whether it is a user token, admin token, or Service App token.
|
|
74
|
+
2. Match the token type against the table above:
|
|
75
|
+
- If **user-level token** → proceed with user-level Call Control, Webhooks, or XSI.
|
|
76
|
+
- If **Service App token** → MUST use Members API endpoints (`/calls/members/{memberId}/*`). Standard call-control commands will fail with 400.
|
|
77
|
+
- If **admin token only** → call control will fail. Advise the user to obtain a user-level token or use a Service App with the correct scopes.
|
|
78
|
+
3. If scope is unclear, warn the user: *"Call Control requires a user-level token with `spark:calls_read` + `spark:calls_write`. Admin tokens get 400 'Target user not authorized'."*
|
|
79
|
+
4. The 12-hour developer token from developer.webex.com works for testing if it was generated with the correct scopes.
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## Step 3: Identify the operation
|
|
84
|
+
|
|
85
|
+
Present this decision matrix if the user is unsure which approach fits their need:
|
|
86
|
+
|
|
87
|
+
| Need | Approach | Tool |
|
|
88
|
+
|------|----------|------|
|
|
89
|
+
| Control calls from an external app (click-to-dial, hold, transfer) | **Call Control API** | `wxcli call-controls` or raw HTTP via `WebexSession` |
|
|
90
|
+
| Control calls on behalf of users (admin/service app) | **Members API** | `wxcli call-controls create-dial-members`, `create-answer-members`, etc. |
|
|
91
|
+
| Get notified when calls start/end/change state (push model) | **Webhooks** | `wxcli webhooks` or raw HTTP |
|
|
92
|
+
| Real-time event streaming for dashboards, CRM screen pops | **XSI Events** | wxcadm `XSIEvents` (ONLY option) |
|
|
93
|
+
| Programmatic call control via BroadWorks back-end | **XSI Actions** | wxcadm `XSI` / `Call` class |
|
|
94
|
+
| Multi-party conference management | **Conference Controls** | `wxcli conference` |
|
|
95
|
+
| Poll for active calls or call history | **Call Control API (GET)** | `wxcli call-controls list` / `list-history` |
|
|
96
|
+
|
|
97
|
+
**Key distinctions:**
|
|
98
|
+
- **Call Control API** = REST API on `api.webex.com`, requires user token, works for 3rd-party call control apps
|
|
99
|
+
- **Webhooks** = push notifications to your HTTPS endpoint when call events occur
|
|
100
|
+
- **XSI Events** = persistent streaming connection to BroadWorks XSP, org-wide or per-user, wxcadm only
|
|
101
|
+
- **Conference Controls** = separate API for multi-party conference management
|
|
102
|
+
|
|
103
|
+
---
|
|
104
|
+
|
|
105
|
+
## Step 4: Check prerequisites
|
|
106
|
+
|
|
107
|
+
Based on the approach identified in Step 3, verify the prerequisites below.
|
|
108
|
+
|
|
109
|
+
### 4a. Call Control prerequisites
|
|
110
|
+
|
|
111
|
+
- Token is **user-level** with `spark:calls_read` + `spark:calls_write` (verified in Step 2).
|
|
112
|
+
- For Service App usage, token has `spark-admin:calls_read` + `spark-admin:calls_write` and you will use the Members API.
|
|
113
|
+
- The target user has a **Webex Calling license** assigned. Users without a calling license return 404 (error 4008).
|
|
114
|
+
- Confirm CLI access: `wxcli call-controls --help`
|
|
115
|
+
|
|
116
|
+
### 4b. Webhook prerequisites
|
|
117
|
+
|
|
118
|
+
- Token has `spark:calls_read` scope.
|
|
119
|
+
- The webhook target URL is **publicly accessible over HTTPS**. For local development, use ngrok or a similar tunnel.
|
|
120
|
+
- No duplicate webhooks exist for the same resource/event combo (duplicates cause duplicate event delivery). Check with: `wxcli webhooks list -o json`
|
|
121
|
+
|
|
122
|
+
### 4c. XSI prerequisites
|
|
123
|
+
|
|
124
|
+
- **XSI must be enabled on the Webex Org.** Contact Cisco TAC to request activation -- there is no self-service toggle.
|
|
125
|
+
- Token includes `spark:xsi` (user) or `spark-admin:xsi` (admin) scope.
|
|
126
|
+
- wxcadm is installed and available.
|
|
127
|
+
- Verify XSI is enabled:
|
|
128
|
+
```python
|
|
129
|
+
webex = wxcadm.Webex(access_token, get_xsi=True)
|
|
130
|
+
print(webex.org.xsi) # Should show 4 XSI endpoint URLs (not None)
|
|
131
|
+
```
|
|
132
|
+
If `webex.org.xsi` is `None`, XSI is not enabled on the org.
|
|
133
|
+
|
|
134
|
+
---
|
|
135
|
+
|
|
136
|
+
## Step 5: Build and present deployment plan [SHOW BEFORE EXECUTING]
|
|
137
|
+
|
|
138
|
+
Before executing any call control, webhook, or XSI operations, present the deployment plan to the user for approval. Include:
|
|
139
|
+
|
|
140
|
+
1. **Approach selected** — which approach from Step 3 (Call Control, Webhooks, XSI, Conference)
|
|
141
|
+
2. **Token type confirmed** — user-level, Service App, or admin (from Step 2)
|
|
142
|
+
3. **Operations to perform** — list of specific commands/API calls that will be executed
|
|
143
|
+
4. **Prerequisites verified** — confirm all Step 4 checks passed
|
|
144
|
+
5. **Risks or warnings** — any relevant Critical Rules that apply (e.g., "webhook auto-deactivation if target URL is unreachable", "XSI recording pause has known bug")
|
|
145
|
+
|
|
146
|
+
Example plan format:
|
|
147
|
+
|
|
148
|
+
```
|
|
149
|
+
## Call Control Deployment Plan
|
|
150
|
+
|
|
151
|
+
**Approach:** Call Control API (user-level)
|
|
152
|
+
**Token:** User OAuth (verified via wxcli whoami)
|
|
153
|
+
|
|
154
|
+
### Operations
|
|
155
|
+
1. Initiate click-to-dial to +12223334444
|
|
156
|
+
2. Monitor call state via list-active
|
|
157
|
+
3. Transfer to +15551234567 when connected
|
|
158
|
+
|
|
159
|
+
### Prerequisites
|
|
160
|
+
- [x] User-level token with spark:calls_read + spark:calls_write
|
|
161
|
+
- [x] Target user has Webex Calling license
|
|
162
|
+
- [x] wxcli call-controls accessible
|
|
163
|
+
|
|
164
|
+
### Warnings
|
|
165
|
+
- Transfer requires the call to be answered first (unanswered = use divert instead)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Wait for user approval before proceeding to Step 6.
|
|
169
|
+
|
|
170
|
+
---
|
|
171
|
+
|
|
172
|
+
## Step 6: Execute via wxcli
|
|
173
|
+
|
|
174
|
+
### 6a. Call control operations
|
|
175
|
+
|
|
176
|
+
#### Call state machine
|
|
177
|
+
|
|
178
|
+
Understanding the call state machine is essential for correct call control:
|
|
179
|
+
|
|
180
|
+
```
|
|
181
|
+
┌──────────────┐
|
|
182
|
+
dial ──────>│ connecting │
|
|
183
|
+
└──────┬───────┘
|
|
184
|
+
│ remote rings
|
|
185
|
+
v
|
|
186
|
+
incoming ────>┌──────────────┐
|
|
187
|
+
│ alerting │──── reject ────> disconnected
|
|
188
|
+
└──────┬───────┘
|
|
189
|
+
│ answer
|
|
190
|
+
v
|
|
191
|
+
┌──────────────┐
|
|
192
|
+
┌────>│ connected │──── hangup ────> disconnected
|
|
193
|
+
│ └──┬────┬──────┘
|
|
194
|
+
│ │ │
|
|
195
|
+
resume │ hold │ │ remote hold
|
|
196
|
+
│ v v
|
|
197
|
+
│ ┌──────┐ ┌────────────┐
|
|
198
|
+
└──│ held │ │ remoteHeld │
|
|
199
|
+
└──────┘ └────────────┘
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
**CallState values:** `connecting`, `alerting`, `connected`, `held`, `remoteHeld`, `disconnected`
|
|
203
|
+
|
|
204
|
+
**Personality values:** `originator` (outgoing), `terminator` (incoming), `clickToDial` (alerting for click-to-dial, becomes `originator` on answer)
|
|
205
|
+
|
|
206
|
+
#### Core call operations via wxcli
|
|
207
|
+
|
|
208
|
+
##### Initiate a call (click-to-dial)
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
wxcli call-controls create --destination "+12223334444"
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Optional: `--endpoint-id DEVICE_ID` to target a specific device.
|
|
215
|
+
|
|
216
|
+
##### Answer an incoming call
|
|
217
|
+
|
|
218
|
+
```bash
|
|
219
|
+
wxcli call-controls create-answer-calls --call-id CALL_ID
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
##### Hold and resume
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
wxcli call-controls create-hold --call-id CALL_ID
|
|
226
|
+
wxcli call-controls create-resume --call-id CALL_ID
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
##### Transfer
|
|
230
|
+
|
|
231
|
+
Three transfer modes:
|
|
232
|
+
|
|
233
|
+
| Mode | CLI flags | Description |
|
|
234
|
+
|------|-----------|-------------|
|
|
235
|
+
| Auto (2 calls) | (no call IDs) | User has exactly 2 calls, auto-selected |
|
|
236
|
+
| Consultative | `--call-id1 X --call-id2 Y` | Transfer two specific calls together |
|
|
237
|
+
| Mute transfer | `--call-id1 X --destination NUM` | Transfer to new destination, waits for answer |
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
# Consultative transfer
|
|
241
|
+
wxcli call-controls create-transfer --call-id1 CALL_ID_1 --call-id2 CALL_ID_2
|
|
242
|
+
|
|
243
|
+
# Mute transfer to a number
|
|
244
|
+
wxcli call-controls create-transfer --call-id1 CALL_ID --destination "+15551234567"
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Important:** Unanswered incoming calls cannot be transferred. Use `create-divert` instead.
|
|
248
|
+
|
|
249
|
+
##### Park and retrieve
|
|
250
|
+
|
|
251
|
+
```bash
|
|
252
|
+
# Park a call (returns the park extension)
|
|
253
|
+
wxcli call-controls create-park --call-id CALL_ID
|
|
254
|
+
|
|
255
|
+
# Retrieve a parked call
|
|
256
|
+
wxcli call-controls create-retrieve --destination PARK_EXTENSION
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
##### Recording control
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
wxcli call-controls create-start-recording --call-id CALL_ID
|
|
263
|
+
wxcli call-controls create-stop-recording --call-id CALL_ID
|
|
264
|
+
wxcli call-controls create-pause-recording --call-id CALL_ID
|
|
265
|
+
wxcli call-controls create-resume-recording --call-id CALL_ID
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
Recording mode determines which actions are available:
|
|
269
|
+
- **On Demand**: start, stop, pause, resume
|
|
270
|
+
- **Always with Pause/Resume**: pause, resume only
|
|
271
|
+
- **Always**: no manual control
|
|
272
|
+
|
|
273
|
+
##### Other actions
|
|
274
|
+
|
|
275
|
+
```bash
|
|
276
|
+
# Reject incoming call
|
|
277
|
+
wxcli call-controls create-reject --call-id CALL_ID
|
|
278
|
+
|
|
279
|
+
# Hangup
|
|
280
|
+
wxcli call-controls create-hangup-calls --call-id CALL_ID
|
|
281
|
+
|
|
282
|
+
# Mute/unmute
|
|
283
|
+
wxcli call-controls create-mute --call-id CALL_ID
|
|
284
|
+
wxcli call-controls create-unmute --call-id CALL_ID
|
|
285
|
+
|
|
286
|
+
# Divert (blind transfer or send to voicemail)
|
|
287
|
+
wxcli call-controls create-divert --call-id CALL_ID --destination "+12223334444"
|
|
288
|
+
wxcli call-controls create-divert --call-id CALL_ID --to-voicemail
|
|
289
|
+
|
|
290
|
+
# Send DTMF tones
|
|
291
|
+
wxcli call-controls create-transmit-dtmf --call-id CALL_ID --dtmf "1,234"
|
|
292
|
+
|
|
293
|
+
# Pick up another user's ringing call
|
|
294
|
+
wxcli call-controls create-pickup --target "+12223334444"
|
|
295
|
+
|
|
296
|
+
# Pull call to another device
|
|
297
|
+
wxcli call-controls create-pull --endpoint-id DEVICE_ID
|
|
298
|
+
|
|
299
|
+
# Push call to executive (assistant only)
|
|
300
|
+
wxcli call-controls create-push --call-id CALL_ID
|
|
301
|
+
|
|
302
|
+
# Barge into another user's call
|
|
303
|
+
wxcli call-controls create-barge-in --target "+12223334444"
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
#### Query active calls and history
|
|
307
|
+
|
|
308
|
+
```bash
|
|
309
|
+
# List all active calls for the user
|
|
310
|
+
wxcli call-controls list -o json
|
|
311
|
+
|
|
312
|
+
# Get details of a specific call (--line-owner-id required for Service App tokens)
|
|
313
|
+
wxcli call-controls show CALL_ID -o json
|
|
314
|
+
wxcli call-controls show CALL_ID --line-owner-id USER_ID -o json
|
|
315
|
+
|
|
316
|
+
# List call history (max 20 per type, 60 total)
|
|
317
|
+
wxcli call-controls list-history -o json
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
#### Service App / Members API commands
|
|
321
|
+
|
|
322
|
+
For Service Apps that control calls on behalf of users:
|
|
323
|
+
|
|
324
|
+
```bash
|
|
325
|
+
# Dial on behalf of a member
|
|
326
|
+
wxcli call-controls create-dial-members MEMBER_ID --destination "+12223334444"
|
|
327
|
+
|
|
328
|
+
# Answer on behalf of a member
|
|
329
|
+
wxcli call-controls create-answer-members MEMBER_ID --call-id CALL_ID
|
|
330
|
+
|
|
331
|
+
# Hangup on behalf of a member
|
|
332
|
+
wxcli call-controls create-hangup-members MEMBER_ID --call-id CALL_ID
|
|
333
|
+
|
|
334
|
+
# List calls for a member
|
|
335
|
+
wxcli call-controls list-calls-members MEMBER_ID -o json
|
|
336
|
+
|
|
337
|
+
# Get call details for a member
|
|
338
|
+
wxcli call-controls show-calls-members MEMBER_ID CALL_ID -o json
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### 6b. Webhook setup for telephony events
|
|
342
|
+
|
|
343
|
+
#### Creating a telephony call webhook
|
|
344
|
+
|
|
345
|
+
Webhooks deliver push notifications to your HTTPS endpoint when call events occur. The webhook target URL must be publicly accessible over HTTPS (use ngrok for local development).
|
|
346
|
+
|
|
347
|
+
##### Via wxcli (preferred)
|
|
348
|
+
|
|
349
|
+
```bash
|
|
350
|
+
# List existing webhooks to check for duplicates
|
|
351
|
+
wxcli webhooks list --output json
|
|
352
|
+
|
|
353
|
+
# Delete old webhook if it exists (avoid duplicate delivery)
|
|
354
|
+
wxcli webhooks delete WEBHOOK_ID
|
|
355
|
+
|
|
356
|
+
# Create webhook for all telephony call events
|
|
357
|
+
wxcli webhooks create \
|
|
358
|
+
--name "My Call Monitor" \
|
|
359
|
+
--target-url "https://your-server.com/webhooks/calls" \
|
|
360
|
+
--resource "telephony_calls" \
|
|
361
|
+
--event "all" \
|
|
362
|
+
--secret "your-hmac-secret"
|
|
363
|
+
|
|
364
|
+
# Verify it was created
|
|
365
|
+
wxcli webhooks list --output json
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
##### Via raw HTTP (for programmatic HMAC verification or complex webhook management)
|
|
369
|
+
|
|
370
|
+
```python
|
|
371
|
+
from wxcli.auth import get_api
|
|
372
|
+
|
|
373
|
+
api = get_api()
|
|
374
|
+
BASE = "https://webexapis.com/v1/webhooks"
|
|
375
|
+
|
|
376
|
+
# Clean up old webhooks first (avoid duplicate delivery)
|
|
377
|
+
existing = list(api.session.follow_pagination(BASE))
|
|
378
|
+
for wh in existing:
|
|
379
|
+
if wh["name"] == "My Call Monitor":
|
|
380
|
+
api.session.rest_delete(f"{BASE}/{wh['id']}")
|
|
381
|
+
|
|
382
|
+
# Create webhook for all telephony call events
|
|
383
|
+
webhook = api.session.rest_post(BASE, json={
|
|
384
|
+
"name": "My Call Monitor",
|
|
385
|
+
"targetUrl": "https://your-server.com/webhooks/calls",
|
|
386
|
+
"resource": "telephony_calls",
|
|
387
|
+
"event": "all",
|
|
388
|
+
"secret": "your-hmac-secret"
|
|
389
|
+
})
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
#### Webhook event types
|
|
393
|
+
|
|
394
|
+
The `event` field (top-level) maps to telephony-specific `data.eventType` values:
|
|
395
|
+
|
|
396
|
+
| Webhook `event` | `data.eventType` | When it fires |
|
|
397
|
+
|-----------------|-------------------|---------------|
|
|
398
|
+
| `created` | `alerting` | Call is ringing |
|
|
399
|
+
| `created` | `answered` | Call was answered |
|
|
400
|
+
| `updated` | `connected` | Call transitioned to connected |
|
|
401
|
+
| `updated` | `held` | User placed call on hold |
|
|
402
|
+
| `updated` | `remoteHeld` | Remote party placed call on hold |
|
|
403
|
+
| `updated` | `resumed` | Held call was resumed |
|
|
404
|
+
| `updated` | `recording` | Recording state changed |
|
|
405
|
+
| `deleted` | `disconnected` | Call ended |
|
|
406
|
+
| `deleted` | `forwarded` | Call was forwarded away |
|
|
407
|
+
|
|
408
|
+
#### Filtering webhooks
|
|
409
|
+
|
|
410
|
+
Narrow which events are delivered using the `filter` parameter:
|
|
411
|
+
|
|
412
|
+
```bash
|
|
413
|
+
# Incoming calls only (filter on personality=terminator)
|
|
414
|
+
wxcli webhooks create \
|
|
415
|
+
--name "Incoming Calls" \
|
|
416
|
+
--target-url "https://example.com/incoming" \
|
|
417
|
+
--resource "telephony_calls" \
|
|
418
|
+
--event "all" \
|
|
419
|
+
--filter "personality=terminator"
|
|
420
|
+
```
|
|
421
|
+
|
|
422
|
+
Available filters: `personality`, `state`, `callType`, `personId`.
|
|
423
|
+
|
|
424
|
+
#### Parsing webhook event payloads
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
def handle_webhook(request_json: dict):
|
|
428
|
+
data = request_json["data"]
|
|
429
|
+
|
|
430
|
+
print(f"Event: {data['eventType']}")
|
|
431
|
+
print(f"Call ID: {data['callId']}")
|
|
432
|
+
print(f"State: {data['state']}")
|
|
433
|
+
print(f"Remote: {data.remote_party.name} ({data.remote_party.number})")
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
The `TelephonyEventData` class inherits from both `WebhookEventData` and `TelephonyCall`, so all call fields are directly accessible.
|
|
437
|
+
|
|
438
|
+
#### HMAC signature verification
|
|
439
|
+
|
|
440
|
+
When a `secret` is provided, verify the `X-Spark-Signature` header:
|
|
441
|
+
|
|
442
|
+
```python
|
|
443
|
+
import hmac, hashlib
|
|
444
|
+
|
|
445
|
+
def verify_signature(body: bytes, signature: str, secret: str) -> bool:
|
|
446
|
+
expected = hmac.new(secret.encode('utf-8'), body, hashlib.sha1).hexdigest()
|
|
447
|
+
return hmac.compare_digest(expected, signature)
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
#### Webhook management
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
# List all webhooks
|
|
454
|
+
wxcli webhooks list --output json
|
|
455
|
+
|
|
456
|
+
# Reactivate an auto-deactivated webhook
|
|
457
|
+
wxcli webhooks update WEBHOOK_ID --json-body '{"name": "Reactivated", "targetUrl": "https://...", "status": "active"}'
|
|
458
|
+
|
|
459
|
+
# Delete a webhook
|
|
460
|
+
wxcli webhooks delete WEBHOOK_ID
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
#### Other telephony webhook resources
|
|
464
|
+
|
|
465
|
+
| Resource | Description |
|
|
466
|
+
|----------|-------------|
|
|
467
|
+
| `telephony_calls` | Call events (alerting, connected, held, disconnected, etc.) |
|
|
468
|
+
| `telephony_conference` | Conference control events |
|
|
469
|
+
| `telephony_mwi` | Voicemail message waiting indicator |
|
|
470
|
+
| `convergedRecordings` | Call recording events |
|
|
471
|
+
|
|
472
|
+
### 6c. XSI real-time events (wxcadm only)
|
|
473
|
+
|
|
474
|
+
> **XSI is wxcadm's unique capability.** It is NOT available via wxcli or the standard Webex REST APIs. XSI connects directly to the BroadWorks call control back-end that powers Webex Calling.
|
|
475
|
+
|
|
476
|
+
#### When to use XSI vs webhooks
|
|
477
|
+
|
|
478
|
+
| Requirement | Use XSI Events | Use Webhooks |
|
|
479
|
+
|-------------|:-:|:-:|
|
|
480
|
+
| Real-time streaming (sub-second latency) | Yes | No (HTTP delivery delay) |
|
|
481
|
+
| Org-wide call monitoring | Yes | Yes (with org-level webhook) |
|
|
482
|
+
| CRM screen pops | Yes | Possible but higher latency |
|
|
483
|
+
| Real-time agent dashboards | Yes | Possible but less reliable |
|
|
484
|
+
| Simple event notifications (email, Slack) | Overkill | Yes |
|
|
485
|
+
| No server infrastructure needed | No (needs long-running process) | Yes (just an HTTPS endpoint) |
|
|
486
|
+
| Call control from events | Yes (XSI Actions) | Requires separate Call Control API call |
|
|
487
|
+
| Works without Cisco TAC enablement | No | Yes |
|
|
488
|
+
|
|
489
|
+
#### Setting up XSI event monitoring
|
|
490
|
+
|
|
491
|
+
```python
|
|
492
|
+
import queue
|
|
493
|
+
import wxcadm
|
|
494
|
+
|
|
495
|
+
# Initialize with XSI endpoints
|
|
496
|
+
webex = wxcadm.Webex(access_token, get_xsi=True)
|
|
497
|
+
|
|
498
|
+
# Create XSIEvents instance (org-level)
|
|
499
|
+
events = wxcadm.XSIEvents(webex.org)
|
|
500
|
+
|
|
501
|
+
# Create a queue for events (size to handle bursts)
|
|
502
|
+
events_queue = queue.Queue(maxsize=1000)
|
|
503
|
+
|
|
504
|
+
# Open channel set (auto-discovers XSPs via DNS SRV, opens streaming connections)
|
|
505
|
+
channel = events.open_channel(events_queue)
|
|
506
|
+
|
|
507
|
+
# Subscribe to call events
|
|
508
|
+
subscription = channel.subscribe(["Advanced Call"])
|
|
509
|
+
|
|
510
|
+
# Process events
|
|
511
|
+
while True:
|
|
512
|
+
event = events_queue.get()
|
|
513
|
+
event_data = event['xsi:Event']
|
|
514
|
+
event_type = event_data['xsi:eventData']['@xsi1:type']
|
|
515
|
+
user_id = event_data.get('xsi:userId', '')
|
|
516
|
+
print(f"[{user_id}] {event_type}")
|
|
517
|
+
```
|
|
518
|
+
|
|
519
|
+
#### Per-user subscription
|
|
520
|
+
|
|
521
|
+
```python
|
|
522
|
+
person = webex.org.get_person_by_email("user@domain.com")
|
|
523
|
+
subscription = channel.subscribe(["Advanced Call"], person=person)
|
|
524
|
+
```
|
|
525
|
+
|
|
526
|
+
#### XSI event types
|
|
527
|
+
|
|
528
|
+
A single outbound call generates 6 events:
|
|
529
|
+
|
|
530
|
+
| Event Type | When |
|
|
531
|
+
|------------|------|
|
|
532
|
+
| `xsi:HookStatusEvent` | Phone goes off-hook |
|
|
533
|
+
| `xsi:CallOriginatedEvent` | Call initiated (dialing) |
|
|
534
|
+
| `xsi:CallUpdatedEvent` | Call state changes |
|
|
535
|
+
| `xsi:CallAnsweredEvent` | Remote party answers |
|
|
536
|
+
| `xsi:CallReleasedEvent` | Call ends |
|
|
537
|
+
| `xsi:HookStatusEvent` | Phone goes on-hook |
|
|
538
|
+
|
|
539
|
+
Additional event types: `xsi:CallReceivedEvent` (incoming), `xsi:CallHeldEvent`, `xsi:CallRetrievedEvent`, `xsi:CallTransferredEvent`, `xsi:CallSubscriptionEvent`.
|
|
540
|
+
|
|
541
|
+
#### XSI call control (XSI-Actions)
|
|
542
|
+
|
|
543
|
+
wxcadm also provides direct call control via XSI-Actions (separate from the Webex REST API):
|
|
544
|
+
|
|
545
|
+
```python
|
|
546
|
+
person = webex.org.get_person_by_email("user@domain.com")
|
|
547
|
+
person.start_xsi()
|
|
548
|
+
|
|
549
|
+
# Originate a call
|
|
550
|
+
call = person.xsi.new_call(address="17192662837")
|
|
551
|
+
|
|
552
|
+
# Mid-call actions
|
|
553
|
+
call.hold()
|
|
554
|
+
call.resume()
|
|
555
|
+
call.transfer("2345")
|
|
556
|
+
call.transfer("2345", type="attended") # Attended transfer
|
|
557
|
+
call.finish_transfer() # Complete attended transfer
|
|
558
|
+
call.conference(address="5678") # Conference with new party
|
|
559
|
+
call.park() # Group call park
|
|
560
|
+
call.park(extension="8001") # Park at specific extension
|
|
561
|
+
call.recording("start") # Start recording
|
|
562
|
+
call.send_dtmf("12345#") # Send DTMF
|
|
563
|
+
call.hangup()
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
#### XSI channel management
|
|
567
|
+
|
|
568
|
+
```python
|
|
569
|
+
# Check active channels
|
|
570
|
+
active = channel.active_channels
|
|
571
|
+
|
|
572
|
+
# Close everything (channels + subscriptions)
|
|
573
|
+
channel.close()
|
|
574
|
+
```
|
|
575
|
+
|
|
576
|
+
Channels auto-refresh hourly (7200-second expiry). Failed channels auto-recover after 60 seconds.
|
|
577
|
+
|
|
578
|
+
### 6d. Conference control operations
|
|
579
|
+
|
|
580
|
+
#### CLI commands
|
|
581
|
+
|
|
582
|
+
```bash
|
|
583
|
+
wxcli conference --help
|
|
584
|
+
```
|
|
585
|
+
|
|
586
|
+
#### Available conference commands
|
|
587
|
+
|
|
588
|
+
| Command | Key Options | Description |
|
|
589
|
+
|---------|-------------|-------------|
|
|
590
|
+
| `wxcli conference list` | `--line-owner-id` | Get conference details |
|
|
591
|
+
| `wxcli conference create` | `--json-body` | Start a conference |
|
|
592
|
+
| `wxcli conference delete` | `--line-owner-id` | Release (end) a conference |
|
|
593
|
+
| `wxcli conference create-add-participant` | `--call-id` (required), `--line-owner-id` | Add a participant |
|
|
594
|
+
| `wxcli conference create-mute` | `--call-id` | Mute a participant |
|
|
595
|
+
| `wxcli conference create-unmute` | `--call-id` | Unmute a participant |
|
|
596
|
+
| `wxcli conference create-deafen` | `--call-id` (required) | Deafen a participant (can't hear) |
|
|
597
|
+
| `wxcli conference create-undeafen` | `--call-id` (required) | Undeafen a participant |
|
|
598
|
+
| `wxcli conference create-hold` | `--line-owner-id` | Hold the conference |
|
|
599
|
+
| `wxcli conference create-resume` | `--line-owner-id` | Resume the conference |
|
|
600
|
+
|
|
601
|
+
**Note:** Conference commands do NOT take a positional conference ID. Use `--line-owner-id` to specify whose conference to operate on (required for Service App tokens).
|
|
602
|
+
|
|
603
|
+
#### 3-way merge via Call Control API
|
|
604
|
+
|
|
605
|
+
The Call Control API also supports merging two active calls into a conference:
|
|
606
|
+
|
|
607
|
+
```bash
|
|
608
|
+
# Merge two calls (user must have one active, one held)
|
|
609
|
+
wxcli call-controls create-transfer --call-id1 CALL_ID_1 --call-id2 CALL_ID_2
|
|
610
|
+
```
|
|
611
|
+
|
|
612
|
+
Or via raw HTTP:
|
|
613
|
+
|
|
614
|
+
```python
|
|
615
|
+
from wxcli.auth import get_api
|
|
616
|
+
api = get_api()
|
|
617
|
+
api.session.rest_post("https://webexapis.com/v1/telephony/calls/conference",
|
|
618
|
+
json={"callId1": call_id_1, "callId2": call_id_2})
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
#### Conference via XSI (wxcadm)
|
|
622
|
+
|
|
623
|
+
```python
|
|
624
|
+
# From an attended transfer, bridge all parties
|
|
625
|
+
call.transfer("2345", type="attended")
|
|
626
|
+
call.conference() # Bridges all parties
|
|
627
|
+
call.finish_transfer() # Drop initiator, leave others
|
|
628
|
+
|
|
629
|
+
# Conference with a new party
|
|
630
|
+
conference = call.conference(address="5678")
|
|
631
|
+
conference.mute(call_id) # Mute a participant
|
|
632
|
+
conference.deaf(call_id) # Deafen a participant
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
---
|
|
636
|
+
|
|
637
|
+
## Step 7: Verification
|
|
638
|
+
|
|
639
|
+
### Verify call control is working
|
|
640
|
+
|
|
641
|
+
```bash
|
|
642
|
+
# List active calls (should return empty list if no calls)
|
|
643
|
+
wxcli call-controls list -o json
|
|
644
|
+
|
|
645
|
+
# Check call history (confirms API access)
|
|
646
|
+
wxcli call-controls list-history -o json
|
|
647
|
+
```
|
|
648
|
+
|
|
649
|
+
### Verify webhook is receiving events
|
|
650
|
+
|
|
651
|
+
```bash
|
|
652
|
+
# List webhooks and check status — look for status: "active"
|
|
653
|
+
wxcli webhooks list --output json
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
If a webhook shows `inactive`, it was auto-deactivated due to delivery failures. Fix the target URL and reactivate:
|
|
657
|
+
|
|
658
|
+
```bash
|
|
659
|
+
wxcli webhooks update WEBHOOK_ID --json-body '{"name": "My Call Monitor", "targetUrl": "https://fixed-url.com/webhooks", "status": "active"}'
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### Verify XSI connectivity
|
|
663
|
+
|
|
664
|
+
```python
|
|
665
|
+
webex = wxcadm.Webex(access_token, get_xsi=True)
|
|
666
|
+
print(webex.org.xsi) # Should show 4 XSI endpoint URLs (not None)
|
|
667
|
+
|
|
668
|
+
person = webex.org.get_person_by_email("user@domain.com")
|
|
669
|
+
person.start_xsi(get_profile=True)
|
|
670
|
+
print(person.xsi.profile) # Should show user profile from BroadWorks
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
If `webex.org.xsi` is `None`, XSI is not enabled on the org -- contact Cisco TAC.
|
|
674
|
+
|
|
675
|
+
---
|
|
676
|
+
|
|
677
|
+
## Step 8: Report results
|
|
678
|
+
|
|
679
|
+
Summarize the completed operations and their outcomes:
|
|
680
|
+
|
|
681
|
+
1. **What was configured** — which approach (Call Control, Webhooks, XSI, Conference) and what specific operations were performed
|
|
682
|
+
2. **Verification results** — confirmation that the configuration is working (API responses, webhook status, XSI connectivity)
|
|
683
|
+
3. **Active resources** — list any persistent resources created (webhooks, XSI subscriptions, etc.) that the user should be aware of
|
|
684
|
+
4. **Next steps** — any follow-up actions the user may want to take (e.g., "webhook is active — test by placing a call", "XSI channel is open — events will stream until the process is stopped")
|
|
685
|
+
5. **Cleanup reminders** — resources that should be cleaned up when no longer needed (e.g., "delete the webhook when done testing", "call `channel.close()` to tear down XSI subscriptions")
|
|
686
|
+
|
|
687
|
+
---
|
|
688
|
+
|
|
689
|
+
## Critical Rules
|
|
690
|
+
|
|
691
|
+
1. **User-level token required for call control.** Admin tokens get 400 "Target user not authorized". Service Apps must use the Members API (`/calls/members/{memberId}/*`). This is the most common failure.
|
|
692
|
+
|
|
693
|
+
2. **Webhook auto-deactivation.** Webhooks that fail to deliver events (target URL returns errors repeatedly) are automatically set to `inactive`. You must explicitly reactivate them via the update API. You cannot deactivate a webhook via API -- only delete it.
|
|
694
|
+
|
|
695
|
+
3. **Webhook resource/event/filter are immutable.** You cannot change these after creation. Delete and recreate instead. Only `name`, `targetUrl`, `secret`, and `status` can be updated.
|
|
696
|
+
|
|
697
|
+
4. **Webhook URL must be HTTPS.** For local development, use ngrok or a similar tunnel.
|
|
698
|
+
|
|
699
|
+
5. **`callId` vs `id` aliasing.** API responses use `id`, webhook events use `callId`. The SDK handles both transparently via the `call_id` property.
|
|
700
|
+
|
|
701
|
+
6. **Transfer restrictions.** Unanswered incoming calls cannot be transferred. Use `divert` (blind transfer / send to voicemail) for unanswered calls.
|
|
702
|
+
|
|
703
|
+
7. **Recording mode dependency.** `start/stop` only work with "On Demand" mode. `pause/resume` work with both "On Demand" and "Always with Pause/Resume". Check the user's recording configuration first.
|
|
704
|
+
|
|
705
|
+
8. **Call history limit.** `list-history` returns max 20 records per type (placed/missed/received), max 60 total.
|
|
706
|
+
|
|
707
|
+
9. **XSI requires Cisco TAC enablement.** There is no self-service toggle. If `webex.org.xsi` returns `None`, XSI is not enabled.
|
|
708
|
+
|
|
709
|
+
10. **XSI events are XML, not JSON.** wxcadm parses them with `xmltodict` into OrderedDicts. The `$` key holds text content, `@` prefix denotes attributes.
|
|
710
|
+
|
|
711
|
+
11. **XSI event volume is high.** A single call generates 6 events. A busy org can produce hundreds of events per second. Size your queue appropriately (start with 500-1000).
|
|
712
|
+
|
|
713
|
+
12. **XSI channel auto-recovery has a 60-second gap.** Failed channels wait 60 seconds before restarting. Events for that XSP are lost during the gap.
|
|
714
|
+
|
|
715
|
+
13. **XSI `recording("pause")` has a known bug (verified 2026-03-18).** Duplicate `elif` in wxcadm source causes `ValueError`. Workaround: call the XSI `PauseRecording` endpoint directly via `requests.put()`.
|
|
716
|
+
|
|
717
|
+
14. **Conference via Call Control API requires two calls.** The user must have one active and one held call to merge. Use `hold` first, then `dial` the second party, then `conference`.
|
|
718
|
+
|
|
719
|
+
15. **Webhook event delivery is not guaranteed to be ordered.** Use `data.eventTimestamp` and `data.callSessionId` to correlate and order events.
|
|
720
|
+
|
|
721
|
+
16. **One webhook per resource/event combo.** Creating duplicates results in duplicate event delivery. Always clean up old webhooks before creating new ones.
|
|
722
|
+
|
|
723
|
+
---
|
|
724
|
+
|
|
725
|
+
## Scope Quick Reference
|
|
726
|
+
|
|
727
|
+
| Scope | Purpose |
|
|
728
|
+
|-------|---------|
|
|
729
|
+
| `spark:calls_read` | List calls, call details, call history, create telephony webhooks (user) |
|
|
730
|
+
| `spark:calls_write` | All call control actions: dial, answer, hold, transfer, park, record (user) |
|
|
731
|
+
| `spark-admin:calls_read` | List/get calls for any member (Service App) |
|
|
732
|
+
| `spark-admin:calls_write` | Call control actions for any member (Service App) |
|
|
733
|
+
| `spark:xsi` | XSI access (user-level) |
|
|
734
|
+
| `spark-admin:xsi` | XSI access (admin-level) |
|
|
735
|
+
| `spark:webrtc_calling` | WebRTC calling |
|
|
736
|
+
| `spark:all` | Firehose webhook (all resources, all events) |
|
|
737
|
+
|
|
738
|
+
---
|
|
739
|
+
|
|
740
|
+
## Context Compaction Recovery
|
|
741
|
+
|
|
742
|
+
If context compacts mid-execution, recover by:
|
|
743
|
+
1. Re-read `docs/reference/call-control.md` for call control API details
|
|
744
|
+
2. Re-read `docs/reference/webhooks-events.md` for webhook setup
|
|
745
|
+
3. Re-read `docs/reference/wxcadm-xsi-realtime.md` for XSI events
|
|
746
|
+
4. Run `wxcli call-controls --help` and `wxcli conference --help` to rediscover CLI commands
|
|
747
|
+
5. Resume from the last completed step
|