Security and operations
Fleet security operations, threat tracking and patches, checksum failures, site audits, activity logs, reports, archives, recipes, providers and settings.
These are the fleet-wide operational routes. Almost all of them are administrator only, gated either by captaincore_admin_permission_check or by an inline current_user_can( 'manage_options' ) closure. Where a route is available to any logged-in user, the entry says so.
Security operations are built on content hashes. During each sync the CLI records a hash for every plugin, theme, must-use plugin and loose file it finds, so one audit of a build covers every site running that exact code.
Security threats
Threats are components in the fleet with known findings. Tracking rows are stored in captaincore_security_threat_tracking, keyed uniquely on slug, version and type.
| Method | Path | Parameters |
|---|---|---|
| GET | /security-threats |
Fleet threat summary |
| GET | /security-threats/affected-sites |
slug, version, type, all required |
| POST | /security-threats/track |
slug, version, type, status |
| POST | /security-threats/note |
slug, version, type, note |
| POST | /security-threats/resolve |
slug, version, type, optional note |
status must be one of new, investigating, reported or resolved. Anything else returns 400 invalid_status. An empty note returns 400 empty_note.
Resolving a threat also writes process log entries onto the affected sites, so the work shows up on each site’s timeline.
curl -u user:app-password \
"https://your-manager.example.com/wp-json/captaincore/v1/security-threats/affected-sites?slug=some-plugin&version=1.2.3&type=plugin"
Security patches
Patches are rebuilt packages that fix a vulnerable build. Rows live in captaincore_security_patch.
| Method | Path | Notes |
|---|---|---|
| POST | /security-patches |
Register. slug, version, patched_version and download_url are required; type defaults to plugin; title, description and severity optional |
| GET | /security-patches |
Every registered patch |
| DELETE | /security-patches/{id} |
Remove one |
| GET | /security-patches/manifest |
Full manifest keyed type|slug|version, with a generated timestamp, for the Cloudflare worker to cache |
| POST | /security-patches/check |
Public. Body takes a components array; returns the patches that apply |
Missing required fields on register return 400 missing_fields. POST /security-patches/check with no array returns 400 missing_components.
Checksums and component inventory
| Method | Path | Notes |
|---|---|---|
| GET | /checksum-failures |
Active environments whose WordPress core checksums failed |
| GET | /plugin-checksum-failures |
The same, for plugins |
| POST | /plugin-diff-preview |
site_slug, plugin_slug, environment. Calls the CLI server directly so HTTP errors surface rather than returning an empty diff |
| GET | /component-hashes |
Distinct hashes for a slug and version; type defaults to plugin |
| GET | /component-sites |
Live environments running a component, by slug, type and optional hash |
| GET | /component-queue |
Un-audited hashes, ranked. limit defaults to 30, plus group_by and model |
| GET | /security-coverage |
Fleet coverage metrics: unique hashes versus audited hashes, for plugins, themes and files |
| GET | /fleet-site-counts |
Map of slug|type to site count |
| GET | /fleet-severity-counts |
Fleet-active components grouped by worst finding severity |
| GET | /update-queue |
The cached update-before-audit queue. not_built is true until wp captaincore update-queue first runs |
| POST | /update-queue/run |
Dispatch a fleet update for one component. slug, type, target. Returns a job token |
| GET | /web-risk-logs |
Google Web Risk run history from captaincore_web_risk_logs |
| POST | /malware-alert |
Send a malware alert email. site_name required |
GET /update-queue never builds inline. The heavy pass, a fleet walk plus wordpress.org lookups, runs from WP-CLI on a schedule so web requests stay fast.
Session monitoring
The CLI collects a daily snapshot of admin accounts, active sessions and injected capabilities per environment. Anomalies are detected against the previous snapshot.
| Method | Path | Notes |
|---|---|---|
| GET | /sites/{site_id}/{environment}/session-snapshots |
Newest first, limit up to 365, default 90. Payloads are decoded |
| GET | /session-anomalies |
Fleet feed of snapshots that fired anomalies. severity defaults to high, limit up to 500, default 100. Full payloads are omitted to keep it light |
Both are administrator only, because the payloads contain administrator IP addresses.
Site audits
Audits are stored reports with findings, covering security, malware, performance, accessibility, debug and incident work. They live in captaincore_site_audits with child rows in captaincore_site_audit_findings.
| Method | Path | Permission |
|---|---|---|
| GET | /site-audits |
Logged in, scoped |
| GET | /sites/{site_id}/site-audits |
Logged in, scoped |
| GET | /site-audits/{id} |
Logged in, scoped |
| GET | /site-audits/{id}/html |
Logged in, scoped |
| POST | /site-audits/request |
Logged in. site_id and environment_id required; report_type defaults to security_audit; notes optional |
| POST | /site-audits/{id}/cancel |
Logged in |
| POST, DELETE | /site-audits/{id}/publish |
Logged in, publishes or withdraws static HTML |
| POST | /site-audits |
Administrator, create directly |
| PUT, DELETE | /site-audits/{id} |
Administrator |
| POST | /site-audits/{id}/findings |
Administrator |
| PUT, DELETE | /site-audits/{id}/findings/{finding_id} |
Administrator |
Coverage for a specific environment is available to any user who can see the site:
GET /sites/{site_id}/environments/{environment_id}/audit-coverage
GET /sites/{site_id}/environments/{environment_id}/audit-coverage/{hash}
Requesting and cancelling an audit both write activity log rows (requested_audit and cancelled_audit).
Fleet core updates
Probe and apply runs are stored as a parent row plus per-site results, so failures can be grouped by error class.
| Method | Path | Notes |
|---|---|---|
| GET | /core-update-runs |
Run history |
| GET | /core-update-runs/{id} |
One run |
| GET | /core-update-runs/{id}/results |
Per-site rows |
| GET | /core-update-runs/{id}/groups |
Results grouped by failure shape |
| PUT | /core-update-results/{result_id} |
Triage one result, for example marking it handled |
Activity logs
GET /activity-logs
Available to any logged-in user, scoped to your accounts. Administrators see everything.
| Parameter | Default | Description |
|---|---|---|
page |
1 |
Page number |
per_page |
50 |
Page size, capped at 200 |
action |
Exact action name | |
entity_type |
site, domain, dns_record, account, email_forward, environment, file |
|
user_id |
Actor | |
account_id |
Single account, must be one of yours | |
date_from, date_to |
Inclusive YYYY-MM-DD |
The response is { items, total, page, pages }. See Activity log for the full action list.
Process logs
Process logs are the timeline notes attached to sites.
| Method | Path | Permission |
|---|---|---|
| GET | /process-logs |
Administrator, whole fleet |
| POST | /process-logs |
Logged in. site_ids required and each is permission checked; process_id optional; description is Markdown; files carries diffs |
| GET | /process-logs/{id} |
Logged in |
| POST | /process-logs/{id} |
Owner or administrator, and the site ids in the route are the ones authorized |
| DELETE | /process-logs/{id} |
Owner or administrator |
| GET, POST | /processes, /processes/{id} |
Administrator, the handbook processes these notes reference |
| GET | /processes/{id}/raw |
Administrator |
Reports
| Method | Path | Permission |
|---|---|---|
| POST | /report/preview |
Logged in. site_ids must all be yours; start_date and end_date optional |
| POST | /report/send |
Logged in, plus recipient |
| POST | /report/default-recipient |
Logged in |
| POST | /account-report/preview, /send, /default-recipient |
Administrator |
| GET, POST | /scheduled-reports |
Logged in |
| PUT, DELETE | /scheduled-reports/{id} |
Logged in |
A scheduled report takes either site_ids or account_id, a recipient, and an interval of monthly (default), quarterly or yearly. Rows land in captaincore_scheduled_reports and are sent by wp captaincore scheduled-reports.
Archives
Archives are stored zip files on remote object storage, listed and shared through the CLI. All three routes check manage_options inside the callback as well as at the permission layer.
| Method | Path | Notes |
|---|---|---|
| GET | /archive |
List, returned straight from Rclone |
| POST | /archive/store |
url must be a valid URL ending in .zip, otherwise 400 |
| POST | /archive/share |
file must match ^[A-Za-z0-9._/-]+$, otherwise 400 invalid_file |
Recipes and scripts
| Method | Path | Notes |
|---|---|---|
| GET | /recipes/ |
Recipes you can see |
| POST | /recipes |
title and content required. public is administrator only; non-admins always get 0 |
| PUT | /recipes/{recipe_id} |
Update your own, or any as administrator |
| DELETE | /recipes/{id} |
Same ownership rule |
| POST | /scripts/schedule |
Schedule code, see Running commands and jobs |
| POST, DELETE | /scripts/{id} |
Update or cancel |
Providers
Provider rows hold the credentials for hosting and registrar integrations, in captaincore_providers.
| Method | Path | Notes |
|---|---|---|
| GET | /providers |
Providers you own, plus the shared house rows |
| POST | /providers |
Create. provider.name and provider.provider required; provider.credentials is an array of {name, value} |
| PUT | /providers/{id} |
Ownership checked. Only name, credentials and provider are writable, never user_id |
| DELETE | /providers/{id} |
Ownership checked |
| GET | /providers/{id}/verify |
Test the credentials |
| POST | /providers/{id}/connect |
Connect and read remote state |
| GET | /providers/{id}/remote-sites |
Sites at the provider |
| POST | /providers/{id}/import |
Import remote sites into CaptainCore |
| POST | /providers/{provider}/new-site |
Provision a new site |
| POST | /providers/{provider}/deploy-to-staging, /deploy-to-production |
Environment deploys |
| GET | /providers/{provider}/themes, /plugins |
Envato purchases |
| GET | /providers/{provider}/theme/{id}/download, /plugin/{id}/download |
Signed download links |
| GET | /provider-actions, /provider-actions/check, /provider-actions/{id}/run |
The queued provisioning chain |
See Integrations for what each provider needs.
Settings
There is no single /settings route. Configuration is split across four endpoints.
| Method | Path | Notes |
|---|---|---|
| GET | /configurations/ |
Branding, portal, pricing and scheduled-task configuration. Logged in |
| POST | /configurations/ |
Update (administrator) |
| PUT | /configurations/global |
Update the global set (administrator) |
| GET | /defaults/ |
Global site defaults (administrator) |
| PUT | /defaults/global |
Update them (administrator) |
| GET | /keys/ |
SSH keys (administrator) |
| POST | /keys |
Add one |
| PUT | /keys/{id} |
Update |
| PUT | /keys/{id}/primary |
Mark primary |
| DELETE | /keys/{id} |
Remove |
| GET | /configs |
Raw config dump (administrator) |
| GET | /site-lookup |
Resolve a domain to its SSH connection and environment (administrator) |
Configuration is stored in the captaincore_configurations site option and pushed to the CLI server on every update, so the CLI and the Manager stay in step.