Skip to content
github-actions[bot] edited this page Nov 5, 2026 · 2 revisions

POST /api/admin/control

Last updated at: 15/10/2026

TOC

Section Description Subsections
Overview Summary of the endpoint's purpose and requirements. null
Supported actions List of available control actions and their requirements. null
Error responses Possible error responses and their meanings. null
Authentication Details on required authentication and CSRF protection. null
Request Payload Structure of the JSON request body. headers, body, example, refresh, refresh-status, refresh-logs, start, stop, restart, redeploy, delete-log, delete-lines, delete-line, delete-last, rotate-logs, restore-log, delete-log-archive, reset-telemetry, delete-event, delete-error, delete-event-group, delete-error-group, delete-events, delete-errors
Implementation Explanation of how each action is executed. null
Testing Instructions for testing the endpoint. requirements, browser-devtools, bash-wsl-curl, powershell, notes

Overview

The POST /api/admin/control endpoint provides 23 authenticated administrative controls for managing Slackzilla's runtime services, deployments, logs, telemetry, log archives, server history records, and administrator sessions.

All requests must be sent as JSON and include a valid administrative session (slackzilla_admin_session cookie) and csrf token or X-CSRF-Token header.

Actions that modify services or stored data additionally require explicit confirmation through the confirmed property.

The logout control ends the current administrator session and clears the slackzilla_admin_session cookie. It is authenticated, CSRF-protected, and requires confirmed: true when called through this endpoint or the terminal control adapter.

Supported actions

Action Additional fields Confirmation Purpose Link
refresh None No Refreshes runtime status and broadcasts updated admin status and summary data. refresh
refresh-status None No Refreshes and returns the current runtime status. refresh-status
refresh-logs None No Refreshes the current log snapshot and returns its size. refresh-logs
logout None Yes Invalidates the current administrator session and clears its session cookie. logout
start None Yes Starts the configured bot systemd service. start
stop None Yes Stops the configured bot systemd service. stop
restart None Yes Restarts the configured bot systemd service. restart
redeploy None Yes Runs the configured deployment script and updates deployment state. redeploy
delete-log None Yes Clears the current log file. delete-log
delete-lines start [number], end [number] Yes Deletes a range of log lines. Both values must be positive integers. delete-lines
delete-line line [number] Yes Deletes one log line. The line number must be a positive integer. delete-line
delete-last count [number] Yes Deletes the specified number of lines from the end of the log. delete-last
rotate-logs None Yes Rotates the current log into an archive. rotate-logs
restore-log archive [string], optional saveCurrent [boolean] Yes Restores a log archive. Set saveCurrent to true to save the current log before restoring. restore-log
delete-log-archive archive [string] Yes Deletes a stored log archive. delete-log-archive
reset-telemetry None Yes Clears runtime telemetry history and broadcasts the updated status. reset-telemetry
delete-event id [string (UUID)] Yes Deletes one server event occurrence by UUID; it cannot clear event history. delete-event
delete-error id [string (UUID)] Yes Deletes one server error occurrence by UUID; other occurrences remain. delete-error
delete-event-group groupId [string] Yes Deletes every occurrence in one grouped server event signature. delete-event-group
delete-error-group groupId [string] Yes Deletes every occurrence in one grouped server error fingerprint. delete-error-group
delete-events ids [string[] (UUIDs)] Yes Deletes selected or filtered server event occurrences in one operation. delete-events
delete-errors ids [string[] (UUIDs)] Yes Deletes selected or matching server error occurrences in one operation. delete-errors

Some actions include additional data. For example, refresh-logs returns the refreshed log size, rotate-logs returns the created archive, and redeploy returns the deployment state.

Invalid or unknown actions return an error response. Dangerous actions without confirmation return 409 CONFIRMATION_REQUIRED. Invalid log ranges return 400 INVALID_LOG_RANGE.

All deletion controls require the literal boolean confirmed: true. Missing, false, or non-boolean confirmation returns 409 CONFIRMATION_REQUIRED.

Control action failures are recorded as server errors and return 500 CONTROL_ACTION_FAILED.

Error responses

For the POST /api/admin/control endpoint, the following error responses may be returned:

Status Error Condition How to fix
400 BAD_REQUEST Request body cannot be parsed. Send valid JSON with the required fields
400 INVALID_LOG_RANGE Log line or count values are not positive integers. Provide valid positive integers for the relevant fields.
400 UNKNOWN_CONTROL_ACTION Unrecognised control action. Use a supported action listed above
403 CSRF_INVALID csrf token is missing or invalid. Provide a valid token via X-CSRF-Token or the csrf body property.
409 CONFIRMATION_REQUIRED A protected action was requested without "confirmed": true. Include "confirmed": true in the request body.
500 CONTROL_ACTION_FAILED Control action failed. The error is recorded, and the admin summary is broadcast. Check server logs for the underlying error and resolve the cause before retrying.

