How to Purge Page Cache on Many Sites at Once with the xCloud Public API and MCP
Updated October 30, 2026 · 7 min read
You can purge the WordPress page cache on 1 to 100 sites with one request: POST /api/v1/sites/bulk/cache-purge from a script, or the matching tool in any AI agent connected to xCloud MCP. A dry run first shows which sites xCloud can purge, and nothing runs until you confirm. You then read each site’s result from GET /api/v1/sites/bulk-operations/{uuid}.
Use it after a theme or plugin deploy across many client sites, or when one change has to show up everywhere at once. Bulk page cache purge is new in xCloud v2.9.7.4.
What the bulk purge clears
The bulk purge clears the server page cache of each WordPress site: the Nginx page cache on Nginx servers, and the LiteSpeed page cache on OpenLiteSpeed servers. This is the same cache that Purge Cache clears on a site’s Caching page in the dashboard.
On some older Nginx servers the API cannot purge the page cache yet. Those sites show not_eligible, so purge them from the site’s Caching page.
It does not clear:
- Cloudflare, including Edge Full Page Cache
- Redis Object Cache or Object Cache Pro
- Sites that are not WordPress sites
A site can be purged when it is a provisioned WordPress site on a provisioned, connected Nginx or OpenLiteSpeed server. Any other site in the list is skipped and the rest still run.
Prerequisites
- An xCloud API token with
write:sitesto preview and submit, andread:sitesto read the results. See How to Access the xCloud API to create one. - A team role of Team Admin, Server Admin or Site Admin, with the permission to manage site caching.
- For MCP, an AI agent connected to xCloud MCP. See How to Connect xCloud MCP to Your AI Agent.
- The UUIDs of the sites to purge.
GET /api/v1/siteslists them, or use the fleet overview.
Step 1: Preview the purge with a dry run
Send the site UUIDs with "dry_run": true. A dry run checks every site and changes nothing: no purge runs and no operation is created.
export XCLOUD_TOKEN='YOUR_API_TOKEN'
curl -X POST 'https://app.xcloud.host/api/v1/sites/bulk/cache-purge' \
--header "Authorization: Bearer $XCLOUD_TOKEN" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--data '{
"sites": [
"3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
"7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b"
],
"dry_run": true
}'
Expected result: a 200 response. Each site shows queued (it would be purged) or skipped with a reason:
{
"success": true,
"message": "Dry run complete. The payload is valid and nothing was created.",
"data": {
"dry_run": true,
"would_create": {
"uuid": null,
"status": "dry_run",
"items": [
{ "site_uuid": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f", "status": "queued", "reason": null, "task_uuid": null, "error": null },
{ "site_uuid": "7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b", "status": "skipped", "reason": "not_eligible", "task_uuid": null, "error": null }
],
"next_actions": []
},
"warnings": []
}
}
reason |
Meaning |
|---|---|
null |
The site can be purged |
not_eligible |
The site is not a provisioned WordPress site on a connected Nginx or OpenLiteSpeed server, or it is on an older Nginx server where the API cannot purge the page cache yet |
not_found |
The UUID does not exist, or you do not have access to that site |
The sites list takes 1 to 100 UUIDs, each one only once. A longer list, a repeated UUID or a value that is not a UUID is refused with 422, and nothing runs.
Step 2: Submit the purge
Send the same list with "confirm": true instead of dry_run. Add an Idempotency-Key header so the request is safe to retry: if the connection drops and you send it again with the same key, xCloud returns the purge that already exists instead of starting a second one.
curl -X POST 'https://app.xcloud.host/api/v1/sites/bulk/cache-purge' \
--header "Authorization: Bearer $XCLOUD_TOKEN" \
--header 'Accept: application/json' \
--header 'Content-Type: application/json' \
--header 'Idempotency-Key: deploy-2026-10-30-cache' \
--data '{
"sites": [
"3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
"7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b"
],
"confirm": true
}'
Expected result: a 202 response with the operation uuid and a next_actions entry that tells you where to read progress:
{
"success": true,
"message": "Bulk page-cache purge admitted.",
"data": {
"uuid": "5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e",
"status": "running",
"items": [
{ "site_uuid": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f", "status": "queued", "reason": null, "task_uuid": null, "error": null },
{ "site_uuid": "7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b", "status": "skipped", "reason": "not_eligible", "task_uuid": null, "error": null }
],
"next_actions": [
{ "action": "poll", "method": "GET", "url": "/api/v1/sites/bulk-operations/5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e" }
]
}
}
A 202 means xCloud accepted the request, not that the caches are already clear. Without "confirm": true (and without "dry_run": true) the request is refused with 422.
To purge sites in another team granted to your token, add the X-Team-Id header. See Multi-Team API Tokens and MCP Access.
Step 3: Poll each site’s result
Read the operation with the URL from next_actions. This call needs read:sites and changes nothing.
curl 'https://app.xcloud.host/api/v1/sites/bulk-operations/5b6c7d8e-9f0a-4b1c-8d2e-3f4a5b6c7d8e' \
--header "Authorization: Bearer $XCLOUD_TOKEN" \
--header 'Accept: application/json'
Expected result: the same shape as Step 2, with each site’s current status. Poll every few seconds until the operation status is no longer running.
Site status |
Meaning |
|---|---|
queued |
Waiting for its turn on its server |
running |
The purge is running on the server |
done |
The purge finished successfully |
failed |
The purge did not finish, or it did not start in time. error says which |
skipped |
Not purged. reason says why |
The operation status is completed when no site failed (sites that were skipped count as not failed), completed_with_failures when some failed and some finished, and failed when sites failed and none finished. An operation where every site was skipped is also completed, so check each site’s status instead of trusting the operation status alone.
xCloud purges one site at a time on each server, and different servers run side by side. Sites that have not started within five minutes of the request are marked failed and nothing ran on them.
If you lose access to a site after submitting, that site shows skipped with not_found in the results.
Step 4: Retry or check failed sites
The error text of a failed site tells you what to do next:
error |
What to do |
|---|---|
Not started before the five-minute deadline; nothing ran. Retry with a new Idempotency-Key. |
Submit those sites again with a new key |
Admission stopped before this purge started; nothing ran. Retry with a new Idempotency-Key. |
Submit those sites again with a new key |
Purge completion was not confirmed. Check the site before retrying. |
Open a page of the site first. The purge may have run. Submit again only if the page is still out of date |
xCloud never retries a failed purge on its own. Send only the failed site UUIDs in the new request.
On OpenLiteSpeed sites, open a page after the purge to confirm visitors see the new version.
Purge with an AI agent over MCP
In an MCP client connected to xCloud, ask in plain language:
Purge the page cache on all my WordPress sites on the server docs-demo.
Do a dry run first and show me which sites will be skipped, then wait for my OK.
The agent calls the sites_bulk_cache-purge tool. A dry run needs no confirmation. The real purge is marked as a destructive tool, so most MCP clients ask you to approve it before it runs. Check your client’s approval setting. On the compact MCP profile, the agent runs the sites.bulk.cache-purge operation through xcloud_execute_destructive, and reads the result with sites.bulk-operations.show through xcloud_execute_read, which changes nothing.
Expected result: the agent lists the sites it will purge and skip, waits for your approval if your client asks for it, then reports each site’s final status.
Troubleshooting
| Response | Cause | Fix |
|---|---|---|
401 |
No bearer token, or the token was revoked | Send Authorization: Bearer <token> with an active token |
403 on submit |
The token lacks write:sites, or your role cannot manage site caching |
Use a token with write:sites and ask the team owner for caching access |
403 on poll |
The token lacks read:sites |
Use a token with read:sites |
404 on poll |
The operation UUID is wrong or belongs to another team | Use the URL from next_actions with the same team |
409 |
A request with the same Idempotency-Key is still being accepted |
Wait a moment and send it again with the same key |
422 |
Invalid list, missing confirm, or the Idempotency-Key was already used with a different body |
Fix the body, or use a new key for a different list |
429 |
More than 30 purge requests in a minute | Wait a minute. Put more sites in one request instead of many small ones |
Frequently asked questions
Does the bulk purge clear Cloudflare, Edge Full Page Cache or Redis?
No. It clears only the server page cache of each WordPress site, the same cache the Purge Cache button on the site’s Caching page clears. Cloudflare and Edge Full Page Cache, Redis Object Cache and Object Cache Pro are not touched.
Why does a site show skipped with the reason not_eligible?
The site is not a provisioned WordPress site on a connected Nginx or OpenLiteSpeed server that xCloud can purge from the API. Some older Nginx servers also show not_eligible, because the API cannot purge their page cache yet. Check that the site and server are provisioned and connected. If the site looks healthy, purge it from its Caching page in the dashboard, or contact support.
Is it safe to send the same purge request twice?
Yes, when you send an Idempotency-Key header. A repeated request with the same key and the same body returns the operation that already exists instead of starting a second purge. The same key with a different body is refused with 422.
Why does polling return 403 when submitting worked?
Submitting needs the write:sites permission, but reading the result needs read:sites. Create a token that has both permissions if one script submits and polls.
Next steps
- Read the full request and response format in the xCloud Public API reference, and authentication and rate limits in the xCloud API documentation overview.
- Set up page caching for a site with xSpeed Cache.
If you run into any issues with bulk page cache purge, feel free to reach out to our support team for help.