Skip to content

HTTP and WebSocket API

The canonical machine-readable contract is openapi.yaml. Paths below are relative to the service origin; when BASE_PATH=/postgis-service, both /postgis-service/... and unprefixed forms are routed by the application. JSON responses use application/json; charset=utf-8. Error JSON is generally {"error":"..."}, although middleware and WebSocket pre-upgrade errors use plain text.

All routes require authentication and a service permission; see Authentication. There is no API version prefix, pagination token, idempotency key, or documented stability policy in source.

Browser and asset routes

Methods Path Behavior
GET / 302 to /databases with request base path
GET /login 303 to Central login; global auth middleware runs first
GET, HEAD /workspace, /connections, /databases, /jobs, /users, /users/detail, /groups, /groups/detail, /network-access, /settings, /terminal Render HTML
GET, HEAD /databases/{id} Render database-detail HTML; ID is passed to the template without integer validation
GET, HEAD /app.js, /style.css, /terminal.js Serve local assets with modification-time revalidation
Any matched method /shared/ui/{path} Delegated to the sibling shared UI handler; exact files/method behavior is owned by that handler, not this service

Connections and target-server access

Method Path Input / result
GET /api/connections Connection array; never returns passwords
POST /api/connections {name,host,port,sslmode,admin_username,admin_password}201 {id}
GET /api/connections/{id} One connection
PUT /api/connections/{id} Same body; blank password retains existing password
DELETE /api/connections/{id} Deletes metadata and cascaded database/rule rows, not the PostgreSQL server
POST /api/connections/{id}/test Pings postgres; returns ok and server version
GET /api/connections/{id}/databases Live non-template, connectable database names
POST /api/connections/{id}/postgis-test Optional {database} (default postgres) → PostGIS status/version
PUT /api/connections/{id}/hba-path {hba_file_path} persists path
GET, POST /api/connections/{id}/pg-users List login roles / create {name,password,can_login?,is_superuser?}
PUT, DELETE /api/connections/{id}/pg-users/{name} Update optional password/login/superuser flags / drop role
GET /api/connections/{id}/pg-users/{name}/access Per-database direct/inherited access matrix
GET, POST /api/connections/{id}/pg-groups List non-login roles / create {name}
DELETE /api/connections/{id}/pg-groups/{name} Drop group role
GET /api/connections/{id}/pg-groups/{name}/access Group database access matrix
POST /api/connections/{id}/pg-groups/{name}/members {member} → grant group to role
DELETE /api/connections/{id}/pg-groups/{name}/members/{member} Revoke membership

Role path names are URL-decoded and validated as safe PostgreSQL identifiers before mutation. Reserved roles cannot be dropped. Database access levels are readonly, readwrite, and admin; bundles apply to all currently grantable non-system schemas and alter default privileges for the connected administrator.

Network access and settings

Method Path Input / result
GET, POST /api/connections/{id}/access-rules List rules/path / create rule
PUT, DELETE /api/connections/{id}/access-rules/{ruleId} Replace or delete a stored rule
POST /api/connections/{id}/access-rules/apply Backup and replace managed HBA block, then pg_reload_conf()
GET /api/settings?connection_id={id} Curated settings groups and restart/modified counts
POST /api/settings/update {connection_id,name,value}ALTER SYSTEM SET and reload

HBA rule body fields are name, cidr, auth_method, database_name, role_name, and optional enabled (default true). Auth methods are only scram-sha-256 and md5; trust is forbidden. An all-address rule with empty database and role scope is rejected. See Configuration for settings validation.

Databases and data

Method Path Input / result
GET /api/databases?connection_id={id} Enriched registered databases; zero/invalid filter means all
POST /api/databases {connection_id,name,purpose?,enable_postgis?}202 database/job IDs
GET /api/databases/{id} Registry, connection, live size/PostGIS, table count, geometry/SRID summary
DELETE /api/databases/{id} {confirm_name} → queued deletion
POST /api/databases/{id}/clone {name} → queued same-connection template clone
POST /api/databases/{id}/backup Queue custom-format backup
GET /api/databases/{id}/backups Artifact metadata array, newest filename first
GET /api/databases/{id}/backups/{filename} Binary artifact download
POST /api/databases/{id}/restore {artifact,mode?,new_database_name?}; mode existing (default) or new
POST /api/databases/{id}/import/upload Multipart file, maximum body 512 MiB → server source_path
POST /api/databases/{id}/import Queue import using {source_path,schema?,table_name?,srid_policy?,layer_name?,overwrite?}
GET /api/databases/{id}/schemas Non-system schemas
GET /api/databases/{id}/tables?schema={name} Base tables with geometry, SRID, estimate, size, index count
GET, POST /api/databases/{id}/access List persisted grants / apply {role_name,level}
PUT, DELETE /api/databases/{id}/access/{name} Apply {level} / revoke PostgreSQL and metadata grant

Upload formats are .gpkg, .zip, .geojson, .json, and .shp. Import accepts those formats; ZIP must contain shapefiles. Schema defaults to public, overwrite defaults true, and accepted SRID policies are effectively blank/preserve/detect or EPSG:<positive integer>. Invalid non-EPSG strings currently behave like preserve rather than returning validation errors.

Restore artifact is a server-side path and must remain under the configured backup directory. Use the backup listing's artifact value; arbitrary client uploads are not accepted by restore.

Jobs

Method Path Behavior
GET /api/jobs?limit={n} Newest first; default 100. A negative/zero value also becomes 100. No maximum is enforced.
GET /api/jobs/{id} One job, including payload, result, progress, stage, and errors
POST /api/jobs/{id}/cancel Cancels only queued; running jobs return 409

See Architecture for worker semantics.

WebSockets

These paths are registered without HTTP method restrictions and are intended for WebSocket GET upgrades:

Path Query Function
/api/terminal/ws/psql required connection_id; optional database default postgres Interactive psql PTY using stored admin credentials
/api/terminal/ws/server optional connection_id and database Restricted line-oriented server terminal; DB maintenance commands require a connection
/api/terminal/ws/logs optional positive lines, default 200 and internally clamped Follows journalctl -u postgresql

Binary frames carry terminal input/output. Text frames carry JSON control messages:

{"type":"resize","cols":120,"rows":40}

Defined control types are resize, pause, resume, filter, ping, pong, error, and info; fields are cols, rows, filter, and message. Logs use pause/resume/filter; PTY bridges use resize and ping/pong where handled. Exact close codes are not defined as a public contract.

The restricted terminal allows only PostgreSQL systemctl status/restart/reload, PostgreSQL journalctl, df -h, free -m, filtered ps aux, vacuumdb, reindexdb, restricted pg_dump, and list-only pg_restore. Shell metacharacters are rejected. See Authentication for origin and admin checks.