Skip to main content
mySites.guru
NewmySites.guru is now a Cloudflare verified serviceWhat it means for your sites

How to Access Your mySites.guru Account Using our Secure API

How to Access Your mySites.guru Account Using our Secure API

The mySites.guru MCP server lets you manage all of your WordPress and Joomla sites by talking to an AI client like Claude. A lot of you asked the obvious follow-up question: what is underneath it, and can I use that directly from my own code?

The answer is yes. Underneath the MCP server is the mySites.guru Agency API, a secure REST API that does everything the MCP server does, and it is the foundation we built the MCP server on top of. This post explains what the API is, how you connect to it securely, and why “secure by design” is a claim we can actually back up rather than a line on a marketing page.

If you have ever wanted to pull your site list into your own dashboard, fire off audits from a cron job, or trigger a round of extension updates from a deploy script, this is the tool for that.

The short version

The mySites.guru Agency API is a REST API at https://manage.mysites.guru/api/v1/ that exposes the same actions you take in the dashboard: a one-call summary of every site, every waiting update across all your sites, audit, backup and snapshot history, and the ability to start audits, backups, snapshots and extension updates. It uses OAuth2 with PKCE, no static keys, with one-hour tokens scoped to your own sites. It is the same engine the MCP server runs on, so you can use the API on its own, the MCP server on its own, or both together.

The API, the MCP server, and how they relate

The Agency API is the engine. It is a plain REST API: your code sends an HTTP request with a token, the API does the work and sends JSON back. The MCP server is a second front door bolted onto that same engine, designed so an AI client can drive it in natural language. Both share the same authentication, the same per-user scoping, and the same underlying actions. The MCP server is, in effect, a thin translation layer that turns “back up all my Joomla sites” from an AI client into the same operations the API exposes directly. The twins are easy to spot: the MCP server’s list_site_summaries, list_available_updates, get_weekly_summary, list_timeline and get_site_vulnerabilities tools read the same data as the API’s site summary, updates, weekly summary, timeline and per-site vulnerabilities endpoints.

That gives you three ways to use mySites.guru programmatically:

  • The API instead of the MCP server. Write a script, a dashboard, or a scheduled job that talks straight to the REST API. No AI client involved.
  • The API alongside the MCP server. Use Claude for ad-hoc, conversational work, and a scripted API integration for the repeatable, scheduled jobs. They share the same account and the same permissions model.
  • The API as a standalone service. Wire mySites.guru into your own agency dashboard, a status page, or an internal tool, with no dependency on any AI tooling at all.

Pick whichever fits the job. Nothing about the API requires you to use the MCP server, and nothing about the MCP server is doing anything the API could not.

What the API can do

The API exposes the same actions you already perform by hand in the dashboard, split into reading data and triggering work.

