Base URL: https://{your-site}/wp-json/captaincore/v1
CaptainCore uses WordPress application passwords for API authentication. Generate one from your Profile > API Access section, then authenticate with HTTP Basic Auth:
curl -u username:application-password https://{your-site}/wp-json/captaincore/v1/sitesNon-admin users are automatically scoped to their own accounts and sites.
The /run/code endpoint lets you execute WP-CLI commands on one or more sites. There are two modes depending on how long the command takes.
For commands that complete in under 5 minutes, send a request and get the result back directly:
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{
"code": "wp option get home",
"environments": [{"site_id": 135, "environment": "production"}]
}' \
https://{your-site}/wp-json/captaincore/v1/run/codeResponse:
{"status": "completed", "response": "https://example.com"}For commands that may take longer (backups, migrations, bulk operations), add "async": true to start the job immediately and get a token back for polling:
1. Start the job:
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{
"code": "wp plugin update --all",
"environments": [{"site_id": 135, "environment": "production"}],
"async": true
}' \
https://{your-site}/wp-json/captaincore/v1/run/codeResponse:
{"status": "queued", "token": "nwaBFBISZEsT..."}2. Poll for the result:
curl -u user:pass \
https://{your-site}/wp-json/captaincore/v1/my-jobs/{token}While running:
{"status": "started", "token": "nwaBFBISZEsT..."}When finished:
{"status": "completed", "response": "...command output...", "token": "nwaBFBISZEsT..."}The async parameter also works with /sites/cli and /sites/bulk-tools.
GET /me
Returns your profile details including name, email, role, and TFA status.
curl -u user:pass https://{your-site}/wp-json/captaincore/v1/mePUT /me/profile
| Field | Type | Description |
|---|---|---|
first_name |
string | First name |
last_name |
string | Last name |
email |
string | Email address |
new_password |
string | New password (optional) |
POST /me/pins
POST /me/application-password # Generate new
POST /me/application-password/rotate # Rotate existing
DELETE /me/application-password # Delete existing
GET /me/tfa_activate # Begin TFA setup (returns QR URI)
POST /me/tfa_validate # Verify TFA code to activate
GET /me/tfa_deactivate # Disable TFA
POST /me/email-subscriber
| Field | Type | Description |
|---|---|---|
enabled |
boolean | Subscribe/unsubscribe from blog post emails |
GET /me/api-docs
Returns the API documentation content.
GET /sites
Returns all sites visible to the authenticated user.
curl -u user:pass https://{your-site}/wp-json/captaincore/v1/sitesGET /sites/{site_id}
curl -u user:pass https://{your-site}/wp-json/captaincore/v1/sites/47POST /sites
POST /sites/{site_id}
DELETE /sites/{site_id}
GET /sites/{site_id}/details
POST /sites/fetch
| Field | Type | Description |
|---|---|---|
post_ids |
array | Array of site IDs |
POST /sites/bulk-tools
Run a bulk tool across multiple environments.
| Field | Type | Required | Description |
|---|---|---|---|
tool |
string | Yes | Tool to run (sync-data, deploy-defaults, activate, deactivate, apply-https, launch, scan-errors, backup, snapshot) |
environments |
array | Yes | Array of environment IDs |
params |
object | No | Extra parameters (varies by tool) |
async |
boolean | No | If true, returns immediately with a job token for polling via /my-jobs/{token} |
Async response:
{"status": "queued", "token": "abc123..."}Poll for results with GET /my-jobs/{token}.
PUT /sites/update
GET /sites/{site_id}/environments
PUT /sites/{site_id}/settings
POST /sites/{site_id}/{environment}/monitor
POST /sites/{site_id}/{environment}/captures
POST /sites/{site_id}/backup
GET /sites/{site_id}/{environment}/sync/data
GET /sites/{site_id}/{environment}/captures/new
GET /sites/{site_id}/environments/{env_id}/push-targets
POST /sites/environments/push
| Field | Type | Description |
|---|---|---|
source_environment_id |
integer | Source environment ID |
target_environment_id |
integer | Target environment ID |
GET /sites/{site_id}/{environment}/domains
POST /sites/{site_id}/{environment}/domains
DELETE /sites/{site_id}/{environment}/domains
PUT /sites/{site_id}/{environment}/domains/primary
GET /sites/{site_id}/{environment}/magiclogin
GET /sites/{site_id}/{environment}/magiclogin/{wp_user_id}
GET /sites/{site_id}/{environment}/phpmyadmin
GET /sites/{site_id}/users
GET /sites/{site_id}/stats
Returns Fathom analytics for a site including visits, pageviews, bounce rate, and average duration.
| Parameter | Type | Required | Description |
|---|---|---|---|
from_at |
string | Yes | Start date (e.g. 2026-01-01) |
to_at |
string | Yes | End date (e.g. 2026-01-31) |
grouping |
string | No | Group results by day, month, or year |
environment |
string | No | Production or Staging |
fathom_id |
string | No | Override the Fathom site ID |
curl -u user:pass \
"https://{your-site}/wp-json/captaincore/v1/sites/84/stats?from_at=2026-01-01&to_at=2026-01-31&grouping=day&environment=Production"POST /sites/{site_id}/stats/share
GET /sites/{site_id}/timeline
GET /sites/{site_id}/usage-breakdown
POST /site/{site_id}/analytics
PUT /sites/{site_id}/fathom
PUT /sites/{site_id}/mailgun
GET /sites/{site_id}/{environment}/logs
POST /sites/{site_id}/{environment}/logs/fetch
See the Update Logs section for the primary update log endpoints (GET /update-logs and GET /update-logs/{hash_before}_{hash_after}).
GET /site/{site_id}/{environment}/backups
GET /sites/{site_id}/{environment}/backups/{backup_id}
GET /site/{site_id}/snapshots
GET /sites/{site_id}/snapshot-link/{snapshot_id}
GET /site/{site_id}/snapshots/{snapshot_id}-{token}/{snapshot_name}
GET /site/{site_id}/{environment}/captures
GET /sites/{site_id}/invite-preview
POST /sites/{site_id}/invite
POST /sites/{site_id}/grant-access
GET /domains
curl -u user:pass https://{your-site}/wp-json/captaincore/v1/domainsGET /domain/{domain_id}
POST /domains
DELETE /domains/{domain_id}
PUT /domains/{domain_id}/account
GET /domain/{domain_id}/lock_{status} # Lock/unlock (status: on/off)
GET /domain/{domain_id}/privacy_{status} # Privacy on/off
GET /domain/{domain_id}/auth_code # Get transfer auth code
POST /domain/{domain_id}/contacts # Update WHOIS contacts
POST /domain/{domain_id}/nameservers # Update nameservers
POST /domain/{domain_id}/update-site-link
| Field | Type | Description |
|---|---|---|
site_id |
integer | Site ID to link domain to |
GET /dns/{domain_id}
curl -u user:pass https://{your-site}/wp-json/captaincore/v1/dns/37POST /dns/{domain_id}/records
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | Yes | Record type: A, AAAA, CNAME, MX, TXT, etc. |
name |
string | Yes | Record name (subdomain or @ for root) |
value |
mixed | Yes | Record value (format varies by type) |
ttl |
integer | Yes | TTL in seconds |
Value formats by record type:
For A, AAAA, ANAME, CNAME, TXT, SPF records — array of value objects:
{ "type": "A", "name": "test", "value": [{"value": "192.0.2.1"}], "ttl": 300 }For MX records — array with server and priority:
{ "type": "MX", "name": "", "value": [{"server": "mail.example.com", "priority": 10}], "ttl": 3600 }Example:
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"type":"A","name":"test","value":[{"value":"192.0.2.1"}],"ttl":300}' \
https://{your-site}/wp-json/captaincore/v1/dns/37/recordsPUT /dns/{domain_id}/records/{record_id}
Same fields as create.
DELETE /dns/{domain_id}/records/{record_id}
curl -X DELETE -u user:pass \
https://{your-site}/wp-json/captaincore/v1/dns/37/records/60146555POST /dns/{domain_id}/bulk
GET /domains/{domain_id}/zone
POST /domains/import
POST /domain/{domain_id}/activate-dns-zone
DELETE /domain/{domain_id}/dns-zone
POST /domain/{domain_id}/activate-forward-email
GET /domain/{domain_id}/email-forwards
POST /domain/{domain_id}/email-forwards
PUT /domain/{domain_id}/email-forwards/{alias_id}
DELETE /domain/{domain_id}/email-forwards/{alias_id}
GET /domain/{domain_id}/email-forwarding/status
GET /domain/{domain_id}/email-forwarding/logs
DELETE /domain/{domain_id}/email-forwarding
GET /domain/{domain_id}/mailgun
POST /domain/{domain_id}/mailgun/setup
POST /domain/{domain_id}/mailgun/verify
POST /domain/{domain_id}/mailgun/deploy
DELETE /domain/{domain_id}/mailgun
GET /domain/{domain_id}/mailgun/events
GET /sites/{site_id}/mailgun-events
GET /domain/{domain_id}/mailgun/suppressions/{type}
DELETE /domain/{domain_id}/mailgun/suppressions/{type}
| Field | Type | Required | Description |
|---|---|---|---|
address |
string | Yes | Email address to remove from suppression list |
GET /accounts
GET /accounts/{account_id}
POST /accounts
PUT /accounts/{account_id}
DELETE /accounts/{account_id}
PUT /accounts/{account_id}/defaults
PUT /accounts/{account_id}/plan
POST /accounts/{account_id}/invites
DELETE /accounts/{account_id}/invites/{invite_id}
DELETE /accounts/{account_id}/users/{user_id}
PUT /accounts/{account_id}/users/{user_id}/level
GET /users
POST /users
GET /users/{user_id}
PUT /users/{user_id}
GET /users/{user_id}/accounts
GET /invites
Looks up a specific invitation by account and token. Returns the account details if the invite is valid.
| Parameter | Type | Required | Description |
|---|---|---|---|
account |
integer | Yes | Account ID (query param) |
token |
string | Yes | Invitation token (query param) |
curl -u user:pass "https://{your-site}/wp-json/captaincore/v1/invites?account=75&token=abc123"POST /invites/accept
| Field | Type | Required | Description |
|---|---|---|---|
account |
integer | Yes | Account ID |
token |
string | Yes | Invitation token |
All quicksave endpoints require site_id and environment as query parameters.
GET /quicksaves
| Parameter | Type | Required | Description |
|---|---|---|---|
site_id |
integer | Yes | Site ID |
environment |
string | Yes | production or staging |
curl -u user:pass \
"https://{your-site}/wp-json/captaincore/v1/quicksaves?site_id=2456&environment=production"GET /quicksaves/search
| Parameter | Type | Required | Description |
|---|---|---|---|
site_id |
integer | Yes | Site ID |
environment |
string | Yes | production or staging |
GET /quicksaves/{hash}
Returns detailed quicksave data including plugin/theme versions and what changed.
| Parameter | Type | Required | Description |
|---|---|---|---|
site_id |
integer | Yes | Site ID (query param) |
environment |
string | Yes | production or staging (query param) |
curl -u user:pass \
"https://{your-site}/wp-json/captaincore/v1/quicksaves/446d35f6...?site_id=2456&environment=production"GET /quicksaves/{hash}/changed
Returns a newline-delimited list of changed files with modification type (M=modified, A=added, D=deleted).
| Parameter | Type | Required | Description |
|---|---|---|---|
site_id |
integer | Yes | Site ID (query param) |
environment |
string | Yes | production or staging (query param) |
GET /quicksaves/{hash}/filediff
Returns a git-style unified diff for a specific file.
| Parameter | Type | Required | Description |
|---|---|---|---|
site_id |
integer | Yes | Site ID (query param) |
environment |
string | Yes | production or staging (query param) |
file |
string | Yes | File path to diff (query param) |
curl -u user:pass \
"https://{your-site}/wp-json/captaincore/v1/quicksaves/446d35f6.../filediff?site_id=2456&environment=production&file=plugins/share-one-drive/includes/UserFolders.php"POST /quicksaves/{hash}/rollback
| Parameter | Type | Required | Description |
|---|---|---|---|
site_id |
integer | Yes | Site ID |
environment |
string | Yes | production or staging |
Update logs track plugin and theme updates applied to a site over time. Each log entry records the quicksave hashes before and after the update, a summary of files changed, and counts of plugins/themes that were updated.
GET /update-logs
Returns update logs for a site environment with quicksave diff support. Both query parameters are required.
| Parameter | Type | Required | Description |
|---|---|---|---|
site_id |
integer | Yes | Site ID (query param) |
environment |
string | Yes | production or staging (query param) |
curl -u user:pass \
"https://{your-site}/wp-json/captaincore/v1/update-logs?site_id=135&environment=production"Response:
[
{
"hash_before": "058d6264b1f845b4371bf109404e1269d19c65ca",
"hash_after": "997b53b4097e04f482fe01da18c97c3e9918602d",
"created_at": "1771427726",
"started_at": "1771401498",
"status": "275 files changed, 4757 insertions(+), 6959 deletions(-)",
"core": "6.9.1",
"theme_count": 2,
"plugin_count": 39,
"core_previous": "6.9.1",
"themes_changed": 0,
"plugins_changed": 6,
"plugins": [],
"themes": []
}
]| Field | Type | Description |
|---|---|---|
hash_before |
string | Quicksave hash before the update |
hash_after |
string | Quicksave hash after the update |
created_at |
string | Unix timestamp when the log was recorded |
started_at |
string | Unix timestamp when the update started |
status |
string | Summary of file changes (git diff stat format) |
core |
string | WordPress core version after the update |
core_previous |
string | WordPress core version before the update |
plugin_count |
integer | Total number of plugins installed |
theme_count |
integer | Total number of themes installed |
plugins_changed |
integer | Number of plugins updated |
themes_changed |
integer | Number of themes updated |
GET /update-logs/{hash_before}_{hash_after}
Returns the detailed diff between two quicksave snapshots from an update log entry. Use the hash_before and hash_after values from the list endpoint.
| Parameter | Type | Required | Description |
|---|---|---|---|
site_id |
integer | Yes | Site ID (query param) |
environment |
string | Yes | production or staging (query param) |
curl -u user:pass \
"https://{your-site}/wp-json/captaincore/v1/update-logs/058d6264b1..._{997b53b409...}?site_id=135&environment=production"GET /activity-logs
GET /process-logs # List all (admin)
POST /process-logs # Create
GET /process-logs/{id} # Get one
POST /process-logs/{id} # Update
DELETE /process-logs/{id} # Delete
GET /recipes
POST /recipes
PUT /recipes/{recipe_id}
DELETE /recipes/{recipe_id}
POST /sites/cli
Executes a built-in command on a site.
API requests (application passwords) execute synchronously and return the result directly. UI requests (nonce-based) return a job token for WebSocket streaming.
| Field | Type | Required | Description |
|---|---|---|---|
post_id |
integer or array | Yes | Site ID (or array of site IDs for bulk) |
command |
string | Yes | Command to run (see list below) |
environment |
string | No | Production or Staging |
value |
string | No | Additional value (varies by command) |
async |
boolean | No | If true, returns immediately with a job token for polling via /my-jobs/{token} |
Available commands: reset-permissions, apply-https, apply-https-with-www, production-to-staging, staging-to-production, launch, scan-errors, and more.
Example (synchronous):
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"post_id":135,"command":"reset-permissions","environment":"Production"}' \
https://{your-site}/wp-json/captaincore/v1/sites/cliSynchronous response:
{"status": "completed", "response": "...command output..."}Example (async):
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"post_id":135,"command":"backup","environment":"Production","async":true}' \
https://{your-site}/wp-json/captaincore/v1/sites/cliAsync response:
{"status": "queued", "token": "abc123..."}Poll for results with GET /my-jobs/{token}.
GET /jobs/{job_id}
Check the status of an async job by task ID. Admin only.
curl -u admin:pass https://{your-site}/wp-json/captaincore/v1/jobs/K9DmZxAuei...Response (in progress):
{"status": "queued", "job_id": "K9DmZxAuei..."}Response (completed):
{"status": "completed", "response": "...output...", "job_id": "K9DmZxAuei..."}GET /my-jobs/{token}
Check the status of a job by token. Scoped to the current user's jobs.
curl -u user:pass https://{your-site}/wp-json/captaincore/v1/my-jobs/2q8ZWFF88x...Response (in progress):
{"status": "queued", "token": "2q8ZWFF88x..."}Response (completed):
{"status": "completed", "response": "...output...", "token": "2q8ZWFF88x..."}POST /run/code
Runs a script (recipe or custom code) on one or more environments.
API requests (application passwords) execute synchronously and return the result directly. UI requests (nonce-based) return a job token for WebSocket streaming.
| Field | Type | Required | Description |
|---|---|---|---|
code |
string | Yes | The script/code to execute |
environments |
array | Yes | Target environments (see formats below) |
async |
boolean | No | If true, returns immediately with a job token for polling via /my-jobs/{token} |
Environment formats:
Array of environment IDs:
{ "code": "wp option get home", "environments": [3365, 3358] }Array of objects with site_id and environment:
{ "code": "wp option get home", "environments": [{"site_id": 135, "environment": "production"}] }Example (synchronous):
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"code":"wp option get home","environments":[{"site_id":135,"environment":"production"}]}' \
https://{your-site}/wp-json/captaincore/v1/run/codeSynchronous response:
{"status": "completed", "response": "https://example.com\n"}Example (async):
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"code":"sleep 15 && wp plugin list","environments":[{"site_id":135,"environment":"production"}],"async":true}' \
https://{your-site}/wp-json/captaincore/v1/run/codeAsync response:
{"status": "queued", "token": "abc123..."}Poll for results with GET /my-jobs/{token}.
POST /scripts/schedule
| Field | Type | Required | Description |
|---|---|---|---|
environment_id |
integer | Yes | Target environment ID |
code |
string | Yes | The code to execute |
run_at |
object | Yes | Schedule with date, time, and timezone fields |
POST /scripts/{script_id}
DELETE /scripts/{script_id}
GET /providers
POST /providers
PUT /providers/{provider_id}
DELETE /providers/{provider_id}
GET /providers/{provider_id}/verify
GET /providers/{provider}/themes
GET /providers/{provider}/plugins
GET /providers/{provider}/theme/{id}/download
GET /providers/{provider}/plugin/{id}/download
GET /providers/{provider_id}/remote-sites
POST /providers/{provider_id}/connect
POST /providers/{provider_id}/import
POST /providers/{provider}/new-site
POST /providers/{provider}/deploy-to-staging
POST /providers/{provider}/deploy-to-production
GET /billing
POST /billing/pay-invoice
POST /billing/payment-methods # Add
PUT /billing/payment-methods/{id}/primary # Set as primary
DELETE /billing/payment-methods/{id} # Remove
POST /billing/ach/setup-intent # Create setup intent
POST /billing/ach/payment-method # Add bank account
POST /billing/ach/verify # Verify micro-deposits
GET /billing/ach/pending # Pending verifications (admin)
POST /billing/ach/admin-verify # Admin verify (admin)
POST /billing/cancel-plan
POST /billing/request-plan-changes
PUT /billing/update
GET /subscriptions
GET /subscriptions/{subscription_id}
GET /upcoming_subscriptions
GET /invoices/{invoice_id}
GET /invoices/{invoice_id}/pdf
POST /filters/sites
Returns site/environment ID pairs matching the given plugin and/or theme filters. Useful for finding all environments that have a specific plugin or theme installed.
| Field | Type | Description |
|---|---|---|
plugins |
array | Array of plugin objects to filter by |
themes |
array | Array of theme objects to filter by |
versions |
array | Array of version filter objects |
statuses |
array | Array of status filter objects |
core |
array | Array of WordPress core versions to filter by |
logic |
string | AND (default) or OR — how plugin/theme filters combine |
version_logic |
string | AND (default) or OR — how version filters combine |
status_logic |
string | AND (default) or OR — how status filters combine |
version_mode |
string | include (default) or exclude — match or exclude versions |
status_mode |
string | include (default) or exclude — match or exclude statuses |
Find all environments with a specific plugin:
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"plugins":[{"name":"search-everything"}]}' \
https://anchor.host/wp-json/captaincore/v1/filters/sitesResponse:
{
"results": [
{"site_id": "395", "environment_id": "467"},
{"site_id": "395", "environment_id": "468"},
{"site_id": "1129", "environment_id": "1365"}
]
}Find all environments with a specific theme:
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"themes":[{"name":"flavstarter"}]}' \
https://anchor.host/wp-json/captaincore/v1/filters/sitesFind environments matching multiple plugins (AND logic):
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"plugins":[{"name":"woocommerce"},{"name":"gravityforms"}]}' \
https://anchor.host/wp-json/captaincore/v1/filters/sitesFind environments matching either plugin (OR logic):
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"plugins":[{"name":"woocommerce"},{"name":"gravityforms"}],"logic":"OR"}' \
https://anchor.host/wp-json/captaincore/v1/filters/sitesFilter by plugin version:
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"plugins":[{"name":"wordpress-seo"}],"versions":[{"slug":"wordpress-seo","name":"26.9","type":"plugins"}]}' \
https://anchor.host/wp-json/captaincore/v1/filters/sitesExclude a specific plugin version (NOT filter):
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"plugins":[{"name":"woocommerce-follow-up-emails"}],"versions":[{"slug":"woocommerce-follow-up-emails","name":"4.9.51","type":"plugins"}],"version_mode":"exclude"}' \
https://anchor.host/wp-json/captaincore/v1/filters/sitesReturns environments that have the plugin installed but are not running version 4.9.51. Use "status_mode":"exclude" similarly to find environments where a plugin is not in a specific status.
Filter by WordPress core version:
curl -X POST -u user:pass \
-H "Content-Type: application/json" \
-d '{"core":["6.8.3","6.7.4"]}' \
https://anchor.host/wp-json/captaincore/v1/filters/sitesPOST /filters
GET /filters/{name}/versions
GET /filters/{name}/statuses
Returns available versions or statuses for a given plugin or theme. Useful for discovering what versions exist across your sites before filtering.
curl -u user:pass https://anchor.host/wp-json/captaincore/v1/filters/search-everything/versionsResponse:
[
{
"name": "search-everything",
"versions": [
{"name": "8.1.9", "slug": "search-everything", "type": "plugins", "count": 2},
{"name": "8.2", "slug": "search-everything", "type": "plugins", "count": 12}
]
}
]curl -u user:pass https://anchor.host/wp-json/captaincore/v1/filters/search-everything/statusesResponse:
[
{
"name": "search-everything",
"statuses": [
{"name": "active", "slug": "search-everything", "type": "plugins", "count": 14}
]
}
]GET /configurations
POST /configurations
PUT /configurations/global
GET /defaults
PUT /defaults/global
GET /archive
POST /archive/share
GET /web-risk-logs
GET /checksum-failures
POST /report/send
POST /report/preview
POST /report/default-recipient
GET /scheduled-reports
POST /scheduled-reports
PUT /scheduled-reports/{id}
DELETE /scheduled-reports/{id}
GET /wp-plugins
GET /wp-themes
GET /running # Running background jobs (admin)
GET /processes # List all processes
GET /processes/{id} # Get a process
PUT /processes/{id} # Update a process
GET /processes/{id}/raw # Get raw process data
GET /environments
POST /site-requests
POST /site-requests/back
POST /site-requests/continue
PUT /site-requests/update
POST /site-requests/delete
GET /requested-sites
GET /keys
POST /keys
PUT /keys/{key_id}
DELETE /keys/{key_id}
PUT /keys/{key_id}/primary
GET /provider-actions
GET /provider-actions/{id}/run
GET /provider-actions/check