Skip to content

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.

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

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.

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.

  • Bodies are JSON (Content-Type: application/json), except the artifact and dump uploads, which take the raw file as application/octet-stream.
  • Request bodies are capped at 50 MB.
  • List routes return {"results": [...]}. A few add count.
  • 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.

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_port and a deployment git_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.

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.

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

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

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.

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.

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.