Note: All errors are returned through the standard error response handler. The 500 response is accompanied by an updated admin summary broadcast.

An example of a 500 CONTROL_ACTION_FAILED response is:

{
    "ok": false,
    "code": "CONTROL_ACTION_FAILED",
    "error": "The 'restart' control action failed due to an internal server error:\n spawn systemctl ENOENT"
}

and a stack trace is recorded in the server logs. To see this error check /admin/errors or /api/admin/errors for the recorded error.

Error: spawn systemctl ENOENT
    at ChildProcess._handle.onexit (node:internal/child_process:287:19)
    at onErrorNT (node:internal/child_process:508:16)
    at process.processTicksAndRejections (node:internal/process/task_queues:90:21)

*this error will happen to all windows hosts since systemctl is not available.

Authentication

Authentication is required for all requests to this endpoint.

Requests must include:

  • A valid slackzilla_admin_session cookie to establish the authenticated administrative session.
  • A valid CSRF token supplied through either the X-CSRF-Token request header or the csrf property in the JSON request body.

The CSRF token must match the token associated with the authenticated session. If both the header and body property are provided, the body property takes precedence.

Requests that fail CSRF validation return 403 CSRF_INVALID.

Actions that require confirmation must additionally include "confirmed": true in the request body. Requests for protected actions without confirmation return 409 CONFIRMATION_REQUIRED.

Request Payload

The endpoint accepts a JSON request body. Every request must include a valid action and CSRF token. Protected actions must also include "confirmed": true.

Headers

Header Required Description
Content-Type Yes Must be application/json.
Cookie Yes Must contain a valid slackzilla_admin_session cookie.
X-CSRF-Token Conditional CSRF token. Required when csrf is not supplied in the request body.

Body

Field Type Required Description
action string Yes Control action to execute. Must be a supported action.
csrf string Conditional CSRF token. Required when X-CSRF-Token is not provided.
confirmed boolean Conditional Must be true for protected actions.
start integer delete-lines Starting log line. Must be a positive integer.
end integer delete-lines Ending log line. Must be a positive integer.
line integer delete-line Log line to delete. Must be a positive integer.
count integer delete-last Number of lines to delete. Must be a positive integer.
archive string restore-log, delete-log-archive Archive identifier.
saveCurrent boolean Optional for restore-log Set to true to save the current log before restoring.
id string (UUID) delete-event, delete-error UUID of the server event or error occurrence to delete.
groupId string delete-event-group, delete-error-group Stable group fingerprint. Must use the appropriate event- or error- prefix.
ids string[] (UUIDs) delete-events, delete-errors Non-empty array of occurrence UUIDs to delete.
archive string delete-log-archive Identifier of the stored log archive to delete.

Example

A basic request:

{
    "action": "refresh"
}

A protected action:

{
    "action": "restart",
    "confirmed": true
}

An action with additional fields:

{
    "action": "delete-lines",
    "start": 2,
    "end": 5,
    "confirmed": true
}

A bulk deletion of server event/errors occurrences:

{
    "action": "delete-events", // or "delete-errors"
    "ids": ["event-occurrence-uuid-1", "event-occurrence-uuid-2"],
    "confirmed": true,
    "csrf": "session-csrf-token"
}

The CSRF token may be supplied either through the X-CSRF-Token header or the csrf body property. If both are provided, the body property takes precedence. The action value must be one of the actions listed in Supported Actions. An example request might be

POST /api/admin/control HTTP/1.1
Host: rylvion.hackclub.app # (or your server host)
Content-Type: application/json
Cookie: slackzilla_admin_session=session-id.signature
X-CSRF-Token: your-csrf-token

{
    "action": "name-of-action",
    "confirmed": true # required for dangerous actions
    "csrf": "your-csrf-token" # not required if X-CSRF-Token header is provided
}

refresh

Refreshes the current runtime status and broadcasts the updated status and admin summary to connected clients. Returns the rendered status summary.

{"action": "refresh"}

refresh-status

Refreshes and broadcasts the current runtime status to connected clients. Returns the rendered status summary.

{"action": "refresh-status"}

refresh-logs

Refreshes the current log snapshot and broadcasts the updated logs to connected clients. Returns the total log file size in bytes.

