Sites and environments
Read and manage sites, their production and staging environments, files, domains, admin tools, stats, performance samples and logs.
A site in CaptainCore is a row in captaincore_sites plus one or more rows in captaincore_environments, typically Production and Staging. Almost everything on this page is scoped to the accounts you belong to.
Remember the casing rule: path segments want lowercase production or staging, while POST /sites/cli and the settings routes want capitalized Production, Staging or Both.
Sites
| Method | Path | Notes |
|---|---|---|
| GET | /sites |
Every site you can access, sorted by name |
| GET | /sites/{site_id} or /sites/{slug} |
Full site object |
| GET | /sites/{site_id}/details |
Site plus account, linked domains and shares |
| POST | /sites/fetch |
Several sites at once, post_ids array or post_id |
| POST | /sites |
Create a site (administrator) |
| POST | /sites/{site_id} |
Patch site details |
| DELETE | /sites/{site_id} |
Mark inactive |
| PUT | /sites/update |
Bulk update (administrator) |
| PUT | /sites/{site_id}/identity |
Change name and slug (administrator) |
| PUT | /sites/{site_id}/accounts |
Reassign accounts (administrator) |
| POST | /sites/{site_id}/remote-sync |
Re-read connection details from the provider (administrator) |
GET /sites returns lightweight listing records. Auth tokens, the raw details blob and status are stripped.
curl -u user:app-password https://your-manager.example.com/wp-json/captaincore/v1/sites
[
{
"site_id": 135,
"account_id": 12,
"customer_id": 12,
"name": "example.com",
"site": "example",
"provider": "kinsta",
"core": "6.9.1",
"home_url": "https://example.com",
"storage": 123456789,
"visits": 15000,
"removed": false,
"environments": [
{ "environment_id": 3365, "environment": "Production", "home_url": "https://example.com", "core": "6.9.1" }
]
}
]
GET /sites/{site_id} accepts either the numeric id or the slug, and the same handler serves both. It is heavier than /details, which is what the site overview screen actually loads.
Creating a site takes a site object with name, site, account_id, provider and at least a Production entry in environments. Optional keys include customer_id, provider_id, provider_site_id and shared_with.
POST /sites/{site_id} merges the keys you send into the stored site details. Non-administrators may only write details.removed: sending true emails a removal request and logs it, false cancels it.
Environments
| Method | Path | Notes |
|---|---|---|
| GET | /sites/{site_id}/environments |
Environments on one site |
| GET | /environments |
Every environment you can reach, source_environment_id excludes one |
| POST | /sites/{site_id}/environments |
Add an environment (administrator) |
| POST | /sites/{site_id}/environments/connect |
Link an existing remote staging environment (administrator) |
| PUT, DELETE | /sites/{site_id}/environments/{environment_id} |
Edit or remove connection settings (administrator) |
| PUT | /sites/{site_id}/settings |
Managed-update settings |
| POST | /sites/{site_id}/{environment}/monitor |
Uptime monitor, monitor is 1 or 0 |
| POST | /sites/{site_id}/{environment}/captures |
Capture pages and optional basic auth |
| POST | /sites/{site_id}/backup |
Backup schedule, settings.active, interval, mode |
| GET | /sites/{site_id}/{environment}/sync/data |
Trigger a data sync |
| GET | /sites/{site_id}/{environment}/captures/new |
Trigger fresh captures |
| GET | /sites/{site_id}/environments/{environment_id}/push-targets |
Where this environment can be pushed |
| POST | /sites/environments/push |
Push one environment onto another |
PUT /sites/{site_id}/settings takes environment (the database name, so Production or Staging) and a value object with updates_enabled, plus optional updates_exclude_themes and updates_exclude_plugins arrays of slugs.
curl -X POST -u user:app-password \
-H "Content-Type: application/json" \
-d '{"source_environment_id": 3365, "target_environment_id": 3366}' \
https://your-manager.example.com/wp-json/captaincore/v1/sites/environments/push
Files
| Method | Path | Notes |
|---|---|---|
| GET | /environment/{environment_id}/files |
path relative to home, default the home root; action is list (default) or view |
| DELETE | /environment/{environment_id}/files |
path required, query or body |
Both viewing and deleting a file are recorded in the activity log with the path and environment.
curl -u user:app-password \
"https://your-manager.example.com/wp-json/captaincore/v1/environment/3365/files?path=wp-content&action=list"
Site domains
These are hostnames attached to a hosting environment at the provider, not registrar records. For registrar and DNS work see Domains, DNS and accounts.
| Method | Path | Notes |
|---|---|---|
| GET | /sites/{site_id}/{environment}/domains |
List hostnames on the environment |
| POST | /sites/{site_id}/{environment}/domains |
Add one, domain_name required, is_wildcardless optional |
| DELETE | /sites/{site_id}/{environment}/domains |
domain_ids array of provider domain ids |
| PUT | /sites/{site_id}/{environment}/domains/primary |
domain_id, plus run_search_and_replace (defaults true) |
| POST | /sites/{site_id}/{environment}/domains/verify |
Ask the provider to verify |
| POST | /providers/kinsta/check-verification |
Poll Kinsta verification state |
Admin tools
| Method | Path | Notes |
|---|---|---|
| GET | /sites/{site_id}/{environment}/magiclogin |
One-time admin login link |
| GET | /sites/{site_id}/{environment}/magiclogin/{wp_user_id} |
Login as a specific WordPress user |
| GET | /sites/{site_id}/{environment}/phpmyadmin |
phpMyAdmin access, provider dependent |
| GET | /sites/{site_id}/users |
Cached WordPress users |
| GET | /sites/{site_id}/timeline |
Site timeline, process log notes and events |
| GET | /sites/{site_id}/usage-breakdown |
Storage and visit breakdown |
| GET | /sites/{site_id}/update-logs |
Update history for this site |
| POST | /sites/{site_id}/invite |
Invite someone to the site’s customer account |
| GET | /sites/{site_id}/invite-preview |
Preview that invite |
| POST | /sites/{site_id}/grant-access |
Grant an existing user access |
curl -u user:app-password \
https://your-manager.example.com/wp-json/captaincore/v1/sites/135/production/magiclogin
Stats
Site analytics come from Fathom. The integration needs a fathom provider row with an api_key credential.
| Method | Path | Key parameters |
|---|---|---|
| GET | /sites/{site_id}/stats |
from_at, to_at, grouping (hour, day, month, year), environment, fathom_id |
| GET | /sites/{site_id}/stats/top-pages |
from_at, to_at, environment, limit (default 10) |
| GET | /sites/{site_id}/stats/top-referrers |
Same shape as top pages |
| POST | /sites/{site_id}/stats/share |
fathom_id, sharing (none, private, public), share_password |
| POST | /site/{site_id}/analytics |
Legacy analytics fetch |
| PUT | /sites/{site_id}/fathom |
Set the tracker id (administrator) |
curl -u user:app-password \
"https://your-manager.example.com/wp-json/captaincore/v1/sites/135/stats?from_at=2026-08-01&to_at=2026-08-31&grouping=day"
Performance
| Method | Path | Notes |
|---|---|---|
| POST | /sites/{site_id}/{environment}/performance-monitor |
enabled true or false |
| GET | /sites/{site_id}/{environment}/performance-monitor |
hours lookback (omit or 0 for everything), format=raw for the sample series |
curl -u user:app-password \
"https://your-manager.example.com/wp-json/captaincore/v1/sites/135/production/performance-monitor?hours=24&format=raw"
Logs
Live logs are read over SSH. Archived logs come from the provider’s rotation, and are on the older singular /site/ prefix.
| Method | Path | Notes |
|---|---|---|
| GET | /sites/{site_id}/{environment}/logs |
List available log files |
| POST | /sites/{site_id}/{environment}/logs/fetch |
file from the list, restricted to A-Z a-z 0-9 . _ / -; limit lines, default 1000 |
| GET | /site/{site_id}/{environment}/logs-archive |
List archived logs |
| GET | /site/{site_id}/{environment}/logs-archive/download |
file must match ^(access|error)\.log-\d{4}-\d{2}-\d{2}-\d+(\.gz)?$ |
| GET | /site/{site_id}/{environment}/logs-archive/view |
Same file pattern, plus lines between 1 and 5000, default 1000 |
curl -X POST -u user:app-password \
-H "Content-Type: application/json" \
-d '{"file":"error.log","limit":200}' \
https://your-manager.example.com/wp-json/captaincore/v1/sites/135/production/logs/fetch
Backups, snapshots and captures
| Method | Path | Notes |
|---|---|---|
| GET | /site/{site_id}/{environment}/backups |
Restic snapshot list |
| GET | /sites/{site_id}/{environment}/backups/{backup_id} |
One backup, with a file query (base64url path) to preview a file |
| GET | /site/{site_id}/snapshots |
Downloadable snapshots |
| GET | /sites/{site_id}/snapshot-link/{snapshot_id} |
Signed download link |
| GET | /site/{site_id}/snapshots/{snapshot_id}-{token}/{name} |
Public, token protected download |
| GET | /site/{site_id}/{environment}/captures |
Visual capture history |
Quicksaves, the daily git history of themes, plugins and core, live on their own routes: /quicksaves, /quicksaves/search, /quicksaves/{hash}, /quicksaves/{hash}/changed, /quicksaves/{hash}/filediff, /quicksaves/{hash}/rollback and /quicksaves/{hash}/sandbox-token. They are served straight from the CLI rather than a Manager table.
Filters
Filters answer “which of my sites run this plugin or theme”.
| Method | Path | Notes |
|---|---|---|
| POST | /filters/sites |
Filter by component, version, status and core |
| GET | /site-filters |
Available filter options |
| GET | /filters/{name}/versions/ |
Versions seen for a slug |
| GET | /filters/{name}/statuses/ |
Statuses seen for a slug |
| GET | /wp-plugins, /wp-themes |
Search the wordpress.org directories |
The full route list, including the administrator-only variants, is in the Endpoint index.