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,1205 @@
|
|
|
1
|
+
<!-- Updated by playbook session 2026-03-18 -->
|
|
2
|
+
# Call Control API Reference
|
|
3
|
+
|
|
4
|
+
Webex Calling Call Control APIs enable 3rd-party applications to manage calls on behalf of users. These are **3rd Party Call Control** APIs only, applicable to **Webex Calling Multi-Tenant users** (not UCM or Dedicated Instance users).
|
|
5
|
+
|
|
6
|
+
> **Base path:** `POST /v1/telephony/calls/{action}`
|
|
7
|
+
> **GET endpoints:** `GET /v1/telephony/calls` and `GET /v1/telephony/calls/{callId}`
|
|
8
|
+
|
|
9
|
+
## Sources
|
|
10
|
+
|
|
11
|
+
- wxc_sdk v1.30.0
|
|
12
|
+
- OpenAPI spec: specs/webex-cloud-calling.json
|
|
13
|
+
- developer.webex.com Call Control APIs
|
|
14
|
+
|
|
15
|
+
## Table of Contents
|
|
16
|
+
|
|
17
|
+
1. [Required Scopes](#required-scopes)
|
|
18
|
+
2. [Raw HTTP Reference](#raw-http-reference-all-call-control-endpoints)
|
|
19
|
+
3. [CLI Examples](#cli-examples)
|
|
20
|
+
4. [Call Connection](#1-call-connection)
|
|
21
|
+
5. [Mid-Call Actions](#2-mid-call-actions)
|
|
22
|
+
6. [Call Details & History](#3-call-details--history)
|
|
23
|
+
7. [Data Models](#4-data-models)
|
|
24
|
+
8. [Service App / Admin API](#5-service-app--admin-api-call-controls-members)
|
|
25
|
+
9. [Additional API: External Voicemail MWI](#6-additional-api-external-voicemail-mwi)
|
|
26
|
+
10. [Common Use Cases](#7-common-use-cases)
|
|
27
|
+
11. [Key Gotchas](#8-key-gotchas)
|
|
28
|
+
12. [See Also](#see-also)
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Required Scopes
|
|
33
|
+
|
|
34
|
+
| Scope | Grants | Used By |
|
|
35
|
+
|-------|--------|---------|
|
|
36
|
+
| `spark:calls_read` | List calls, get call details, call history | User tokens (personal) |
|
|
37
|
+
| `spark:calls_write` | All call control actions (dial, answer, hold, transfer, etc.) | User tokens (personal) |
|
|
38
|
+
| `spark-admin:calls_read` | List calls, get call details for any member | Service App tokens (admin) |
|
|
39
|
+
| `spark-admin:calls_write` | All call control actions for any member | Service App tokens (admin) |
|
|
40
|
+
|
|
41
|
+
- **User-level APIs** (`CallsApi`) use `spark:calls_read` / `spark:calls_write` and operate on the authenticated user's calls.
|
|
42
|
+
- **Service App / Admin APIs** (`CallControlsMembersApi`) use `spark-admin:calls_read` / `spark-admin:calls_write` and operate on any person, workspace, or virtual line by `member_id`.
|
|
43
|
+
|
|
44
|
+
---
|
|
45
|
+
|
|
46
|
+
## Raw HTTP Reference (All Call Control Endpoints)
|
|
47
|
+
|
|
48
|
+
All call control endpoints use `https://webexapis.com/v1/telephony/calls/{action}`. Most are POST actions that take a JSON body. GET endpoints retrieve call state.
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from wxc_sdk import WebexSimpleApi
|
|
52
|
+
api = WebexSimpleApi()
|
|
53
|
+
BASE = "https://webexapis.com/v1"
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### User-Level Call Actions
|
|
57
|
+
|
|
58
|
+
| Action | Method | URL | Body Fields |
|
|
59
|
+
|--------|--------|-----|-------------|
|
|
60
|
+
| Dial | POST | `{BASE}/telephony/calls/dial` | `destination` (required), `endpointId`, `lineOwnerId` |
|
|
61
|
+
| Answer | POST | `{BASE}/telephony/calls/answer` | `callId` (required), `endpointId`, `lineOwnerId` |
|
|
62
|
+
| Reject | POST | `{BASE}/telephony/calls/reject` | `callId` (required), `action`, `lineOwnerId` |
|
|
63
|
+
| Hangup | POST | `{BASE}/telephony/calls/hangup` | `callId` (required), `lineOwnerId` |
|
|
64
|
+
| Hold | POST | `{BASE}/telephony/calls/hold` | `callId` (required), `lineOwnerId` |
|
|
65
|
+
| Resume | POST | `{BASE}/telephony/calls/resume` | `callId` (required), `lineOwnerId` |
|
|
66
|
+
| Mute | POST | `{BASE}/telephony/calls/mute` | `callId` (required), `lineOwnerId` |
|
|
67
|
+
| Unmute | POST | `{BASE}/telephony/calls/unmute` | `callId` (required), `lineOwnerId` |
|
|
68
|
+
| Divert | POST | `{BASE}/telephony/calls/divert` | `callId` (required), `destination`, `toVoicemail`, `lineOwnerId` |
|
|
69
|
+
| Transfer | POST | `{BASE}/telephony/calls/transfer` | `callId1`, `callId2`, `destination`, `lineOwnerId` |
|
|
70
|
+
| Park | POST | `{BASE}/telephony/calls/park` | `callId` (required), `destination`, `isGroupPark`, `lineOwnerId` |
|
|
71
|
+
| Retrieve | POST | `{BASE}/telephony/calls/retrieve` | `destination`, `endpointId`, `lineOwnerId` |
|
|
72
|
+
| Pull | POST | `{BASE}/telephony/calls/pull` | `endpointId`, `lineOwnerId` |
|
|
73
|
+
| Push | POST | `{BASE}/telephony/calls/push` | `callId`, `lineOwnerId` |
|
|
74
|
+
| Pickup | POST | `{BASE}/telephony/calls/pickup` | `target`, `endpointId`, `lineOwnerId` |
|
|
75
|
+
| Barge In | POST | `{BASE}/telephony/calls/bargeIn` | `target` (required), `endpointId`, `lineOwnerId` |
|
|
76
|
+
| Conference | POST | `{BASE}/telephony/calls/conference` | `callId1`, `callId2`, `lineOwnerId` |
|
|
77
|
+
| Start Recording | POST | `{BASE}/telephony/calls/startRecording` | `callId` (required), `lineOwnerId` |
|
|
78
|
+
| Stop Recording | POST | `{BASE}/telephony/calls/stopRecording` | `callId` (required), `lineOwnerId` |
|
|
79
|
+
| Pause Recording | POST | `{BASE}/telephony/calls/pauseRecording` | `callId` (required), `lineOwnerId` |
|
|
80
|
+
| Resume Recording | POST | `{BASE}/telephony/calls/resumeRecording` | `callId` (required), `lineOwnerId` |
|
|
81
|
+
| Transmit DTMF | POST | `{BASE}/telephony/calls/transmitDtmf` | `callId` (required), `dtmf` (required), `lineOwnerId` |
|
|
82
|
+
|
|
83
|
+
### User-Level Read Endpoints
|
|
84
|
+
|
|
85
|
+
| Action | Method | URL | Query Params | Response Key |
|
|
86
|
+
|--------|--------|-----|-------------|--------------|
|
|
87
|
+
| List Calls | GET | `{BASE}/telephony/calls` | `lineOwnerId` | `calls` |
|
|
88
|
+
| Get Call Details | GET | `{BASE}/telephony/calls/{callId}` | `lineOwnerId` | (direct object) |
|
|
89
|
+
| List Call History | GET | `{BASE}/telephony/calls/history` | `type` | `history` |
|
|
90
|
+
|
|
91
|
+
### Service App / Members Endpoints
|
|
92
|
+
|
|
93
|
+
| Action | Method | URL | Body Fields |
|
|
94
|
+
|--------|--------|-----|-------------|
|
|
95
|
+
| Dial by Member | POST | `{BASE}/telephony/calls/members/{memberId}/dial` | `destination`, `endpointId` |
|
|
96
|
+
| Answer by Member | POST | `{BASE}/telephony/calls/members/{memberId}/answer` | `callId`, `endpointId` |
|
|
97
|
+
| Hangup by Member | POST | `{BASE}/telephony/calls/members/{memberId}/hangup` | `callId` |
|
|
98
|
+
| List Calls by Member | GET | `{BASE}/telephony/calls/members/{memberId}/calls` | (none) |
|
|
99
|
+
| Get Call Details by Member | GET | `{BASE}/telephony/calls/members/{memberId}/calls/{callId}` | (none) |
|
|
100
|
+
|
|
101
|
+
### Raw HTTP Examples
|
|
102
|
+
|
|
103
|
+
#### Dial a call
|
|
104
|
+
|
|
105
|
+
```python
|
|
106
|
+
body = {"destination": "+12223334444", "endpointId": "Y2lzY29zcGFyay..."}
|
|
107
|
+
result = api.session.rest_post(f"{BASE}/telephony/calls/dial", json=body)
|
|
108
|
+
# Returns: {callId, callSessionId}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
#### List active calls
|
|
112
|
+
|
|
113
|
+
```python
|
|
114
|
+
result = api.session.rest_get(f"{BASE}/telephony/calls")
|
|
115
|
+
calls = result.get("calls", [])
|
|
116
|
+
# Each call: {id, callSessionId, personality, state, remoteParty: {name, number, ...}, created, answered, ...}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
#### Get call details
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
result = api.session.rest_get(f"{BASE}/telephony/calls/{call_id}")
|
|
123
|
+
# Returns full call object with state, remoteParty, timestamps, etc.
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
#### List call history
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
result = api.session.rest_get(f"{BASE}/telephony/calls/history", params={"type": "placed"})
|
|
130
|
+
history = result.get("history", [])
|
|
131
|
+
# Each record: {type, name, number, privacyEnabled, time}
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
#### Hold, then transfer
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
# Put caller on hold
|
|
138
|
+
api.session.rest_post(f"{BASE}/telephony/calls/hold", json={"callId": caller_call_id})
|
|
139
|
+
|
|
140
|
+
# Dial consult target
|
|
141
|
+
consult = api.session.rest_post(f"{BASE}/telephony/calls/dial", json={"destination": "+15551234567"})
|
|
142
|
+
|
|
143
|
+
# Transfer both calls together
|
|
144
|
+
api.session.rest_post(f"{BASE}/telephony/calls/transfer", json={
|
|
145
|
+
"callId1": caller_call_id,
|
|
146
|
+
"callId2": consult["callId"]
|
|
147
|
+
})
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
#### Park and retrieve
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
# Park
|
|
154
|
+
parked = api.session.rest_post(f"{BASE}/telephony/calls/park", json={"callId": call_id})
|
|
155
|
+
park_number = parked.get("parkedAgainst", {}).get("number")
|
|
156
|
+
|
|
157
|
+
# Retrieve (from any device)
|
|
158
|
+
retrieved = api.session.rest_post(f"{BASE}/telephony/calls/retrieve", json={"destination": park_number})
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
#### Service App: Dial on behalf of a member
|
|
162
|
+
|
|
163
|
+
```python
|
|
164
|
+
body = {"destination": "+12223334444"}
|
|
165
|
+
result = api.session.rest_post(f"{BASE}/telephony/calls/members/{member_id}/dial", json=body)
|
|
166
|
+
# Returns: {callId, callSessionId}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
#### External Voicemail MWI
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
body = {"action": "SET"} # or "CLEAR"
|
|
173
|
+
api.session.rest_post(f"{BASE}/telephony/externalVoicemail/mwi", json=body, params={
|
|
174
|
+
"id": user_id,
|
|
175
|
+
"orgId": org_id
|
|
176
|
+
})
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Raw HTTP Gotchas
|
|
180
|
+
|
|
181
|
+
1. **All action endpoints are POST** -- even hold, resume, mute, unmute. Only list/details/history are GET.
|
|
182
|
+
2. **Response varies by action** -- `dial`, `pickup`, `retrieve`, `pull`, `bargeIn` return `{callId, callSessionId}`. Most others return 204 (no content).
|
|
183
|
+
3. **Transfer response depends on mode** -- auto/consultative returns 204; mute transfer returns 201 with `{callId, callSessionId}`.
|
|
184
|
+
4. **`id` vs `callId`** -- GET responses return `id` as the call identifier. Webhook events use `callId`. When passing to action endpoints, always use `callId` in the request body.
|
|
185
|
+
5. **`lineOwnerId`** is optional on all endpoints -- only needed when controlling a secondary line belonging to another user/workspace/virtual line.
|
|
186
|
+
6. **Members API does not have `lineOwnerId`** -- the member_id in the URL serves the same purpose.
|
|
187
|
+
7. **No pagination on call list** -- `list_calls` returns all active calls for the user (typically a small number).
|
|
188
|
+
8. **History max 20 per type** -- `list_call_history` returns at most 20 records per type (placed/missed/received), max 60 total.
|
|
189
|
+
|
|
190
|
+
---
|
|
191
|
+
|
|
192
|
+
## CLI Examples
|
|
193
|
+
|
|
194
|
+
> **Important:** Call control commands require a **user-level OAuth token**, not an admin token. Admin tokens return 400 "Target user not authorized". Configure wxcli with a user's personal access token: `wxcli configure`.
|
|
195
|
+
|
|
196
|
+
### Command Reference
|
|
197
|
+
|
|
198
|
+
All 29 commands in the `call-controls` group:
|
|
199
|
+
|
|
200
|
+
| Command | Description | Key Options |
|
|
201
|
+
|---------|-------------|-------------|
|
|
202
|
+
| `create` | Dial | `--destination` (required), `--endpoint-id`, `--line-owner-id` |
|
|
203
|
+
| `create-answer-calls` | Answer | `--call-id` (required), `--endpoint-id`, `--line-owner-id` |
|
|
204
|
+
| `create-reject` | Reject | `--call-id` (required), `--action`, `--line-owner-id` |
|
|
205
|
+
| `create-hangup-calls` | Hangup | `--call-id` (required), `--line-owner-id` |
|
|
206
|
+
| `create-hold` | Hold | `--call-id` (required), `--line-owner-id` |
|
|
207
|
+
| `create-resume` | Resume | `--call-id` (required), `--line-owner-id` |
|
|
208
|
+
| `create-mute` | Mute | `--call-id` (required), `--line-owner-id` |
|
|
209
|
+
| `create-unmute` | Unmute | `--call-id` (required), `--line-owner-id` |
|
|
210
|
+
| `create-divert` | Divert | `--call-id` (required), `--destination`, `--to-voicemail`, `--line-owner-id` |
|
|
211
|
+
| `create-transfer` | Transfer | `--call-id1`, `--call-id2`, `--destination`, `--line-owner-id` |
|
|
212
|
+
| `create-park` | Park | `--call-id` (required), `--destination`, `--is-group-park`, `--line-owner-id` |
|
|
213
|
+
| `create-retrieve` | Retrieve | `--destination`, `--endpoint-id`, `--line-owner-id` |
|
|
214
|
+
| `create-pull` | Pull | `--endpoint-id`, `--line-owner-id` |
|
|
215
|
+
| `create-push` | Push | `--call-id`, `--line-owner-id` |
|
|
216
|
+
| `create-pickup` | Pickup | `--target`, `--endpoint-id`, `--line-owner-id` |
|
|
217
|
+
| `create-barge-in` | Barge In | `--target` (required), `--endpoint-id`, `--line-owner-id` |
|
|
218
|
+
| `create-start-recording` | Start Recording | `--call-id`, `--line-owner-id` |
|
|
219
|
+
| `create-stop-recording` | Stop Recording | `--call-id`, `--line-owner-id` |
|
|
220
|
+
| `create-pause-recording` | Pause Recording | `--call-id`, `--line-owner-id` |
|
|
221
|
+
| `create-resume-recording` | Resume Recording | `--call-id`, `--line-owner-id` |
|
|
222
|
+
| `create-transmit-dtmf` | Transmit DTMF | `--call-id`, `--dtmf`, `--line-owner-id` |
|
|
223
|
+
| `list` | List Calls | `--line-owner-id`, `-o table\|json` |
|
|
224
|
+
| `show` | Get Call Details | `CALL_ID` (positional, required), `--line-owner-id`, `-o table\|json` |
|
|
225
|
+
| `list-history` | List Call History | `--type placed\|missed\|received`, `-o table\|json` |
|
|
226
|
+
| `create-dial` | Dial by Member ID | `MEMBER_ID` (positional), `--destination` (required), `--endpoint-id` |
|
|
227
|
+
| `create-answer-members` | Answer by Member ID | `MEMBER_ID` (positional), `--call-id` (required), `--endpoint-id` |
|
|
228
|
+
| `create-hangup-members` | Hangup by Member ID | `MEMBER_ID` (positional), `--call-id` (required) |
|
|
229
|
+
| `list-calls` | List Calls by Member ID | `MEMBER_ID` (positional), `-o table\|json` |
|
|
230
|
+
| `show-calls` | Get Call Details by Member ID | `MEMBER_ID` `CALL_ID` (positional), `-o table\|json` |
|
|
231
|
+
|
|
232
|
+
### Call Connection
|
|
233
|
+
|
|
234
|
+
```bash
|
|
235
|
+
# Dial a number (rings all user devices, then places outbound call)
|
|
236
|
+
wxcli call-controls create --destination "+12223334444"
|
|
237
|
+
|
|
238
|
+
# Dial an extension
|
|
239
|
+
wxcli call-controls create --destination "1234"
|
|
240
|
+
|
|
241
|
+
# Dial on a specific device/app
|
|
242
|
+
wxcli call-controls create --destination "+12223334444" --endpoint-id Y2lzY29zcGFyay...
|
|
243
|
+
|
|
244
|
+
# Answer an incoming call
|
|
245
|
+
wxcli call-controls create-answer-calls --call-id Y2lzY29zcGFyay...
|
|
246
|
+
|
|
247
|
+
# Answer on a specific device
|
|
248
|
+
wxcli call-controls create-answer-calls --call-id Y2lzY29zcGFyay... --endpoint-id Y2lzY29zcGFyay...
|
|
249
|
+
|
|
250
|
+
# Reject an incoming call (defaults to busy)
|
|
251
|
+
wxcli call-controls create-reject --call-id Y2lzY29zcGFyay...
|
|
252
|
+
|
|
253
|
+
# Reject with a specific action (busy, temporarilyUnavailable, ignore)
|
|
254
|
+
wxcli call-controls create-reject --call-id Y2lzY29zcGFyay... --action temporarilyUnavailable
|
|
255
|
+
|
|
256
|
+
# Hang up a call
|
|
257
|
+
wxcli call-controls create-hangup-calls --call-id Y2lzY29zcGFyay...
|
|
258
|
+
|
|
259
|
+
# Pick up a call from your call pickup group
|
|
260
|
+
wxcli call-controls create-pickup
|
|
261
|
+
|
|
262
|
+
# Pick up a call from a specific user
|
|
263
|
+
wxcli call-controls create-pickup --target "+12223334444"
|
|
264
|
+
|
|
265
|
+
# Divert a call to another number
|
|
266
|
+
wxcli call-controls create-divert --call-id Y2lzY29zcGFyay... --destination "+15551234567"
|
|
267
|
+
|
|
268
|
+
# Divert a call to voicemail
|
|
269
|
+
wxcli call-controls create-divert --call-id Y2lzY29zcGFyay... --to-voicemail
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
### Mid-Call Actions
|
|
273
|
+
|
|
274
|
+
```bash
|
|
275
|
+
# Hold a call
|
|
276
|
+
wxcli call-controls create-hold --call-id Y2lzY29zcGFyay...
|
|
277
|
+
|
|
278
|
+
# Resume a held call
|
|
279
|
+
wxcli call-controls create-resume --call-id Y2lzY29zcGFyay...
|
|
280
|
+
|
|
281
|
+
# Mute a call
|
|
282
|
+
wxcli call-controls create-mute --call-id Y2lzY29zcGFyay...
|
|
283
|
+
|
|
284
|
+
# Unmute a call
|
|
285
|
+
wxcli call-controls create-unmute --call-id Y2lzY29zcGFyay...
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
### Transfer
|
|
289
|
+
|
|
290
|
+
```bash
|
|
291
|
+
# Auto transfer (user has exactly 2 calls -- they are merged automatically)
|
|
292
|
+
wxcli call-controls create-transfer
|
|
293
|
+
|
|
294
|
+
# Consultative/attended transfer (specify both call IDs)
|
|
295
|
+
wxcli call-controls create-transfer --call-id1 Y2lzY29zcGFyay_call1... --call-id2 Y2lzY29zcGFyay_call2...
|
|
296
|
+
|
|
297
|
+
# Mute transfer (transfer to a new destination; waits for answer)
|
|
298
|
+
wxcli call-controls create-transfer --call-id1 Y2lzY29zcGFyay... --destination "+15551234567"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Park / Retrieve
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
# Park a call (parks against self; returns the park extension number)
|
|
305
|
+
wxcli call-controls create-park --call-id Y2lzY29zcGFyay...
|
|
306
|
+
|
|
307
|
+
# Park a call at a specific extension
|
|
308
|
+
wxcli call-controls create-park --call-id Y2lzY29zcGFyay... --destination "7001"
|
|
309
|
+
|
|
310
|
+
# Park using the call park group (auto-selects an available slot)
|
|
311
|
+
wxcli call-controls create-park --call-id Y2lzY29zcGFyay... --is-group-park
|
|
312
|
+
|
|
313
|
+
# Retrieve a parked call (use the park number from the park response)
|
|
314
|
+
wxcli call-controls create-retrieve --destination "7001"
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Recording Control
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# Start recording (user must have "On Demand" recording mode)
|
|
321
|
+
wxcli call-controls create-start-recording --call-id Y2lzY29zcGFyay...
|
|
322
|
+
|
|
323
|
+
# Pause recording (e.g., for sensitive info like credit card numbers)
|
|
324
|
+
wxcli call-controls create-pause-recording --call-id Y2lzY29zcGFyay...
|
|
325
|
+
|
|
326
|
+
# Resume recording
|
|
327
|
+
wxcli call-controls create-resume-recording --call-id Y2lzY29zcGFyay...
|
|
328
|
+
|
|
329
|
+
# Stop recording
|
|
330
|
+
wxcli call-controls create-stop-recording --call-id Y2lzY29zcGFyay...
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
### Other Actions
|
|
334
|
+
|
|
335
|
+
```bash
|
|
336
|
+
# Transmit DTMF tones (comma = pause between digits)
|
|
337
|
+
wxcli call-controls create-transmit-dtmf --call-id Y2lzY29zcGFyay... --dtmf "1,234"
|
|
338
|
+
|
|
339
|
+
# Pull a call to a different device (move call between desk phone, mobile, desktop)
|
|
340
|
+
wxcli call-controls create-pull --endpoint-id Y2lzY29zcGFyay...
|
|
341
|
+
|
|
342
|
+
# Push a call to the executive (executive-assistant feature only)
|
|
343
|
+
wxcli call-controls create-push --call-id Y2lzY29zcGFyay...
|
|
344
|
+
|
|
345
|
+
# Barge in on another user's active call
|
|
346
|
+
wxcli call-controls create-barge-in --target "+12223334444"
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
### Call Details & History
|
|
350
|
+
|
|
351
|
+
```bash
|
|
352
|
+
# List all active calls
|
|
353
|
+
wxcli call-controls list
|
|
354
|
+
wxcli call-controls list -o json
|
|
355
|
+
|
|
356
|
+
# Get details for a specific active call
|
|
357
|
+
wxcli call-controls show Y2lzY29zcGFyay...
|
|
358
|
+
wxcli call-controls show Y2lzY29zcGFyay... -o table
|
|
359
|
+
|
|
360
|
+
# List call history (all types -- placed, missed, received; max 20 each)
|
|
361
|
+
wxcli call-controls list-history
|
|
362
|
+
|
|
363
|
+
# List only missed calls
|
|
364
|
+
wxcli call-controls list-history --type missed
|
|
365
|
+
|
|
366
|
+
# List only placed calls as JSON
|
|
367
|
+
wxcli call-controls list-history --type placed -o json
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
### Service App / Members API
|
|
371
|
+
|
|
372
|
+
> These commands use `spark-admin:calls_read` / `spark-admin:calls_write` scopes and operate on behalf of a person, workspace, or virtual line by member ID.
|
|
373
|
+
|
|
374
|
+
```bash
|
|
375
|
+
# Dial on behalf of a user (Service App token required)
|
|
376
|
+
wxcli call-controls create-dial <member_id> --destination "+12223334444"
|
|
377
|
+
|
|
378
|
+
# Answer a call on behalf of a user
|
|
379
|
+
wxcli call-controls create-answer-members <member_id> --call-id Y2lzY29zcGFyay...
|
|
380
|
+
|
|
381
|
+
# Hang up a call on behalf of a user
|
|
382
|
+
wxcli call-controls create-hangup-members <member_id> --call-id Y2lzY29zcGFyay...
|
|
383
|
+
|
|
384
|
+
# List active calls for a user
|
|
385
|
+
wxcli call-controls list-calls <member_id>
|
|
386
|
+
|
|
387
|
+
# Get call details for a specific call on a user
|
|
388
|
+
wxcli call-controls show-calls <member_id> Y2lzY29zcGFyay...
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
### Hold, Consult, Transfer Pattern (CLI Workflow)
|
|
392
|
+
|
|
393
|
+
A common call center pattern: put the caller on hold, dial a consult target, then transfer both calls together.
|
|
394
|
+
|
|
395
|
+
```bash
|
|
396
|
+
# Step 1: Put the current call on hold
|
|
397
|
+
wxcli call-controls create-hold --call-id <caller_call_id>
|
|
398
|
+
|
|
399
|
+
# Step 2: Dial the transfer target
|
|
400
|
+
wxcli call-controls create --destination "+15551234567"
|
|
401
|
+
# Note the new call_id from the response
|
|
402
|
+
|
|
403
|
+
# Step 3: After speaking with the transfer target, transfer both calls
|
|
404
|
+
wxcli call-controls create-transfer --call-id1 <caller_call_id> --call-id2 <consult_call_id>
|
|
405
|
+
```
|
|
406
|
+
|
|
407
|
+
---
|
|
408
|
+
|
|
409
|
+
## 1. Call Connection
|
|
410
|
+
|
|
411
|
+
### Dial (Click-to-Call)
|
|
412
|
+
|
|
413
|
+
Initiate an outbound call. Alerts all user devices (or a specific endpoint). When the user answers on one device, the outbound call is placed from that device to the destination.
|
|
414
|
+
|
|
415
|
+
```
|
|
416
|
+
POST /v1/telephony/calls/dial
|
|
417
|
+
```
|
|
418
|
+
|
|
419
|
+
**SDK Signature:**
|
|
420
|
+
```python
|
|
421
|
+
CallsApi.dial(
|
|
422
|
+
destination: str, # digits, URI, SIP address, tel: URI
|
|
423
|
+
endpoint_id: str = None, # specific device/app to alert
|
|
424
|
+
line_owner_id: str = None # secondary line owner (user/workspace/virtual line)
|
|
425
|
+
) -> CallInfo
|
|
426
|
+
```
|
|
427
|
+
|
|
428
|
+
**Request body:**
|
|
429
|
+
```json
|
|
430
|
+
{
|
|
431
|
+
"destination": "+12223334444",
|
|
432
|
+
"endpointId": "Y2lzY29zcGFyay..."
|
|
433
|
+
}
|
|
434
|
+
```
|
|
435
|
+
|
|
436
|
+
**Response (201):**
|
|
437
|
+
```json
|
|
438
|
+
{
|
|
439
|
+
"callId": "Y2lzY29zcGFyay...",
|
|
440
|
+
"callSessionId": "OGQ3YzhkNzgt..."
|
|
441
|
+
}
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
**Destination formats:** `1234`, `2223334444`, `+12223334444`, `*73`, `tel:+12223334444`, `user@company.domain`, `sip:user@company.domain`
|
|
445
|
+
|
|
446
|
+
---
|
|
447
|
+
|
|
448
|
+
### Answer
|
|
449
|
+
|
|
450
|
+
Answer an incoming call on a specific device (or the user's primary device if no endpoint specified).
|
|
451
|
+
|
|
452
|
+
```
|
|
453
|
+
POST /v1/telephony/calls/answer
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
**SDK Signature:**
|
|
457
|
+
```python
|
|
458
|
+
CallsApi.answer(
|
|
459
|
+
call_id: str,
|
|
460
|
+
endpoint_id: str = None,
|
|
461
|
+
line_owner_id: str = None
|
|
462
|
+
) -> None
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
**Request body:**
|
|
466
|
+
```json
|
|
467
|
+
{
|
|
468
|
+
"callId": "Y2lzY29zcGFyay...",
|
|
469
|
+
"endpointId": "Y2lzY29zcGFyay..."
|
|
470
|
+
}
|
|
471
|
+
```
|
|
472
|
+
|
|
473
|
+
**Notes:**
|
|
474
|
+
- Rejected if the device is not alerting for the call.
|
|
475
|
+
- Rejected if the device does not support answer via API.
|
|
476
|
+
|
|
477
|
+
---
|
|
478
|
+
|
|
479
|
+
### Pickup
|
|
480
|
+
|
|
481
|
+
Pick up an incoming call ringing on another user's device. Initiates a new call (similar to dial) to perform the pickup.
|
|
482
|
+
|
|
483
|
+
```
|
|
484
|
+
POST /v1/telephony/calls/pickup
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
**SDK Signature:**
|
|
488
|
+
```python
|
|
489
|
+
CallsApi.pickup(
|
|
490
|
+
target: str = None, # user to pick up from; omit for call pickup group
|
|
491
|
+
endpoint_id: str = None,
|
|
492
|
+
line_owner_id: str = None
|
|
493
|
+
) -> CallInfo
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
- **No target:** picks up from the user's call pickup group.
|
|
497
|
+
- **With target:** picks up from the specified user (digits or URI).
|
|
498
|
+
|
|
499
|
+
**Response:** Returns `CallInfo` (callId + callSessionId).
|
|
500
|
+
|
|
501
|
+
---
|
|
502
|
+
|
|
503
|
+
### Reject
|
|
504
|
+
|
|
505
|
+
Reject an unanswered incoming call.
|
|
506
|
+
|
|
507
|
+
```
|
|
508
|
+
POST /v1/telephony/calls/reject
|
|
509
|
+
```
|
|
510
|
+
|
|
511
|
+
**SDK Signature:**
|
|
512
|
+
```python
|
|
513
|
+
CallsApi.reject(
|
|
514
|
+
call_id: str,
|
|
515
|
+
action: RejectAction = None, # defaults to 'busy' if omitted
|
|
516
|
+
line_owner_id: str = None
|
|
517
|
+
) -> None
|
|
518
|
+
```
|
|
519
|
+
|
|
520
|
+
**RejectAction values:**
|
|
521
|
+
|
|
522
|
+
| Value | Behavior |
|
|
523
|
+
|-------|----------|
|
|
524
|
+
| `busy` | Send the call to busy (default) |
|
|
525
|
+
| `temporarilyUnavailable` | Send the call to temporarily unavailable |
|
|
526
|
+
| `ignore` | Continue ringback to caller, stop alerting user's devices |
|
|
527
|
+
|
|
528
|
+
---
|
|
529
|
+
|
|
530
|
+
### Divert (Blind Transfer)
|
|
531
|
+
|
|
532
|
+
Divert a call to another destination or to voicemail.
|
|
533
|
+
|
|
534
|
+
```
|
|
535
|
+
POST /v1/telephony/calls/divert
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
**SDK Signature:**
|
|
539
|
+
```python
|
|
540
|
+
CallsApi.divert(
|
|
541
|
+
call_id: str,
|
|
542
|
+
destination: str = None, # required if toVoicemail is false
|
|
543
|
+
to_voicemail: bool = None, # True = send to voicemail
|
|
544
|
+
line_owner_id: str = None
|
|
545
|
+
) -> None
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
**Request body examples:**
|
|
549
|
+
|
|
550
|
+
Divert to another number:
|
|
551
|
+
```json
|
|
552
|
+
{
|
|
553
|
+
"callId": "Y2lzY29zcGFyay...",
|
|
554
|
+
"destination": "+12223334444"
|
|
555
|
+
}
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
Divert to own voicemail:
|
|
559
|
+
```json
|
|
560
|
+
{
|
|
561
|
+
"callId": "Y2lzY29zcGFyay...",
|
|
562
|
+
"toVoicemail": true
|
|
563
|
+
}
|
|
564
|
+
```
|
|
565
|
+
|
|
566
|
+
Divert to another user's voicemail:
|
|
567
|
+
```json
|
|
568
|
+
{
|
|
569
|
+
"callId": "Y2lzY29zcGFyay...",
|
|
570
|
+
"destination": "+12223334444",
|
|
571
|
+
"toVoicemail": true
|
|
572
|
+
}
|
|
573
|
+
```
|
|
574
|
+
|
|
575
|
+
### Gotchas
|
|
576
|
+
|
|
577
|
+
- **Answer rejection:** Answer is rejected if the device is not alerting for the call, or if the device does not support answer via API.
|
|
578
|
+
|
|
579
|
+
---
|
|
580
|
+
|
|
581
|
+
## 2. Mid-Call Actions
|
|
582
|
+
|
|
583
|
+
### Hold
|
|
584
|
+
|
|
585
|
+
Place a connected call on hold.
|
|
586
|
+
|
|
587
|
+
```
|
|
588
|
+
POST /v1/telephony/calls/hold
|
|
589
|
+
```
|
|
590
|
+
|
|
591
|
+
**SDK Signature:**
|
|
592
|
+
```python
|
|
593
|
+
CallsApi.hold(call_id: str, line_owner_id: str = None) -> None
|
|
594
|
+
```
|
|
595
|
+
|
|
596
|
+
---
|
|
597
|
+
|
|
598
|
+
### Resume
|
|
599
|
+
|
|
600
|
+
Resume a held call.
|
|
601
|
+
|
|
602
|
+
```
|
|
603
|
+
POST /v1/telephony/calls/resume
|
|
604
|
+
```
|
|
605
|
+
|
|
606
|
+
**SDK Signature:**
|
|
607
|
+
```python
|
|
608
|
+
CallsApi.resume(call_id: str, line_owner_id: str = None) -> None
|
|
609
|
+
```
|
|
610
|
+
|
|
611
|
+
---
|
|
612
|
+
|
|
613
|
+
### Transfer
|
|
614
|
+
|
|
615
|
+
Transfer two calls together. Supports multiple transfer modes depending on parameters.
|
|
616
|
+
|
|
617
|
+
```
|
|
618
|
+
POST /v1/telephony/calls/transfer
|
|
619
|
+
```
|
|
620
|
+
|
|
621
|
+
**SDK Signature:**
|
|
622
|
+
```python
|
|
623
|
+
CallsApi.transfer(
|
|
624
|
+
call_id1: str = None,
|
|
625
|
+
call_id2: str = None,
|
|
626
|
+
destination: str = None,
|
|
627
|
+
line_owner_id: str = None
|
|
628
|
+
) -> CallInfo
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
**Transfer modes:**
|
|
632
|
+
|
|
633
|
+
| Mode | Parameters | Response | Description |
|
|
634
|
+
|------|-----------|----------|-------------|
|
|
635
|
+
| **Auto (2 calls)** | Neither callId1/callId2 | 204 | User has exactly 2 calls; they are automatically selected and transferred |
|
|
636
|
+
| **Consultative / Attended** | `callId1` + `callId2` | 204 | Transfer two specific calls together (supervised transfer) |
|
|
637
|
+
| **Mute Transfer** | `callId1` + `destination` | 201 | Transfer call to new destination; waits for destination to answer before completing. If destination doesn't answer, call is not transferred |
|
|
638
|
+
|
|
639
|
+
**Note:** Unanswered incoming calls cannot be transferred. Use `divert` instead.
|
|
640
|
+
|
|
641
|
+
---
|
|
642
|
+
|
|
643
|
+
### Park
|
|
644
|
+
|
|
645
|
+
Park a connected call. Returns the extension/number to use for retrieval.
|
|
646
|
+
|
|
647
|
+
```
|
|
648
|
+
POST /v1/telephony/calls/park
|
|
649
|
+
```
|
|
650
|
+
|
|
651
|
+
**SDK Signature:**
|
|
652
|
+
```python
|
|
653
|
+
CallsApi.park(
|
|
654
|
+
call_id: str,
|
|
655
|
+
destination: str = None, # where to park; omit to park against self
|
|
656
|
+
is_group_park: bool = None, # True = auto-select from call park group
|
|
657
|
+
line_owner_id: str = None
|
|
658
|
+
) -> TelephonyParty # parkedAgainst details including number
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
**Response:** Returns a `TelephonyParty` object (the `parkedAgainst` party). The `number` field from this response is used as the destination for the `retrieve` command.
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
### Retrieve (Unpark)
|
|
666
|
+
|
|
667
|
+
Retrieve a parked call. Initiates a new call (similar to dial) to perform the retrieval.
|
|
668
|
+
|
|
669
|
+
```
|
|
670
|
+
POST /v1/telephony/calls/retrieve
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
**SDK Signature:**
|
|
674
|
+
```python
|
|
675
|
+
CallsApi.retrieve(
|
|
676
|
+
destination: str = None, # where the call is parked; omit if parked against self
|
|
677
|
+
endpoint_id: str = None,
|
|
678
|
+
line_owner_id: str = None
|
|
679
|
+
) -> CallInfo
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
---
|
|
683
|
+
|
|
684
|
+
### Pull
|
|
685
|
+
|
|
686
|
+
Pull a call from one device to another. Useful for moving a call between desk phone, mobile app, and desktop app.
|
|
687
|
+
|
|
688
|
+
```
|
|
689
|
+
POST /v1/telephony/calls/pull
|
|
690
|
+
```
|
|
691
|
+
|
|
692
|
+
**SDK Signature:**
|
|
693
|
+
```python
|
|
694
|
+
CallsApi.pull(
|
|
695
|
+
endpoint_id: str = None,
|
|
696
|
+
line_owner_id: str = None
|
|
697
|
+
) -> CallInfo
|
|
698
|
+
```
|
|
699
|
+
|
|
700
|
+
A temporary new call is initiated. When the user answers on the target device, that device connects to the pulled call and the temporary call is released.
|
|
701
|
+
|
|
702
|
+
---
|
|
703
|
+
|
|
704
|
+
### Push (Executive Assistant)
|
|
705
|
+
|
|
706
|
+
Push a call from an assistant to the associated executive.
|
|
707
|
+
|
|
708
|
+
```
|
|
709
|
+
POST /v1/telephony/calls/push
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
**SDK Signature:**
|
|
713
|
+
```python
|
|
714
|
+
CallsApi.push(
|
|
715
|
+
call_id: str = None,
|
|
716
|
+
line_owner_id: str = None
|
|
717
|
+
) -> None
|
|
718
|
+
```
|
|
719
|
+
|
|
720
|
+
**Note:** Only valid when the assistant's call is associated with an executive.
|
|
721
|
+
|
|
722
|
+
---
|
|
723
|
+
|
|
724
|
+
### Barge In
|
|
725
|
+
|
|
726
|
+
Barge into another user's answered call. Initiates a new call (similar to dial).
|
|
727
|
+
|
|
728
|
+
```
|
|
729
|
+
POST /v1/telephony/calls/bargeIn
|
|
730
|
+
```
|
|
731
|
+
|
|
732
|
+
**SDK Signature:**
|
|
733
|
+
```python
|
|
734
|
+
CallsApi.barge_in(
|
|
735
|
+
target: str, # user to barge in on (digits or URI)
|
|
736
|
+
endpoint_id: str = None,
|
|
737
|
+
line_owner_id: str = None
|
|
738
|
+
) -> CallInfo
|
|
739
|
+
```
|
|
740
|
+
|
|
741
|
+
---
|
|
742
|
+
|
|
743
|
+
### Conference (3-Way Merge)
|
|
744
|
+
|
|
745
|
+
Merge two active calls into a three-way conference call. The user must have two calls (one active, one held) to merge.
|
|
746
|
+
|
|
747
|
+
```
|
|
748
|
+
POST /v1/telephony/calls/conference
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
**SDK Signature:**
|
|
752
|
+
```python
|
|
753
|
+
CallsApi.conference(
|
|
754
|
+
call_id1: str = None,
|
|
755
|
+
call_id2: str = None,
|
|
756
|
+
line_owner_id: str = None
|
|
757
|
+
) -> None
|
|
758
|
+
```
|
|
759
|
+
|
|
760
|
+
If `call_id1` and `call_id2` are omitted, the user must have exactly two calls; they are automatically selected and merged. When specified, both calls are merged into a three-way conference with the user.
|
|
761
|
+
|
|
762
|
+
---
|
|
763
|
+
|
|
764
|
+
### Hangup
|
|
765
|
+
|
|
766
|
+
Disconnect a call. If used on an unanswered incoming call, the call is rejected and sent to busy.
|
|
767
|
+
|
|
768
|
+
```
|
|
769
|
+
POST /v1/telephony/calls/hangup
|
|
770
|
+
```
|
|
771
|
+
|
|
772
|
+
**SDK Signature:**
|
|
773
|
+
```python
|
|
774
|
+
CallsApi.hangup(call_id: str, line_owner_id: str = None) -> None
|
|
775
|
+
```
|
|
776
|
+
|
|
777
|
+
---
|
|
778
|
+
|
|
779
|
+
### Mute / Unmute
|
|
780
|
+
|
|
781
|
+
Mute or unmute a call. Only valid on calls that report `muteCapable: true` in call details.
|
|
782
|
+
|
|
783
|
+
```
|
|
784
|
+
POST /v1/telephony/calls/mute
|
|
785
|
+
POST /v1/telephony/calls/unmute
|
|
786
|
+
```
|
|
787
|
+
|
|
788
|
+
**SDK Signatures:**
|
|
789
|
+
```python
|
|
790
|
+
CallsApi.mute(call_id: str, line_owner_id: str = None) -> None
|
|
791
|
+
CallsApi.unmute(call_id: str, line_owner_id: str = None) -> None
|
|
792
|
+
```
|
|
793
|
+
|
|
794
|
+
---
|
|
795
|
+
|
|
796
|
+
### Recording Control
|
|
797
|
+
|
|
798
|
+
Control call recording. Availability depends on the user's call recording mode.
|
|
799
|
+
|
|
800
|
+
| Endpoint | SDK Method | Recording Mode Required |
|
|
801
|
+
|----------|-----------|------------------------|
|
|
802
|
+
| `POST .../startRecording` | `start_recording(call_id, line_owner_id)` | "On Demand" |
|
|
803
|
+
| `POST .../stopRecording` | `stop_recording(call_id, line_owner_id)` | "On Demand" |
|
|
804
|
+
| `POST .../pauseRecording` | `pause_recording(call_id, line_owner_id)` | "On Demand" or "Always with Pause/Resume" |
|
|
805
|
+
| `POST .../resumeRecording` | `resume_recording(call_id, line_owner_id)` | "On Demand" or "Always with Pause/Resume" |
|
|
806
|
+
|
|
807
|
+
**RecordingState values:**
|
|
808
|
+
|
|
809
|
+
| Value | Description |
|
|
810
|
+
|-------|-------------|
|
|
811
|
+
| `pending` | Recording requested but not yet started |
|
|
812
|
+
| `started` | Recording is active |
|
|
813
|
+
| `paused` | Recording is paused |
|
|
814
|
+
| `stopped` | Recording has been stopped |
|
|
815
|
+
| `failed` | Recording failed |
|
|
816
|
+
|
|
817
|
+
---
|
|
818
|
+
|
|
819
|
+
### Transmit DTMF
|
|
820
|
+
|
|
821
|
+
Send DTMF tones on an active call.
|
|
822
|
+
|
|
823
|
+
```
|
|
824
|
+
POST /v1/telephony/calls/transmitDtmf
|
|
825
|
+
```
|
|
826
|
+
|
|
827
|
+
**SDK Signature:**
|
|
828
|
+
```python
|
|
829
|
+
CallsApi.transmit_dtmf(
|
|
830
|
+
call_id: str = None,
|
|
831
|
+
dtmf: str = None, # e.g. "1,234" (comma = pause)
|
|
832
|
+
line_owner_id: str = None
|
|
833
|
+
) -> None
|
|
834
|
+
```
|
|
835
|
+
|
|
836
|
+
**Valid DTMF characters:** `0-9`, `*`, `#`, `A`, `B`, `C`, `D`
|
|
837
|
+
**Pause:** Use a comma `,` to insert a pause between digits. Example: `"1,234"` sends `1`, pauses, then sends `2`, `3`, `4`.
|
|
838
|
+
|
|
839
|
+
### Gotchas
|
|
840
|
+
|
|
841
|
+
- **Transfer restrictions:** Unanswered incoming calls cannot be transferred. Use `divert` instead.
|
|
842
|
+
- **Push is executive-assistant only:** `push` is only valid when the assistant's call is associated with an executive.
|
|
843
|
+
- **Mute capability check:** Only calls that report `muteCapable: true` in call details support `mute`/`unmute`. Always check before calling.
|
|
844
|
+
- **DTMF pause character:** Use a comma `,` to insert a pause between DTMF digits. This is not documented prominently in the API reference.
|
|
845
|
+
- **Recording mode dependency:** `start_recording`/`stop_recording` only work when the user's recording mode is "On Demand". `pause_recording`/`resume_recording` work with both "On Demand" and "Always with Pause/Resume".
|
|
846
|
+
|
|
847
|
+
---
|
|
848
|
+
|
|
849
|
+
## 3. Call Details & History
|
|
850
|
+
|
|
851
|
+
### List Active Calls
|
|
852
|
+
|
|
853
|
+
Get all active calls for the user.
|
|
854
|
+
|
|
855
|
+
```
|
|
856
|
+
GET /v1/telephony/calls
|
|
857
|
+
```
|
|
858
|
+
|
|
859
|
+
**SDK Signature:**
|
|
860
|
+
```python
|
|
861
|
+
CallsApi.list_calls(line_owner_id: str = None) -> list[TelephonyCall]
|
|
862
|
+
```
|
|
863
|
+
|
|
864
|
+
---
|
|
865
|
+
|
|
866
|
+
### Get Call Details
|
|
867
|
+
|
|
868
|
+
Get details of a specific active call.
|
|
869
|
+
|
|
870
|
+
```
|
|
871
|
+
GET /v1/telephony/calls/{callId}
|
|
872
|
+
```
|
|
873
|
+
|
|
874
|
+
**SDK Signature:**
|
|
875
|
+
```python
|
|
876
|
+
CallsApi.call_details(
|
|
877
|
+
call_id: str,
|
|
878
|
+
line_owner_id: str = None
|
|
879
|
+
) -> TelephonyCall
|
|
880
|
+
```
|
|
881
|
+
|
|
882
|
+
---
|
|
883
|
+
|
|
884
|
+
### List Call History
|
|
885
|
+
|
|
886
|
+
Get the user's call history. Returns a maximum of **20 records per type**.
|
|
887
|
+
|
|
888
|
+
```
|
|
889
|
+
GET /v1/telephony/calls/history
|
|
890
|
+
```
|
|
891
|
+
|
|
892
|
+
**SDK Signature:**
|
|
893
|
+
```python
|
|
894
|
+
CallsApi.call_history(history_type: HistoryType = None) -> list[CallHistoryRecord]
|
|
895
|
+
```
|
|
896
|
+
|
|
897
|
+
**HistoryType values:**
|
|
898
|
+
|
|
899
|
+
| Value | Description |
|
|
900
|
+
|-------|-------------|
|
|
901
|
+
| `placed` | Outgoing calls placed by the user |
|
|
902
|
+
| `missed` | Incoming calls not answered |
|
|
903
|
+
| `received` | Incoming calls answered |
|
|
904
|
+
|
|
905
|
+
If `history_type` is omitted, all types are returned (up to 20 each = max 60 total).
|
|
906
|
+
|
|
907
|
+
**CallHistoryRecord fields:**
|
|
908
|
+
|
|
909
|
+
| Field | Type | Description |
|
|
910
|
+
|-------|------|-------------|
|
|
911
|
+
| `type` | HistoryType | placed, missed, or received |
|
|
912
|
+
| `name` | str (optional) | Party name (if available and privacy not enabled) |
|
|
913
|
+
| `number` | str (optional) | Party number (digits or URI) |
|
|
914
|
+
| `privacy_enabled` | bool | Whether privacy is enabled |
|
|
915
|
+
| `time` | datetime | When the record was created (placed=call time, missed=disconnect time, received=answer time) |
|
|
916
|
+
|
|
917
|
+
### Gotchas
|
|
918
|
+
|
|
919
|
+
- **Call history limit:** `call_history` returns a maximum of 20 records per type (placed/missed/received). If `history_type` is omitted, all types are returned (up to 20 each = max 60 total).
|
|
920
|
+
- **No pagination on call list:** `list_calls` returns all active calls for the user (typically a small number). There is no pagination support.
|
|
921
|
+
|
|
922
|
+
---
|
|
923
|
+
|
|
924
|
+
## 4. Data Models
|
|
925
|
+
|
|
926
|
+
### TelephonyCall (Call Object)
|
|
927
|
+
|
|
928
|
+
The primary call object returned by list/details endpoints and included in webhook event data.
|
|
929
|
+
|
|
930
|
+
| Field | Type | Description |
|
|
931
|
+
|-------|------|-------------|
|
|
932
|
+
| `call_id` | str | Unique call identifier (aliased from `id` in API responses, `callId` in events) |
|
|
933
|
+
| `call_session_id` | str | Session ID to correlate multiple calls in the same session |
|
|
934
|
+
| `personality` | Personality | Whether user is originator, terminator, or clickToDial |
|
|
935
|
+
| `state` | CallState | Current call state |
|
|
936
|
+
| `remote_party` | TelephonyParty | Details of the other party |
|
|
937
|
+
| `appearance` | int (optional) | Appearance value for ordering calls consistent with device display |
|
|
938
|
+
| `created` | datetime | When the call was created |
|
|
939
|
+
| `answered` | datetime (optional) | When the call was answered |
|
|
940
|
+
| `redirections` | list[Redirection] | Previous redirections (most recent first), only present when state is alerting |
|
|
941
|
+
| `recall` | Recall (optional) | Recall details (e.g., park recall) |
|
|
942
|
+
| `recording_state` | RecordingState (optional) | Current recording state, only present if recording was invoked |
|
|
943
|
+
| `disconnected` | datetime (optional) | When the call was disconnected |
|
|
944
|
+
| `mute_capable` | bool (optional) | Whether the call supports mute/unmute API |
|
|
945
|
+
| `muted` | bool (optional) | Whether the call is currently muted |
|
|
946
|
+
|
|
947
|
+
### CallInfo (Dial/Pickup/Retrieve Response)
|
|
948
|
+
|
|
949
|
+
Returned by actions that initiate a new call.
|
|
950
|
+
|
|
951
|
+
| Field | Type | Description |
|
|
952
|
+
|-------|------|-------------|
|
|
953
|
+
| `call_id` | str | Unique call identifier |
|
|
954
|
+
| `call_session_id` | str | Session ID for correlating related calls |
|
|
955
|
+
|
|
956
|
+
### Personality
|
|
957
|
+
|
|
958
|
+
| Value | Description |
|
|
959
|
+
|-------|-------------|
|
|
960
|
+
| `originator` | An outgoing call originated by the user |
|
|
961
|
+
| `terminator` | An incoming call received by the user |
|
|
962
|
+
| `clickToDial` | Alerting for a Click-to-Dial action; becomes `originator` when answered |
|
|
963
|
+
|
|
964
|
+
### CallState
|
|
965
|
+
|
|
966
|
+
| Value | Description |
|
|
967
|
+
|-------|-------------|
|
|
968
|
+
| `connecting` | Remote party is being alerted |
|
|
969
|
+
| `alerting` | User's devices are alerting for incoming or Click-to-Dial call |
|
|
970
|
+
| `connected` | Call is connected |
|
|
971
|
+
| `held` | User has placed the call on hold |
|
|
972
|
+
| `remoteHeld` | Remote party (same org) has placed the call on hold |
|
|
973
|
+
| `disconnected` | Call has been disconnected |
|
|
974
|
+
|
|
975
|
+
### CallType
|
|
976
|
+
|
|
977
|
+
| Value | Description |
|
|
978
|
+
|-------|-------------|
|
|
979
|
+
| `location` | Party is within the same location |
|
|
980
|
+
| `organization` | Party is within the same org but different location |
|
|
981
|
+
| `external` | Party is outside the organization |
|
|
982
|
+
| `emergency` | Emergency call destination |
|
|
983
|
+
| `repair` | Repair call destination |
|
|
984
|
+
| `other` | Does not match any defined type (e.g., feature activation code) |
|
|
985
|
+
|
|
986
|
+
### TelephonyParty
|
|
987
|
+
|
|
988
|
+
| Field | Type | Description |
|
|
989
|
+
|-------|------|-------------|
|
|
990
|
+
| `name` | str (optional) | Party name (if available and privacy not enabled) |
|
|
991
|
+
| `number` | str | Party number (digits or URI) |
|
|
992
|
+
| `person_id` | str (optional) | Party's person ID |
|
|
993
|
+
| `place_id` | str (optional) | Party's place ID |
|
|
994
|
+
| `privacy_enabled` | bool (optional) | Whether privacy is enabled |
|
|
995
|
+
| `call_type` | CallType (optional) | Call type for the party |
|
|
996
|
+
|
|
997
|
+
### RedirectReason
|
|
998
|
+
|
|
999
|
+
| Value | Description |
|
|
1000
|
+
|-------|-------------|
|
|
1001
|
+
| `busy` | Forwarded by Call Forwarding Busy |
|
|
1002
|
+
| `noAnswer` | Forwarded by Call Forwarding No Answer |
|
|
1003
|
+
| `unavailable` | Forwarded by Business Continuity |
|
|
1004
|
+
| `unconditional` | Forwarded by Call Forwarding Always |
|
|
1005
|
+
| `timeOfDay` | Forwarded by Selective Call Forwarding (schedule) |
|
|
1006
|
+
| `divert` | Redirected by divert action |
|
|
1007
|
+
| `followMe` | Redirected by Simultaneous Ring |
|
|
1008
|
+
| `huntGroup` | Redirected by Hunt Group routing |
|
|
1009
|
+
| `callQueue` | Redirected by Call Queue routing |
|
|
1010
|
+
| `unknown` | Unknown redirect reason |
|
|
1011
|
+
|
|
1012
|
+
### RejectAction
|
|
1013
|
+
|
|
1014
|
+
| Value | Behavior |
|
|
1015
|
+
|-------|----------|
|
|
1016
|
+
| `busy` | Send to busy (default) |
|
|
1017
|
+
| `temporarilyUnavailable` | Send to temporarily unavailable |
|
|
1018
|
+
| `ignore` | Continue ringback, stop alerting user devices |
|
|
1019
|
+
|
|
1020
|
+
### RecordingState
|
|
1021
|
+
|
|
1022
|
+
| Value | Description |
|
|
1023
|
+
|-------|-------------|
|
|
1024
|
+
| `pending` | Requested but not yet started |
|
|
1025
|
+
| `started` | Recording is active |
|
|
1026
|
+
| `paused` | Recording is paused |
|
|
1027
|
+
| `stopped` | Recording has been stopped |
|
|
1028
|
+
| `failed` | Recording failed |
|
|
1029
|
+
|
|
1030
|
+
---
|
|
1031
|
+
|
|
1032
|
+
## 5. Service App / Admin API (Call Controls Members)
|
|
1033
|
+
|
|
1034
|
+
For **Service Apps** that need to control calls on behalf of users, workspaces, or virtual lines. Uses `spark-admin:calls_read` and `spark-admin:calls_write` scopes.
|
|
1035
|
+
|
|
1036
|
+
> **Note:** The `spark-admin:calls_read` and `spark-admin:calls_write` scopes listed above for the Members API cannot be confirmed from any publicly indexed developer.webex.com page. They may be accurate but should be verified against the live API reference or Webex TAC before building production integrations against the Members API.
|
|
1037
|
+
|
|
1038
|
+
**Base path:** `POST /v1/telephony/calls/members/{memberId}/{action}`
|
|
1039
|
+
|
|
1040
|
+
The Members API mirrors the user-level API but adds `member_id` and `org_id` parameters.
|
|
1041
|
+
|
|
1042
|
+
### Available Members Endpoints
|
|
1043
|
+
|
|
1044
|
+
| Action | SDK Method | Returns |
|
|
1045
|
+
|--------|-----------|---------|
|
|
1046
|
+
| List Calls | `CallControlsMembersApi.list_calls(member_id, org_id)` | `list[TelephonyCall]` |
|
|
1047
|
+
| Get Call Details | `CallControlsMembersApi.get_call_details(member_id, call_id, org_id)` | `TelephonyCall` |
|
|
1048
|
+
| Dial | `CallControlsMembersApi.dial(member_id, destination, endpoint_id, org_id)` | `CallInfo` |
|
|
1049
|
+
| Answer | `CallControlsMembersApi.answer(member_id, call_id, endpoint_id, org_id)` | None |
|
|
1050
|
+
| Hangup | `CallControlsMembersApi.hangup(member_id, call_id, org_id)` | None |
|
|
1051
|
+
|
|
1052
|
+
**`member_id`** can be one of: person ID, workspace ID, or virtual line ID.
|
|
1053
|
+
|
|
1054
|
+
### Gotchas
|
|
1055
|
+
|
|
1056
|
+
- **Members API supports a limited action set.** Only Dial, Answer, Hangup, List Calls, and Get Call Details are available. Hold, Resume, Transfer, Mute, Park, and Barge-in are user-level API operations only and are NOT available on the Members API path. Service App integrations requiring these operations must use user-level OAuth tokens (`spark:calls_write`) acting as the target user.
|
|
1057
|
+
|
|
1058
|
+
---
|
|
1059
|
+
|
|
1060
|
+
## 6. Additional API: External Voicemail MWI
|
|
1061
|
+
|
|
1062
|
+
Set or clear Message Waiting Indicator (MWI) for a person or workspace. Service App only.
|
|
1063
|
+
|
|
1064
|
+
```
|
|
1065
|
+
POST /v1/telephony/externalVoicemail/mwi?id={userId}&orgId={orgId}
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
**SDK Signature:**
|
|
1069
|
+
```python
|
|
1070
|
+
CallsApi.update_external_voicemail_mwi(
|
|
1071
|
+
id: str, # person or workspace ID
|
|
1072
|
+
action: ExternalVoicemailMwiAction, # 'SET' or 'CLEAR'
|
|
1073
|
+
org_id: str = None
|
|
1074
|
+
) -> None
|
|
1075
|
+
```
|
|
1076
|
+
|
|
1077
|
+
**Scope required:** `spark-admin:calls_write`
|
|
1078
|
+
|
|
1079
|
+
### CLI: `external-voicemail` (MWI Control)
|
|
1080
|
+
|
|
1081
|
+
The `external-voicemail` CLI group sets or clears the Message Waiting Indicator (MWI) for a person or workspace. Requires a Service App token with `spark-admin:calls_write` scope.
|
|
1082
|
+
|
|
1083
|
+
| Command | Description |
|
|
1084
|
+
|---------|-------------|
|
|
1085
|
+
| `external-voicemail create` | Set or clear MWI status for a user or workspace |
|
|
1086
|
+
|
|
1087
|
+
```bash
|
|
1088
|
+
# Set MWI (light the voicemail indicator) for a user
|
|
1089
|
+
wxcli external-voicemail create --id <person_id> --action SET
|
|
1090
|
+
|
|
1091
|
+
# Clear MWI (turn off the voicemail indicator) for a user
|
|
1092
|
+
wxcli external-voicemail create --id <person_id> --action CLEAR
|
|
1093
|
+
|
|
1094
|
+
# Set MWI for a workspace phone
|
|
1095
|
+
wxcli external-voicemail create --id <workspace_id> --action SET
|
|
1096
|
+
```
|
|
1097
|
+
|
|
1098
|
+
---
|
|
1099
|
+
|
|
1100
|
+
## 7. Common Use Cases
|
|
1101
|
+
|
|
1102
|
+
### Click-to-Dial from CRM
|
|
1103
|
+
```python
|
|
1104
|
+
from wxc_sdk import WebexSimpleApi
|
|
1105
|
+
|
|
1106
|
+
api = WebexSimpleApi(tokens=tokens)
|
|
1107
|
+
|
|
1108
|
+
# Place a call from the CRM contact page
|
|
1109
|
+
result = api.telephony.calls.dial(destination="+12223334444")
|
|
1110
|
+
print(f"Call initiated: {result.call_id}")
|
|
1111
|
+
```
|
|
1112
|
+
|
|
1113
|
+
### Agent Dashboard: List Active Calls
|
|
1114
|
+
```python
|
|
1115
|
+
calls = api.telephony.calls.list_calls()
|
|
1116
|
+
for call in calls:
|
|
1117
|
+
print(f"{call.call_id} | {call.state} | {call.remote_party.name} ({call.remote_party.number})")
|
|
1118
|
+
```
|
|
1119
|
+
|
|
1120
|
+
### Consultative Transfer
|
|
1121
|
+
```python
|
|
1122
|
+
# Agent has two calls: original caller and the transfer target
|
|
1123
|
+
# Transfer them together
|
|
1124
|
+
api.telephony.calls.transfer(call_id1=original_call_id, call_id2=consult_call_id)
|
|
1125
|
+
```
|
|
1126
|
+
|
|
1127
|
+
### Hold, Consult, Transfer Pattern
|
|
1128
|
+
```python
|
|
1129
|
+
# 1. Put caller on hold
|
|
1130
|
+
api.telephony.calls.hold(call_id=caller_call_id)
|
|
1131
|
+
|
|
1132
|
+
# 2. Dial the transfer target
|
|
1133
|
+
consult = api.telephony.calls.dial(destination="+15551234567")
|
|
1134
|
+
|
|
1135
|
+
# 3. After speaking with transfer target, transfer both calls
|
|
1136
|
+
api.telephony.calls.transfer(call_id1=caller_call_id, call_id2=consult.call_id)
|
|
1137
|
+
```
|
|
1138
|
+
|
|
1139
|
+
### Park and Retrieve
|
|
1140
|
+
```python
|
|
1141
|
+
# Park the call
|
|
1142
|
+
parked = api.telephony.calls.park(call_id=call_id)
|
|
1143
|
+
print(f"Parked against: {parked.number}")
|
|
1144
|
+
|
|
1145
|
+
# Later, retrieve it (from any device)
|
|
1146
|
+
retrieved = api.telephony.calls.retrieve(destination=parked.number)
|
|
1147
|
+
```
|
|
1148
|
+
|
|
1149
|
+
### Call Recording Control
|
|
1150
|
+
```python
|
|
1151
|
+
# Start recording (user must have "On Demand" recording mode)
|
|
1152
|
+
api.telephony.calls.start_recording(call_id=call_id)
|
|
1153
|
+
|
|
1154
|
+
# Pause for sensitive info (credit card, SSN)
|
|
1155
|
+
api.telephony.calls.pause_recording(call_id=call_id)
|
|
1156
|
+
|
|
1157
|
+
# Resume
|
|
1158
|
+
api.telephony.calls.resume_recording(call_id=call_id)
|
|
1159
|
+
|
|
1160
|
+
# Stop
|
|
1161
|
+
api.telephony.calls.stop_recording(call_id=call_id)
|
|
1162
|
+
```
|
|
1163
|
+
|
|
1164
|
+
### Service App: Control Calls for a User
|
|
1165
|
+
```python
|
|
1166
|
+
# Using admin/service app credentials with spark-admin:calls_write
|
|
1167
|
+
from wxc_sdk.telephony.call_contols_members import CallControlsMembersApi
|
|
1168
|
+
|
|
1169
|
+
# Dial on behalf of a user
|
|
1170
|
+
result = members_api.dial(
|
|
1171
|
+
member_id="person-uuid-here",
|
|
1172
|
+
destination="+12223334444"
|
|
1173
|
+
)
|
|
1174
|
+
```
|
|
1175
|
+
|
|
1176
|
+
---
|
|
1177
|
+
|
|
1178
|
+
## 8. Key Gotchas
|
|
1179
|
+
|
|
1180
|
+
1. **3rd Party Call Control only** -- These APIs do not work with Webex app's native calling. They are for building external call control applications.
|
|
1181
|
+
|
|
1182
|
+
2. **Multi-Tenant only** -- Not applicable for UCM or Dedicated Instance users.
|
|
1183
|
+
|
|
1184
|
+
3. **Service Apps cannot use CallsApi** -- Service Apps must use the `CallControlsMembersApi` (members endpoint) instead.
|
|
1185
|
+
|
|
1186
|
+
4. **`callId` vs `id`** -- The API returns `id` in direct call responses but `callId` in webhook events. The SDK's `TelephonyCall` model handles both aliases transparently via the `call_id` property.
|
|
1187
|
+
|
|
1188
|
+
5. **Click-to-Dial personality transition** -- A dial request starts with `personality: clickToDial` while alerting the user's devices. Once the user answers, it transitions to `personality: originator`.
|
|
1189
|
+
|
|
1190
|
+
6. **Transfer restrictions** -- Unanswered incoming calls cannot be transferred. Use `divert` for unanswered calls.
|
|
1191
|
+
|
|
1192
|
+
7. **`lineOwnerId` parameter** -- Present on nearly all methods. Used when the API caller has a secondary line belonging to another user, workspace, or virtual line on their device.
|
|
1193
|
+
|
|
1194
|
+
8. **Recording mode dependency** -- `start_recording` / `stop_recording` only work when the user's recording mode is "On Demand". `pause_recording` / `resume_recording` work with both "On Demand" and "Always with Pause/Resume".
|
|
1195
|
+
|
|
1196
|
+
9. **Mute capability check** -- Always check `muteCapable` in call details before calling `mute` or `unmute`. Not all calls support it.
|
|
1197
|
+
|
|
1198
|
+
10. **Call history limit** -- `call_history` returns a maximum of 20 records per type (placed/missed/received).
|
|
1199
|
+
|
|
1200
|
+
---
|
|
1201
|
+
|
|
1202
|
+
## See Also
|
|
1203
|
+
|
|
1204
|
+
- **[webhooks-events.md](webhooks-events.md)** — Real-time call event notifications via webhooks. The `TelephonyEventData` model inherits from `TelephonyCall` documented here; use webhooks for event-driven call control rather than polling `list_calls`.
|
|
1205
|
+
- **[person-call-settings-media.md](person-call-settings-media.md)** — Call recording configuration (recording mode, compliance announcements). Recording mode determines which recording control actions are available in this API.
|