{"action": "refresh-logs"}

logout

Invalidates the current administrator session server-side and clears the slackzilla_admin_session cookie. The request still requires an authenticated session, a valid CSRF token and explicit confirmation.

{"action": "logout", "confirmed": true}

start

Starts the configured bot systemd service. After successful execution, the endpoint refreshes and broadcasts the runtime status.

{"action": "start", "confirmed": true}

stop

Stops the configured bot systemd service. After successful execution, the endpoint refreshes and broadcasts the runtime status.

{"action": "stop", "confirmed": true}

restart

Restarts the configured bot systemd service. After successful execution, the endpoint refreshes and broadcasts the runtime status.

{"action": "restart", "confirmed": true}

redeploy

Runs the configured deployment script and captures its output in the application log. Saves the resulting deployment state, refreshes runtime status and broadcasts deployment and admin summary updates. Returns the saved deployment state.

{"action": "redeploy", "confirmed": true}

delete-log

Clears the contents of the current log file without removing the file itself. Refreshes and broadcasts the updated log information.

{"action": "delete-log", "confirmed": true}

delete-lines

Deletes a range of lines from the current log using the supplied start and end values. Both values must be positive integers. Refreshes and broadcasts the updated log information.

{"action": "delete-lines", "start": 10, "end": 20, "confirmed": true}

delete-line

Deletes one specified line from the current log. The line value must be a positive integer. Refreshes and broadcasts the updated log information.

{"action": "delete-line", "line": 15, "confirmed": true}

delete-last

Deletes the specified number of lines from the end of the current log. The count value must be a positive integer. Refreshes and broadcasts the updated log information.

{"action": "delete-last", "count": 50, "confirmed": true}

rotate-logs

Archives the current log and rotates it using the log storage system. Refreshes and broadcasts the updated log information. Returns the identifier of the created archive.

{"action": "rotate-logs", "confirmed": true}

restore-log

Restores the current log from the specified archive. The optional saveCurrent property can be set to true to save the existing log before restoration. Refreshes and broadcasts the updated log information.

{"action": "restore-log", "archive": "archive-filename", "saveCurrent": true, "confirmed": true}

delete-log-archive

Permanently deletes the specified stored log archive.

{"action": "delete-log-archive", "archive": "archive-filename", "confirmed": true}

reset-telemetry

Clears the runtime telemetry history, refreshes runtime status and broadcasts the updated status to connected clients.

{"action": "reset-telemetry", "confirmed": true}

delete-event

Deletes one server event occurrence identified by its UUID. Other occurrences belonging to the same event group remain untouched. The updated event history is persisted to metrics.json.

{"action": "delete-event", "id": "7bdf4991cc73964bb82399f858acfff31502ee24cf5ed2e320776b868de53ada", "confirmed": true}

delete-error

Deletes one server error occurrence identified by its UUID. Other occurrences sharing the same error fingerprint remain untouched. The updated error history is persisted to server-errors.json.

{"action": "delete-error", "id": "4b903737-9fc7-45b1-9066-4867f85a5d64", "confirmed": true}

delete-event-group

Deletes every occurrence belonging to the specified server event group. The groupId must use the event- prefix followed by 64 lowercase hexadecimal characters. The updated event history is persisted to metrics.json.

{"action": "delete-event-group", "groupId": "event-74841258f702e52fce550d31012937b2459a59cebb4786689f5761d590fcc5d1", "confirmed": true}

delete-error-group

Deletes every occurrence belonging to the specified server error group. The groupId must use the error- prefix followed by 64 lowercase hexadecimal characters. The updated error history is persisted to server-errors.json.

{"action": "delete-error-group", "groupId": "error-b6c3c9d6ef889ad91265e063c1077925f58fdf9b585514f6fc43fe632d687e99", "confirmed": true}

delete-events

Deletes the server event occurrences identified by the supplied non-empty ids array. Each entry must be a valid UUID. Other event occurrences remain available.

{"action": "delete-events", "ids": ["39580ef4-8ab1-4955-b1e6-322d3633a58f", "481e1774-2952-42c7-97c7-a9da3fb07746"], "confirmed": true}

delete-errors

Deletes the server error occurrences identified by the supplied non-empty ids array. Each entry must be a valid UUID. Other error occurrences remain available.

{"action": "delete-errors", "ids": ["4b903737-9fc7-45b1-9066-4867f85a5d64", "5c014848-afda-46c2-a177-5978096b6e75"], "confirmed": true}

Implementation

notes: context is found on server.js and context.store is server/database/store.js

