API overview
The panel’s web UI is a client of the same HTTP API you can call. This page covers what every route has in common. The routes themselves are listed by resource on the other reference pages.
Base URL
Section titled “Base URL”The API is served from the panel’s own origin, at the root path. For example,
https://panel.example.com/apps/. Behind the installer’s Nginx vhost the
server listens on 127.0.0.1:8000 (PORT).
Paths are exactly as listed. Collection routes end with a slash (/apps/,
/teams/). Item routes don’t (/apps/{id}).
Authentication
Section titled “Authentication”Every route requires authentication except POST /auth/login,
POST /auth/login/mfa and POST /webhooks/apps/{appId}.
| Header | Credential |
|---|---|
Authorization: Bearer <jwt> |
Session token from POST /auth/login (or /auth/login/mfa). |
Authorization: Bearer gsl_… |
Personal API token from POST /me/security/tokens. |
X-API-Token: gsl_… |
The same API token, in a separate header. |
An expired, revoked or deactivated credential gets 401. An MFA challenge
token isn’t accepted as a credential.
Permission levels
Section titled “Permission levels”Each route lists the permission it needs:
| Level | Meaning |
|---|---|
| Public | No credential. |
| Authenticated | Any signed-in user. |
| Viewer / Developer / Admin / Owner | At least that role in the team that owns the resource. Superusers pass every team check. See Teams, projects and apps. |
| Member | A member of the team (any role). |
| Superuser | A user with is_superuser: true. |
A non-member and an under-privileged member get the same 403.
Requests and responses
Section titled “Requests and responses”- Bodies are JSON (
Content-Type: application/json), except the artifact and dump uploads, which take the raw file asapplication/octet-stream. - Request bodies are capped at 50 MB.
- List routes return
{"results": [...]}. A few addcount. - Many mutating routes only queue work for the worker and return
{"detail": "… queued."}or the row in a pending state. Poll the row, or use a WebSocket, for the outcome. - Timestamps are ISO 8601 in UTC.
Key casing
Section titled “Key casing”Request bodies always use camelCase (sourceType, isSecret). Responses
come in two styles:
- Objects that mirror a database row use snake_case column names: users,
teams, members, projects, apps, env vars, deployments, build logs, domains,
metric samples, API tokens, SSH keys, audit entries, Applications and their
versions, managed services, alert rules and events, notifications and the
SMTP settings. For example, an app has
internal_portand a deploymentgit_commit_sha. - Responses the API assembles itself use camelCase:
canRollback,myRole, the metrics summary, cron jobs and runs, the webhook status, firewall state, Postgres, MongoDB, storage and mail objects, quotas and/system/info.
Each reference page says which style a response uses when it matters.
Errors
Section titled “Errors”Every non-2xx response is JSON:
{ "error": { "status": 409, "code": "port_in_use", "message": "Port 4001 is already in use by another app.", "details": null }}Validation failures (400) include details, a map of field to message.
Common statuses: 400 bad input, 401 unauthenticated, 403 forbidden,
404 not found, 409 conflict, 422 refused by a business rule, 429
rate limited, 503 a dependency (such as artifact storage) unavailable.
Rate limits
Section titled “Rate limits”| Scope | Limit |
|---|---|
| Default, every route | 300 requests/minute per client IP |
POST /auth/login |
60/minute |
POST /auth/login/mfa |
30/minute |
POST /auth/totp/setup, /enable, /disable, /recovery-codes |
10/minute |
POST /webhooks/apps/{appId} |
120/minute, 5 MB bodies |
Budgets are kept in Redis and shared by every API isolate. If Redis is unreachable, requests are allowed and a warning is logged. Failed sign-ins have a separate throttle (10 per account per address, 50 per account and 100 per address per 15 minutes).
OpenAPI document
Section titled “OpenAPI document”The panel serves a live OpenAPI 3.1 document generated from its controllers,
mounted under /docs:
| Path | Content |
|---|---|
/docs/openapi.json |
The OpenAPI document |
/docs/docs |
Swagger UI |
/docs/redoc |
ReDoc |
WebSockets
Section titled “WebSockets”Live streams are served under /ws, outside the REST pipeline. After the
socket opens, send one JSON text frame with a session JWT and the ids.
The server answers {"ready": true}, or {"error": "<code>"} and closes.
| Path | First frame | Permission |
|---|---|---|
/ws/apps/{id}/logs |
{"token", "appId"} |
Viewer |
/ws/apps/{id}/build-logs/{deploymentId} |
{"token", "appId", "deploymentId"} |
Viewer. The deployment must belong to the app. |
/ws/apps/{id}/exec/{execId} |
{"token", "appId", "execId"} |
Viewer |
/ws/services/{id}/logs |
{"token", "serviceId"} |
Superuser |
Messages are {"message": "<JSON {stream, line}>", "ts": "<ISO time>"}.
Error codes: auth_required, invalid_token, app_not_found,
deployment_not_found, deployment_required, exec_required,
service_required, forbidden.
MCP endpoint
Section titled “MCP endpoint”POST /mcp is a Model Context Protocol server (Streamable HTTP, stateless).
Authenticate with an API token. It exposes the tools search_api, api_get
and api_change, generated from the OpenAPI document. They cover every route
except sign-in and webhook deliveries. File uploads aren’t available. Each
tool call runs through the normal API pipeline. See
Use the API with tokens.
Other paths on the panel origin
Section titled “Other paths on the panel origin”| Path | What |
|---|---|
/admin |
GisilaStudio database admin, only when STUDIO_ENABLED=1 and a non-default STUDIO_PASSWORD is set. |
/ and other non-API paths |
The web UI (a single-page app). Browser navigations that ask for HTML get index.html. |