Reading data

  • Your profile: uuid, email, name and company
  • Your full list of sites, with platform, version and lifecycle, PHP and database versions, tags, connection status, last audit and backup times and a count of core vulnerabilities
  • A one-call summary of every site, built from data already held, with update and vulnerability counts, last snapshot, audit and backup times, SSL expiry, and a needs-attention flag with the reasons behind it; this is the endpoint that filters by platform, tag, needs-attention or a list of up to 100 hash ids (hash_ids), and sorts by name, last snapshot, last completed backup or waiting updates. Each row also has php_unofficial_build, set when a site runs a PHP version above the last official release of an end-of-life branch (7.4.34, say, when PHP’s last 7.4 was 7.4.33), which means the host’s own build, whose fixes cannot be checked
  • A single site’s full detail, including connector version, schedules, SSL expiry, the latest core version, published core vulnerabilities and the Cloudflare zone state when you have connected Cloudflare. For Joomla it also reports download_keys_missing, the number of enabled update sites that need a download key the site does not have (updates for those extensions fail until it is set); the keys themselves are never returned
  • Every known vulnerability on one site: vulnerable extensions and CMS core, both sorted worst first (critical, high, medium, low, unknown), each extension row with its name, installed version, patched version, CVE, severity, title and a dashboard_url. Extension matches use today’s advisory rules against the extension list from the last snapshot, so a newly published advisory shows up without waiting for a new snapshot. Filter by severity (a comma list), and send If-None-Match with the weak ETag from the last reply to get a 304 with no body when nothing has changed (a 304 still counts against the rate limit)
  • Every extension update waiting across all your sites in one list, each row flagged when it is a major version jump, when it has been snoozed or its site’s updates paused, and when it closes a known vulnerability (with the CVE); narrow it with site (one site’s hash id) or extension (one exact update key)
  • A timeline of what ran on your sites and what your team did, newest first. Only the account owner’s token can read it; a team member’s gets a 403. Rows are grouped: one group per activity per day, one per site per day for outages and hacks, one per run of actions by a person or API client, plus release, advisory and core news rows. Pick the window with from and to (local days, the last 7 by default, at most 90 days back) and tz (an IANA zone, UTC by default), filter by event (snapshots, audits, backups, updates, uptime, security, alerts, extensions, ssl, cloudflare, team, releases, advisories), outcome (ok, failed, warn), trigger (you, teammate, schedule, api, mcp) or hashId for one site, and take 1 to 500 groups at a time (limit, default 100). Text that came from a site is never included, and a failure is explained in mySites.guru’s own words in reason
  • A week in review for the whole account, the same data as the weekly summary email: snapshots, audits, backups, updates, alerts and outages per day, core upgrades, the busiest sites by updates, what needs you, and the week-on-week change
  • Audit results for a site (the 50 most recent), and the full detail of any individual audit
  • A site’s backups and their status (the 50 most recent)
  • A site’s snapshots (the 20 most recent)
  • The extensions installed on a site, with their installed versions
  • The tags across your account
  • Your email notification switches, the same ones as the Email Notifications page, each with its current value, plus downtimeonly (Downtime alerts only); a team member sees fewer switches than the owner, as on the page

Triggering work

  • Start a new audit on a site (if another audit is already running on the same server, it waits and starts when that server is free)
  • Start a new backup, with an optional comment
  • Take a new snapshot
  • Queue extension updates for a site, for Joomla extensions and WordPress plugins and themes alike
  • Turn one email notification switch on or off, with a body like {"key": "robotsblocked", "value": false}; an unknown key or a non-boolean value gets a 422

The four job-starting endpoints return 202 Accepted immediately and run the job in the background, as they do when you click the button in the dashboard. You get a confirmation that the job was queued, not a response that blocks until a backup finishes, and the reply includes a timeline_url: a link to that site in the mySites.guru Timeline, filtered to that kind of job, where the job shows when it finishes. Changing a notification switch is the exception: it takes effect at once and the reply confirms it. Queued updates go through the same per-server Update Queue as the dashboard, so sites sharing a server update one at a time, and every one of them appears in the Update Log. A snoozed update, or one on a site with updates paused, is skipped rather than queued: the reply lists it with "skipped": "snoozed", and a call where every update named is snoozed returns 409 with the error snoozed (how snoozing works).

The important principle is that the API never grants more than you already have. Every action maps to something your account can already do. If you cannot see a site in the dashboard, no token issued to you can reach it through the API either.

How you connect: OAuth2 with PKCE

This is the part that earns the “secure” in the title, so it is worth walking through properly. If OAuth flows make your eyes glaze over, the headline is: no passwords leave your app, nothing long-lived is sitting around to be stolen, and you approve each connection yourself.

The API uses the OAuth2 Authorization Code flow with PKCE, and that is the only supported method. There are no static API keys to leak, no basic-auth passwords sitting in a config file, and no long-lived bearer tokens that work forever if they escape. If you have integrated with Google, GitHub or a bank’s API, the shape of this will be familiar. OAuth-aware clients can also discover the endpoints for themselves from the authorization server metadata and the API’s protected resource metadata, which is where a 401 response’s WWW-Authenticate header points.