Action Dependent function Description What function/action is used to perform this action Originating file
Authentication context.auth.requireSession() Verifies that the request has an authenticated admin session. Called before processing any control action. server/lib/auth.js
Session logout context.auth.logout() Invalidates the current session and clears the administrator cookie. logout server/lib/auth.js
CSRF validation context.auth.verifyCsrf() Validates the CSRF token before processing the action. Called before processing any control action. server/lib/auth.js
Request parsing context.parseBody() Parses the incoming JSON request body. Called before processing any control action. server/lib/http.js
Confirmation validation dangerousActions.includes() Checks whether an action requires explicit confirmation before execution. Checks the dangerousActions array against the requested action. handleControlApi()
Log deletion context.store.deleteLogFile() Clears the contents of the current log file. delete-log server/database/store.js
Log line deletion context.store.deleteLogLines() Deletes a specified range of log lines or a single line. delete-lines, delete-line server/database/store.js
Last log deletion context.store.deleteLastLogLines() Removes the specified number of lines from the end of the log. delete-last server/database/store.js
Log rotation context.store.rotateLog() Archives the current log and rotates it. rotate-logs server/database/store.js
Log restoration context.store.restoreLogArchive() Restores a selected log archive, optionally saving the current log. restore-log server/database/store.js
Archive deletion context.store.deleteLogArchive() Deletes a specified log archive. delete-log-archive server/database/store.js
Telemetry reset context.resetTelemetry() Clears collected telemetry data. reset-telemetry server/server.js
Event group deletion context.store.deleteServerEventGroup() Deletes all occurrences in one server event group and persists metrics.json. delete-event-group server/database/store.js
Error group deletion context.store.deleteServerErrorGroup() Deletes all occurrences in one server error group and persists server-errors.json. delete-error-group server/database/store.js
Event bulk deletion context.store.deleteServerEvents() Deletes the submitted event occurrence IDs and persists metrics.json. delete-events server/database/store.js
Error bulk deletion context.store.deleteServerErrors() Deletes the submitted error occurrence IDs and persists server-errors.json. delete-errors server/database/store.js
Deployment context.runDeployScript() Executes the deployment script and captures its output. redeploy server/lib/system.js
Deployment state context.saveDeploymentState() Saves the deployment status, timestamp, output and result. redeploy, deployment error handler server/database/store.js
Service management context.runSystemctl() Executes system service commands to start, stop or restart the bot. start, stop, restart server/lib/system.js
Status refresh context.refreshAndBroadcastStatus() Refreshes system status and broadcasts the updated information. start, stop, restart, redeploy, reset-telemetry, refresh, refresh-status, deployment error handler server/server.js
Log refresh context.refreshAndBroadcastLogs() Refreshes log data and broadcasts the updated logs to connected admin clients. delete-log, delete-lines, delete-last, delete-line, rotate-logs, restore-log, refresh-logs server/server.js
Dashboard summary context.buildAdminSummary() Generates the admin dashboard summary, including the CSRF token. redeploy, refresh, deployment error handler server/server.js
Event broadcasting context.broadcast() Sends deployment, status or summary events to connected admin clients. redeploy (deploy and summary events), refresh (summary event), deployment error handler (deploy and summary events) server/server.js
Status rendering context.renderStatusSummary() Generates the current status summary for the API response. refresh, refresh-status server/server.js
Error recording context.recordServerError() Records errors that occur during control action execution. catch block for failed control actions. server/server.js
Error response context.sendError() Returns structured error responses for invalid requests or failed actions. Authentication, CSRF validation, confirmation validation, invalid log ranges, unknown actions, control action failures and malformed requests. server/lib/http.js
Success response context.sendOk() Returns a successful API response containing the action result. All successfully completed control actions. server/lib/http.js

Testing

Test POST /api/admin/control using Browser DevTools, Bash/WSL, or PowerShell.

Requirements

  • An authenticated admin session with a valid slackzilla_admin_session cookie.
  • A valid CSRF token sent through the X-CSRF-Token header.
  • A supported action. Dangerous actions also require confirmed: true.

Replace action-name in the examples with a supported action.

1. Browser DevTools

Open DevTools (F12), select Console, and run:

const csrf = document.querySelector('meta[name="csrf-token"]')?.content; // or retrieve it from `/api/session` if not present in the DOM

if (!csrf)
    throw new Error("CSRF token unavailable. Check admin authentication.");

