See Who Did What on Your Team with the xCloud Public API and MCP

Updated November 3, 2026 · 7 min read

Summarize with:
Share:

Team activity tells you who did what in your xCloud team over the last 30 days, newest first. Use it to answer “who deleted example.com?” or “what did my team do this week?” from a script or an AI agent. Call GET /api/v1/activity, or ask an agent to run the activity_list MCP tool. It only reads data, and it changes nothing on your servers.

The dashboard already shows the same history on the All Events page. Open it with View All Events in the events menu at the top of the dashboard. For one server or site, see How to View Logs and Events for Your Server and Site.

Prerequisites

  • Your role: the team owner, or a Team Admin with the server logs and events permission. In the member’s permissions, this is the one that reads “Allows members to handle and manage server related events or triggers and server logs for troubleshooting or analysis”. Server Admins and Site Admins cannot read team activity.
  • Your token: an xCloud API token with both read:servers and read:sites. A read-only token is enough. See How to Access the xCloud API to create one.
  • For MCP: the token or connection must also allow MCP (mcp:invoke). An OAuth connection from an MCP client works too. See How to Connect xCloud MCP to Your AI Agent.

What each entry holds

Field What it holds
uuid, name The entry’s ID and its name, such as Backup Site: example.com
type, status The kind of action, and queued, running, finished, failed, timeout or killed
created_at, finished_at When it started and ended. finished_at is null while it is queued or running
server The server’s uuid and name, and deleted: true if the server has since been archived. null when the entry has no server, or the server was permanently deleted
site The site’s uuid and name. null when the entry names no site or the site is gone
site_deleted true only when the entry recorded a site that no longer exists
initiated_by The uuid and name of the person who started it. null when xCloud started it itself, or the person’s account was deleted

Emails, command output and scripts are never included.

Step 1: List your team’s recent activity

Send a GET request with your token. Store the token in an environment variable instead of pasting it into the command.

export XCLOUD_TOKEN='xc_live_xxxxxxxxxxxx'

curl 'https://app.xcloud.host/api/v1/activity?per_page=25' \
  --header "Authorization: Bearer $XCLOUD_TOKEN" \
  --header 'Accept: application/json'

Expected result: a 200 response with the newest entries first and a pagination block. per_page is 10 by default and 100 at most. Increase page to read further back.

{
  "success": true,
  "message": "Success",
  "data": {
    "items": [
      {
        "uuid": "9b1f2a3d-4e5f-4a7b-8c9d-0e1f2a3b4c5d",
        "name": "Backup Site: example.com",
        "type": "system",
        "status": "finished",
        "created_at": "2026-11-03T09:30:00+00:00",
        "finished_at": "2026-11-03T09:31:00+00:00",
        "server": {
          "uuid": "9a1f0c2e-4b7d-4e8a-9c3f-1d2e3f4a5b6c",
          "name": "docs-demo",
          "deleted": false
        },
        "site": {
          "uuid": "3c4d5e6f-7a8b-4c9d-8e0f-1a2b3c4d5e6f",
          "name": "example.com"
        },
        "site_deleted": false,
        "initiated_by": {
          "uuid": "7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b",
          "name": "Jane Doe"
        }
      }
    ],
    "pagination": { "total": 1, "per_page": 25, "current_page": 1, "last_page": 1 }
  }
}

To read another team you have access to, add the X-Team-Id header with that team’s UUID from GET /api/v1/teams. See Multi-Team API Tokens and MCP Access.

Step 2: Find who deleted a site

Search for the site’s domain. A deleted site has no ID left to filter by, so search is the way to find it. It matches 3 to 100 characters against the entry’s name.

curl 'https://app.xcloud.host/api/v1/activity?search=old.example.com' \
  --header "Authorization: Bearer $XCLOUD_TOKEN" \
  --header 'Accept: application/json'

Expected result: in most cases, the deletion entry is named Deleting Site (<domain> on <server>), and initiated_by holds who deleted it:

{
  "name": "Deleting Site (old.example.com on docs-demo)",
  "status": "finished",
  "created_at": "2026-11-03T08:56:00+00:00",
  "site": null,
  "site_deleted": false,
  "initiated_by": {
    "uuid": "7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b",
    "name": "Jane Doe"
  }
}

The deletion entry reads site: null and site_deleted: false, because it does not record the site. So don’t filter on site_deleted to find deletions. That field is true only on other entries, the ones that recorded the site before it was deleted.

If the search finds no such entry, the deletion may be one that team activity leaves out.

Step 3: Narrow the list

Combine any of these filters as query parameters:

Filter What it does
server One server’s UUID. Archived servers work too; a permanently deleted server returns an empty list
site One live site’s UUID
initiated_by One person’s UUID, taken from initiated_by.uuid in an earlier response
type One kind of action, such as deployment, custom, system, cleanup or security_patch. A value that isn’t allowed returns 422 with the full list
status queued, running, finished, failed, timeout or killed
since, until A time window. since can go back 30 days at most, and until cannot be in the future
search 3 to 100 characters matched against the entry’s name

For example, this lists what failed for one person since 1 November:

curl -G 'https://app.xcloud.host/api/v1/activity' \
  --data-urlencode 'since=2026-11-01T00:00:00+06:00' \
  --data-urlencode 'status=failed' \
  --data-urlencode 'initiated_by=7e8f9a0b-1c2d-4e3f-8a4b-5c6d7e8f9a0b' \
  --header "Authorization: Bearer $XCLOUD_TOKEN" \
  --header 'Accept: application/json'

Expected result: only the entries that match every filter. Without since, the list starts 30 days ago.

since and until need a date, a time and an offset, such as 2026-11-01T00:00:00Z. A bare date returns 422. When you build the URL yourself, send the + in an offset as %2B, or use Z. --data-urlencode does this for you.

An unknown UUID in server, site or initiated_by returns an empty page with 200, not a 404. So an empty list can also mean the UUID is wrong, or that it belongs to a deleted site or a permanently deleted server.

Step 4: Ask an AI agent

In an MCP client connected to xCloud, ask in plain language:

Who deleted old.example.com in my xCloud team, and when?
What did my team do on xCloud this week? List anything that failed.

The agent runs the activity_list tool, which returns the same data as the API. On the compact MCP profile, the agent finds the activity.list operation with search and runs it through xcloud_execute_read, which changes nothing.

Expected result: an answer that names the person, the action and the time. If you have more than one team, name the team in the prompt.

See who started an event on one server

GET /api/v1/servers/{uuid}/tasks lists one server’s events, and each one now has the same initiated_by field. It needs only read:servers and permission to see that server’s logs and events, so people who can’t read team activity may still be able to use it.

curl 'https://app.xcloud.host/api/v1/servers/SERVER_UUID/tasks?per_page=10' \
  --header "Authorization: Bearer $XCLOUD_TOKEN" \
  --header 'Accept: application/json'

Expected result: the server’s events, newest first, with a short output preview and initiated_by as {uuid, name} or null. On a white-label team, initiated_by is also null when you don’t hold the permission on the white label’s owner team.

What team activity leaves out

  • Some server deletions. Archiving a server leaves no entry, and neither does removing it from xCloud only. Deleting it from its provider too, which always happens for xCloud and white-label servers, adds an entry named DeleteServer with initiated_by. That entry does not name the server once the server is gone.
  • The names of permanently deleted servers. Entries stay for 30 days. server.deleted is true for an archived server. For a permanently deleted server, server is null.
  • Some site deletions. If the site never started setting up, or its server had not finished setting up, there is no Deleting Site entry. Sites removed along with their server have none either.
  • Anything older than 30 days. To keep a longer record, save the results on your side on a schedule.
  • Servers you cannot access. If your access is limited to selected servers, the list covers only those, so entries for archived or permanently deleted servers may not appear.
  • Other teams. Each request reads one team.

Troubleshooting

Response Cause Fix
401 No bearer token, or the token was revoked Send Authorization: Bearer <token> with an active token
403 “Invalid ability provided.” The token is missing read:servers or read:sites Create a token with both. Tokens cannot be edited
403 with both permissions You are a Server Admin or Site Admin, or a Team Admin without the server logs and events permission Ask the team owner to change your role or permission
422 “The since format is invalid.” A bare date, or a + in the offset that wasn’t encoded Send a full date and time. Use Z or %2B
422 “The since must not be older than 30 days.” The window starts too far back Use a since within the last 30 days
422 “The until must not be in the future.” until is more than 5 minutes ahead Use the current time, or leave until out
422 on search The term is shorter than 3 or longer than 100 characters Search for a longer part of the domain, or a shorter one
Empty list with 200 Nothing matches, or a UUID is unknown or belongs to a deleted site or a permanently deleted server Remove filters one at a time. For a deleted site or server, use search
initiated_by is null xCloud started the action itself, or the person’s account was deleted No fix needed. The action is still listed

Frequently asked questions

How do I find out who deleted a site in xCloud?

Call GET /api/v1/activity with search set to the site’s domain, or ask an AI agent connected to xCloud MCP. The matching entry is named Deleting Site, followed by the domain and the server, and initiated_by holds the name of the person who deleted it. Entries stay for 30 days. Some deletions leave no such entry, such as when the site never started setting up or its server had not finished setting up.

Why does GET /api/v1/activity return 403?

Either your token is missing read:servers or read:sites, or your role is not allowed. Only the team owner, or a Team Admin with the server logs and events permission, can read team activity. Server Admins and Site Admins receive 403.

Why does my since filter return 422?

since and until need a full date and time with an offset, such as 2026-11-01T00:00:00Z. A bare date such as 2026-11-01 is rejected. since also cannot be more than 30 days ago, and a + in an offset must be sent as %2B in the URL.

Can I see who deleted a server?

Sometimes. If the server is also deleted from its provider, which always happens for xCloud and white-label servers, the list has an entry named DeleteServer, and initiated_by holds the name of the person who deleted it. That entry does not name the server once the server is gone. Archiving a server leaves no entry, and neither does removing a server from xCloud only. Entries stay for 30 days. server.deleted is true for an archived server. For a permanently deleted server, server is null.

Next steps

If you run into any issues with team activity, feel free to reach out to our support team for help.