Step 1: Register an API client

Open the API Clients page in your account settings and create a new client (this is the account owner’s job). You receive a client_id. There is no client_secret, because PKCE replaces it. You add the redirect URI (or URIs, one per line) your application will use, and you are done.

Step 2: Generate a PKCE pair

Before sending the user off to authorize, your application generates a one-time secret called a code verifier, and a hashed version of it called a code challenge:

// Browser example using the Web Crypto API
const verifier = base64url(crypto.getRandomValues(new Uint8Array(32)));
const challenge = base64url(
  await crypto.subtle.digest('SHA-256', new TextEncoder().encode(verifier))
);

You keep the verifier private and send only the challenge in the next step. This is what stops an intercepted authorization code from being useful to anyone but you.

Step 3: Send the user to authorize

Your application redirects the user to the authorization endpoint, asking for exactly the scopes it needs, with a random state value you check when the user comes back:

GET https://manage.mysites.guru/oauth/authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://yourapp.example.com/callback
  &scope=api:profile:read api:sites:read
  &code_challenge=BASE64URL_SHA256_OF_VERIFIER
  &code_challenge_method=S256
  &state=RANDOM_NONCE

The user arrives at a mySites.guru consent screen, signs in if they are not already, and sees exactly which permissions your application is asking for. Your application never sees their password. If they approve, they are sent back to your redirect URI with a short-lived authorization code.

The mySites.guru Authorization Request screen for an API client: the permissions it asks for, from reading your sites to installing updates, above Authorize and Deny buttons

The consent screen the user approves. Each line is a plain-English description of one requested scope, so the user sees exactly what they are granting before they click Authorize.

Step 4: Exchange the code for tokens

Your application swaps the code, plus the original verifier, for tokens:

POST https://manage.mysites.guru/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=authorization_code
&code=AUTH_CODE_FROM_CALLBACK
&redirect_uri=https://yourapp.example.com/callback
&client_id=YOUR_CLIENT_ID
&code_verifier=YOUR_ORIGINAL_VERIFIER

You get back an access token and a refresh token:

{
  "token_type": "Bearer",
  "expires_in": 3600,
  "access_token": "eyJ...",
  "refresh_token": "def502..."
}

Step 5: Call the API

From here, every request has the access token:

GET https://manage.mysites.guru/api/v1/sites
Authorization: Bearer eyJ...

And a response comes back as JSON. Every list endpoint except the timeline returns the whole set in one response, and meta tells you how many rows that was. The timeline is the one that pages: each reply has a next_before cursor and a has_more flag, and you pass the cursor back as before to read older groups.

{
  "data": [
    {
      "hash_id": "aB3xY9",
      "url": "https://acme.example.com",
      "friendly_name": "Acme Corp",
      "platform": "Joomla",
      "version": "5.4.8",
      "cms_lifecycle": "security_only",
      "cms_eol_date": "2027-10-12",
      "php_version": "8.3.27",
      "db_version": "10.11.14-MariaDB",
      "db_support_status": "supported",
      "db_eol_date": "2028-02-16",
      "tags": [
        { "slug": "client", "name": "Client", "color": "#3b82f6" }
      ],
      "is_connected": true,
      "last_audit": "2026-06-06T18:54:25+00:00",
      "last_backup": "2026-06-06T02:00:00+00:00",
      "core_vulnerability_count": 0
    }
  ],
  "meta": { "total": 87 }
}

The interactive demo does exactly this against your own account, and its redirect URI is already allowed for every API client, so you only paste in your client_id. Here it is calling GET /api/v1/sites/{hashId}/audits/{id} and getting a real audit back: files scanned, suspect files, hidden files, missing core files, and the hacked flag, all from one signed request.

