Skip to main content
mySites.guru

JCE Profiles Hack (12th June): Joomla sites running JCE are being actively exploited. Find and fix rogue profiles and webshells across every site.

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

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

Last week we introduced the mySites.guru MCP server, which lets you manage your whole WordPress and Joomla estate 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.

Beta Preview Limited scope for now

The set of endpoints available today is deliberately small. We have shipped a focused starting point, we are watching usage and listening to feedback, and we will grow it from there. Treat what follows as the ground floor, not the finished feature.

The short version

The mySites.guru Agency API is a REST API that exposes the same actions you take in the dashboard, including listing sites, reading audits and backups, and triggering audits, backups, snapshots and updates. It uses OAuth2 with PKCE, no static keys, with short-lived 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

Worth being clear about this up front, because it shapes everything else.

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 we launched last week 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.

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 account profile and plan details
  • Your full list of sites, with platform, version, PHP version and connection status, filterable by platform or tag
  • A single site’s full detail
  • Audit results for a site, and the full detail of any individual audit
  • A site’s backups and their status
  • A site’s snapshots
  • The extensions installed on a site
  • The tags across your account

Triggering work:

  • Start a new audit on a site
  • Start a new backup
  • Take a new snapshot
  • Trigger extension updates

The triggering endpoints return immediately and run the job in the background, exactly 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.

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.

Step 1: Register an API client

In your dashboard, go to Account then API Clients and create a new client. You receive a client_id. There is deliberately no client_secret, because PKCE replaces it. You add the redirect URI (or URIs) 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:

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 lands on 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 consent screen. A black header with the mySites.guru logo reads "Authorization Request" and "test wants to access your account". Below, a Permissions Requested list with ten checkmarked items: read your list of sites and their details, modify your sites and their settings, view audit results and reports, run audits on your sites, view backup history and status, create and manage backups, view available updates, install updates on your sites, read your tags and groups, and read your profile information. A black Authorize button and an outlined Deny button sit below, with a note that access can be revoked at any time from account settings.

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 carries the access token:

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

And a response comes back as JSON:

{
"data": [
{
"hash_id": "aB3xY9",
"url": "https://acme.example.com",
"friendly_name": "Acme Corp",
"platform": "Joomla",
"version": "5.2.1",
"php_version": "8.3.4",
"db_version": "8.0.36",
"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"
}
],
"meta": { "current_page": 1, "per_page": 25, "total": 87 }
}

The interactive demo bundled with the API does exactly this against your own account. 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 carries 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 actually 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 tied 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 token cannot reach a site its owner could not already reach in the dashboard. This check is not done once at login and trusted thereafter, it runs on each request.

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 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.

Short-lived tokens and per-user resolution

Access tokens expire after an hour. Permissions are tied to 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.

HTTPS only, rate limited, revocable

Redirect URIs must be HTTPS (the only exception is localhost, for local development). The API is rate limited per token, so a runaway script is contained rather than allowed to hammer the platform. And every client you create is listed in your dashboard under Account then API Clients, where you can revoke any of them in one click. Revoking a client cuts off its access.

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.

A worked example: a nightly audit report

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 summarising any site whose audit score dropped overnight.

With the API, that is a small scheduled script:

  1. Refresh your access token if it has expired.
  2. Call GET /api/v1/sites to get your site list.
  3. For each site, call GET /api/v1/sites/{hashId}/audits and read the most recent score.
  4. Compare against yesterday’s stored scores and assemble the ones that fell.
  5. Email yourself the list.

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 dropped an audit score last night?” 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)

Being honest about the edges is part of being secure and trustworthy.

The API currently covers reading and triggering the core operations listed above. It does not yet offer webhooks or event subscriptions, so you poll for changes rather than being pushed them. The full developer reference documentation is being finalised and is not published yet, so for now the entry point is the Account then API Clients screen in your dashboard, and the flow described in this post. When the reference docs go live we will link them here.

If there is an operation you can do in the dashboard that you want exposed through the API, tell us. The API deliberately 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. Go to Account then API Clients and create a client.
  3. Note your client_id and add your redirect URI.
  4. Run the Authorization Code with PKCE flow described above against the /oauth/authorize and /oauth/token endpoints.
  5. Call https://manage.mysites.guru/api/v1/ with your Bearer token.

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 integrate with the platform. You can list sites, read audit and backup data, list installed extensions, and trigger audits, backups, snapshots, and extension updates, all over standard JSON requests. It exposes the same actions you already perform in the dashboard, and it is the same 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. This is the only supported method: there are no static API keys and no basic auth. You register an API client in your dashboard under Account then API Clients, receive a client_id (there is no client secret, the PKCE verifier replaces it), and your application sends the user to mySites.guru to log in and approve the connection. Your app 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 only. Site-level 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. Permissions are resolved per user when the token is issued, redirect URIs must be HTTPS, and the API is rate limited per token. You approve each connection on a consent screen and can revoke any client from your dashboard.
What can the API actually do?
Read endpoints cover your profile, your sites and their details, audit results, backups, snapshots, installed extensions, and tags. Write endpoints trigger new audits, backups, snapshots, and extension updates. Triggered actions return immediately and run in the background, the same way they do when you click the button in the dashboard. 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 to your dashboard, go to Account then API Clients, and create a new client. You will get a client_id and can add your redirect URIs. From there your application runs the standard OAuth2 Authorization Code flow with PKCE against the authorize and token endpoints, then calls the API with the resulting Bearer token. Full developer reference documentation is on the way.

What our users say

John Flanagan
John FlanaganVice President - GovSites - Spatial Data Logic
★★★★★

mySites.guru is one of the pillars of our operation. The cost for the full suite is less than I would expect to pay for a single function (site upgrades, extension management, audits, backup triggering, secure logins, etc) and Phil is a wealth of knowledge when it comes to troubleshooting. If you are running a website without this platform, chances are something is lurking under the hood that this would uncover in a minute.

Read more reviews

Read all 189 reviews →

Ready to Take Control?

Start with a free site audit. No credit card required.

Get Your Free Site Audit