> ## Documentation Index
> Fetch the complete documentation index at: https://docs.mainwp.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Sites Endpoints

> Route-level reference for MainWP REST API v2 site endpoints, including site listing, sync, plugin/theme operations, client/cost lookups, and site batch actions.

Use these endpoints to manage child sites in MainWP Dashboard.

<Note>
  Use the [MainWP Postman collection](https://www.postman.com/mainwp/mainwp/collection/ujfddk4/mainwp-rest-api-v2-current) as the source of truth for request and response schemas.
</Note>

`{id_or_domain}` accepts either a numeric site ID or a site domain.

## Route Matrix

### Global Site Routes

| Method | Path | Purpose | Key Params |
| - | - | - | - |
| GET | `/sites` | List sites | `page`, `per_page`, `search`, `include`, `exclude`, `status`, `with_tags`, `full_data` |
| GET | `/sites/basic` | List lightweight site records | `page`, `per_page`, `search`, `include`, `exclude`, `status` |
| GET | `/sites/count` | Count sites | `include`, `exclude`, `status` |
| POST, PUT, PATCH | `/sites/sync` | Trigger sync for all sites | Optional filters like `include`, `exclude` |
| POST, PUT, PATCH | `/sites/reconnect` | Trigger reconnect for all sites | Optional filters |
| POST, PUT, PATCH | `/sites/disconnect` | Disconnect all matched sites | Optional filters |
| POST, PUT, PATCH | `/sites/check` | Run connection checks for all sites | Optional filters |
| POST | `/sites/add` | Add a child site | `url`, `admin`, plus `adminpassword` and/or `uniqueid`; optional `name`, `groupids`, `client_id` |
| POST | `/sites/batch` | Batch create/update/delete sites | `create[]`, `update[]`, `delete[]` payload; site creates use the same connection authentication fields as `/sites/add` |

### Per-Site Routes

| Method | Path | Purpose | Key Params |
| - | - | - | - |
| GET | `/sites/{id_or_domain}` | Get full site details | `id_or_domain`, optional `with_tags` |
| POST, PUT, PATCH | `/sites/{id_or_domain}/edit` | Update site fields | `name`, `groupids`, `client_id`, other editable site fields |
| POST, PUT, PATCH | `/sites/{id_or_domain}/sync` | Sync one site | `id_or_domain` |
| GET | `/sites/{id_or_domain}/security` | Fetch security snapshot | `id_or_domain` |
| GET | `/sites/{id_or_domain}/plugins` | List plugins on one site | `status`, `search`, `page`, `per_page`, `must_use` |
| POST, PUT, PATCH | `/sites/{id_or_domain}/plugins/activate` | Activate plugin(s) | `slug` (single or comma list) |
| POST, PUT, PATCH | `/sites/{id_or_domain}/plugins/deactivate` | Deactivate plugin(s) | `slug` |
| DELETE | `/sites/{id_or_domain}/plugins/delete` | Delete plugin(s) | `slug` |
| GET | `/sites/{id_or_domain}/plugins/abandoned` | List abandoned plugins | Standard list filters |
| GET | `/sites/{id_or_domain}/themes` | List themes on one site | `status`, `search`, `page`, `per_page` |
| POST, PUT, PATCH | `/sites/{id_or_domain}/themes/activate` | Activate a theme | `slug` |
| DELETE | `/sites/{id_or_domain}/themes/delete` | Delete theme(s) | `slug` |
| GET | `/sites/{id_or_domain}/themes/abandoned` | List abandoned themes | Standard list filters |
| GET | `/sites/{id_or_domain}/non-mainwp-changes` | Show external/non-MainWP changes | `id_or_domain`, optional `source`, `actions`, `contexts`, `total_count`, `page`, `per_page` |
| POST, PUT, PATCH | `/sites/{id_or_domain}/reconnect` | Reconnect one site | `id_or_domain` |
| POST, PUT, PATCH | `/sites/{id_or_domain}/disconnect` | Disconnect one site | `id_or_domain` |
| POST, PUT, PATCH | `/sites/{id_or_domain}/suspend` | Suspend one site | `id_or_domain` |
| POST, PUT, PATCH | `/sites/{id_or_domain}/unsuspend` | Unsuspend one site | `id_or_domain` |
| POST, PUT, PATCH | `/sites/{id_or_domain}/check` | Run check for one site | `id_or_domain` |
| DELETE | `/sites/{id_or_domain}/remove` | Remove site from Dashboard | `id_or_domain` |

### Site Relationship Routes

| Method | Path | Purpose | Key Params |
| - | - | - | - |
| GET | `/sites/{id_or_domain}/client` | Get client linked to a site | `id_or_domain` |
| GET | `/sites/{id_or_domain}/costs` | Get costs linked to a site | `id_or_domain` |

<Note>
  When creating a site through REST API, the site URL and administrator username are always required. Include `adminpassword` when Password Authentication is enabled on the child site, include `uniqueid` when Unique Security ID is enabled, or include both when both methods are enabled. MainWP Child no longer allows both Password Authentication and Unique Security ID to be disabled.
</Note>

***

## Representative Requests

### Connection Input Types

When adding or editing sites, use the expected JSON types instead of relying on automatic conversion:

| Field | Applies To | Accepted Values |
| - | - | - |
| `force_use_ipv4` | Add and edit | `0` to disable, `1` to force IPv4, or `2` to use the global setting; JSON `false` and `true` are also accepted for `0` and `1` |
| `ssl_verify` | Add | JSON `true` or `false`; `null` is rejected |
| `uniqueid` | Add and edit | String containing the child's Unique Security ID; `uniqueId` is accepted as a fallback alias |
| `groupids` | Add and edit | Comma-separated tag IDs in a string, such as `"3,7"` |

Omitting `force_use_ipv4` when adding a site uses the global setting for the connection attempt. Invalid values, such as `3` for `force_use_ipv4` or `null` for `ssl_verify`, return HTTP 400. Check the error response for the affected parameter and correct it before retrying. Site creation inside `/sites/batch` and global `/batch` uses the same connection input validation.

### Update Site Tags

Use `groupids` when updating tags through `/sites/{id_or_domain}/edit`. It replaces the site's tag assignments rather than adding to them.

| Request | Result |
| - | - |
| `"groupids": "3,7"` | Assigns tags 3 and 7 and removes other tag assignments |
| `"groupids": ""` | Removes all tag assignments from the site |
| Omit `groupids` | Keeps the site's current tag assignments |

Each ID must be a positive integer identifying an existing tag accessible to the authenticated API user. Duplicate IDs are removed, and spaces around IDs are allowed. Tag names, zero, negative IDs, nonexistent or inaccessible IDs, and empty entries such as `"3,,7"` are rejected. The endpoint does not create tags.

```bash theme={null}
curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"groupids":"3,7"}' \
  "https://your-dashboard.com/wp-json/mainwp/v2/sites/12/edit"
```

Sending `tags`, even with an empty value, or sending `groupids` as an array or another non-string type returns HTTP 400 with `rest_invalid_param`. Invalid tag IDs are checked before any site fields are saved and return `success: 0`, `group_updated: false`, and `group_message` explaining the failure.

Check the response body even when the HTTP status is 200. A successful tag update includes `success: 1`, `group_updated: true`, and `group_message: "Tags updated successfully."`.

If valid IDs pass validation but saving the tag assignments fails, other requested site fields may already have been saved. That response is:

```json theme={null}
{
  "success": 0,
  "group_updated": false,
  "group_message": "Failed to update tags or invalid tag IDs.",
  "message": "Group associations could not be updated, but the other requested fields were saved."
}
```

Read the site's current values before retrying; `success: 0` does not guarantee that the entire edit was rolled back.

### List sites

```bash theme={null}
curl -H "Authorization: Bearer YOUR_API_KEY" \
  "https://your-dashboard.com/wp-json/mainwp/v2/sites?page=1&per_page=20&status=connected"
```

```json theme={null}
{
  "success": 1,
  "total": 2,
  "data": [
    {
      "id": 12,
      "name": "Example Site",
      "url": "https://example.com",
      "status": "connected"
    }
  ]
}
```

### Activate a plugin on one site

```bash theme={null}
curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"slug":"akismet/akismet.php"}' \
  "https://your-dashboard.com/wp-json/mainwp/v2/sites/12/plugins/activate"
```

```json theme={null}
{
  "success": 1,
  "message": "Plugin activated successfully."
}
```

### Batch site operations

```bash theme={null}
curl -X POST \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "create": [{"url":"https://new-site.com","name":"New Site","admin":"admin","uniqueid":"xxxxx"}],
    "update": [{"id":12,"name":"Renamed Site"}],
    "delete": [31]
  }' \
  "https://your-dashboard.com/wp-json/mainwp/v2/sites/batch"
```

```json theme={null}
{
  "create": [{"success": 1}],
  "update": [{"success": 1}],
  "delete": [{"success": 1}]
}
```

***

## Related Resources

* [REST API Overview](/api-reference/rest-api/overview)
* [Updates Endpoints](/api-reference/rest-api/updates)
* [Clients Endpoints](/api-reference/rest-api/clients)
* [Batch Endpoint](/api-reference/rest-api/batch)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.