-
-
Notifications
You must be signed in to change notification settings - Fork 24
API Sites
Read endpoints for monitored sites. Write endpoints (PUT /v1/site, POST /v1/site/:id,
refresh, fix-update) are documented in this file as they ship in Phase 2.
All requests must carry a valid API token; see overview.md for transports.
List sites visible to the authenticated user, with filtering and pagination.
| Name | Type | Default | Description |
|---|---|---|---|
search |
string | — | Substring match against the site name and URL. |
enabled |
int | — | Filter by enabled flag (0 or 1). |
cmsType |
string | — | Filter by CMS type. Must be a known CMSType enum value (e.g. joomla, wordpress). Unknown values return 400 validation.bad_request. |
limit |
int | 50 | Page size. Negative values are clamped to zero (returns the empty page). |
offset |
int | 0 | Zero-based offset. |
{
"success": true,
"data": [
{
"id": 1,
"name": "example.com",
"url": "https://example.com/",
"enabled": true,
"cmsType": "joomla"
}
],
"pagination": {
"total": 1,
"limit": 50,
"offset": 0
}
}| Status | code |
When |
|---|---|---|
| 400 | validation.bad_request |
cmsType is not a known enum value. |
| 401 | auth.invalid_token |
Missing or invalid token. |
ACL: super-users see all sites; non-super users see sites for which they hold
panopticon.read (filtering is applied by the underlying Model\Site query).
Return the full record for a single site, including its complete config Registry.
| Name | Type | Description |
|---|---|---|
id |
int | Site primary key (positive). |
{
"success": true,
"data": {
"id": 1,
"name": "example.com",
"url": "https://example.com/administrator/index.php?option=com_panopticon",
"baseUrl": "https://example.com/",
"enabled": true,
"cmsType": "joomla",
"created_on": "2026-01-15T12:34:56+00:00",
"created_by": 42,
"modified_on": "2026-04-09T09:21:10+00:00",
"modified_by": 42,
"notes": "Production site",
"config": {
"config": {
"downloadkey": "…",
"core_update": { … },
"extensions": { … },
"username": "…",
"password": "…"
}
}
}
}Important. The
configobject is returned verbatim, with no redaction. Every secret stored against the site (download keys, basic-auth credentials, custom headers, …) is in the response. See overview.md § Secrets and theconfigfield.
| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
The user lacks panopticon.read on this site and is not a super-user. |
| 404 | site.not_found |
No site exists with that id. |
The endpoints below are the JSON equivalents of the Add Site, Edit Site, Refresh
and Fix Joomla core-update site actions in the web UI. Request bodies use the same
flat shape: top-level fields (name, url, enabled, notes, groups) plus a nested
config object whose keys are dot-paths into the site Registry (e.g. config.apiKey,
config.core_update.time.hour). Send only the keys you want changed; everything else is
preserved.
The config object is not redacted on output — see
overview.md § Secrets and the config field.
Create a new monitored site.
{
"name": "example.com",
"url": "https://example.com/api",
"enabled": true,
"notes": "Production site",
"groups": [1, 2],
"config": {
"config": {
"cmsType": "joomla",
"apiKey": "..."
}
}
}name and url are required. enabled defaults to true. groups is an array of
integer group ids that becomes config.groups.
{
"success": true,
"data": {
"id": 42,
"name": "example.com",
"url": "https://example.com/api",
"enabled": true,
"cmsType": "joomla",
"notes": "Production site",
"config": { "config": { "cmsType": "joomla", "apiKey": "..." } }
},
"message": "Site created successfully."
}| Status | code |
When |
|---|---|---|
| 400 | validation.bad_request |
Missing required fields (name/url) or malformed payload types. |
| 400 | request.invalid_json |
Body is not valid JSON. |
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.super, panopticon.admin and panopticon.addown. |
| 422 | validation.unprocessable |
The model's check() rejected the payload (e.g. empty trimmed name). |
ACL: matches the legacy UI onBeforeAdd/canAddEditOrSave — super, global admin, or
panopticon.addown.
Audit: writes site.create to #__audit_log with target_type = "site" and
details = {name, url}.
Modify an existing site. Only the keys present in the request body are updated. config
keys are merged into the existing Registry (per-key set, not full replace).
{
"name": "renamed.example.com",
"enabled": false,
"config": { "config.domain.warning": 180 }
}Same shape as PUT /v1/site.
| Status | code |
When |
|---|---|---|
| 400 | validation.bad_request |
Empty body or invalid field types. |
| 400 | request.invalid_json |
Body is not valid JSON. |
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller is neither super, nor panopticon.admin, nor owner with editown. |
| 404 | site.not_found |
No site exists with that id. |
| 422 | validation.unprocessable |
The model's check() rejected the payload. |
ACL: super → always allowed; otherwise panopticon.admin on the site, or panopticon.editown
when the caller is the owner (created_by).
Audit: writes site.update.
Synchronously refresh the site's information (the same code path as Refresh in the UI).
This invokes the refreshsiteinfo task callback inline and may take several seconds.
Empty.
{ "success": true, "data": null, "message": "Site information refreshed successfully." }| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.read on the site and is not super. |
| 404 | site.not_found |
No site exists with that id. |
| 500 | (none) | The refresh callback raised an exception. |
Audit: writes site.refresh.
Clear the "stuck Joomla core update" flag on a Joomla site. Equivalent to the UI's
Fix Joomla core update site button: posts to the connector's
/v1/panopticon/core/update endpoint. Joomla sites only.
Empty.
{ "success": true, "data": null, "message": "Joomla core update site fixed successfully." }| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.admin on the site and is not super. |
| 404 | site.not_found |
No site exists with that id. |
| 422 | site.wrong_cms |
The site is not a Joomla site. |
| 500 | (none) | The connector call raised an exception. |
Audit: writes site.fix_joomla_core_update.
This file documents the read-only Sites surface. Write endpoints arrive with the Phase 2
phase2-sites-writesub-plan; do not assume the absence of an endpoint here means it does not exist on the wire.
These three endpoints schedule, cancel, and clear the per-site CMS-update task (Joomla
joomlaupdate or WordPress wordpressupdate). They reuse the same shared helpers
(Task\Trait\EnqueueJoomlaUpdateTrait, EnqueueWordPressUpdateTrait) that the UI controller
uses, so behaviour is identical to clicking Schedule update / Cancel / Clear failed
update in the web UI.
Schedule the CMS update task for the site.
{ "force": false }force: true schedules the update even if the site already reports the latest version.
{ "success": true, "data": null, "message": "CMS update scheduled successfully." }| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.run on the site and is not a super-user. |
| 404 | site.not_found |
No site exists with that id. |
| 422 | site.wrong_cms |
CMS type is not Joomla or WordPress. |
ACL: panopticon.run. Audit: site.cmsupdate.schedule.
The integration-test happy path is not executed because scheduling exercises the task queue and indirectly the connector; only the 401/403/404/422 branches are asserted.
Cancel a scheduled CMS update that has not started running. Mirrors the legacy
unscheduleJoomlaUpdate / unscheduleWordPressUpdate.
{ "success": true, "data": null, "message": "CMS update cancelled successfully." }| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.run on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 404 | task.not_scheduled |
The site has no scheduled CMS update task. |
| 422 | task.running |
The task is currently RUNNING/WILL_RESUME and cannot be cancelled. |
| 422 | site.wrong_cms |
CMS type is not Joomla or WordPress. |
Audit: site.cmsupdate.cancel.
Delete a CMS update task (typically used to clear a failed task so a new one can be scheduled).
{ "success": true, "data": null, "message": "CMS update error cleared successfully." }| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.run on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 404 | task.not_scheduled |
No CMS update task exists for this site. |
| 422 | site.wrong_cms |
CMS type is not Joomla or WordPress. |
Audit: site.cmsupdate.clear.
These endpoints manage the per-site extension/plugin update flow. The "list" endpoint returns
the site's extensions.list registry verbatim — no redaction (see overview.md § Secrets).
List all extensions (Joomla) or plugins (WordPress) reported by the site.
{
"success": true,
"data": {
"extensions": [
{
"id": 42,
"name": "com_example",
"description": "Example Component",
"type": "component",
"enabled": true,
"downloadkey": {
"supported": true,
"valid": true,
"prefix": "",
"suffix": "",
"updatesites": [7],
"value": "ABC-123-XYZ"
}
}
],
"quickInfo": { "site_id": 1, "key": "joomla", "hasUpdates": false }
}
}| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.read on the site. |
| 404 | site.not_found |
No site exists with that id. |
ACL: panopticon.read. No audit entry (read-only).
Synchronously refresh installed-extensions information by calling the
refreshinstalledextensions task callback inline (same code path as the UI Refresh
extensions action). May take several seconds.
{ "success": true, "data": null, "message": "Extensions information refreshed successfully." }| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.read on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 500 | (none) | The refresh callback raised an exception. |
ACL: panopticon.read. Audit: site.extensions.refresh.
Happy-path integration test is skipped — running the refresh callback hits the connector.
Clear (delete) a failed extensions-update task; reschedule it if items remain in the queue.
{ "success": true, "data": null, "message": "Extensions update error cleared successfully." }| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.run on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 404 | task.not_scheduled |
No extensions update task exists for this site. |
| 422 | site.wrong_cms |
CMS type is not Joomla or WordPress. |
Audit: site.extensions.clear.
Reschedule the extensions update task. With {"resetqueue": true} in the body, the per-site
queue is also emptied first.
{ "resetqueue": true }{ "success": true, "data": null, "message": "Extensions update reset successfully." }| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.run on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 422 | site.wrong_cms |
CMS type is not Joomla or WordPress. |
Audit: site.extensions.reset.
Enqueue a single extension/plugin for update and trigger the extensions task to run immediately.
{ "success": true, "data": null, "message": "Extension update scheduled successfully." }| Status | code |
When |
|---|---|---|
| 400 | validation.bad_request |
extId is not a positive integer. |
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.run on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 404 | extension.not_found |
The extension is not present in extensions.list. |
| 409 | task.already_scheduled |
The extension is already queued. |
| 422 | site.wrong_cms |
CMS type is not Joomla or WordPress. |
Audit: site.extension.scheduleupdate.
Remove a single extension from the update queue.
| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.run on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 404 | task.not_scheduled |
The extension is not in the queue. |
| 422 | site.wrong_cms |
CMS type is not Joomla or WordPress. |
Audit: site.extension.cancelupdate.
Return the download-key info for a Joomla extension. Joomla sites only.
{
"success": true,
"data": {
"extensionId": 42,
"name": "Example Component",
"downloadkey": {
"supported": true,
"valid": true,
"prefix": "",
"suffix": "",
"updatesites": [7],
"value": "ABC-123-XYZ"
}
}
}| Status | code |
When |
|---|---|---|
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.admin on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 404 | extension.not_found |
The extension does not exist on this site. |
| 422 | site.wrong_cms |
The site is not a Joomla site. |
ACL: panopticon.admin. Audit: site.extension.downloadkey.get.
Save a new download-key value for a Joomla extension. Delegates to
Model\Site::saveDownloadKey() which pushes the value to the remote connector.
{ "key": "ABC-123-XYZ" }key may also be null to clear.
| Status | code |
When |
|---|---|---|
| 400 | validation.bad_request |
key field missing or not a string/null. |
| 401 | auth.invalid_token |
Missing or invalid token. |
| 403 | auth.forbidden |
Caller lacks panopticon.admin on the site. |
| 404 | site.not_found |
No site exists with that id. |
| 404 | extension.not_found |
The extension does not exist on this site. |
| 422 | site.wrong_cms |
The site is not a Joomla site. |
| 422 | extension.invalid_download_key |
The extension does not support download keys / remote NACK. |
Audit: site.extension.downloadkey.set.
Happy-path integration test is skipped — saving a download key calls the remote connector over HTTP. Only the auth / validation / not-found branches are exercised.
- overview.md — cross-cutting concerns (auth, envelope, error codes).
-
../openapi.yaml— machine-readable OpenAPI 3.1 specification.
Documentation Copyright ©2023–2025 Akeeba Ltd.
Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.3 or any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. A copy of the license is included in the section entitled "GNU Free Documentation License".
You can also obtain a copy of the GNU Free Documentation License from the Free Software Foundation
- Overview pages
- Working with sites
- Site Overview
- Backup Management with Akeeba Backup Pro
- Security Management with Admin Tools Pro
- Core File Integrity Check
- Scheduled Update Summary
- Scheduled Action Summary
- Backup Tasks
- Scanner Tasks
- System Configuration
- Managing Sites
- Mail templates
- Web Push Notifications
- Legal Policies
- Users and Groups
- Tasks
- Log files
- Update Panopticon
- Database Backups
- Fixing your session save path
- The .htaccess file
- Advanced Customisation (user code)
- Plugins
- Custom CSS
- Custom Templates
- Advanced Permissions
- .env For Configuration
- API Overview
- Sites endpoints
- Stats & Site Status endpoints
- System configuration endpoints
- Tasks endpoints
- Self-update endpoints