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,1898 @@
|
|
|
1
|
+
<!-- Updated by playbook session 2026-03-18 -->
|
|
2
|
+
# Person Call Settings -- Voicemail, Caller ID, Privacy & Recording
|
|
3
|
+
|
|
4
|
+
Reference for per-person (also virtual line and workspace) call settings covering voicemail, caller ID, anonymous call rejection, privacy, barge-in, call recording, call intercept, monitoring, push-to-talk, and music on hold.
|
|
5
|
+
|
|
6
|
+
All APIs in this group follow the same structural pattern: they extend `PersonSettingsApiChild`, which builds REST endpoints using the formula `people/{person_id}/features/{feature}` for persons (with alternate URL patterns for workspaces, virtual lines, and locations). Each sub-API exposes a `read()` and `configure()` method pair, sometimes with additional action methods.
|
|
7
|
+
|
|
8
|
+
## Sources
|
|
9
|
+
|
|
10
|
+
- wxc_sdk v1.30.0 (PersonSettingsApi)
|
|
11
|
+
- OpenAPI spec: specs/webex-cloud-calling.json
|
|
12
|
+
- developer.webex.com Person Call Settings APIs
|
|
13
|
+
|
|
14
|
+
## Required Scopes
|
|
15
|
+
|
|
16
|
+
| Feature | Read Scope | Write Scope | Notes |
|
|
17
|
+
|---------|-----------|------------|-------|
|
|
18
|
+
| Voicemail | `spark-admin:people_read` | `spark-admin:people_write` | Self: `spark:people_read` / `spark:people_write` |
|
|
19
|
+
| Voicemail Passcode | `spark-admin:telephony_config_write` | `spark-admin:telephony_config_write` | Write-only; uses `telephony/config/people` path |
|
|
20
|
+
| Voicemail PIN Reset | `spark-admin:people_write` | `spark-admin:people_write` | Write-only action |
|
|
21
|
+
| Caller ID | `spark-admin:people_read` | `spark-admin:people_write` | Self: `spark:people_read` / `spark:people_write` |
|
|
22
|
+
| Agent Caller ID | `spark-admin:telephony_config_read` | `spark-admin:telephony_config_write` | Available caller IDs uses `spark-admin:people_read` |
|
|
23
|
+
| Anonymous Call Rejection | `spark-admin:workspaces_read` | `spark-admin:workspaces_write` | Workspace-only admin endpoint. No admin-level `/people/{id}` path exists; self-service via `/me` only. |
|
|
24
|
+
| Privacy | `spark-admin:people_read` | `spark-admin:people_write` | |
|
|
25
|
+
| Barge-In | `spark-admin:people_read` | `spark-admin:people_write` | Self: `spark:people_read` / `spark:people_write` |
|
|
26
|
+
| Call Recording | `spark-admin:people_read` | `spark-admin:people_write` | |
|
|
27
|
+
| Call Intercept | `spark-admin:people_read` | `spark-admin:people_write` | Greeting upload: self `spark:people_write` also works |
|
|
28
|
+
| Monitoring | `spark-admin:people_read` | `spark-admin:people_write` | |
|
|
29
|
+
| Push-to-Talk | `spark-admin:people_read` | `spark-admin:people_write` | |
|
|
30
|
+
| Music on Hold | `spark-admin:telephony_config_read` | `spark-admin:telephony_config_write` | Uses `telephony/config/people` path |
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
## Table of Contents
|
|
35
|
+
|
|
36
|
+
1. [Voicemail](#1-voicemail)
|
|
37
|
+
2. [Caller ID](#2-caller-id)
|
|
38
|
+
3. [Agent Caller ID](#3-agent-caller-id)
|
|
39
|
+
4. [Anonymous Call Rejection](#4-anonymous-call-rejection)
|
|
40
|
+
5. [Privacy](#5-privacy)
|
|
41
|
+
6. [Barge-In](#6-barge-in)
|
|
42
|
+
7. [Call Recording](#7-call-recording)
|
|
43
|
+
8. [Call Intercept](#8-call-intercept)
|
|
44
|
+
9. [Monitoring](#9-monitoring)
|
|
45
|
+
10. [Push-to-Talk](#10-push-to-talk)
|
|
46
|
+
11. [Music on Hold](#11-music-on-hold)
|
|
47
|
+
12. [Common Patterns](#12-common-patterns)
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## 1. Voicemail
|
|
52
|
+
|
|
53
|
+
**API class:** `VoicemailApi`
|
|
54
|
+
**Feature key:** `voicemail`
|
|
55
|
+
**Source:** `wxc_sdk/person_settings/voicemail.py`
|
|
56
|
+
|
|
57
|
+
### Data Models
|
|
58
|
+
|
|
59
|
+
#### `VoicemailSettings`
|
|
60
|
+
|
|
61
|
+
Top-level settings object returned by `read()` and passed to `configure()`.
|
|
62
|
+
|
|
63
|
+
| Field | Type | Description |
|
|
64
|
+
|-------|------|-------------|
|
|
65
|
+
| `enabled` | `bool` | Voicemail is enabled or disabled |
|
|
66
|
+
| `send_all_calls` | `VoicemailEnabled` | Settings for sending all calls to voicemail |
|
|
67
|
+
| `send_busy_calls` | `VoicemailEnabledWithGreeting` | Settings for sending calls to voicemail when line is busy |
|
|
68
|
+
| `send_unanswered_calls` | `UnansweredCalls` | Settings for calls sent to voicemail when unanswered |
|
|
69
|
+
| `notifications` | `VoicemailNotifications` | Settings for new voicemail notifications |
|
|
70
|
+
| `transfer_to_number` | `VoicemailTransferToNumber` | Transfer to a different number by pressing 0 |
|
|
71
|
+
| `email_copy_of_message` | `VoicemailCopyOfMessage` | Send copy of voicemail audio via email |
|
|
72
|
+
| `message_storage` | `VoicemailMessageStorage` | Message storage settings (internal vs. external) |
|
|
73
|
+
| `fax_message` | `VoicemailFax` | Fax message settings |
|
|
74
|
+
| `voice_message_forwarding_enabled` | `bool` | Read-only; excluded from updates |
|
|
75
|
+
|
|
76
|
+
#### `VoicemailEnabledWithGreeting` (extends `VoicemailEnabled`)
|
|
77
|
+
|
|
78
|
+
| Field | Type | Description |
|
|
79
|
+
|-------|------|-------------|
|
|
80
|
+
| `enabled` | `bool` | Whether this condition is active |
|
|
81
|
+
| `greeting` | `Greeting` | `DEFAULT` or `CUSTOM` (.wav file) |
|
|
82
|
+
| `greeting_uploaded` | `bool` | Read-only; indicates custom greeting exists |
|
|
83
|
+
| `audio_file` | `MediaFile` | Details of the custom audio file |
|
|
84
|
+
|
|
85
|
+
#### `UnansweredCalls` (extends `VoicemailEnabledWithGreeting`)
|
|
86
|
+
|
|
87
|
+
| Field | Type | Description |
|
|
88
|
+
|-------|------|-------------|
|
|
89
|
+
| `number_of_rings` | `int` | Rings before unanswered call goes to voicemail |
|
|
90
|
+
| `system_max_number_of_rings` | `int` | Read-only; system-wide max for number_of_rings |
|
|
91
|
+
|
|
92
|
+
#### Default Settings
|
|
93
|
+
|
|
94
|
+
`VoicemailSettings.default()` returns:
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
VoicemailSettings(
|
|
98
|
+
enabled=True,
|
|
99
|
+
send_all_calls=VoicemailEnabled(enabled=False),
|
|
100
|
+
send_busy_calls=VoicemailEnabledWithGreeting(enabled=False, greeting=Greeting.default),
|
|
101
|
+
send_unanswered_calls=UnansweredCalls(enabled=True, greeting=Greeting.default, number_of_rings=3),
|
|
102
|
+
notifications=VoicemailNotifications(enabled=False),
|
|
103
|
+
transfer_to_number=VoicemailTransferToNumber(enabled=False),
|
|
104
|
+
email_copy_of_message=VoicemailCopyOfMessage(enabled=False),
|
|
105
|
+
message_storage=VoicemailMessageStorage(mwi_enabled=True, storage_type=StorageType.internal),
|
|
106
|
+
fax_message=VoicemailFax(enabled=False),
|
|
107
|
+
voice_message_forwarding_enabled=False,
|
|
108
|
+
)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Methods
|
|
112
|
+
|
|
113
|
+
#### `read`
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
VoicemailApi.read(entity_id: str, org_id: str = None) -> VoicemailSettings
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Retrieve voicemail settings for a person, virtual line, or workspace.
|
|
120
|
+
|
|
121
|
+
- **Scopes (read):** `spark-admin:people_read` (admin) or `spark:people_read` (self)
|
|
122
|
+
|
|
123
|
+
#### `configure`
|
|
124
|
+
|
|
125
|
+
```python
|
|
126
|
+
VoicemailApi.configure(entity_id: str, settings: VoicemailSettings, org_id: str = None)
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Update voicemail settings. The `settings.update()` method automatically strips read-only fields (`greeting_uploaded`, `system_max_number_of_rings`, `voice_message_forwarding_enabled`) before sending.
|
|
130
|
+
|
|
131
|
+
- **Scopes (write):** `spark-admin:people_write` (admin) or `spark:people_write` (self)
|
|
132
|
+
|
|
133
|
+
#### `configure_busy_greeting`
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
VoicemailApi.configure_busy_greeting(
|
|
137
|
+
entity_id: str,
|
|
138
|
+
content: Union[BufferedReader, str],
|
|
139
|
+
upload_as: str = None,
|
|
140
|
+
org_id: str = None,
|
|
141
|
+
)
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
Upload a custom `.wav` greeting for the busy condition. Uses multipart/form-data with `audio/wav` content type. Endpoint: `actions/uploadBusyGreeting/invoke`.
|
|
145
|
+
|
|
146
|
+
- `content` can be a file path (str) or an open binary reader.
|
|
147
|
+
- `upload_as` is required if `content` is a reader (must be a `.wav` filename).
|
|
148
|
+
|
|
149
|
+
#### `configure_no_answer_greeting`
|
|
150
|
+
|
|
151
|
+
```python
|
|
152
|
+
VoicemailApi.configure_no_answer_greeting(
|
|
153
|
+
entity_id: str,
|
|
154
|
+
content: Union[BufferedReader, str],
|
|
155
|
+
upload_as: str = None,
|
|
156
|
+
org_id: str = None,
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Same as above but for the no-answer condition. Endpoint: `actions/uploadNoAnswerGreeting/invoke`.
|
|
161
|
+
|
|
162
|
+
#### `modify_passcode`
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
VoicemailApi.modify_passcode(entity_id: str, passcode: str, org_id: str = None)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
Set a new voicemail passcode. Passcode length must be 6-30 characters.
|
|
169
|
+
|
|
170
|
+
- **Scopes:** `spark-admin:telephony_config_write`
|
|
171
|
+
- **Note:** Uses a different URL pattern: `telephony/config/people/{person_id}/voicemail/passcode`
|
|
172
|
+
|
|
173
|
+
#### `reset_pin`
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
VoicemailApi.reset_pin(entity_id: str, org_id: str = None)
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Reset the voicemail PIN. Endpoint: `actions/resetPin/invoke` (POST).
|
|
180
|
+
|
|
181
|
+
- **Scopes:** `spark-admin:people_write`
|
|
182
|
+
|
|
183
|
+
### Usage Example (from `examples/modify_voicemail.py`)
|
|
184
|
+
|
|
185
|
+
```python
|
|
186
|
+
from wxc_sdk import WebexSimpleApi
|
|
187
|
+
|
|
188
|
+
api = WebexSimpleApi()
|
|
189
|
+
vm = api.person_settings.voicemail
|
|
190
|
+
|
|
191
|
+
# Read current settings
|
|
192
|
+
vm_settings = vm.read(person_id=person_id)
|
|
193
|
+
|
|
194
|
+
# Modify number of rings
|
|
195
|
+
vm_settings.send_unanswered_calls.number_of_rings = 6
|
|
196
|
+
|
|
197
|
+
# Write back
|
|
198
|
+
vm.configure(person_id, settings=vm_settings)
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
The example script reads a CSV of usernames, filters to calling users, and bulk-updates ring count using `ThreadPoolExecutor`.
|
|
202
|
+
|
|
203
|
+
### CLI Examples
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
# Read voicemail settings for a person
|
|
207
|
+
wxcli user-settings show-voicemail PERSON_ID
|
|
208
|
+
|
|
209
|
+
# Read voicemail settings as JSON
|
|
210
|
+
wxcli user-settings show-voicemail PERSON_ID -o json
|
|
211
|
+
|
|
212
|
+
# Enable voicemail for a person
|
|
213
|
+
wxcli user-settings update-voicemail PERSON_ID --enabled
|
|
214
|
+
|
|
215
|
+
# Disable voicemail for a person
|
|
216
|
+
wxcli user-settings update-voicemail PERSON_ID --no-enabled
|
|
217
|
+
|
|
218
|
+
# Update voicemail with full settings (nested objects require --json-body)
|
|
219
|
+
wxcli user-settings update-voicemail PERSON_ID --json-body '{
|
|
220
|
+
"enabled": true,
|
|
221
|
+
"sendAllCalls": {"enabled": false},
|
|
222
|
+
"sendBusyCalls": {"enabled": false, "greeting": "DEFAULT"},
|
|
223
|
+
"sendUnansweredCalls": {"enabled": true, "greeting": "DEFAULT", "numberOfRings": 6},
|
|
224
|
+
"notifications": {"enabled": false},
|
|
225
|
+
"transferToNumber": {"enabled": false},
|
|
226
|
+
"emailCopyOfMessage": {"enabled": false},
|
|
227
|
+
"messageStorage": {"mwiEnabled": true, "storageType": "INTERNAL"},
|
|
228
|
+
"faxMessage": {"enabled": false}
|
|
229
|
+
}'
|
|
230
|
+
|
|
231
|
+
# Upload a custom busy voicemail greeting
|
|
232
|
+
wxcli user-settings configure-busy-voicemail PERSON_ID
|
|
233
|
+
|
|
234
|
+
# Upload a custom no-answer voicemail greeting
|
|
235
|
+
wxcli user-settings configure-no-answer PERSON_ID
|
|
236
|
+
|
|
237
|
+
# Reset voicemail PIN
|
|
238
|
+
wxcli user-settings reset-voicemail-pin PERSON_ID
|
|
239
|
+
|
|
240
|
+
# Set voicemail passcode
|
|
241
|
+
wxcli user-settings update-passcode PERSON_ID --passcode "123456"
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Raw HTTP
|
|
245
|
+
|
|
246
|
+
#### Read Voicemail Settings
|
|
247
|
+
|
|
248
|
+
```
|
|
249
|
+
GET https://webexapis.com/v1/people/{personId}/features/voicemail
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
```python
|
|
253
|
+
result = api.session.rest_get(f"{BASE}/people/{person_id}/features/voicemail")
|
|
254
|
+
# Response:
|
|
255
|
+
# {
|
|
256
|
+
# "enabled": true,
|
|
257
|
+
# "sendAllCalls": {"enabled": false},
|
|
258
|
+
# "sendBusyCalls": {"enabled": false, "greeting": "DEFAULT", "greetingUploaded": false},
|
|
259
|
+
# "sendUnansweredCalls": {"enabled": true, "greeting": "DEFAULT", "numberOfRings": 3, "systemMaxNumberOfRings": 20},
|
|
260
|
+
# "notifications": {"enabled": false, "destination": ""},
|
|
261
|
+
# "transferToNumber": {"enabled": false, "destination": ""},
|
|
262
|
+
# "emailCopyOfMessage": {"enabled": false, "emailId": ""},
|
|
263
|
+
# "messageStorage": {"mwiEnabled": true, "storageType": "INTERNAL"},
|
|
264
|
+
# "faxMessage": {"enabled": false},
|
|
265
|
+
# "voiceMessageForwardingEnabled": false
|
|
266
|
+
# }
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
#### Configure Voicemail Settings
|
|
270
|
+
|
|
271
|
+
```
|
|
272
|
+
PUT https://webexapis.com/v1/people/{personId}/features/voicemail
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
```python
|
|
276
|
+
body = {
|
|
277
|
+
"enabled": True,
|
|
278
|
+
"sendAllCalls": {"enabled": False},
|
|
279
|
+
"sendBusyCalls": {"enabled": False, "greeting": "DEFAULT"},
|
|
280
|
+
"sendUnansweredCalls": {"enabled": True, "greeting": "DEFAULT", "numberOfRings": 6},
|
|
281
|
+
"notifications": {"enabled": False},
|
|
282
|
+
"transferToNumber": {"enabled": False},
|
|
283
|
+
"emailCopyOfMessage": {"enabled": False},
|
|
284
|
+
"messageStorage": {"mwiEnabled": True, "storageType": "INTERNAL"},
|
|
285
|
+
"faxMessage": {"enabled": False}
|
|
286
|
+
}
|
|
287
|
+
api.session.rest_put(f"{BASE}/people/{person_id}/features/voicemail", json=body)
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
#### Upload Busy Greeting
|
|
291
|
+
|
|
292
|
+
```
|
|
293
|
+
POST https://webexapis.com/v1/people/{personId}/features/voicemail/actions/uploadBusyGreeting/invoke
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Multipart/form-data with `.wav` file. Uses `rest_post` with file upload.
|
|
297
|
+
|
|
298
|
+
#### Upload No-Answer Greeting
|
|
299
|
+
|
|
300
|
+
```
|
|
301
|
+
POST https://webexapis.com/v1/people/{personId}/features/voicemail/actions/uploadNoAnswerGreeting/invoke
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
Multipart/form-data with `.wav` file. Uses `rest_post` with file upload.
|
|
305
|
+
|
|
306
|
+
#### Reset Voicemail PIN
|
|
307
|
+
|
|
308
|
+
```
|
|
309
|
+
POST https://webexapis.com/v1/people/{personId}/features/voicemail/actions/resetPin/invoke
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
```python
|
|
313
|
+
api.session.rest_post(f"{BASE}/people/{person_id}/features/voicemail/actions/resetPin/invoke")
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
#### Modify Voicemail Passcode
|
|
317
|
+
|
|
318
|
+
```
|
|
319
|
+
PUT https://webexapis.com/v1/telephony/config/people/{personId}/voicemail/passcode
|
|
320
|
+
```
|
|
321
|
+
|
|
322
|
+
```python
|
|
323
|
+
body = {"passcode": "123456"}
|
|
324
|
+
api.session.rest_put(f"{BASE}/telephony/config/people/{person_id}/voicemail/passcode", json=body)
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
**Gotchas:**
|
|
328
|
+
- Exclude read-only fields from PUT body: `greetingUploaded`, `systemMaxNumberOfRings`, `voiceMessageForwardingEnabled`.
|
|
329
|
+
- Passcode endpoint uses `telephony/config/people` path (not `people/{id}/features`). Requires `spark-admin:telephony_config_write` scope.
|
|
330
|
+
- Greeting uploads use POST with multipart/form-data, not JSON.
|
|
331
|
+
|
|
332
|
+
---
|
|
333
|
+
|
|
334
|
+
## 2. Caller ID
|
|
335
|
+
|
|
336
|
+
**API class:** `CallerIdApi`
|
|
337
|
+
**Feature key:** `callerId`
|
|
338
|
+
**Source:** `wxc_sdk/person_settings/caller_id.py`
|
|
339
|
+
|
|
340
|
+
### Data Models
|
|
341
|
+
|
|
342
|
+
#### `CallerIdSelectedType` (Enum)
|
|
343
|
+
|
|
344
|
+
| Value | Description |
|
|
345
|
+
|-------|-------------|
|
|
346
|
+
| `DIRECT_LINE` | Show the caller's direct line number and/or extension |
|
|
347
|
+
| `LOCATION_NUMBER` | Show the main number for the location |
|
|
348
|
+
| `MOBILE_NUMBER` | Show the mobile number for this person |
|
|
349
|
+
| `CUSTOM` | Show the value from `custom_number` |
|
|
350
|
+
|
|
351
|
+
#### `ExternalCallerIdNamePolicy` (Enum)
|
|
352
|
+
|
|
353
|
+
| Value | Description |
|
|
354
|
+
|-------|-------------|
|
|
355
|
+
| `DIRECT_LINE` | Show the caller's direct line name |
|
|
356
|
+
| `LOCATION` | Show the site name for the location |
|
|
357
|
+
| `OTHER` | Show the value from `custom_external_caller_id_name` |
|
|
358
|
+
|
|
359
|
+
#### `CallerId`
|
|
360
|
+
|
|
361
|
+
| Field | Type | Description |
|
|
362
|
+
|-------|------|-------------|
|
|
363
|
+
| `caller_id_types` | `list[CallerIdSelectedType]` | Read-only. Allowed types for `selected`. (JSON alias: `types`) |
|
|
364
|
+
| `selected` | `CallerIdSelectedType` | Which type of outgoing caller ID is used (number portion) |
|
|
365
|
+
| `direct_number` | `str` | Direct line number (shown if `DIRECT_LINE` selected) |
|
|
366
|
+
| `extension_number` | `str` | Extension number (shown if `DIRECT_LINE` selected) |
|
|
367
|
+
| `location_number` | `str` | Location number (shown if `LOCATION_NUMBER` selected) |
|
|
368
|
+
| `mobile_number` | `str` | Mobile number (shown if `MOBILE_NUMBER` selected) |
|
|
369
|
+
| `toll_free_location_number` | `bool` | Indicates if the location number is toll-free |
|
|
370
|
+
| `custom_number` | `str` | Custom number (shown if `CUSTOM` selected). Must be from the entity's location or a matching location. |
|
|
371
|
+
| `first_name` | `str` | **Deprecated.** Use `direct_line_caller_id_name` and `dial_by_first_name` instead. |
|
|
372
|
+
| `last_name` | `str` | **Deprecated.** Use `direct_line_caller_id_name` and `dial_by_last_name` instead. |
|
|
373
|
+
| `block_in_forward_calls_enabled` | `bool` | Block identity when receiving transferred/forwarded calls |
|
|
374
|
+
| `external_caller_id_name_policy` | `ExternalCallerIdNamePolicy` | Which external caller ID name policy is used |
|
|
375
|
+
| `custom_external_caller_id_name` | `str` | Custom name shown when policy is `OTHER` |
|
|
376
|
+
| `location_external_caller_id_name` | `str` | Read-only. Location's caller ID name. |
|
|
377
|
+
| `additional_external_caller_id_direct_line_enabled` | `bool` | Set user's main number as additional external caller ID |
|
|
378
|
+
| `additional_external_caller_id_location_number_enabled` | `bool` | Set location main number as additional external caller ID |
|
|
379
|
+
| `additional_external_caller_id_custom_number` | `str` | Set any number across location as additional external caller ID |
|
|
380
|
+
| `display_name` | `str` | **Deprecated.** Use `direct_line_caller_id_name` and `dial_by_name` instead. |
|
|
381
|
+
| `display_detail` | `str` | **Deprecated.** Use `direct_line_caller_id_name` and `dial_by_name` instead. |
|
|
382
|
+
| `direct_line_caller_id_name` | `DirectLineCallerIdName` | Settings for direct line caller ID name |
|
|
383
|
+
| `dial_by_name` | `str` | Name used for dial-by-name functions |
|
|
384
|
+
| `dial_by_first_name` | `str` | First name for dial-by-name |
|
|
385
|
+
| `dial_by_last_name` | `str` | Last name for dial-by-name |
|
|
386
|
+
|
|
387
|
+
**Note:** Number fields (`direct_number`, `location_number`, `mobile_number`, `custom_number`) are validated through the `plus1` E.164 normalizer.
|
|
388
|
+
|
|
389
|
+
### Methods
|
|
390
|
+
|
|
391
|
+
#### `read`
|
|
392
|
+
|
|
393
|
+
```python
|
|
394
|
+
CallerIdApi.read(entity_id: str, org_id: str = None) -> CallerId
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
- **Scopes:** `spark-admin:people_read` or `spark:people_read` (self)
|
|
398
|
+
|
|
399
|
+
#### `configure` (parameter-based)
|
|
400
|
+
|
|
401
|
+
```python
|
|
402
|
+
CallerIdApi.configure(
|
|
403
|
+
entity_id: str,
|
|
404
|
+
org_id: str = None,
|
|
405
|
+
selected: CallerIdSelectedType = None,
|
|
406
|
+
custom_number: str = None,
|
|
407
|
+
first_name: str = None,
|
|
408
|
+
last_name: str = None,
|
|
409
|
+
external_caller_id_name_policy: ExternalCallerIdNamePolicy = None,
|
|
410
|
+
custom_external_caller_id_name: str = None,
|
|
411
|
+
)
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Update caller ID using individual parameters. Only non-None parameters are sent.
|
|
415
|
+
|
|
416
|
+
- **Scopes:** `spark-admin:people_write` or `spark:people_write` (self)
|
|
417
|
+
|
|
418
|
+
#### `configure_settings` (object-based)
|
|
419
|
+
|
|
420
|
+
```python
|
|
421
|
+
CallerIdApi.configure_settings(entity_id: str, settings: CallerId, org_id: str = None)
|
|
422
|
+
```
|
|
423
|
+
|
|
424
|
+
Update caller ID by passing a full `CallerId` object. Uses `settings.update()` which limits to `fields_for_update` and excludes read-only fields.
|
|
425
|
+
|
|
426
|
+
```python
|
|
427
|
+
# Example: enable block-in-forward-calls
|
|
428
|
+
caller_id_settings = api.person_settings.caller_id.read(entity_id=person_id)
|
|
429
|
+
caller_id_settings.block_in_forward_calls_enabled = True
|
|
430
|
+
api.person_settings.caller_id.configure_settings(entity_id=person_id, settings=caller_id_settings)
|
|
431
|
+
```
|
|
432
|
+
|
|
433
|
+
### CLI Examples
|
|
434
|
+
|
|
435
|
+
```bash
|
|
436
|
+
# Read caller ID settings for a person
|
|
437
|
+
wxcli user-settings list PERSON_ID
|
|
438
|
+
|
|
439
|
+
# Read caller ID settings as JSON
|
|
440
|
+
wxcli user-settings list PERSON_ID -o json
|
|
441
|
+
|
|
442
|
+
# Set caller ID to direct line
|
|
443
|
+
wxcli user-settings update-caller-id-features PERSON_ID --selected DIRECT_LINE
|
|
444
|
+
|
|
445
|
+
# Set caller ID to location number
|
|
446
|
+
wxcli user-settings update-caller-id-features PERSON_ID --selected LOCATION_NUMBER
|
|
447
|
+
|
|
448
|
+
# Set caller ID to a custom number
|
|
449
|
+
wxcli user-settings update-caller-id-features PERSON_ID --selected CUSTOM --custom-number "+12125559999"
|
|
450
|
+
|
|
451
|
+
# Set external caller ID name policy to location name
|
|
452
|
+
wxcli user-settings update-caller-id-features PERSON_ID --external-caller-id-name-policy LOCATION
|
|
453
|
+
|
|
454
|
+
# Set external caller ID name policy to custom name
|
|
455
|
+
wxcli user-settings update-caller-id-features PERSON_ID \
|
|
456
|
+
--external-caller-id-name-policy OTHER \
|
|
457
|
+
--custom-external-caller-id-name "Sales Department"
|
|
458
|
+
|
|
459
|
+
# Block identity when receiving forwarded calls
|
|
460
|
+
wxcli user-settings update-caller-id-features PERSON_ID --block-in-forward-calls-enabled
|
|
461
|
+
|
|
462
|
+
# Set dial-by-name fields
|
|
463
|
+
wxcli user-settings update-caller-id-features PERSON_ID \
|
|
464
|
+
--dial-by-first-name "Jane" --dial-by-last-name "Doe"
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Raw HTTP
|
|
468
|
+
|
|
469
|
+
#### Read Caller ID Settings
|
|
470
|
+
|
|
471
|
+
```
|
|
472
|
+
GET https://webexapis.com/v1/people/{personId}/features/callerId
|
|
473
|
+
```
|
|
474
|
+
|
|
475
|
+
```python
|
|
476
|
+
result = api.session.rest_get(f"{BASE}/people/{person_id}/features/callerId")
|
|
477
|
+
# Response:
|
|
478
|
+
# {
|
|
479
|
+
# "types": ["DIRECT_LINE", "LOCATION_NUMBER", "CUSTOM"],
|
|
480
|
+
# "selected": "DIRECT_LINE",
|
|
481
|
+
# "directNumber": "+12125551234",
|
|
482
|
+
# "extensionNumber": "1234",
|
|
483
|
+
# "locationNumber": "+12125550000",
|
|
484
|
+
# "blockInForwardCallsEnabled": false,
|
|
485
|
+
# "externalCallerIdNamePolicy": "DIRECT_LINE",
|
|
486
|
+
# "locationExternalCallerIdName": "Main Office",
|
|
487
|
+
# "additionalExternalCallerIdDirectLineEnabled": false,
|
|
488
|
+
# "additionalExternalCallerIdLocationNumberEnabled": false,
|
|
489
|
+
# "dialByFirstName": "Jane",
|
|
490
|
+
# "dialByLastName": "Doe"
|
|
491
|
+
# }
|
|
492
|
+
```
|
|
493
|
+
|
|
494
|
+
#### Configure Caller ID Settings
|
|
495
|
+
|
|
496
|
+
```
|
|
497
|
+
PUT https://webexapis.com/v1/people/{personId}/features/callerId
|
|
498
|
+
```
|
|
499
|
+
|
|
500
|
+
```python
|
|
501
|
+
body = {
|
|
502
|
+
"selected": "DIRECT_LINE",
|
|
503
|
+
"blockInForwardCallsEnabled": True,
|
|
504
|
+
"externalCallerIdNamePolicy": "DIRECT_LINE"
|
|
505
|
+
}
|
|
506
|
+
api.session.rest_put(f"{BASE}/people/{person_id}/features/callerId", json=body)
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
**Gotchas:**
|
|
510
|
+
- `types` is read-only (returned as JSON key `types`); do not include in PUT body.
|
|
511
|
+
- `locationExternalCallerIdName` is read-only.
|
|
512
|
+
- `selected` values: `"DIRECT_LINE"`, `"LOCATION_NUMBER"`, `"MOBILE_NUMBER"`, `"CUSTOM"`.
|
|
513
|
+
- `externalCallerIdNamePolicy` values: `"DIRECT_LINE"`, `"LOCATION"`, `"OTHER"`.
|
|
514
|
+
- When `selected` is `"CUSTOM"`, include `customNumber` in the body.
|
|
515
|
+
|
|
516
|
+
---
|
|
517
|
+
|
|
518
|
+
## 3. Agent Caller ID
|
|
519
|
+
|
|
520
|
+
**API class:** `AgentCallerIdApi`
|
|
521
|
+
**Feature key:** `agent`
|
|
522
|
+
**Source:** `wxc_sdk/person_settings/agent_caller_id.py`
|
|
523
|
+
|
|
524
|
+
Allows agents to set their outgoing caller ID to a call queue or hunt group instead of their personal caller ID.
|
|
525
|
+
|
|
526
|
+
### Data Models
|
|
527
|
+
|
|
528
|
+
#### `AvailableCallerIdType` (Enum)
|
|
529
|
+
|
|
530
|
+
| Value | Description |
|
|
531
|
+
|-------|-------------|
|
|
532
|
+
| `CALL_QUEUE` | A call queue has been selected |
|
|
533
|
+
| `HUNT_GROUP` | A hunt group has been selected |
|
|
534
|
+
|
|
535
|
+
#### `AgentCallerId`
|
|
536
|
+
|
|
537
|
+
| Field | Type | Description |
|
|
538
|
+
|-------|------|-------------|
|
|
539
|
+
| `id` | `str` | Call queue or hunt group unique identifier |
|
|
540
|
+
| `type` | `AvailableCallerIdType` | `CALL_QUEUE` or `HUNT_GROUP` |
|
|
541
|
+
| `name` | `str` | Call queue or hunt group name |
|
|
542
|
+
| `phone_number` | `str` | Phone number (if set) |
|
|
543
|
+
| `extension` | `str` | Extension number (if set) |
|
|
544
|
+
|
|
545
|
+
#### `QueueCallerId`
|
|
546
|
+
|
|
547
|
+
Internal model used for the read response. Contains:
|
|
548
|
+
|
|
549
|
+
| Field | Type | Description |
|
|
550
|
+
|-------|------|-------------|
|
|
551
|
+
| `queue_caller_id_enabled` | `bool` | `true` when using the selected queue for caller ID; `false` for agent's own |
|
|
552
|
+
| `selected_queue` | `AgentCallerId` | The selected queue/hunt group (empty when disabled) |
|
|
553
|
+
|
|
554
|
+
### Methods
|
|
555
|
+
|
|
556
|
+
#### `available_caller_ids`
|
|
557
|
+
|
|
558
|
+
```python
|
|
559
|
+
AgentCallerIdApi.available_caller_ids(entity_id: str, org_id: str = None) -> list[AgentCallerId]
|
|
560
|
+
```
|
|
561
|
+
|
|
562
|
+
Get call queues and hunt groups available for caller ID use by this agent.
|
|
563
|
+
|
|
564
|
+
- **Scopes:** `spark-admin:people_read`
|
|
565
|
+
- **Endpoint:** `telephony/config/people/{entity_id}/agent/availableCallerIds`
|
|
566
|
+
|
|
567
|
+
#### `read`
|
|
568
|
+
|
|
569
|
+
```python
|
|
570
|
+
AgentCallerIdApi.read(entity_id: str) -> AgentCallerId
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
Retrieve the agent's currently selected caller ID.
|
|
574
|
+
|
|
575
|
+
- **Scopes:** `spark-admin:telephony_config_read`
|
|
576
|
+
- **Endpoint:** `telephony/config/people/{entity_id}/agent/callerId`
|
|
577
|
+
|
|
578
|
+
#### `configure`
|
|
579
|
+
|
|
580
|
+
```python
|
|
581
|
+
AgentCallerIdApi.configure(entity_id: str, selected_caller_id: str = None)
|
|
582
|
+
```
|
|
583
|
+
|
|
584
|
+
Set the agent's caller ID to a specific call queue or hunt group. Pass `None` to revert to the agent's own caller ID.
|
|
585
|
+
|
|
586
|
+
- **Scopes:** `spark-admin:telephony_config_write`
|
|
587
|
+
- Body: `{"selectedCallerId": "<id_or_null>"}`
|
|
588
|
+
|
|
589
|
+
### CLI Examples
|
|
590
|
+
|
|
591
|
+
```bash
|
|
592
|
+
# List available caller IDs (call queues/hunt groups) for an agent
|
|
593
|
+
wxcli user-settings list-available-caller-ids PERSON_ID
|
|
594
|
+
|
|
595
|
+
# Read the agent's currently selected caller ID
|
|
596
|
+
wxcli user-settings show-caller-id PERSON_ID
|
|
597
|
+
|
|
598
|
+
# Read agent caller ID as JSON
|
|
599
|
+
wxcli user-settings show-caller-id PERSON_ID -o json
|
|
600
|
+
|
|
601
|
+
# Set agent caller ID to a specific call queue
|
|
602
|
+
wxcli user-settings update-caller-id-agent PERSON_ID --selected-caller-id QUEUE_ID
|
|
603
|
+
|
|
604
|
+
# Revert agent caller ID to the agent's own caller ID
|
|
605
|
+
wxcli user-settings update-caller-id-agent PERSON_ID --json-body '{"selectedCallerId": null}'
|
|
606
|
+
```
|
|
607
|
+
|
|
608
|
+
### Raw HTTP
|
|
609
|
+
|
|
610
|
+
> **Note:** Agent Caller ID uses the `telephony/config/people` path, not `people/{id}/features`.
|
|
611
|
+
|
|
612
|
+
#### List Available Agent Caller IDs
|
|
613
|
+
|
|
614
|
+
```
|
|
615
|
+
GET https://webexapis.com/v1/telephony/config/people/{personId}/agent/availableCallerIds
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
```python
|
|
619
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/people/{person_id}/agent/availableCallerIds")
|
|
620
|
+
# Response:
|
|
621
|
+
# {
|
|
622
|
+
# "availableCallerIds": [
|
|
623
|
+
# {"id": "queue-id", "type": "CALL_QUEUE", "name": "Sales Queue", "phoneNumber": "+12125551234", "extension": "8001"},
|
|
624
|
+
# {"id": "hg-id", "type": "HUNT_GROUP", "name": "Support HG", "extension": "8002"}
|
|
625
|
+
# ]
|
|
626
|
+
# }
|
|
627
|
+
```
|
|
628
|
+
|
|
629
|
+
#### Read Agent Caller ID
|
|
630
|
+
|
|
631
|
+
```
|
|
632
|
+
GET https://webexapis.com/v1/telephony/config/people/{personId}/agent/callerId
|
|
633
|
+
```
|
|
634
|
+
|
|
635
|
+
```python
|
|
636
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/people/{person_id}/agent/callerId")
|
|
637
|
+
# Response:
|
|
638
|
+
# {
|
|
639
|
+
# "queueCallerIdEnabled": true,
|
|
640
|
+
# "selectedQueue": {"id": "queue-id", "type": "CALL_QUEUE", "name": "Sales Queue", ...}
|
|
641
|
+
# }
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
#### Configure Agent Caller ID
|
|
645
|
+
|
|
646
|
+
```
|
|
647
|
+
PUT https://webexapis.com/v1/telephony/config/people/{personId}/agent/callerId
|
|
648
|
+
```
|
|
649
|
+
|
|
650
|
+
```python
|
|
651
|
+
body = {"selectedCallerId": "queue-id"}
|
|
652
|
+
api.session.rest_put(f"{BASE}/telephony/config/people/{person_id}/agent/callerId", json=body)
|
|
653
|
+
|
|
654
|
+
# To revert to the agent's own caller ID:
|
|
655
|
+
body = {"selectedCallerId": None}
|
|
656
|
+
api.session.rest_put(f"{BASE}/telephony/config/people/{person_id}/agent/callerId", json=body)
|
|
657
|
+
```
|
|
658
|
+
|
|
659
|
+
**Gotchas:**
|
|
660
|
+
- Uses `telephony_config_read`/`write` scopes (not `people_read`/`write`).
|
|
661
|
+
- Pass `null` for `selectedCallerId` to revert to agent's own caller ID.
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## 4. Anonymous Call Rejection
|
|
666
|
+
|
|
667
|
+
**API class:** `AnonCallsApi`
|
|
668
|
+
**Feature key:** `anonymousCallReject`
|
|
669
|
+
**Source:** `wxc_sdk/person_settings/anon_calls.py`
|
|
670
|
+
|
|
671
|
+
When enabled, blocks all incoming calls from unidentified or blocked caller IDs.
|
|
672
|
+
|
|
673
|
+
> **Note from source:** This API is documented as "only available for professional licensed workspaces," and live testing confirms this. The OpenAPI spec only defines endpoints for `/me` (self) and `/workspaces/{id}` -- no admin-level `/people/{id}` endpoint exists. Attempting `GET /v1/telephony/config/people/{personId}/anonymousCallReject` returns 404. The workspace endpoint requires a Professional-licensed workspace (error 25409 returned for non-professional workspaces). The SDK's `PersonSettingsApiChild` base class constructs the person URL pattern, but the API does not accept it.
|
|
674
|
+
|
|
675
|
+
### Methods
|
|
676
|
+
|
|
677
|
+
#### `read`
|
|
678
|
+
|
|
679
|
+
```python
|
|
680
|
+
AnonCallsApi.read(entity_id: str, org_id: str = None) -> bool
|
|
681
|
+
```
|
|
682
|
+
|
|
683
|
+
Returns a simple boolean: `True` if anonymous call rejection is enabled.
|
|
684
|
+
|
|
685
|
+
- **Scopes:** `spark-admin:workspaces_read` (workspace admin), `spark:people_read` (self via `/me`). No admin-level person endpoint exists.
|
|
686
|
+
|
|
687
|
+
#### `configure`
|
|
688
|
+
|
|
689
|
+
```python
|
|
690
|
+
AnonCallsApi.configure(entity_id: str, enabled: bool, org_id: str = None)
|
|
691
|
+
```
|
|
692
|
+
|
|
693
|
+
Enable or disable anonymous call rejection.
|
|
694
|
+
|
|
695
|
+
- Body: `{"enabled": true|false}`
|
|
696
|
+
|
|
697
|
+
### CLI Examples
|
|
698
|
+
|
|
699
|
+
```bash
|
|
700
|
+
# Read anonymous call rejection settings for a workspace
|
|
701
|
+
# Note: In wxcli, anonymous call rejection is under workspace-settings, not user-settings.
|
|
702
|
+
# The API is documented as "only available for professional licensed workspaces."
|
|
703
|
+
wxcli workspace-settings show-anonymous-call-reject WORKSPACE_ID
|
|
704
|
+
|
|
705
|
+
# Enable anonymous call rejection for a workspace
|
|
706
|
+
wxcli workspace-settings update-anonymous-call-reject WORKSPACE_ID --enabled
|
|
707
|
+
|
|
708
|
+
# Disable anonymous call rejection for a workspace
|
|
709
|
+
wxcli workspace-settings update-anonymous-call-reject WORKSPACE_ID --no-enabled
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
### Raw HTTP
|
|
713
|
+
|
|
714
|
+
> **WARNING: No admin-level person endpoint exists.** The path `people/{personId}/features/anonymousCallReject` returns 404. Only the workspace admin path and the self-service `/me` path work.
|
|
715
|
+
|
|
716
|
+
#### Read Anonymous Call Rejection (Workspace — admin token)
|
|
717
|
+
|
|
718
|
+
```
|
|
719
|
+
GET https://webexapis.com/v1/telephony/config/workspaces/{workspaceId}/anonymousCallReject
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
```python
|
|
723
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/workspaces/{workspace_id}/anonymousCallReject")
|
|
724
|
+
# Response:
|
|
725
|
+
# {
|
|
726
|
+
# "enabled": true
|
|
727
|
+
# }
|
|
728
|
+
```
|
|
729
|
+
|
|
730
|
+
#### Read Anonymous Call Rejection (Self — user token, calling-licensed user)
|
|
731
|
+
|
|
732
|
+
```
|
|
733
|
+
GET https://webexapis.com/v1/telephony/config/people/me/settings/anonymousCallReject
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
```python
|
|
737
|
+
# Requires calling-licensed user token with spark:telephony_config_read scope
|
|
738
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/people/me/settings/anonymousCallReject")
|
|
739
|
+
# Response:
|
|
740
|
+
# {
|
|
741
|
+
# "enabled": true
|
|
742
|
+
# }
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
#### Configure Anonymous Call Rejection (Workspace — admin token)
|
|
746
|
+
|
|
747
|
+
```
|
|
748
|
+
PUT https://webexapis.com/v1/telephony/config/workspaces/{workspaceId}/anonymousCallReject
|
|
749
|
+
```
|
|
750
|
+
|
|
751
|
+
```python
|
|
752
|
+
body = {"enabled": True}
|
|
753
|
+
api.session.rest_put(f"{BASE}/telephony/config/workspaces/{workspace_id}/anonymousCallReject", json=body)
|
|
754
|
+
```
|
|
755
|
+
|
|
756
|
+
#### Configure Anonymous Call Rejection (Self — user token, calling-licensed user)
|
|
757
|
+
|
|
758
|
+
```
|
|
759
|
+
PUT https://webexapis.com/v1/telephony/config/people/me/settings/anonymousCallReject
|
|
760
|
+
```
|
|
761
|
+
|
|
762
|
+
```python
|
|
763
|
+
# Requires calling-licensed user token with spark:telephony_config_write scope
|
|
764
|
+
body = {"enabled": True}
|
|
765
|
+
api.session.rest_put(f"{BASE}/telephony/config/people/me/settings/anonymousCallReject", json=body)
|
|
766
|
+
```
|
|
767
|
+
|
|
768
|
+
---
|
|
769
|
+
|
|
770
|
+
## 5. Privacy
|
|
771
|
+
|
|
772
|
+
**API class:** `PrivacyApi`
|
|
773
|
+
**Feature key:** `privacy`
|
|
774
|
+
**Source:** `wxc_sdk/person_settings/privacy.py`
|
|
775
|
+
|
|
776
|
+
Controls whether the entity's line can be monitored by others and whether they are reachable via Auto Attendant services.
|
|
777
|
+
|
|
778
|
+
### Data Model
|
|
779
|
+
|
|
780
|
+
#### `Privacy`
|
|
781
|
+
|
|
782
|
+
| Field | Type | Description |
|
|
783
|
+
|-------|------|-------------|
|
|
784
|
+
| `aa_extension_dialing_enabled` | `bool` | Enable auto attendant extension dialing |
|
|
785
|
+
| `aa_naming_dialing_enabled` | `bool` | Enable auto attendant dialing by first or last name |
|
|
786
|
+
| `enable_phone_status_directory_privacy` | `bool` | Enable phone status directory privacy |
|
|
787
|
+
| `enable_phone_status_pickup_barge_in_privacy` | `bool` | When `true`, only people in `monitoring_agents` can pick up the call or barge in by dialing the extension |
|
|
788
|
+
| `monitoring_agents` | `list[Union[str, PersonPlaceAgent]]` | List of people allowed to monitor. For updates, can pass IDs (strings) directly. |
|
|
789
|
+
|
|
790
|
+
### Methods
|
|
791
|
+
|
|
792
|
+
#### `read`
|
|
793
|
+
|
|
794
|
+
```python
|
|
795
|
+
PrivacyApi.read(entity_id: str, org_id: str = None) -> Privacy
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
- **Scopes:** `spark-admin:people_read`
|
|
799
|
+
|
|
800
|
+
#### `configure`
|
|
801
|
+
|
|
802
|
+
```python
|
|
803
|
+
PrivacyApi.configure(entity_id: str, settings: Privacy, org_id: str = None)
|
|
804
|
+
```
|
|
805
|
+
|
|
806
|
+
- **Scopes:** `spark-admin:people_write`
|
|
807
|
+
- When updating `monitoring_agents`, the SDK extracts IDs from `PersonPlaceAgent` objects (using `agent_id`) or passes strings directly.
|
|
808
|
+
|
|
809
|
+
### CLI Examples
|
|
810
|
+
|
|
811
|
+
```bash
|
|
812
|
+
# Read privacy settings for a person
|
|
813
|
+
wxcli user-settings list-privacy PERSON_ID
|
|
814
|
+
|
|
815
|
+
# Read privacy settings as JSON
|
|
816
|
+
wxcli user-settings list-privacy PERSON_ID -o json
|
|
817
|
+
|
|
818
|
+
# Enable AA extension dialing and directory privacy
|
|
819
|
+
wxcli user-settings update-privacy PERSON_ID \
|
|
820
|
+
--aa-extension-dialing-enabled \
|
|
821
|
+
--enable-phone-status-directory-privacy
|
|
822
|
+
|
|
823
|
+
# Disable AA naming dialing
|
|
824
|
+
wxcli user-settings update-privacy PERSON_ID --no-aa-naming-dialing-enabled
|
|
825
|
+
|
|
826
|
+
# Enable pickup/barge-in privacy
|
|
827
|
+
wxcli user-settings update-privacy PERSON_ID --enable-phone-status-pickup-barge-in-privacy
|
|
828
|
+
|
|
829
|
+
# Update privacy with monitoring agents list (requires --json-body)
|
|
830
|
+
wxcli user-settings update-privacy PERSON_ID --json-body '{
|
|
831
|
+
"aaExtensionDialingEnabled": true,
|
|
832
|
+
"aaNamingDialingEnabled": true,
|
|
833
|
+
"enablePhoneStatusDirectoryPrivacy": true,
|
|
834
|
+
"enablePhoneStatusPickupBargeInPrivacy": true,
|
|
835
|
+
"monitoringAgents": ["PERSON_ID_1", "PERSON_ID_2"]
|
|
836
|
+
}'
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
### Raw HTTP
|
|
840
|
+
|
|
841
|
+
#### Read Privacy Settings
|
|
842
|
+
|
|
843
|
+
```
|
|
844
|
+
GET https://webexapis.com/v1/people/{personId}/features/privacy
|
|
845
|
+
```
|
|
846
|
+
|
|
847
|
+
```python
|
|
848
|
+
result = api.session.rest_get(f"{BASE}/people/{person_id}/features/privacy")
|
|
849
|
+
# Response:
|
|
850
|
+
# {
|
|
851
|
+
# "aaExtensionDialingEnabled": true,
|
|
852
|
+
# "aaNamingDialingEnabled": true,
|
|
853
|
+
# "enablePhoneStatusDirectoryPrivacy": false,
|
|
854
|
+
# "enablePhoneStatusPickupBargeInPrivacy": false,
|
|
855
|
+
# "monitoringAgents": [
|
|
856
|
+
# {"id": "person-id", "firstName": "Jane", "lastName": "Doe", ...}
|
|
857
|
+
# ]
|
|
858
|
+
# }
|
|
859
|
+
```
|
|
860
|
+
|
|
861
|
+
#### Configure Privacy Settings
|
|
862
|
+
|
|
863
|
+
```
|
|
864
|
+
PUT https://webexapis.com/v1/people/{personId}/features/privacy
|
|
865
|
+
```
|
|
866
|
+
|
|
867
|
+
```python
|
|
868
|
+
body = {
|
|
869
|
+
"aaExtensionDialingEnabled": True,
|
|
870
|
+
"aaNamingDialingEnabled": True,
|
|
871
|
+
"enablePhoneStatusDirectoryPrivacy": True,
|
|
872
|
+
"enablePhoneStatusPickupBargeInPrivacy": False,
|
|
873
|
+
"monitoringAgents": ["person-id-1", "person-id-2"]
|
|
874
|
+
}
|
|
875
|
+
api.session.rest_put(f"{BASE}/people/{person_id}/features/privacy", json=body)
|
|
876
|
+
```
|
|
877
|
+
|
|
878
|
+
**Gotchas:**
|
|
879
|
+
- `monitoringAgents` accepts a flat list of person IDs for updates, even though reads return full agent objects.
|
|
880
|
+
- Uses `people/{id}/features/privacy` path (not `telephony/config/people`). <!-- Updated by playbook session 2026-03-18 -->
|
|
881
|
+
|
|
882
|
+
---
|
|
883
|
+
|
|
884
|
+
## 6. Barge-In
|
|
885
|
+
|
|
886
|
+
**API class:** `BargeApi`
|
|
887
|
+
**Feature key:** `bargeIn`
|
|
888
|
+
**Source:** `wxc_sdk/person_settings/barge.py`
|
|
889
|
+
|
|
890
|
+
Enables the use of a Feature Access Code (FAC) to answer a call directed to another subscriber, or barge-in on an already-answered call. Works across locations.
|
|
891
|
+
|
|
892
|
+
### Data Model
|
|
893
|
+
|
|
894
|
+
#### `BargeSettings`
|
|
895
|
+
|
|
896
|
+
| Field | Type | Description |
|
|
897
|
+
|-------|------|-------------|
|
|
898
|
+
| `enabled` | `bool` | Whether barge-in is enabled (required, not optional) |
|
|
899
|
+
| `tone_enabled` | `bool` | Whether a stutter dial tone plays when someone barges in (required, not optional) |
|
|
900
|
+
|
|
901
|
+
### Methods
|
|
902
|
+
|
|
903
|
+
#### `read`
|
|
904
|
+
|
|
905
|
+
```python
|
|
906
|
+
BargeApi.read(entity_id: str, org_id: str = None) -> BargeSettings
|
|
907
|
+
```
|
|
908
|
+
|
|
909
|
+
- **Scopes:** `spark-admin:people_read` or `spark:people_read` (self)
|
|
910
|
+
|
|
911
|
+
#### `configure`
|
|
912
|
+
|
|
913
|
+
```python
|
|
914
|
+
BargeApi.configure(entity_id: str, barge_settings: BargeSettings, org_id: str = None)
|
|
915
|
+
```
|
|
916
|
+
|
|
917
|
+
- **Scopes:** `spark-admin:people_write` or `spark:people_write` (self)
|
|
918
|
+
- Serializes the full `BargeSettings` object as JSON body.
|
|
919
|
+
|
|
920
|
+
### CLI Examples
|
|
921
|
+
|
|
922
|
+
```bash
|
|
923
|
+
# Read barge-in settings for a person
|
|
924
|
+
wxcli user-settings show-barge-in PERSON_ID
|
|
925
|
+
|
|
926
|
+
# Read barge-in settings as JSON
|
|
927
|
+
wxcli user-settings show-barge-in PERSON_ID -o json
|
|
928
|
+
|
|
929
|
+
# Enable barge-in with tone
|
|
930
|
+
wxcli user-settings update-barge-in PERSON_ID --enabled --tone-enabled
|
|
931
|
+
|
|
932
|
+
# Enable barge-in without tone
|
|
933
|
+
wxcli user-settings update-barge-in PERSON_ID --enabled --no-tone-enabled
|
|
934
|
+
|
|
935
|
+
# Disable barge-in entirely
|
|
936
|
+
wxcli user-settings update-barge-in PERSON_ID --no-enabled --no-tone-enabled
|
|
937
|
+
```
|
|
938
|
+
|
|
939
|
+
### Raw HTTP
|
|
940
|
+
|
|
941
|
+
#### Read Barge-In Settings
|
|
942
|
+
|
|
943
|
+
```
|
|
944
|
+
GET https://webexapis.com/v1/people/{personId}/features/bargeIn
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
```python
|
|
948
|
+
result = api.session.rest_get(f"{BASE}/people/{person_id}/features/bargeIn")
|
|
949
|
+
# Response:
|
|
950
|
+
# {
|
|
951
|
+
# "enabled": true,
|
|
952
|
+
# "toneEnabled": true
|
|
953
|
+
# }
|
|
954
|
+
```
|
|
955
|
+
|
|
956
|
+
#### Configure Barge-In Settings
|
|
957
|
+
|
|
958
|
+
```
|
|
959
|
+
PUT https://webexapis.com/v1/people/{personId}/features/bargeIn
|
|
960
|
+
```
|
|
961
|
+
|
|
962
|
+
```python
|
|
963
|
+
body = {
|
|
964
|
+
"enabled": True,
|
|
965
|
+
"toneEnabled": True
|
|
966
|
+
}
|
|
967
|
+
api.session.rest_put(f"{BASE}/people/{person_id}/features/bargeIn", json=body)
|
|
968
|
+
```
|
|
969
|
+
|
|
970
|
+
#### Beta: User Self-Service Barge-In
|
|
971
|
+
|
|
972
|
+
> **Beta API** — May change without notice.
|
|
973
|
+
|
|
974
|
+
Users can read/modify their own barge-in settings via user-level OAuth:
|
|
975
|
+
|
|
976
|
+
- `GET /telephony/config/people/me/settings/bargeIn`
|
|
977
|
+
- `PUT /telephony/config/people/me/settings/bargeIn`
|
|
978
|
+
|
|
979
|
+
The admin-path equivalent at `/people/{personId}/features/bargeIn` remains the stable, non-beta option for admin-managed configuration.
|
|
980
|
+
|
|
981
|
+
---
|
|
982
|
+
|
|
983
|
+
## 7. Call Recording
|
|
984
|
+
|
|
985
|
+
**API class:** `CallRecordingApi`
|
|
986
|
+
**Feature key:** `callRecording`
|
|
987
|
+
**Source:** `wxc_sdk/person_settings/call_recording.py`
|
|
988
|
+
|
|
989
|
+
Provides hosted call recording for replay and archival, for quality assurance, security, and training.
|
|
990
|
+
|
|
991
|
+
### Data Models
|
|
992
|
+
|
|
993
|
+
#### `Record` (Enum)
|
|
994
|
+
|
|
995
|
+
| Value | Description |
|
|
996
|
+
|-------|-------------|
|
|
997
|
+
| `Always` | Recording is always enabled |
|
|
998
|
+
| `Never` | Recording is never enabled |
|
|
999
|
+
| `On Demand` | Recording is started/stopped manually by user |
|
|
1000
|
+
| `Always with Pause/Resume` | Always enabled with ability to pause and resume |
|
|
1001
|
+
| `On Demand with User Initiated Start` | Started manually by user |
|
|
1002
|
+
|
|
1003
|
+
#### `NotificationType` (Enum)
|
|
1004
|
+
|
|
1005
|
+
| Value | Description |
|
|
1006
|
+
|-------|-------------|
|
|
1007
|
+
| `None` | No notification sound when paused/resumed |
|
|
1008
|
+
| `Beep` | A beep sound plays when paused/resumed |
|
|
1009
|
+
| `Play Announcement` | A verbal announcement plays when paused/resumed |
|
|
1010
|
+
|
|
1011
|
+
#### `NotificationRepeat`
|
|
1012
|
+
|
|
1013
|
+
| Field | Type | Description |
|
|
1014
|
+
|-------|------|-------------|
|
|
1015
|
+
| `interval` | `int` | Interval in seconds (10-1800) for periodic warning beep |
|
|
1016
|
+
| `enabled` | `bool` | Whether the ongoing recording tone plays at the interval |
|
|
1017
|
+
|
|
1018
|
+
#### `Notification`
|
|
1019
|
+
|
|
1020
|
+
| Field | Type | Description |
|
|
1021
|
+
|-------|------|-------------|
|
|
1022
|
+
| `notification_type` | `NotificationType` | Type of notification (JSON alias: `type`) |
|
|
1023
|
+
| `enabled` | `bool` | Whether notification feature is active |
|
|
1024
|
+
|
|
1025
|
+
#### `StartStopAnnouncement`
|
|
1026
|
+
|
|
1027
|
+
| Field | Type | Description |
|
|
1028
|
+
|-------|------|-------------|
|
|
1029
|
+
| `internal_calls_enabled` | `bool` | Play start/stop announcement for internal calls |
|
|
1030
|
+
| `pstn_calls_enabled` | `bool` | Play start/stop announcement for PSTN calls |
|
|
1031
|
+
|
|
1032
|
+
#### `CallRecordingAccessSettings`
|
|
1033
|
+
|
|
1034
|
+
| Field | Type | Description |
|
|
1035
|
+
|-------|------|-------------|
|
|
1036
|
+
| `view_and_play_recordings_enabled` | `bool` | Person can view and play recordings |
|
|
1037
|
+
| `download_recordings_enabled` | `bool` | Person can download recordings |
|
|
1038
|
+
| `delete_recordings_enabled` | `bool` | Person can delete recordings |
|
|
1039
|
+
| `share_recordings_enabled` | `bool` | Person can share recordings |
|
|
1040
|
+
|
|
1041
|
+
#### `PostCallRecordingSettings`
|
|
1042
|
+
|
|
1043
|
+
| Field | Type | Description |
|
|
1044
|
+
|-------|------|-------------|
|
|
1045
|
+
| `summary_and_action_items_enabled` | `bool` | Undocumented field; present in SDK source (`call_recording.py` line 83) with `# TODO: undocumented, issue 201` |
|
|
1046
|
+
| `transcript_enabled` | `bool` | Undocumented field; present in SDK source (`call_recording.py` line 84) with `# TODO: undocumented, issue 201` |
|
|
1047
|
+
|
|
1048
|
+
#### `CallRecordingSetting`
|
|
1049
|
+
|
|
1050
|
+
| Field | Type | Description |
|
|
1051
|
+
|-------|------|-------------|
|
|
1052
|
+
| `enabled` | `bool` | Whether call recording is enabled |
|
|
1053
|
+
| `record` | `Record` | Which scenario triggers recording |
|
|
1054
|
+
| `record_voicemail_enabled` | `bool` | Also record voicemail messages |
|
|
1055
|
+
| `start_stop_announcement_enabled` | `bool` | Play announcement at start/stop |
|
|
1056
|
+
| `notification` | `Notification` | Pause/resume notification settings |
|
|
1057
|
+
| `repeat` | `NotificationRepeat` | Periodic beep settings |
|
|
1058
|
+
| `service_provider` | `str` | Read-only. Service provider name (excluded from updates). |
|
|
1059
|
+
| `external_group` | `str` | Read-only. Service provider group (excluded from updates). |
|
|
1060
|
+
| `external_identifier` | `str` | Read-only. Unique identifier at provider (excluded from updates). |
|
|
1061
|
+
| `start_stop_announcement` | `StartStopAnnouncement` | Separate start/stop per internal vs. PSTN |
|
|
1062
|
+
| `call_recording_access_settings` | `CallRecordingAccessSettings` | User's access to their own recordings |
|
|
1063
|
+
| `post_call_recording_settings` | `PostCallRecordingSettings` | Post-call summary/transcript settings |
|
|
1064
|
+
|
|
1065
|
+
#### Default Settings
|
|
1066
|
+
|
|
1067
|
+
```python
|
|
1068
|
+
CallRecordingSetting.default() # Returns:
|
|
1069
|
+
CallRecordingSetting(
|
|
1070
|
+
enabled=False,
|
|
1071
|
+
record=Record.never,
|
|
1072
|
+
record_voicemail_enabled=False,
|
|
1073
|
+
start_stop_announcement_enabled=False,
|
|
1074
|
+
notification=Notification(notification_type=NotificationType.none, enabled=False),
|
|
1075
|
+
repeat=NotificationRepeat(interval=15, enabled=False),
|
|
1076
|
+
start_stop_announcement=StartStopAnnouncement(
|
|
1077
|
+
internal_calls_enabled=False,
|
|
1078
|
+
pstn_calls_enabled=False,
|
|
1079
|
+
),
|
|
1080
|
+
)
|
|
1081
|
+
```
|
|
1082
|
+
|
|
1083
|
+
### Methods
|
|
1084
|
+
|
|
1085
|
+
#### `read`
|
|
1086
|
+
|
|
1087
|
+
```python
|
|
1088
|
+
CallRecordingApi.read(entity_id: str, org_id: str = None) -> CallRecordingSetting
|
|
1089
|
+
```
|
|
1090
|
+
|
|
1091
|
+
- **Scopes:** `spark-admin:people_read` (Note: the SDK source docstring incorrectly says `people_write` for read; this is a documentation bug in the SDK -- read operations use `people_read` per the consistent pattern across all PersonSettingsApiChild endpoints)
|
|
1092
|
+
|
|
1093
|
+
#### `configure`
|
|
1094
|
+
|
|
1095
|
+
```python
|
|
1096
|
+
CallRecordingApi.configure(entity_id: str, recording: CallRecordingSetting, org_id: str = None)
|
|
1097
|
+
```
|
|
1098
|
+
|
|
1099
|
+
- **Scopes:** `spark-admin:people_write`
|
|
1100
|
+
- **Gotcha:** When `notification.notification_type` is `None` (the enum value), the update method converts it to JSON `null` (the API returns the string `"None"` on reads but expects `null` on writes).
|
|
1101
|
+
- Read-only fields (`service_provider`, `external_group`, `external_identifier`) are automatically excluded.
|
|
1102
|
+
|
|
1103
|
+
### CLI Examples
|
|
1104
|
+
|
|
1105
|
+
```bash
|
|
1106
|
+
# Read call recording settings for a person
|
|
1107
|
+
wxcli user-settings show-call-recording PERSON_ID
|
|
1108
|
+
|
|
1109
|
+
# Read call recording settings as JSON
|
|
1110
|
+
wxcli user-settings show-call-recording PERSON_ID -o json
|
|
1111
|
+
|
|
1112
|
+
# Enable call recording with "Always" mode
|
|
1113
|
+
wxcli user-settings update-call-recording PERSON_ID --enabled --record "Always"
|
|
1114
|
+
|
|
1115
|
+
# Set call recording to "On Demand with User Initiated Start"
|
|
1116
|
+
wxcli user-settings update-call-recording PERSON_ID --enabled --record "On Demand with User Initiated Start"
|
|
1117
|
+
|
|
1118
|
+
# Disable call recording
|
|
1119
|
+
wxcli user-settings update-call-recording PERSON_ID --no-enabled --record "Never"
|
|
1120
|
+
|
|
1121
|
+
# Enable call recording with voicemail recording
|
|
1122
|
+
wxcli user-settings update-call-recording PERSON_ID --enabled --record "Always" --record-voicemail-enabled
|
|
1123
|
+
|
|
1124
|
+
# Full recording config with notifications (requires --json-body)
|
|
1125
|
+
wxcli user-settings update-call-recording PERSON_ID --json-body '{
|
|
1126
|
+
"enabled": true,
|
|
1127
|
+
"record": "Always with Pause/Resume",
|
|
1128
|
+
"recordVoicemailEnabled": false,
|
|
1129
|
+
"startStopAnnouncementEnabled": true,
|
|
1130
|
+
"notification": {"type": null, "enabled": false},
|
|
1131
|
+
"repeat": {"interval": 15, "enabled": false},
|
|
1132
|
+
"startStopAnnouncement": {"internalCallsEnabled": true, "pstnCallsEnabled": true}
|
|
1133
|
+
}'
|
|
1134
|
+
```
|
|
1135
|
+
|
|
1136
|
+
### Raw HTTP
|
|
1137
|
+
|
|
1138
|
+
> **Note:** The CLI uses `people/{id}/features/callRecording`. The user-provided URL pattern `telephony/config/people/{personId}/callRecording` is the wxc_sdk remapped path; the actual raw HTTP endpoint is `people/{id}/features/callRecording`. <!-- Updated by playbook session 2026-03-18 -->
|
|
1139
|
+
|
|
1140
|
+
#### Read Call Recording Settings
|
|
1141
|
+
|
|
1142
|
+
```
|
|
1143
|
+
GET https://webexapis.com/v1/people/{personId}/features/callRecording
|
|
1144
|
+
```
|
|
1145
|
+
|
|
1146
|
+
```python
|
|
1147
|
+
result = api.session.rest_get(f"{BASE}/people/{person_id}/features/callRecording")
|
|
1148
|
+
# Response:
|
|
1149
|
+
# {
|
|
1150
|
+
# "enabled": false,
|
|
1151
|
+
# "record": "Never",
|
|
1152
|
+
# "recordVoicemailEnabled": false,
|
|
1153
|
+
# "startStopAnnouncementEnabled": false,
|
|
1154
|
+
# "notification": {"type": null, "enabled": false},
|
|
1155
|
+
# "repeat": {"interval": 15, "enabled": false},
|
|
1156
|
+
# "serviceProvider": "...",
|
|
1157
|
+
# "externalGroup": "...",
|
|
1158
|
+
# "externalIdentifier": "...",
|
|
1159
|
+
# "startStopAnnouncement": {"internalCallsEnabled": false, "pstnCallsEnabled": false},
|
|
1160
|
+
# "callRecordingAccessSettings": {
|
|
1161
|
+
# "viewAndPlayRecordingsEnabled": true,
|
|
1162
|
+
# "downloadRecordingsEnabled": true,
|
|
1163
|
+
# "deleteRecordingsEnabled": true,
|
|
1164
|
+
# "shareRecordingsEnabled": true
|
|
1165
|
+
# }
|
|
1166
|
+
# }
|
|
1167
|
+
```
|
|
1168
|
+
|
|
1169
|
+
#### Configure Call Recording Settings
|
|
1170
|
+
|
|
1171
|
+
```
|
|
1172
|
+
PUT https://webexapis.com/v1/people/{personId}/features/callRecording
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
```python
|
|
1176
|
+
body = {
|
|
1177
|
+
"enabled": True,
|
|
1178
|
+
"record": "Always",
|
|
1179
|
+
"recordVoicemailEnabled": False,
|
|
1180
|
+
"startStopAnnouncementEnabled": False,
|
|
1181
|
+
"notification": {"type": None, "enabled": False},
|
|
1182
|
+
"repeat": {"interval": 15, "enabled": False},
|
|
1183
|
+
"startStopAnnouncement": {"internalCallsEnabled": False, "pstnCallsEnabled": False}
|
|
1184
|
+
}
|
|
1185
|
+
api.session.rest_put(f"{BASE}/people/{person_id}/features/callRecording", json=body)
|
|
1186
|
+
```
|
|
1187
|
+
|
|
1188
|
+
**Gotchas:**
|
|
1189
|
+
- Exclude read-only fields from PUT body: `serviceProvider`, `externalGroup`, `externalIdentifier`.
|
|
1190
|
+
- `record` values: `"Always"`, `"Never"`, `"On Demand"`, `"Always with Pause/Resume"`, `"On Demand with User Initiated Start"`.
|
|
1191
|
+
- `notification.type`: API returns `"None"` as a string on reads but expects JSON `null` on writes. Pass `None` (Python) which serializes to `null`.
|
|
1192
|
+
|
|
1193
|
+
---
|
|
1194
|
+
|
|
1195
|
+
## 8. Call Intercept
|
|
1196
|
+
|
|
1197
|
+
**API class:** `CallInterceptApi`
|
|
1198
|
+
**Feature key:** `intercept`
|
|
1199
|
+
**Source:** `wxc_sdk/person_settings/call_intercept.py`
|
|
1200
|
+
|
|
1201
|
+
Gracefully takes an entity's phone out of service while providing callers with informative announcements and alternative routing options.
|
|
1202
|
+
|
|
1203
|
+
### Data Models
|
|
1204
|
+
|
|
1205
|
+
#### `InterceptTypeIncoming` (Enum)
|
|
1206
|
+
|
|
1207
|
+
| Value | Description |
|
|
1208
|
+
|-------|-------------|
|
|
1209
|
+
| `INTERCEPT_ALL` | All incoming calls are intercepted |
|
|
1210
|
+
| `ALLOW_ALL` | Incoming calls are not intercepted |
|
|
1211
|
+
|
|
1212
|
+
#### `InterceptTypeOutgoing` (Enum)
|
|
1213
|
+
|
|
1214
|
+
| Value | Description |
|
|
1215
|
+
|-------|-------------|
|
|
1216
|
+
| `INTERCEPT_ALL` | All outgoing calls are intercepted |
|
|
1217
|
+
| `ALLOW_LOCAL_ONLY` | Only non-local calls are intercepted |
|
|
1218
|
+
|
|
1219
|
+
#### `InterceptNumber`
|
|
1220
|
+
|
|
1221
|
+
| Field | Type | Description |
|
|
1222
|
+
|-------|------|-------------|
|
|
1223
|
+
| `enabled` | `bool` | If true, caller hears this number announced |
|
|
1224
|
+
| `destination` | `str` | The number the caller hears |
|
|
1225
|
+
|
|
1226
|
+
#### `InterceptAnnouncements`
|
|
1227
|
+
|
|
1228
|
+
| Field | Type | Description |
|
|
1229
|
+
|-------|------|-------------|
|
|
1230
|
+
| `greeting` | `Greeting` | `DEFAULT` or `CUSTOM` |
|
|
1231
|
+
| `file_name` | `str` | Read-only. Filename of custom greeting (empty string if none uploaded). Excluded from updates. |
|
|
1232
|
+
| `new_number` | `InterceptNumber` | Announcement about a new number |
|
|
1233
|
+
| `zero_transfer` | `InterceptNumber` | How the call is handled if 0 is pressed |
|
|
1234
|
+
|
|
1235
|
+
#### `InterceptSettingIncoming`
|
|
1236
|
+
|
|
1237
|
+
| Field | Type | Description |
|
|
1238
|
+
|-------|------|-------------|
|
|
1239
|
+
| `intercept_type` | `InterceptTypeIncoming` | (JSON alias: `type`) |
|
|
1240
|
+
| `voicemail_enabled` | `bool` | If true, destination is voicemail |
|
|
1241
|
+
| `announcements` | `InterceptAnnouncements` | Announcement settings |
|
|
1242
|
+
|
|
1243
|
+
#### `InterceptSettingOutgoing`
|
|
1244
|
+
|
|
1245
|
+
| Field | Type | Description |
|
|
1246
|
+
|-------|------|-------------|
|
|
1247
|
+
| `intercept_type` | `InterceptTypeOutgoing` | (JSON alias: `type`) |
|
|
1248
|
+
| `transfer_enabled` | `bool` | Allow transfer/forwarding for intercepted calls |
|
|
1249
|
+
| `destination` | `str` | Number to transfer outbound calls to |
|
|
1250
|
+
|
|
1251
|
+
#### `InterceptSetting`
|
|
1252
|
+
|
|
1253
|
+
| Field | Type | Description |
|
|
1254
|
+
|-------|------|-------------|
|
|
1255
|
+
| `enabled` | `bool` | Whether call intercept is active |
|
|
1256
|
+
| `incoming` | `InterceptSettingIncoming` | Incoming call intercept configuration |
|
|
1257
|
+
| `outgoing` | `InterceptSettingOutgoing` | Outgoing call intercept configuration |
|
|
1258
|
+
|
|
1259
|
+
#### Default Settings
|
|
1260
|
+
|
|
1261
|
+
```python
|
|
1262
|
+
InterceptSetting.default() # Returns:
|
|
1263
|
+
InterceptSetting(
|
|
1264
|
+
enabled=False,
|
|
1265
|
+
incoming=InterceptSettingIncoming(
|
|
1266
|
+
intercept_type=InterceptTypeIncoming.intercept_all,
|
|
1267
|
+
voicemail_enabled=False,
|
|
1268
|
+
announcements=InterceptAnnouncements(
|
|
1269
|
+
greeting=Greeting.default,
|
|
1270
|
+
new_number=InterceptNumber(enabled=False),
|
|
1271
|
+
zero_transfer=InterceptNumber(enabled=False),
|
|
1272
|
+
),
|
|
1273
|
+
),
|
|
1274
|
+
outgoing=InterceptSettingOutgoing(
|
|
1275
|
+
intercept_type=InterceptTypeOutgoing.intercept_all,
|
|
1276
|
+
transfer_enabled=False,
|
|
1277
|
+
),
|
|
1278
|
+
)
|
|
1279
|
+
```
|
|
1280
|
+
|
|
1281
|
+
### Methods
|
|
1282
|
+
|
|
1283
|
+
#### `read`
|
|
1284
|
+
|
|
1285
|
+
```python
|
|
1286
|
+
CallInterceptApi.read(entity_id: str, org_id: str = None) -> InterceptSetting
|
|
1287
|
+
```
|
|
1288
|
+
|
|
1289
|
+
- **Scopes:** `spark-admin:people_read`
|
|
1290
|
+
|
|
1291
|
+
#### `configure`
|
|
1292
|
+
|
|
1293
|
+
```python
|
|
1294
|
+
CallInterceptApi.configure(entity_id: str, intercept: InterceptSetting, org_id: str = None)
|
|
1295
|
+
```
|
|
1296
|
+
|
|
1297
|
+
- **Scopes:** `spark-admin:people_write`
|
|
1298
|
+
|
|
1299
|
+
#### `greeting`
|
|
1300
|
+
|
|
1301
|
+
```python
|
|
1302
|
+
CallInterceptApi.greeting(
|
|
1303
|
+
entity_id: str,
|
|
1304
|
+
content: Union[BufferedReader, str],
|
|
1305
|
+
upload_as: str = None,
|
|
1306
|
+
org_id: str = None,
|
|
1307
|
+
)
|
|
1308
|
+
```
|
|
1309
|
+
|
|
1310
|
+
Upload a custom intercept greeting (`.wav` file). Uses multipart/form-data. Endpoint: `actions/announcementUpload/invoke`.
|
|
1311
|
+
|
|
1312
|
+
- `content`: file path (str) or open binary reader.
|
|
1313
|
+
- `upload_as`: required if `content` is a reader.
|
|
1314
|
+
- **Scopes:** `spark-admin:people_write` or `spark:people_write` (self)
|
|
1315
|
+
|
|
1316
|
+
### CLI Examples
|
|
1317
|
+
|
|
1318
|
+
```bash
|
|
1319
|
+
# Read call intercept settings for a person
|
|
1320
|
+
wxcli user-settings show-intercept PERSON_ID
|
|
1321
|
+
|
|
1322
|
+
# Read call intercept settings as JSON
|
|
1323
|
+
wxcli user-settings show-intercept PERSON_ID -o json
|
|
1324
|
+
|
|
1325
|
+
# Enable call intercept
|
|
1326
|
+
wxcli user-settings update-intercept PERSON_ID --enabled
|
|
1327
|
+
|
|
1328
|
+
# Disable call intercept
|
|
1329
|
+
wxcli user-settings update-intercept PERSON_ID --no-enabled
|
|
1330
|
+
|
|
1331
|
+
# Enable call intercept with full incoming/outgoing config (requires --json-body)
|
|
1332
|
+
wxcli user-settings update-intercept PERSON_ID --json-body '{
|
|
1333
|
+
"enabled": true,
|
|
1334
|
+
"incoming": {
|
|
1335
|
+
"type": "INTERCEPT_ALL",
|
|
1336
|
+
"voicemailEnabled": true,
|
|
1337
|
+
"announcements": {
|
|
1338
|
+
"greeting": "DEFAULT",
|
|
1339
|
+
"newNumber": {"enabled": true, "destination": "+12125559999"},
|
|
1340
|
+
"zeroTransfer": {"enabled": true, "destination": "+12125550000"}
|
|
1341
|
+
}
|
|
1342
|
+
},
|
|
1343
|
+
"outgoing": {
|
|
1344
|
+
"type": "ALLOW_LOCAL_ONLY",
|
|
1345
|
+
"transferEnabled": false
|
|
1346
|
+
}
|
|
1347
|
+
}'
|
|
1348
|
+
|
|
1349
|
+
# Upload a custom intercept greeting
|
|
1350
|
+
wxcli user-settings configure-call-intercept PERSON_ID
|
|
1351
|
+
```
|
|
1352
|
+
|
|
1353
|
+
### Raw HTTP
|
|
1354
|
+
|
|
1355
|
+
#### Read Call Intercept Settings
|
|
1356
|
+
|
|
1357
|
+
```
|
|
1358
|
+
GET https://webexapis.com/v1/people/{personId}/features/intercept
|
|
1359
|
+
```
|
|
1360
|
+
|
|
1361
|
+
```python
|
|
1362
|
+
result = api.session.rest_get(f"{BASE}/people/{person_id}/features/intercept")
|
|
1363
|
+
# Response:
|
|
1364
|
+
# {
|
|
1365
|
+
# "enabled": false,
|
|
1366
|
+
# "incoming": {
|
|
1367
|
+
# "type": "INTERCEPT_ALL",
|
|
1368
|
+
# "voicemailEnabled": false,
|
|
1369
|
+
# "announcements": {
|
|
1370
|
+
# "greeting": "DEFAULT",
|
|
1371
|
+
# "fileName": "",
|
|
1372
|
+
# "newNumber": {"enabled": false, "destination": ""},
|
|
1373
|
+
# "zeroTransfer": {"enabled": false, "destination": ""}
|
|
1374
|
+
# }
|
|
1375
|
+
# },
|
|
1376
|
+
# "outgoing": {
|
|
1377
|
+
# "type": "INTERCEPT_ALL",
|
|
1378
|
+
# "transferEnabled": false,
|
|
1379
|
+
# "destination": ""
|
|
1380
|
+
# }
|
|
1381
|
+
# }
|
|
1382
|
+
```
|
|
1383
|
+
|
|
1384
|
+
#### Configure Call Intercept Settings
|
|
1385
|
+
|
|
1386
|
+
```
|
|
1387
|
+
PUT https://webexapis.com/v1/people/{personId}/features/intercept
|
|
1388
|
+
```
|
|
1389
|
+
|
|
1390
|
+
```python
|
|
1391
|
+
body = {
|
|
1392
|
+
"enabled": True,
|
|
1393
|
+
"incoming": {
|
|
1394
|
+
"type": "INTERCEPT_ALL",
|
|
1395
|
+
"voicemailEnabled": True,
|
|
1396
|
+
"announcements": {
|
|
1397
|
+
"greeting": "DEFAULT",
|
|
1398
|
+
"newNumber": {"enabled": False},
|
|
1399
|
+
"zeroTransfer": {"enabled": False}
|
|
1400
|
+
}
|
|
1401
|
+
},
|
|
1402
|
+
"outgoing": {
|
|
1403
|
+
"type": "INTERCEPT_ALL",
|
|
1404
|
+
"transferEnabled": False
|
|
1405
|
+
}
|
|
1406
|
+
}
|
|
1407
|
+
api.session.rest_put(f"{BASE}/people/{person_id}/features/intercept", json=body)
|
|
1408
|
+
```
|
|
1409
|
+
|
|
1410
|
+
#### Upload Custom Intercept Greeting
|
|
1411
|
+
|
|
1412
|
+
```
|
|
1413
|
+
POST https://webexapis.com/v1/people/{personId}/features/intercept/actions/announcementUpload/invoke
|
|
1414
|
+
```
|
|
1415
|
+
|
|
1416
|
+
Multipart/form-data with `.wav` file. Uses `rest_post` with file upload.
|
|
1417
|
+
|
|
1418
|
+
**Gotchas:**
|
|
1419
|
+
- `incoming.announcements.fileName` is read-only; do not include in PUT body.
|
|
1420
|
+
- `incoming.type` values: `"INTERCEPT_ALL"`, `"ALLOW_ALL"`.
|
|
1421
|
+
- `outgoing.type` values: `"INTERCEPT_ALL"`, `"ALLOW_LOCAL_ONLY"`.
|
|
1422
|
+
- The JSON key for intercept type is `type` (not `interceptType`), matching the SDK's JSON alias.
|
|
1423
|
+
|
|
1424
|
+
---
|
|
1425
|
+
|
|
1426
|
+
## 9. Monitoring
|
|
1427
|
+
|
|
1428
|
+
**API class:** `MonitoringApi`
|
|
1429
|
+
**Feature key:** `monitoring`
|
|
1430
|
+
**Source:** `wxc_sdk/person_settings/monitoring.py`
|
|
1431
|
+
|
|
1432
|
+
Shows specified people, places, virtual lines, or call park extensions that are being monitored. Monitors line status (on-call, parked).
|
|
1433
|
+
|
|
1434
|
+
### Data Models
|
|
1435
|
+
|
|
1436
|
+
#### `MonitoredElementMember` (extends `MonitoredMember`)
|
|
1437
|
+
|
|
1438
|
+
| Field | Type | Description |
|
|
1439
|
+
|-------|------|-------------|
|
|
1440
|
+
| (inherited fields) | | From `MonitoredMember` (member_id, first_name, last_name, etc.) |
|
|
1441
|
+
| `location_id` | `str` | The location ID for this monitored member |
|
|
1442
|
+
|
|
1443
|
+
Has a property `ci_location_id` that converts `location_id` to UUID format.
|
|
1444
|
+
|
|
1445
|
+
#### `MonitoredElement`
|
|
1446
|
+
|
|
1447
|
+
| Field | Type | Description |
|
|
1448
|
+
|-------|------|-------------|
|
|
1449
|
+
| `member` | `MonitoredElementMember` | Monitored person or place |
|
|
1450
|
+
| `cpe` | `CallParkExtension` | Monitored call park extension (JSON alias: `callparkextension`) |
|
|
1451
|
+
|
|
1452
|
+
#### `Monitoring`
|
|
1453
|
+
|
|
1454
|
+
| Field | Type | Description |
|
|
1455
|
+
|-------|------|-------------|
|
|
1456
|
+
| `call_park_notification_enabled` | `bool` | Enable/disable call park notifications |
|
|
1457
|
+
| `monitored_elements` | `list[Union[str, MonitoredElement]]` | Monitored elements (max 50). For updates, can pass IDs (strings) directly. |
|
|
1458
|
+
|
|
1459
|
+
**Convenience properties:**
|
|
1460
|
+
- `monitored_cpes` -> `list[CallParkExtension]` -- filters to just call park extensions
|
|
1461
|
+
- `monitored_members` -> `list[MonitoredElementMember]` -- filters to just members
|
|
1462
|
+
|
|
1463
|
+
### Methods
|
|
1464
|
+
|
|
1465
|
+
#### `read`
|
|
1466
|
+
|
|
1467
|
+
```python
|
|
1468
|
+
MonitoringApi.read(entity_id: str, org_id: str = None) -> Monitoring
|
|
1469
|
+
```
|
|
1470
|
+
|
|
1471
|
+
- **Scopes:** `spark-admin:people_read`
|
|
1472
|
+
|
|
1473
|
+
#### `configure`
|
|
1474
|
+
|
|
1475
|
+
```python
|
|
1476
|
+
MonitoringApi.configure(entity_id: str, settings: Monitoring, org_id: str = None)
|
|
1477
|
+
```
|
|
1478
|
+
|
|
1479
|
+
- **Scopes:** `spark-admin:people_write`
|
|
1480
|
+
- **Max 50 elements.** The SDK extracts IDs from `MonitoredElement` objects (using `member.member_id` or `cpe.cpe_id`) or passes strings directly.
|
|
1481
|
+
- Body format:
|
|
1482
|
+
```json
|
|
1483
|
+
{
|
|
1484
|
+
"enableCallParkNotification": true,
|
|
1485
|
+
"monitoredElements": ["id1", "id2", ...]
|
|
1486
|
+
}
|
|
1487
|
+
```
|
|
1488
|
+
|
|
1489
|
+
### CLI Examples
|
|
1490
|
+
|
|
1491
|
+
```bash
|
|
1492
|
+
# Read monitoring settings for a person
|
|
1493
|
+
wxcli user-settings list-monitoring PERSON_ID
|
|
1494
|
+
|
|
1495
|
+
# Read monitoring settings as JSON
|
|
1496
|
+
wxcli user-settings list-monitoring PERSON_ID -o json
|
|
1497
|
+
|
|
1498
|
+
# Enable call park notification
|
|
1499
|
+
wxcli user-settings update-monitoring PERSON_ID --enable-call-park-notification
|
|
1500
|
+
|
|
1501
|
+
# Disable call park notification
|
|
1502
|
+
wxcli user-settings update-monitoring PERSON_ID --no-enable-call-park-notification
|
|
1503
|
+
|
|
1504
|
+
# Update monitored elements list (requires --json-body for element IDs)
|
|
1505
|
+
wxcli user-settings update-monitoring PERSON_ID --json-body '{
|
|
1506
|
+
"enableCallParkNotification": true,
|
|
1507
|
+
"monitoredElements": ["PERSON_ID_1", "PERSON_ID_2", "CPE_ID_1"]
|
|
1508
|
+
}'
|
|
1509
|
+
```
|
|
1510
|
+
|
|
1511
|
+
### Raw HTTP
|
|
1512
|
+
|
|
1513
|
+
#### Read Monitoring Settings
|
|
1514
|
+
|
|
1515
|
+
```
|
|
1516
|
+
GET https://webexapis.com/v1/people/{personId}/features/monitoring
|
|
1517
|
+
```
|
|
1518
|
+
|
|
1519
|
+
```python
|
|
1520
|
+
result = api.session.rest_get(f"{BASE}/people/{person_id}/features/monitoring")
|
|
1521
|
+
# Response:
|
|
1522
|
+
# {
|
|
1523
|
+
# "enableCallParkNotification": true,
|
|
1524
|
+
# "monitoredElements": [
|
|
1525
|
+
# {
|
|
1526
|
+
# "member": {
|
|
1527
|
+
# "id": "person-id", "firstName": "Jane", "lastName": "Doe",
|
|
1528
|
+
# "phoneNumber": "+12223334444", "extension": "1234",
|
|
1529
|
+
# "locationId": "location-id"
|
|
1530
|
+
# }
|
|
1531
|
+
# },
|
|
1532
|
+
# {
|
|
1533
|
+
# "callparkextension": {
|
|
1534
|
+
# "id": "cpe-id", "name": "CPE 1001", "extension": "1001"
|
|
1535
|
+
# }
|
|
1536
|
+
# }
|
|
1537
|
+
# ]
|
|
1538
|
+
# }
|
|
1539
|
+
```
|
|
1540
|
+
|
|
1541
|
+
#### Configure Monitoring Settings
|
|
1542
|
+
|
|
1543
|
+
```
|
|
1544
|
+
PUT https://webexapis.com/v1/people/{personId}/features/monitoring
|
|
1545
|
+
```
|
|
1546
|
+
|
|
1547
|
+
```python
|
|
1548
|
+
body = {
|
|
1549
|
+
"enableCallParkNotification": True,
|
|
1550
|
+
"monitoredElements": ["person-id-1", "person-id-2", "cpe-id-1"]
|
|
1551
|
+
}
|
|
1552
|
+
api.session.rest_put(f"{BASE}/people/{person_id}/features/monitoring", json=body)
|
|
1553
|
+
```
|
|
1554
|
+
|
|
1555
|
+
**Gotchas:**
|
|
1556
|
+
- Maximum 50 monitored elements.
|
|
1557
|
+
- For updates, pass a flat list of IDs (person, place, or call park extension IDs). Reads return full objects with nested `member` or `callparkextension` details.
|
|
1558
|
+
- The JSON key for call park extensions is `callparkextension` (lowercase, no hyphen).
|
|
1559
|
+
|
|
1560
|
+
---
|
|
1561
|
+
|
|
1562
|
+
## 10. Push-to-Talk
|
|
1563
|
+
|
|
1564
|
+
**API class:** `PushToTalkApi`
|
|
1565
|
+
**Feature key:** `pushToTalk`
|
|
1566
|
+
**Source:** `wxc_sdk/person_settings/push_to_talk.py`
|
|
1567
|
+
|
|
1568
|
+
Allows desk phones to function as one-way or two-way intercoms connecting people in different parts of the organization.
|
|
1569
|
+
|
|
1570
|
+
### Data Models
|
|
1571
|
+
|
|
1572
|
+
#### `PTTConnectionType` (Enum)
|
|
1573
|
+
|
|
1574
|
+
| Value | Description |
|
|
1575
|
+
|-------|-------------|
|
|
1576
|
+
| `ONE_WAY` | Initiators can chat but the target cannot respond |
|
|
1577
|
+
| `TWO_WAY` | Both parties can communicate |
|
|
1578
|
+
|
|
1579
|
+
#### `PushToTalkAccessType` (Enum)
|
|
1580
|
+
|
|
1581
|
+
| Value | Description |
|
|
1582
|
+
|-------|-------------|
|
|
1583
|
+
| `ALLOW_MEMBERS` | List of people allowed to use PTT with this person |
|
|
1584
|
+
| `BLOCK_MEMBERS` | List of people blocked from using PTT with this person |
|
|
1585
|
+
|
|
1586
|
+
#### `PushToTalkSettings`
|
|
1587
|
+
|
|
1588
|
+
| Field | Type | Description |
|
|
1589
|
+
|-------|------|-------------|
|
|
1590
|
+
| `allow_auto_answer` | `bool` | When enabled, person receives and auto-answers PTT calls |
|
|
1591
|
+
| `connection_type` | `PTTConnectionType` | One-way or two-way |
|
|
1592
|
+
| `access_type` | `PushToTalkAccessType` | Allow-list or block-list mode |
|
|
1593
|
+
| `members` | `list[Union[str, MonitoredMember]]` | People allowed or blocked. For updates, can pass member IDs (strings) directly. |
|
|
1594
|
+
|
|
1595
|
+
### Methods
|
|
1596
|
+
|
|
1597
|
+
#### `read`
|
|
1598
|
+
|
|
1599
|
+
```python
|
|
1600
|
+
PushToTalkApi.read(entity_id: str, org_id: str = None) -> PushToTalkSettings
|
|
1601
|
+
```
|
|
1602
|
+
|
|
1603
|
+
- **Scopes:** `spark-admin:people_read`
|
|
1604
|
+
|
|
1605
|
+
#### `configure`
|
|
1606
|
+
|
|
1607
|
+
```python
|
|
1608
|
+
PushToTalkApi.configure(entity_id: str, settings: PushToTalkSettings, org_id: str = None)
|
|
1609
|
+
```
|
|
1610
|
+
|
|
1611
|
+
- **Scopes:** `spark-admin:people_write`
|
|
1612
|
+
- Members are flattened to a list of IDs before sending (extracted from `MonitoredMember.member_id` or passed as strings).
|
|
1613
|
+
- Serializes with `exclude_none=False` and `exclude_unset=True`, so explicitly set `None` values are preserved in the request.
|
|
1614
|
+
|
|
1615
|
+
### CLI Examples
|
|
1616
|
+
|
|
1617
|
+
```bash
|
|
1618
|
+
# Read push-to-talk settings for a person
|
|
1619
|
+
wxcli user-settings list-push-to-talk PERSON_ID
|
|
1620
|
+
|
|
1621
|
+
# Read push-to-talk settings as JSON
|
|
1622
|
+
wxcli user-settings list-push-to-talk PERSON_ID -o json
|
|
1623
|
+
|
|
1624
|
+
# Enable push-to-talk with auto-answer
|
|
1625
|
+
wxcli user-settings update-push-to-talk PERSON_ID --allow-auto-answer
|
|
1626
|
+
|
|
1627
|
+
# Disable push-to-talk auto-answer
|
|
1628
|
+
wxcli user-settings update-push-to-talk PERSON_ID --no-allow-auto-answer
|
|
1629
|
+
|
|
1630
|
+
# Full push-to-talk config with connection type and members (requires --json-body)
|
|
1631
|
+
wxcli user-settings update-push-to-talk PERSON_ID --json-body '{
|
|
1632
|
+
"allowAutoAnswer": true,
|
|
1633
|
+
"connectionType": "TWO_WAY",
|
|
1634
|
+
"accessType": "ALLOW_MEMBERS",
|
|
1635
|
+
"members": ["PERSON_ID_1", "PERSON_ID_2"]
|
|
1636
|
+
}'
|
|
1637
|
+
```
|
|
1638
|
+
|
|
1639
|
+
### Raw HTTP
|
|
1640
|
+
|
|
1641
|
+
#### Read Push-to-Talk Settings
|
|
1642
|
+
|
|
1643
|
+
```
|
|
1644
|
+
GET https://webexapis.com/v1/people/{personId}/features/pushToTalk
|
|
1645
|
+
```
|
|
1646
|
+
|
|
1647
|
+
```python
|
|
1648
|
+
result = api.session.rest_get(f"{BASE}/people/{person_id}/features/pushToTalk")
|
|
1649
|
+
# Response:
|
|
1650
|
+
# {
|
|
1651
|
+
# "allowAutoAnswer": true,
|
|
1652
|
+
# "connectionType": "TWO_WAY",
|
|
1653
|
+
# "accessType": "ALLOW_MEMBERS",
|
|
1654
|
+
# "members": [
|
|
1655
|
+
# {"id": "person-id", "firstName": "Jane", "lastName": "Doe", ...}
|
|
1656
|
+
# ]
|
|
1657
|
+
# }
|
|
1658
|
+
```
|
|
1659
|
+
|
|
1660
|
+
#### Configure Push-to-Talk Settings
|
|
1661
|
+
|
|
1662
|
+
```
|
|
1663
|
+
PUT https://webexapis.com/v1/people/{personId}/features/pushToTalk
|
|
1664
|
+
```
|
|
1665
|
+
|
|
1666
|
+
```python
|
|
1667
|
+
body = {
|
|
1668
|
+
"allowAutoAnswer": True,
|
|
1669
|
+
"connectionType": "TWO_WAY",
|
|
1670
|
+
"accessType": "ALLOW_MEMBERS",
|
|
1671
|
+
"members": ["person-id-1", "person-id-2"]
|
|
1672
|
+
}
|
|
1673
|
+
api.session.rest_put(f"{BASE}/people/{person_id}/features/pushToTalk", json=body)
|
|
1674
|
+
```
|
|
1675
|
+
|
|
1676
|
+
**Gotchas:**
|
|
1677
|
+
- `members` accepts a flat list of person IDs for updates, even though reads return full member objects.
|
|
1678
|
+
- `connectionType` values: `"ONE_WAY"`, `"TWO_WAY"`.
|
|
1679
|
+
- `accessType` values: `"ALLOW_MEMBERS"`, `"BLOCK_MEMBERS"`.
|
|
1680
|
+
|
|
1681
|
+
---
|
|
1682
|
+
|
|
1683
|
+
## 11. Music on Hold
|
|
1684
|
+
|
|
1685
|
+
**API class:** `MusicOnHoldApi`
|
|
1686
|
+
**Feature key:** `musicOnHold`
|
|
1687
|
+
**Source:** `wxc_sdk/person_settings/moh.py`
|
|
1688
|
+
|
|
1689
|
+
Music played when a caller is put on hold or the call is parked.
|
|
1690
|
+
|
|
1691
|
+
### Data Model
|
|
1692
|
+
|
|
1693
|
+
#### `MusicOnHold`
|
|
1694
|
+
|
|
1695
|
+
| Field | Type | Description |
|
|
1696
|
+
|-------|------|-------------|
|
|
1697
|
+
| `moh_enabled` | `bool` | Music on hold enabled/disabled for the entity |
|
|
1698
|
+
| `moh_location_enabled` | `bool` | Read-only. Whether MoH is enabled at the location level. Excluded from updates. |
|
|
1699
|
+
| `greeting` | `Greeting` | `DEFAULT` or `CUSTOM` |
|
|
1700
|
+
| `audio_announcement_file` | `AnnAudioFile` | Custom audio file details (when greeting is `CUSTOM`) |
|
|
1701
|
+
|
|
1702
|
+
**Important interaction between `moh_location_enabled` and `moh_enabled`:**
|
|
1703
|
+
|
|
1704
|
+
| `moh_location_enabled` | `moh_enabled` | Result |
|
|
1705
|
+
|------------------------|---------------|--------|
|
|
1706
|
+
| `false` | `true` | MoH is **disabled** for user |
|
|
1707
|
+
| `true` | `false` | MoH is **off** for user |
|
|
1708
|
+
| `true` | `true` | MoH plays for user |
|
|
1709
|
+
|
|
1710
|
+
### Methods
|
|
1711
|
+
|
|
1712
|
+
#### `read`
|
|
1713
|
+
|
|
1714
|
+
```python
|
|
1715
|
+
MusicOnHoldApi.read(entity_id: str, org_id: str = None) -> MusicOnHold
|
|
1716
|
+
```
|
|
1717
|
+
|
|
1718
|
+
- **Scopes:** `spark-admin:telephony_config_read`
|
|
1719
|
+
|
|
1720
|
+
#### `configure`
|
|
1721
|
+
|
|
1722
|
+
```python
|
|
1723
|
+
MusicOnHoldApi.configure(entity_id: str, settings: MusicOnHold, org_id: str = None)
|
|
1724
|
+
```
|
|
1725
|
+
|
|
1726
|
+
- **Scopes:** `spark-admin:telephony_config_write`
|
|
1727
|
+
- **Prerequisite:** Music on hold must be enabled at the location level for the person-level setting to take effect.
|
|
1728
|
+
|
|
1729
|
+
### CLI Examples
|
|
1730
|
+
|
|
1731
|
+
```bash
|
|
1732
|
+
# Read music on hold settings for a person
|
|
1733
|
+
wxcli user-settings show-music-on-hold PERSON_ID
|
|
1734
|
+
|
|
1735
|
+
# Read music on hold settings as JSON
|
|
1736
|
+
wxcli user-settings show-music-on-hold PERSON_ID -o json
|
|
1737
|
+
|
|
1738
|
+
# Enable music on hold with default greeting
|
|
1739
|
+
wxcli user-settings update-music-on-hold PERSON_ID --moh-enabled --greeting DEFAULT
|
|
1740
|
+
|
|
1741
|
+
# Enable music on hold with custom greeting
|
|
1742
|
+
wxcli user-settings update-music-on-hold PERSON_ID --moh-enabled --greeting CUSTOM
|
|
1743
|
+
|
|
1744
|
+
# Disable music on hold
|
|
1745
|
+
wxcli user-settings update-music-on-hold PERSON_ID --no-moh-enabled
|
|
1746
|
+
|
|
1747
|
+
# Full music on hold config with audio file reference (requires --json-body)
|
|
1748
|
+
wxcli user-settings update-music-on-hold PERSON_ID --json-body '{
|
|
1749
|
+
"mohEnabled": true,
|
|
1750
|
+
"greeting": "CUSTOM",
|
|
1751
|
+
"audioAnnouncementFile": {"id": "ANNOUNCEMENT_FILE_ID"}
|
|
1752
|
+
}'
|
|
1753
|
+
```
|
|
1754
|
+
|
|
1755
|
+
### Raw HTTP
|
|
1756
|
+
|
|
1757
|
+
> **Note:** Music on Hold uses the `telephony/config/people` path, not `people/{id}/features`.
|
|
1758
|
+
|
|
1759
|
+
#### Read Music on Hold Settings
|
|
1760
|
+
|
|
1761
|
+
```
|
|
1762
|
+
GET https://webexapis.com/v1/telephony/config/people/{personId}/musicOnHold
|
|
1763
|
+
```
|
|
1764
|
+
|
|
1765
|
+
```python
|
|
1766
|
+
result = api.session.rest_get(f"{BASE}/telephony/config/people/{person_id}/musicOnHold")
|
|
1767
|
+
# Response:
|
|
1768
|
+
# {
|
|
1769
|
+
# "mohEnabled": true,
|
|
1770
|
+
# "mohLocationEnabled": true,
|
|
1771
|
+
# "greeting": "DEFAULT",
|
|
1772
|
+
# "audioAnnouncementFile": {...}
|
|
1773
|
+
# }
|
|
1774
|
+
```
|
|
1775
|
+
|
|
1776
|
+
#### Configure Music on Hold Settings
|
|
1777
|
+
|
|
1778
|
+
```
|
|
1779
|
+
PUT https://webexapis.com/v1/telephony/config/people/{personId}/musicOnHold
|
|
1780
|
+
```
|
|
1781
|
+
|
|
1782
|
+
```python
|
|
1783
|
+
body = {
|
|
1784
|
+
"mohEnabled": True,
|
|
1785
|
+
"greeting": "DEFAULT",
|
|
1786
|
+
"audioAnnouncementFile": {"id": "announcement-file-id"}
|
|
1787
|
+
}
|
|
1788
|
+
api.session.rest_put(f"{BASE}/telephony/config/people/{person_id}/musicOnHold", json=body)
|
|
1789
|
+
```
|
|
1790
|
+
|
|
1791
|
+
**Gotchas:**
|
|
1792
|
+
- `mohLocationEnabled` is read-only; do not include in PUT body.
|
|
1793
|
+
- Person-level MoH only works if MoH is also enabled at the location level (`mohLocationEnabled` must be `true`).
|
|
1794
|
+
- Uses `spark-admin:telephony_config_read`/`write` scopes (not `people_read`/`write`).
|
|
1795
|
+
|
|
1796
|
+
---
|
|
1797
|
+
|
|
1798
|
+
## 12. Common Patterns
|
|
1799
|
+
|
|
1800
|
+
### URL Construction
|
|
1801
|
+
|
|
1802
|
+
All APIs in this group use `PersonSettingsApiChild.f_ep()` to build endpoints. The pattern depends on the entity type:
|
|
1803
|
+
|
|
1804
|
+
| Entity Type | URL Pattern |
|
|
1805
|
+
|-------------|-------------|
|
|
1806
|
+
| Person | `people/{entity_id}/features/{feature}` |
|
|
1807
|
+
| Workspace | `workspaces/{entity_id}/features/{feature}` |
|
|
1808
|
+
| Virtual Line | `telephony/config/virtualLines/{entity_id}/{feature}` |
|
|
1809
|
+
| Location | `telephony/config/locations/{entity_id}/{feature}` |
|
|
1810
|
+
|
|
1811
|
+
Some features have alternate URL mappings (defined in `common.py`). Notable remaps for persons:
|
|
1812
|
+
|
|
1813
|
+
- `agent` -> `telephony/config/people/{id}/agent/...`
|
|
1814
|
+
- `musicOnHold` -> `telephony/config/people/{id}/musicOnHold`
|
|
1815
|
+
- `voicemail` passcode -> `telephony/config/people/{id}/voicemail/passcode`
|
|
1816
|
+
|
|
1817
|
+
### Read/Update Pattern
|
|
1818
|
+
|
|
1819
|
+
Every sub-API follows the same pattern:
|
|
1820
|
+
|
|
1821
|
+
1. `read(entity_id, org_id=None)` -- GET request, returns a data model
|
|
1822
|
+
2. `configure(entity_id, settings, org_id=None)` -- PUT request with JSON body
|
|
1823
|
+
3. Some APIs have additional action methods (greeting uploads, PIN resets)
|
|
1824
|
+
|
|
1825
|
+
### Scopes Summary
|
|
1826
|
+
|
|
1827
|
+
| Operation | Typical Admin Scope | Typical Self Scope |
|
|
1828
|
+
|-----------|--------------------|--------------------|
|
|
1829
|
+
| Read settings | `spark-admin:people_read` | `spark:people_read` |
|
|
1830
|
+
| Update settings | `spark-admin:people_write` | `spark:people_write` |
|
|
1831
|
+
| Telephony config read | `spark-admin:telephony_config_read` | -- |
|
|
1832
|
+
| Telephony config write | `spark-admin:telephony_config_write` | -- |
|
|
1833
|
+
|
|
1834
|
+
APIs using `telephony_config_*` scopes: Agent Caller ID, Music on Hold, Voicemail passcode.
|
|
1835
|
+
|
|
1836
|
+
### Greeting/Audio Upload Pattern
|
|
1837
|
+
|
|
1838
|
+
Three APIs support custom audio upload (all `.wav` format, multipart/form-data):
|
|
1839
|
+
|
|
1840
|
+
| API | Method | Endpoint Suffix |
|
|
1841
|
+
|-----|--------|----------------|
|
|
1842
|
+
| Voicemail | `configure_busy_greeting()` | `actions/uploadBusyGreeting/invoke` |
|
|
1843
|
+
| Voicemail | `configure_no_answer_greeting()` | `actions/uploadNoAnswerGreeting/invoke` |
|
|
1844
|
+
| Call Intercept | `greeting()` | `actions/announcementUpload/invoke` |
|
|
1845
|
+
|
|
1846
|
+
All accept either a file path (str) or `BufferedReader`. When passing a reader, `upload_as` (a `.wav` filename) is required.
|
|
1847
|
+
|
|
1848
|
+
### Update Exclusions (Read-Only Fields)
|
|
1849
|
+
|
|
1850
|
+
Each model's `update()` method strips fields that cannot be written:
|
|
1851
|
+
|
|
1852
|
+
| Model | Excluded Fields |
|
|
1853
|
+
|-------|----------------|
|
|
1854
|
+
| `VoicemailSettings` | `greeting_uploaded`, `system_max_number_of_rings`, `voice_message_forwarding_enabled` |
|
|
1855
|
+
| `CallerId` | `caller_id_types` (not in `fields_for_update`) |
|
|
1856
|
+
| `CallRecordingSetting` | `service_provider`, `external_group`, `external_identifier` |
|
|
1857
|
+
| `InterceptSetting` | `incoming.announcements.file_name` |
|
|
1858
|
+
| `MusicOnHold` | `moh_location_enabled` |
|
|
1859
|
+
|
|
1860
|
+
### Entity Applicability
|
|
1861
|
+
|
|
1862
|
+
Not all settings apply equally to all entity types:
|
|
1863
|
+
|
|
1864
|
+
| Setting | Person | Workspace | Virtual Line |
|
|
1865
|
+
|---------|--------|-----------|-------------|
|
|
1866
|
+
| Voicemail | Yes | Yes | Yes |
|
|
1867
|
+
| Caller ID | Yes | Yes | Yes |
|
|
1868
|
+
| Agent Caller ID | Yes | -- | Yes |
|
|
1869
|
+
| Anonymous Call Rejection | No (admin `/people/{id}` endpoint does not exist; self via `/me` only) | Yes (Professional-licensed workspaces only) | -- |
|
|
1870
|
+
| Privacy | Yes | Yes | Yes |
|
|
1871
|
+
| Barge-In | Yes | Yes | Yes |
|
|
1872
|
+
| Call Recording | Yes | Yes | Yes |
|
|
1873
|
+
| Call Intercept | Yes | Yes | Yes |
|
|
1874
|
+
| Monitoring | Yes | Yes | -- |
|
|
1875
|
+
| Push-to-Talk | Yes | Yes | Yes |
|
|
1876
|
+
| Music on Hold | Yes | Yes | Yes |
|
|
1877
|
+
|
|
1878
|
+
---
|
|
1879
|
+
|
|
1880
|
+
## Gotchas (Cross-Cutting)
|
|
1881
|
+
|
|
1882
|
+
- **Read-only fields cause silent failures.** Every PUT endpoint in this group has read-only fields that must be excluded from the request body. If you include them, the API may return 400 or silently ignore the entire request. Key offenders: `greetingUploaded`, `systemMaxNumberOfRings`, `voiceMessageForwardingEnabled` (voicemail); `types`, `locationExternalCallerIdName` (caller ID); `serviceProvider`, `externalGroup`, `externalIdentifier` (call recording); `fileName` (call intercept); `mohLocationEnabled` (music on hold).
|
|
1883
|
+
- **Nested settings require `--json-body`.** The wxcli generator skips deeply nested object/array body fields. For voicemail (sendBusyCalls, sendUnansweredCalls, notifications, etc.), call intercept (incoming/outgoing), call recording (notification, repeat, startStopAnnouncement), monitoring (monitoredElements), push-to-talk (members), and privacy (monitoringAgents), use `--json-body` with the full JSON payload.
|
|
1884
|
+
- **Three different URL path patterns.** Most features use `people/{id}/features/{feature}`, but Agent Caller ID uses `telephony/config/people/{id}/agent/...`, Music on Hold uses `telephony/config/people/{id}/musicOnHold`, and Voicemail Passcode uses `telephony/config/people/{id}/voicemail/passcode`. The corresponding scopes differ too (`telephony_config_*` vs `people_*`).
|
|
1885
|
+
- **Scope mismatch between read and write.** Agent Caller ID uses `people_read` for listing available IDs but `telephony_config_read` for reading the current selection. Always check the specific scope required per method.
|
|
1886
|
+
- **Music on Hold depends on location-level setting.** Even if `mohEnabled` is `true` for a person, MoH will not play unless `mohLocationEnabled` is also `true` at the location level. The person-level API cannot change the location-level setting.
|
|
1887
|
+
- **`notification.type` null serialization.** Call Recording's `notification.type` returns the string `"None"` on reads but expects JSON `null` on writes. In wxcli, pass `"type": null` in `--json-body`.
|
|
1888
|
+
- **Anonymous Call Rejection has NO admin-level person endpoint.** Live API testing confirms that `GET /v1/people/{personId}/features/anonymousCallReject` and `GET /v1/telephony/config/people/{personId}/anonymousCallReject` both return 404. The only working paths are: (1) workspace admin: `/telephony/config/workspaces/{workspaceId}/anonymousCallReject` (requires Professional-licensed workspace, error 25409 otherwise), and (2) self-service: `/telephony/config/people/me/settings/anonymousCallReject` (requires calling-licensed user token with `spark:telephony_config_read/write`). The wxcli CLI only exposes it under `workspace-settings`, not `user-settings`.
|
|
1889
|
+
- **Monitoring has a 50-element maximum.** The `monitoredElements` list accepts at most 50 entries (persons, places, virtual lines, and call park extensions combined). The API does not surface this limit in error messages clearly.
|
|
1890
|
+
- **Members lists return objects but accept IDs.** Privacy (`monitoringAgents`), Monitoring (`monitoredElements`), and Push-to-Talk (`members`) all return full member objects on reads but accept flat lists of ID strings on writes.
|
|
1891
|
+
|
|
1892
|
+
---
|
|
1893
|
+
|
|
1894
|
+
## See Also
|
|
1895
|
+
|
|
1896
|
+
- **[Location Call Settings — Core](location-calling-core.md)** — Location-level voicemail policies (transcription toggle), org-wide voicemail settings (expiry, forwarding), and location-level call intercept that govern person-level defaults
|
|
1897
|
+
- **[Location Recording — Advanced](location-recording-advanced.md)** — Location/org-level call recording vendor settings that must be configured before per-person recording works
|
|
1898
|
+
- **[self-service-call-settings.md](self-service-call-settings.md)** -- User-level `/people/me/` endpoints for self-service call settings, including 6 user-only settings with no admin path.
|