| name | audit-compliance |
| description | Pull and analyze Webex audit logs, security events, and compliance data.
Covers admin audit trail, security audit events, authorization review,
service app credential management, and data sources (the JWT-authenticated
endpoints service apps register to receive streamed Webex data).
Guides from query design through export.
NOT for: org health assessment (use org-health skill), CDR/call analytics (use reporting skill),
or license auditing (use manage-licensing skill).
|
| allowed-tools | Read, Grep, Glob, Bash |
| argument-hint | ["audit-type -- e.g. \"admin audit\"","security events","compliance review","authorization check"] |
Audit & Compliance Workflow
Checkpoint — do NOT proceed until you can answer these:
- What date parameter format do audit event APIs require? (Answer: ISO 8601 format with timezone — e.g.,
2026-03-01T00:00:00.000Z. Queries without timezone may return unexpected results.)
- What is the difference between admin audit events and security audit events? (Answer: Admin audit tracks configuration changes by admins. Security audit tracks login events, token grants, and authorization changes.)
If you cannot answer both, you skipped reading this skill. Go back and read it.
Step 1: Load references
- Read
docs/reference/admin-audit-security.md for audit event APIs, security audit scopes, event categories, and date parameter conventions
- For data source operations (Step 6f) only, read
docs/reference/admin-apps-data.md § "Data Source Registration Flow" — skip this unless the user asks about data sources or streaming Webex data to a service app
Mandatory --help verification: Before constructing any wxcli command, run wxcli <group> --help to verify the subcommand exists, then wxcli <group> <subcommand> --help to verify the exact flags (e.g. wxcli audit-events list --help and wxcli security-audit --help — date/range parameter names are spec-generated, not guessable). Do NOT rely on examples in this skill or reference docs — the CLI is auto-generated and flag names may differ from what documentation suggests.
Step 2: Verify auth token
Before any API calls, confirm the user has a working auth token:
wxcli whoami
If this fails, stop and resolve authentication first (wxcli configure).
Required scopes by audit type
| Audit Type | CLI Group | Scope | Date Params | Notes |
|---|
| Admin audit events | audit-events | Standard admin token | --from / --to | Full or read-only admin. No special scope beyond admin auth. |
| Security audit events | security-audit | audit:events_read | --start-time / --end-time | Specifically required. Standard admin token without this scope returns 401/403. |
| Platform events (compliance) | events | Standard admin token | --from / --to | Full or read-only admin. Compliance officer role also works. |
| Authorizations review | authorizations | Standard admin token | N/A | Lists OAuth grants for users and the org. Full admin required for delete. |
| Service app tokens | service-apps | Admin + service app credentials | N/A | Requires client-id, client-secret, and target-org-id. |
| Data sources | data-sources | spark-admin:datasource_read / _write | N/A | A full-admin PAT is not enough — see the gotcha in Step 6f. list-schemas works without the scope; list returns 403. |
Verification gate
Run a quick probe for the audit type the user needs. If it fails, stop and fix auth before proceeding.
wxcli audit-events list-event-categories -o json
wxcli security-audit list \
--start-time "2026-03-18T00:00:00.000Z" \
--end-time "2026-03-19T00:00:00.000Z" \
--limit 1 \
-o json
wxcli events list \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
--limit 1 \
-o json
wxcli authorizations show -o json
If the probe returns 401/403, the token lacks the required scope. Resolve before continuing.
Step 3: Identify the operation
Ask the user what they want to investigate. Present this decision matrix if they are unsure:
| Need | Operation | CLI Group |
|---|
| Who changed what in Control Hub | Admin audit events | audit-events |
| Security incidents (failed logins, policy changes) | Security audit events | security-audit |
| Compliance review (messages, calls, meetings) | Platform events | events |
| Review OAuth grants and integrations | Authorization audit | authorizations |
| Create/rotate service app credentials | Service app token | service-apps |
| List available audit event categories | Category reference | audit-events |
| Register/inspect where Webex streams data to a service app | Data source management | data-sources |
Step 4: Check prerequisites
4a. Confirm date range and filters
All audit queries require scoping. Confirm with the user:
- Date range — What period to cover? Use ISO 8601 format (
2026-03-18T00:00:00.000Z).
- Filters — Any specific actor (admin/user), event category, resource type, or event type?
- Date parameter names —
audit-events and events use --from/--to. security-audit uses --start-time/--end-time. Mixing them produces errors.
4b. Resolve actor IDs if filtering by person
If the user wants to filter by a specific admin or user, resolve their person ID first:
wxcli people list --email "admin@company.com" -o json
For event category filtering on admin audit, discover available categories:
wxcli audit-events list-event-categories -o json
This returns the exact category names (treat as case-sensitive — always use exact values from this list).
Step 5: Build and present deployment plan -- [SHOW BEFORE EXECUTING]
Present the query plan to the user for approval before executing. Include:
- Which API —
audit-events, security-audit, events, authorizations, or service-apps
- Date range — Start and end dates, using the correct parameter names for the chosen API
- Filters — Actor ID, event category, resource type, event type (if any)
- Output format and destination — Screen display, file export, or pipe to analysis
- Destructive operations — Flag any delete/revoke operations and require explicit confirmation
Example plan format:
Audit Query Plan:
API: wxcli security-audit list
Date range: 2026-03-12 to 2026-03-19 (--start-time / --end-time)
Filters: --event-categories "Logins"
Output: JSON to screen
Destructive: No
Do not proceed to Step 6 until the user approves the plan.
Step 6: Execute via wxcli
Execute the approved query plan. Jump to the sub-step matching the audit type identified in Step 3.
6a. Admin audit events (audit-events)
Use wxcli audit-events to see who changed what in Control Hub. Every admin action is logged: user created, setting changed, license assigned, location modified, policy updated.
List audit events with a date range:
wxcli audit-events list \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
Filter by admin (actor):
wxcli audit-events list \
--actor-id "Y2lzY29zcGFyazovL3VzL1BFT1BMRS8xMjM0" \
--from "2026-03-01T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
Filter by event category:
wxcli audit-events list \
--event-categories "Users" \
--from "2026-03-01T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
Limit results for a quick check:
wxcli audit-events list \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
--limit 50 \
-o json
6b. Security audit events (security-audit)
Use wxcli security-audit for security-related events: login failures, suspicious activity, security policy changes, authentication anomalies. This is the API to use when investigating security incidents or feeding events into an external SIEM.
List security events for a date range:
wxcli security-audit list \
--start-time "2026-03-12T00:00:00.000Z" \
--end-time "2026-03-19T00:00:00.000Z" \
-o json
Note: security-audit uses --start-time/--end-time, NOT --from/--to like the other audit APIs.
Filter by actor:
wxcli security-audit list \
--actor-id "Y2lzY29zcGFyazovL3VzL1BFT1BMRS8xMjM0" \
--start-time "2026-03-01T00:00:00.000Z" \
--end-time "2026-03-19T00:00:00.000Z" \
-o json
Filter by event category:
wxcli security-audit list \
--event-categories "Logins" \
--start-time "2026-03-18T00:00:00.000Z" \
--end-time "2026-03-19T00:00:00.000Z" \
-o json
Export for SIEM ingestion:
wxcli security-audit list \
--start-time "2026-03-12T00:00:00.000Z" \
--end-time "2026-03-19T00:00:00.000Z" \
-o json > security_events_export.json
wxcli security-audit list \
--start-time "2026-03-18T00:00:00.000Z" \
--end-time "2026-03-19T00:00:00.000Z" \
-o json >> siem_feed.json
6c. Platform events — compliance (events)
Use wxcli events for general Webex platform activity: messages created/deleted, calls placed, meetings held, memberships changed. This is the API for compliance reviews, eDiscovery, and building integrations that react to platform activity.
List events with a date range:
wxcli events list \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
Filter by resource type:
wxcli events list \
--service-type calling \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
wxcli events list \
--resource messages \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
Filter by event type:
wxcli events list \
--type deleted \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
wxcli events list \
--resource messages \
--type created \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
Compliance review for a specific user:
wxcli people list --email "user@company.com" -o json
wxcli events list \
--actor-id "Y2lzY29zcGFyazovL3VzL1BFT1BMRS8xMjM0" \
--from "2026-03-01T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json
wxcli events show "Y2lzY29zcGFyazovL3VzL0VWRU5ULzU2Nzg5"
Event resource types reference:
| Resource | Description |
|---|
messages | Messages sent/deleted in rooms |
memberships | Room membership changes |
rooms | Room creation/updates |
telephony_calls | Webex Calling call events |
meetings | Meeting events |
recordings | Recording events |
meetingMessages | In-meeting chat messages |
Event types reference:
| Type | Description |
|---|
created | Resource was created |
updated | Resource was updated |
deleted | Resource was deleted |
ended | Resource ended (calls, meetings) |
6d. Authorization audit (authorizations)
Use wxcli authorizations to review OAuth grants and integrations authorized in the org. This reveals which third-party apps and integrations have access to user or org data.
List authorizations for a user:
wxcli authorizations list --person-email "user@company.com" -o json
wxcli authorizations list --person-id "Y2lzY29zcGFyazovL3VzL1BFT1BMRS8xMjM0" -o json
Check token expiration status:
wxcli authorizations show -o json
Revoke an OAuth authorization by client ID:
This is destructive -- it revokes access for an integration across the org. Always confirm with the user before executing.
wxcli authorizations delete --client-id "C1234567890abcdef" --force
Delete a specific authorization by ID:
This is destructive -- it removes a specific authorization. Always confirm with the user before executing.
wxcli authorizations delete-authorizations "Y2lzY29zcGFyazovL3VzL0FVVEhPUklaQVRJT04vMTIz" --force
6e. Service app credential management (service-apps)
Use wxcli service-apps to create access tokens for service applications. Service apps are non-interactive integrations that act on behalf of an org.
Create a service app access token:
wxcli service-apps create APPLICATION_ID \
--client-id "C1234567890abcdef" \
--client-secret "secret_value_here" \
--target-org-id "Y2lzY29zcGFyazovL3VzL09SR0FOSVpBVElPTi8xMjM0"
The returned token is short-lived. Store it immediately -- the secret is only shown once at creation time.
6f. Data sources (data-sources)
Use wxcli data-sources to manage where Webex pushes data to a service app. This is the outbound counterpart to the pull-based audit APIs above: instead of you querying events, you register an endpoint and Webex streams data to it, authenticated with a JWT that Webex mints from the parameters you supply.
A data source is always tied to a schema, which fixes the data type and transport. Discover schemas before registering anything — do not assume a schema exists for the data you want.
Discover the schemas this org supports:
wxcli data-sources list-schemas
wxcli data-sources show "523e1b7f-4693-47bc-b84e-a7b7a505fb0b"
Verified against a live org, the returned schemas were audio_forking_schema (gRPC), VoiceVirtualAgent_WebSocket (web-socket), and VA_service_schema (gRPC) — all appType: serviceApp. These are real-time media/AI streaming schemas, not audit or compliance event feeds. If the user wants message, call, or admin event history, this is the wrong API — use events, audit-events, or security-audit (Steps 6a-6c).
Read registered data sources:
wxcli data-sources list
wxcli data-sources show-data-sources "DATA_SOURCE_ID"
Register a data source (write — show the plan first):
wxcli data-sources create \
--schema-id "SCHEMA_ID_FROM_LIST_SCHEMAS" \
--url "https://your-endpoint.example.com/webex-data" \
--audience "your-service-app-name" \
--subject "data-source-purpose" \
--nonce "UNIQUE_NONCE_VALUE" \
--token-lifetime-minutes "1440"
Maintain and remove:
wxcli data-sources update "DATA_SOURCE_ID" \
--status "disabled" \
--error-message "Paused for maintenance window"
wxcli data-sources update "DATA_SOURCE_ID" --status "active"
wxcli data-sources delete "DATA_SOURCE_ID" --force
Scope gotcha (verified live): data-sources list returns 403 "missing required scopes" even with a full-admin personal access token, while data-sources list-schemas succeeds with the same token. The data source APIs require spark-admin:datasource_read / spark-admin:datasource_write, which PATs do not carry. If you hit this 403, do not retry or assume the org has no data sources — the token is the problem. Use a service app or an OAuth integration with those scopes explicitly selected.
Step 7: Verify
After executing the query, verify the results are correct and complete.
Quick verification checks
- Non-empty results — If the query returned empty, check: date range too narrow? Wrong filter values? Misspelled
--resource type (returns empty, not error)?
- Expected scope — Do results cover the expected time period and event types?
- Actor correlation — If filtering by actor, confirm the returned events match the expected admin/user.
Spot-check a specific record
wxcli events show "EVENT_ID_FROM_RESULTS"
wxcli audit-events list \
--from "2026-03-18T12:00:00.000Z" \
--to "2026-03-18T13:00:00.000Z" \
--limit 5 \
-o json
Step 8: Report results
After retrieving and verifying audit data, analyze and present the results.
Summarize admin changes by category
wxcli audit-events list \
--from "2026-03-01T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json | python3.11 -c "
import json, sys
from collections import Counter
data = json.load(sys.stdin)
if isinstance(data, dict):
data = data.get('items', [data])
categories = Counter(e.get('eventCategory', 'Unknown') for e in data)
for cat, count in categories.most_common():
print(f'{cat}: {count} events')
"
Identify most active admins
wxcli audit-events list \
--from "2026-03-01T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json | python3.11 -c "
import json, sys
from collections import Counter
data = json.load(sys.stdin)
if isinstance(data, dict):
data = data.get('items', [data])
actors = Counter(e.get('actorEmail', e.get('actorId', 'Unknown')) for e in data)
for actor, count in actors.most_common(10):
print(f'{actor}: {count} actions')
"
Count events by resource type
wxcli events list \
--from "2026-03-18T00:00:00.000Z" \
--to "2026-03-19T00:00:00.000Z" \
-o json | python3.11 -c "
import json, sys
from collections import Counter
data = json.load(sys.stdin)
if isinstance(data, dict):
data = data.get('items', [data])
resources = Counter(e.get('resource', 'Unknown') for e in data)
for res, count in resources.most_common():
print(f'{res}: {count} events')
"
List all OAuth integrations for a user
wxcli authorizations list --person-email "user@company.com" -o json | python3.11 -c "
import json, sys
data = json.load(sys.stdin)
if isinstance(data, dict):
data = data.get('items', [data])
for auth in data:
print(f\"App: {auth.get('applicationName', 'Unknown')} | Client: {auth.get('clientId', 'N/A')} | Scope: {auth.get('scope', 'N/A')}\")
"
Critical Rules
audit-events and security-audit are different APIs with different scopes. audit-events = admin changes in Control Hub, works with standard admin token. security-audit = security/login events, requires audit:events_read scope. Do not confuse them.
security-audit requires audit:events_read scope specifically. A standard admin token without this scope returns 401 or 403. If you get a scope error on security-audit list, the token needs the audit:events_read scope added.
- Date range filtering is essential. Without date parameters, you get the full event stream, which can be enormous and slow. Always specify a date range.
- Date parameter names differ across APIs.
audit-events and events use --from/--to. security-audit uses --start-time/--end-time. Mixing them up produces errors. See Step 2 scopes table for the mapping.
- Events API covers all platform events, not just calling. Filter by
--resource and --type to narrow results. Use --service-type calling to scope to Webex Calling events only.
authorizations delete revokes access -- this is destructive. It removes an OAuth grant by client ID across the org. Always confirm with the user before executing. delete-authorizations removes a specific authorization by ID.
- Service app token creation returns a short-lived token. Store it immediately. The credentials (
client-secret) are only shown once at creation time and cannot be retrieved later.
- Always show the query plan before executing (Step 5). Present which API, date range, filters, and output format to the user for confirmation before running queries.
- ISO 8601 datetime format required. All date parameters expect ISO 8601 format:
2026-03-18T00:00:00.000Z. Other formats return errors or unexpected results.
- Event categories — treat as case-sensitive. Always run
wxcli audit-events list-event-categories first (Step 4b) to discover the exact category names before filtering. Use exact values from the list output.
events list resource types are not validated client-side. Misspelled --resource values return empty result sets, not errors. Use the known resource types listed in Step 6c.
data-sources needs its own scopes -- a full-admin PAT gets 403. spark-admin:datasource_read/_write are not carried by personal access tokens. list-schemas works without them, so a passing list-schemas does NOT mean list will work. Do not read a 403 here as "the org has no data sources."
data-sources show and show-data-sources take different IDs. show SCHEMA_ID returns a schema definition. show-data-sources DATA_SOURCE_ID returns a registered data source. Passing the wrong ID type to either one fails.
- Data sources push data out; they are not an audit query API. They stream real-time media/AI payloads (audio forking, voice virtual agent) to a service app endpoint. For event history use
events, audit-events, or security-audit instead.
Scope Quick Reference
| Scope | Grants Access To |
|---|
| Standard admin token | Admin audit events (wxcli audit-events), platform events (wxcli events), authorizations (wxcli authorizations) |
audit:events_read | Security audit events (wxcli security-audit) |
| Compliance officer role | Platform events with compliance-level access (wxcli events) |
spark-admin:datasource_read | List and retrieve data sources (wxcli data-sources list, show-data-sources) |
spark-admin:datasource_write | Register, update, delete data sources (wxcli data-sources create, update, delete) |
Error Handling
| Error | Cause | Fix |
|---|
401/403 on security-audit list | Token missing audit:events_read scope | Regenerate token with audit:events_read scope or use a service app with that scope |
Empty results from events list | Wrong --resource value or no events in date range | Check resource type spelling against Step 6c resource types table; widen the date range |
403 on authorizations list | Insufficient admin privileges | Requires full admin, not read-only |
Empty results from audit-events list | Date range too narrow or no admin activity | Widen the date range; verify org has admin activity in that period |
| 400 on date parameters | Wrong date format or wrong parameter names for the API | Use ISO 8601 (2026-03-18T00:00:00.000Z); check Step 2 table for which date params the API expects |
403 on data-sources list (but list-schemas works) | PAT does not carry spark-admin:datasource_read | Use a service app or OAuth integration with the datasource scopes selected — see Step 6f |
404 / ID error on data-sources show | Passed a data source ID to the schema command | show takes a SCHEMA_ID; use show-data-sources DATA_SOURCE_ID for a registered source |
Context Compaction Recovery
If context compacts mid-execution, recover by:
- Read
docs/reference/admin-audit-security.md to recover API details, scopes, and date parameter conventions
- Check what data has already been retrieved by reviewing recent command output
- Resume from the first incomplete step