The mySites.guru API demo after authorising. The token bar shows the granted api: scopes (api:sites:read, api:sites:write, api:audits:read, api:audits:write and more). A GET request to /api/v1/sites/hashId/audits/id has been executed and returns HTTP 200 with a JSON body: id, status Complete, started_at and completed_at timestamps, files_scanned 13693, suspect_files 1, hacked false, hidden_files 58, hidden_folders 3, files_777 0, folders_777 0, zero_bytes 3 and missing_core_files 1.

The bundled demo running a live audit lookup against a real site, returning HTTP 200. The token has the api: scopes granted on the consent screen.

Step 6: Refresh when the token expires

Access tokens last one hour. When one expires, your application uses the refresh token (valid for one month) to get a new pair, without sending the user through the consent screen again:

POST https://manage.mysites.guru/oauth/token
Content-Type: application/x-www-form-urlencoded

grant_type=refresh_token
&refresh_token=def502...
&client_id=YOUR_CLIENT_ID

The old refresh token is invalidated and you receive a fresh pair. Short-lived access tokens with rotating refresh tokens mean that even in the worst case, an exposed access token is useful for at most an hour.

Why “secure by design” is more than a slogan

Security here is not a feature bolted on afterwards. It falls out of how the API is built. Here is what that means in practice.

No static secrets

Because the only supported flow is Authorization Code with PKCE, there is no permanent API key that grants access forever. The thing your application holds long term is a refresh token scoped to a specific user’s approval, and even that expires. There is no shared secret to find in a leaked .env file and replay.

Tokens are scoped to your own sites, and re-checked every time

When a token is issued, the permissions are resolved for that specific user. On every single request to a site-specific endpoint, the API independently confirms that the site belongs to the user’s company, and, if the user is a restricted team member, that the site is one they are allowed to see. A site that does not exist gets a 404 not_found; a site that belongs to another account gets a 403 access_denied. A token cannot reach a site its owner could not already reach in the dashboard, and the check runs on each request rather than once at login.

Scopes mean least privilege

Your application asks only for the scopes it needs, such as api:sites:read on its own, or api:audits:write to trigger audits. The full list is api:profile:read, api:sites:read, api:sites:write (reserved, no endpoint uses it yet), api:audits:read and api:audits:write, api:backups:read and api:backups:write, api:updates:read and api:updates:write, api:tags:read, and api:preferences:read and api:preferences:write for the notification switches. The consent screen shows the user exactly what they are granting before they approve. A read-only reporting dashboard never needs to ask for write access, and a user can see that it has not. A token keeps the scopes it was issued with, so if your application later needs another one, it sends the user through the consent screen again rather than widening its reach without asking.

Short-lived tokens and per-user resolution

Access tokens expire after an hour. Permissions are resolved for the user who approved the connection, not baked into a shared client, so the same integration approved by two different people gets each person’s own access and never leaks one user’s reach to another.

Rate limited and revocable

Each access token gets 1,000 requests an hour, the hour starting at the token’s first request. Go over it and you get an HTTP 429 with a Retry-After header saying how many seconds to wait, so a runaway script is contained rather than allowed to hammer the platform. And every client you create is listed on the API Clients page, where you can revoke any of them in one click. A revoked client can no longer be authorised or refresh its tokens; an access token it already holds keeps working only until it expires, which is at most an hour away.

This is the same security model we described for the MCP server, for the simple reason that they share it. The MCP server is secure for the same reasons the API is: it is the same OAuth2 layer underneath.

What does a morning report look like through the API?