const result = await fetch("/api/admin/control", {
    method: "POST",
    headers: {
        "Content-Type": "application/json",
        "X-CSRF-Token": csrf,
    },
    credentials: "same-origin",
    body: JSON.stringify({
        action: "action-name",
        confirmed: true,
    }),
});

console.log(await result.json());

The browser automatically sends the session cookie.The CSRF meta tag is populated after the frontend retrieves the authenticated session from /api/session.

2. Bash / WSL (curl)

Requires curl and jq.

BASE_URL="http://localhost:9000"
SESSION_COOKIE="YOUR_SESSION_COOKIE"
ACTION="action-name"

CSRF=$(curl -fsS "$BASE_URL/api/session" \
    -H "Cookie: slackzilla_admin_session=$SESSION_COOKIE" \
    | jq -er '.data.csrfToken // empty') || {
    echo "Failed to retrieve CSRF token. Check your session."
    exit 1
}

curl -fsS "$BASE_URL/api/admin/control" \
    -H "Content-Type: application/json" \
    -H "Cookie: slackzilla_admin_session=$SESSION_COOKIE" \
    -H "X-CSRF-Token: $CSRF" \
    -d "{\"action\":\"$ACTION\",\"confirmed\":true}"

WSL networking: If Slackzilla runs on Windows and localhost does not reach it, find the Windows host address from WSL:

ip route | awk '/default/ {print $3}'

Set BASE_URL to http://<WINDOWS_HOST_IP>:9000, replacing the placeholder with the reported address.

Obtain your session cookie from your authenticated browser session or the embedded terminal's sudo authentication flow.

3. PowerShell

Replace the session cookie and action, then run:

& {
    $BaseUrl = "http://localhost:9000"
    $SessionCookie = "YOUR_SESSION_COOKIE"
    $WebSession = New-Object Microsoft.PowerShell.Commands.WebRequestSession
    $Cookie = New-Object System.Net.Cookie
    $Cookie.Name = "slackzilla_admin_session"
    $Cookie.Value = $SessionCookie
    $Cookie.Domain = ([uri]$BaseUrl).Host
    $WebSession.Cookies.Add($Cookie)

    $Session = Invoke-RestMethod -Uri "$BaseUrl/api/session" -WebSession $WebSession
    $Csrf = $Session.data.csrfToken

    if (-not $Csrf) {
        throw "CSRF token unavailable. Check your session."
    }

    $Headers = @{ "X-CSRF-Token" = $Csrf }
    $Body = @{ action = "action-name"; confirmed = $true } | ConvertTo-Json

    $Result = Invoke-RestMethod -Uri "$BaseUrl/api/admin/control" `
        -Method Post -WebSession $WebSession -Headers $Headers `
        -ContentType "application/json" -Body $Body

    $Result | ConvertTo-Json -Depth 10
}

4. all cases

POST /api/admin/control HTTP/1.1
Host: localhost:9000
Content-Type: application/json
Cookie: slackzilla_admin_session=YOUR_SESSION
X-CSRF-Token: YOUR_CSRF_TOKEN

{
    "action": "action-name",
    "confirmed": true
}

or type in the embedded terminal:

api post /api/admin/control --headers "X-CSRF-Token: YOUR_CSRF_TOKEN" --body '{"action":"action-name","confirmed":true}'

OR

sudo execute YOUR_ACTION_NAME
Master Password re-prompt: *******

For terminal logout, use sudo logout or sudo execute logout. Both use the same authenticated, CSRF-protected control path and require master-password re-authentication and confirmation in the terminal.

Notes

  • confirmed can be omitted for actions that do not require confirmation.
  • The X-CSRF-Token header is mandatory. A separate csrf body field is unnecessary when the header is provided.
  • Successful requests return ok: true; failures return an error response.
  • Control-action failures retain the underlying diagnostic message in the error response and are also recorded server-side.
  • Windows compatibility: Actions such as start, stop, and restart depend on Linux's systemctl utility. Running them directly on Windows may return CONTROL_ACTION_FAILED with spawn systemctl ENOENT.
  • Security: Never share your session cookie or CSRF token (it has 8hrs lifespan). Both are associated with your authenticated session.

Terminal API diagnostics

The embedded terminal supports api get for an explicit allow-list of public same-origin API routes. Administrative API requests, including api post /api/admin/control, still require the current administrator session and CSRF token; the terminal retrieves the current token from /api/session when needed. It does not permit arbitrary external URLs or use terminal API requests to bypass control confirmation, re-authentication, or rate limits.

Successful terminal login reports only Session: active and CSRF token: available. Raw session cookies and raw CSRF values are not printed or persisted in terminal output.

Clone this wiki locally