| name | wpe-labs:installs |
| description | List, inspect, create, and copy WordPress installations and sites across WP Engine environments. Use when managing sites/installs, checking environment details (PHP version, cname, IP), or copying production to staging. Requires WP Engine API credentials; no local tooling needed beyond curl and jq. |
List and manage WP Engine sites and WordPress installations. Covers the full lifecycle: browsing what exists, creating new sites and installs, and copying environments (e.g. production → staging). Works for any WP Engine account holder with API credentials. Requires only curl and jq.
Create API credentials at: **https://my.wpengine.com/api_access** → Generate credentials
Set as env vars before running:
export WPE_USERNAME="your-api-username"
export WPE_PASSWORD="your-api-password"
Or pass inline: -u "your-api-username:your-api-password"
<quick_start>
List all sites across all accounts:
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
"https://api.wpengineapi.com/v1/sites" | \
jq '[.results[] | {id, name, account_id}]'
List all installs with environment and cname:
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
"https://api.wpengineapi.com/v1/installs" | \
jq '[.results[] | {id, name, environment, cname, php_version, site_id}]'
</quick_start>
**Step 1: List sites (optionally filtered by account)**
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
"https://api.wpengineapi.com/v1/sites" | \
jq -r '.results[] | "\(.id)\t\(.name)\t\(.account_id)"'
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
"https://api.wpengineapi.com/v1/sites?account_id=$ACCOUNT_ID" | \
jq -r '.results[] | "\(.id)\t\(.name)"'
If count > 100, paginate with ?limit=100&offset=100.
Step 2: List installs for a site
SITE_ID="your-site-uuid"
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
"https://api.wpengineapi.com/v1/installs?site_id=$SITE_ID" | \
jq '[.results[] | {id, name, environment, cname, ip, php_version, wpe_version}]'
Step 3: Get details on a specific install
INSTALL_ID="your-install-uuid"
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
"https://api.wpengineapi.com/v1/installs/$INSTALL_ID" | \
jq '{id, name, environment, cname, ip, php_version, wpe_version, account_id, site_id}'
Step 4: Create a new site + install
SITE=$(curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
-H "Content-Type: application/json" \
-X POST "https://api.wpengineapi.com/v1/sites" \
-d "{\"name\": \"my-new-site\", \"account_id\": \"$ACCOUNT_ID\"}")
SITE_ID=$(echo "$SITE" | jq -r '.id')
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
-H "Content-Type: application/json" \
-X POST "https://api.wpengineapi.com/v1/installs" \
-d "{
\"name\": \"my-new-site\",
\"account_id\": \"$ACCOUNT_ID\",
\"site_id\": \"$SITE_ID\",
\"environment\": \"production\"
}"
Step 4b: Rename a site
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
-H "Content-Type: application/json" \
-X PATCH "https://api.wpengineapi.com/v1/sites/$SITE_ID" \
-d '{"name": "new-site-name"}' | jq '{id, name}'
Step 4c: Update an install
Move an install to a different site or change its environment:
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
-H "Content-Type: application/json" \
-X PATCH "https://api.wpengineapi.com/v1/installs/$INSTALL_ID" \
-d '{"environment": "staging"}' | jq '{id, name, environment}'
Fields: site_id (uuid, move to different site), environment (production, staging, development, or null).
Step 4d: Per-install daily usage
Get granular daily usage metrics for a specific install:
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
"https://api.wpengineapi.com/v1/installs/$INSTALL_ID/usage?first_date=2025-03-01&last_date=2025-03-31" | jq .
Trigger a disk usage refresh for a specific install:
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
-X POST "https://api.wpengineapi.com/v1/installs/$INSTALL_ID/usage/refresh_disk_usage"
Step 5: Copy an install (e.g. production → staging)
⚠️ GUARD — confirm before copying.
install_copy overwrites the destination install's files and/or database. This cannot be undone without a backup.
Before submitting ANY copy request, you MUST:
- Resolve and show both install names and environments (e.g. "mysite production → mysite staging")
- State explicitly: "This will overwrite [destination name] with content from [source name]. All existing data on [destination] will be replaced. Confirm?"
- For bulk operations (multiple sites), list every source→destination pair and confirm the full list before submitting any request
- Wait for explicit confirmation — do NOT proceed on ambiguous input
SOURCE_INSTALL_ID="prod-install-uuid"
DEST_INSTALL_ID="staging-install-uuid"
curl -s -u "$WPE_USERNAME:$WPE_PASSWORD" \
-H "User-Agent: wpe-labs-skills/installs" \
-H "Content-Type: application/json" \
-X POST "https://api.wpengineapi.com/v1/install_copy" \
-d "{
\"source_environment_id\": \"$SOURCE_INSTALL_ID\",
\"destination_environment_id\": \"$DEST_INSTALL_ID\",
\"custom_options\": {
\"include_files\": true,
\"include_db\": true
},
\"notification_emails\": [\"you@example.com\"]
}"
Returns 202 Accepted. The copy runs asynchronously — notify the user when emails confirm completion.
Selective DB copy (specific tables only):
-d "{
\"source_environment_id\": \"$SOURCE_INSTALL_ID\",
\"destination_environment_id\": \"$DEST_INSTALL_ID\",
\"custom_options\": {
\"include_files\": false,
\"include_db\": true,
\"db_tables\": [\"wp_posts\", \"wp_postmeta\", \"wp_options\"]
}
}"
<destructive_operations>
🔴 DELETE /sites and DELETE /installs are permanently destructive.
Deleting a site or install removes all WordPress files, databases, and configuration. There is no undo.
You MUST follow this sequence before executing either DELETE:
- Confirm the site/install name and ID by fetching it — never trust user-provided IDs alone
- Check whether a recent backup exists via
wpe-labs:backups; if not, recommend creating one first
- State explicitly: "This will PERMANENTLY DELETE [name] ([environment]). All files and database data will be destroyed and cannot be recovered. This is irreversible. Type 'DELETE [name]' to confirm."
- Require the user to type the install name as confirmation — do NOT accept "yes" or "ok"
- Only then execute the DELETE
If you are ever unsure whether the user intends deletion vs. some other action, ask for clarification before proceeding.
</destructive_operations>
<api_reference>
Base URL: https://api.wpengineapi.com/v1
Auth: HTTP Basic Auth with credentials from https://my.wpengine.com/api_access
| Endpoint | Purpose |
|---|
GET /sites | List sites (paginated, filterable by account_id) |
POST /sites | Create site (name, account_id) |
GET /sites/{site_id} | Get site details |
PATCH /sites/{site_id} | Update site name |
DELETE /sites/{site_id} | Delete site |
GET /installs | List installs (paginated, filterable by site_id, account_id) |
POST /installs | Create install (name, account_id, site_id, environment) |
GET /installs/{install_id} | Get install details |
PATCH /installs/{install_id} | Update install |
DELETE /installs/{install_id} | Delete install |
POST /install_copy | Copy install between environments (async, 202) |
Install fields: id, name, account_id, site_id, environment (production/staging/development), cname, ip, php_version, wpe_version
install_copy options: include_files (bool), include_db (bool), db_tables (string array for selective table copy)
PATCH /sites/{id} fields: name (string)
PATCH /installs/{id} fields: site_id (uuid), environment (production/staging/development/null)
GET /installs/{id}/usage params: first_date, last_date (both required for custom range, max 13 months back)
</api_reference>
**install_copy returns 202 but nothing happens** — The copy is asynchronous. Wait for the notification email. Do not re-submit; duplicate copies can overwrite in-progress work.
Can't find install_id — Run GET /installs and filter by site name: jq '.results[] | select(.name | test("mysite"))'
Create install fails with 422 — name must be lowercase letters, numbers, and hyphens only. environment must be exactly production, staging, or development.
429 Too Many Requests — Add a short delay between requests when iterating over many sites or installs.
Credentials fail — Regenerate at https://my.wpengine.com/api_access. Note: these are separate from your portal login credentials.
<success_criteria>
- All sites listed from
/sites with account association
- All installs listed per site with environment, cname, IP, and PHP version
- Specific install details retrievable by ID
- New site + install created when requested
- Install copy submitted with source/destination confirmed and user notified of async completion
</success_criteria>