To make this concrete, picture the kind of thing the API is built for. You run an agency with 80 client sites and you want a single email each morning telling you which sites need attention, why, and which waiting updates close a known vulnerability. With the API, that is a small scheduled script built around a few calls:

  1. Refresh your access token if it has expired.
  2. Call GET /api/v1/timeline?outcome=failed&from=YESTERDAY for what failed overnight: every failed audit, backup, snapshot or update since yesterday, grouped by activity and day, each with the reason in mySites.guru’s own words. One request covers the whole account.
  3. Call GET /api/v1/sites/summary?needs_attention=true. Every site that needs action comes back in one response, each with its attention_reasons: hacked, updates or a core update available, vulnerable extensions, core vulnerabilities, PHP missing the 21 October 2026 security release, unchecked template overrides on a Joomla 4+ site, disconnected, or a stale snapshot. The meta block includes a one-sentence summary, such as “4 of 80 sites need attention”, and a count per reason.
  4. Call GET /api/v1/updates and keep the rows whose security flag is set. Each of those is an installed version with a known vulnerability that the available version fixes, named with its CVE, across every site you manage.
  5. Optionally, queue those updates. The extension.key on an update row is the site’s own update key, not the key the update endpoint takes, so look each one up in that site’s GET /api/v1/sites/{hashId}/extensions list first, then send the matching key values to POST /api/v1/sites/{hashId}/extensions/update. The updates go into the per-server Update Queue, so two sites on the same server never update at once, and each one shows up in the Update Log.
  6. Email yourself the overnight failures, the meta.summary line and the list of security updates you queued.

That is a handful of requests whatever the number of sites you manage, which sits comfortably inside the 1,000 an hour each token gets. On a Monday, add GET /api/v1/weekly-summary for the same week in review the weekly summary email gives you: snapshots, audits, backups, updates, alerts and outages per day, and the change on the week before.

No browser, no clicking through 80 dashboards, no AI client in the loop. Just your own code, running on your own schedule, talking to a secure API. If you would rather ask the same question conversationally now and then, the MCP server answers “which of my sites need attention this morning?” from an AI client, using this exact same data.

For agencies already leaning on scheduled audits, updates and backups inside mySites.guru, the API is the natural next step when you want that automation wired into your own systems rather than ours.

What the API does not do (yet)

For most data you poll for changes. Snapshots run about every 12 hours, and the summary and the updates list change when a site is snapshotted or checked, so polling more often returns the same data. The exception is uptime: down and up alerts can be pushed to a signed webhook as they happen.

Only the timeline paginates, with the before cursor, and it reaches back about 92 days, which is how long its raw rows are kept. Every other list endpoint returns the whole set in one response, by design, and meta.total tells you how many rows that was. The installed extensions list for a site tells you what is installed and at what version, but not whether a version is out of date; that question is answered by GET /updates, which lists every waiting update across all your sites. The api:sites:write scope exists on the consent screen but no endpoint uses it yet.

The developer reference is published at manage.mysites.guru/api-docs, with a machine-readable OpenAPI spec alongside it and the interactive demo for trying calls against your own account.

If there is an operation you can do in the dashboard that you want exposed through the API, tell us. The API mirrors the dashboard, so the roadmap for it is driven by what you actually want to automate.

Getting started

  1. Sign in to your mySites.guru dashboard.
  2. Open the API Clients page in your account settings and create a client.
  3. Note your client_id and add your redirect URIs, one per line.
  4. Run the Authorization Code with PKCE flow described above against the /oauth/authorize and /oauth/token endpoints, or paste your client_id into the demo to watch it happen first.
  5. Call https://manage.mysites.guru/api/v1/ with your Bearer token, with the developer reference open beside you.

If you are not yet a mySites.guru subscriber, you can start with a free audit or see everything the platform does first. The API, like the MCP server, is there to let you bend mySites.guru around your own workflow rather than the other way around.

Further Reading


Want to manage your sites without writing a line of code? The mySites.guru MCP server runs on this same API and lets you do it all in plain language from an AI client.

Frequently Asked Questions

What is the mySites.guru API?
The mySites.guru Agency API is a REST API that lets your own tooling, dashboards or scripts work with your account. You can list your sites, read a one-call summary of every site, see every extension update waiting across all your sites, read audit, backup and snapshot history, read a timeline of what ran on your sites and what your team did, list every known vulnerability on one site, list installed extensions and tags, read and change your email notification switches, and trigger audits, backups, snapshots and extension updates, all over JSON. It exposes the same actions you already take in the dashboard, and it is the foundation the mySites.guru MCP server is built on.
How does authentication work on the mySites.guru API?
The API uses the OAuth2 Authorization Code flow with PKCE, and that is the only method: there are no static API keys and no basic auth. The account owner creates an API client on the API Clients page in account settings, receives a client_id (there is no client secret, the PKCE verifier replaces it) and registers the redirect URIs the application will use. Your application sends the user to mySites.guru to sign in and approve the connection, so it never sees the user's password, and the access token it receives is scoped to that user's own sites.
Can I use the API instead of the MCP server?
Yes. The API and the MCP server are two front doors to the same engine. You can use the API on its own without ever touching the MCP server, use the MCP server on its own with an AI client like Claude, or use both side by side. The API suits your own scripts, cron jobs and dashboards. The MCP server suits natural-language control from an AI client. Both authenticate through the same OAuth2 layer and both respect the same per-user scoping.
Is the mySites.guru API secure?
It is secure by design. Every token is issued through OAuth2 with PKCE, expires after one hour, and is scoped to the authenticated user's own sites. Site access is checked on every request against the user's company and any team restrictions, so a token can never reach a site the user could not already see. You approve each connection on a consent screen that lists every requested scope in plain English, each token is limited to 1,000 requests an hour, and you can revoke any client in one click. A revoked client cannot be authorised again or refresh its tokens, and any access token it still holds stops working within the hour.
What can the API actually do?
Read endpoints cover your profile, your sites and each site's full detail, a one-call summary of every site with a needs-attention flag, every extension update waiting across all your sites, a week-in-review summary, a timeline of what ran on your sites and what your team did (account owner only), every known vulnerability on one site sorted worst first, audit results, backups, snapshots, installed extensions, tags and your email notification switches. Write endpoints start audits, backups and snapshots, queue extension updates and turn a notification switch on or off. Each job-starting write returns 202 Accepted straight away and the job runs in the background, the same way it does when you click the button in the dashboard; the notification switch changes at once. The API mirrors what you can already do by hand, so it never grants more access than your account already has.
Do I need to be a developer to use the API?
To call the API directly, yes, you need to be comfortable with OAuth2 and writing HTTP requests in a language like JavaScript, PHP or Python. If you want the same capabilities without writing code, the MCP server gives you natural-language control through an AI client instead, and it runs on this same API underneath. Pick the API when you want precise, scripted automation, and the MCP server when you want conversational control.
How do I get started with the mySites.guru API?
Sign in, open the API Clients page in your account settings at https://manage.mysites.guru/en/account/api-clients and create a client. You get a client_id and register your redirect URIs. Your application then runs the OAuth2 Authorization Code flow with PKCE against the authorize and token endpoints and calls the API with the resulting Bearer token. The developer reference is at https://manage.mysites.guru/api-docs/ and an interactive demo at https://manage.mysites.guru/api-demo/ runs the whole flow against your own account with only your client_id.
EU icon: AI MODIFIEDWritten and edited by a human, with AI assistance. Our approach to AI

What our users say

Tomasz
TomaszAL-TAIR
★★★★★

I've been managing multiple Joomla! websites for years, and I honestly can't believe I wasn't using mySites.guru sooner. It has completely changed the way I maintain and monitor my sites. The service is incredibly useful, making it easy to keep track of updates, security, backups, and the overall health of all my Joomla! installations from one place. It's a huge time-saver and makes managing multiple websites so much more convenient. On top of that, the pricing is extremely attractive for everything you get. The value is outstanding, especially if you manage more than one Joomla! website. I highly recommend mySites.guru to anyone working with Joomla!. It's one of those tools that, once you start using it, you wonder how you ever managed without it.

Read more reviews
Artur Żugaj
Artur ŻugajWebart IT
★★★★★

A very helpful tool, with website monitoring, updates, backups, scanning, and unlimited sites. One price for many sites. I wholeheartedly recommend it. Fantastic.

Read more reviews

Read all 303 reviews →

Ready to Take Control?

One free audit of one site · no card · about 2 minutes to connect

Get Your Free Site Audit