Complete HTTP endpoint reference for all scorpiox servers — scorpiox-server (CGI routing, JWT, SSE), scorpiox-host (session gateway), scorpiox-ws2tcp (WebSocket bridge), and scorpiox-server-email (SMTP/IMAP).
Scorpiox ships 4 HTTP/TCP servers, all written in pure C with zero dependencies. Together they expose 24 endpoints covering web hosting, session management, WebSocket bridging, and email protocols.
# 4 servers, 24 endpoints, all pure C
scorpiox-server :8080 # HTTP + CGI + JWT + SSE
scorpiox-host :7432 # Session gateway + REST API
scorpiox-ws2tcp :6080 # WebSocket-to-TCP bridge
scorpiox-server-email :25/587/993 # SMTP + IMAP
Lightweight HTTP server — executes Python scripts as CGI routes with JWT auth, CORS, SSE streaming, and git-deploy auto-pull.
Session gateway server — tracks AI coding sessions, events, and message queuing with REST API.
SMTP + IMAP email server with TLS (STARTTLS), DKIM signing, aliases, and per-user mail filtering.
WebSocket-to-TCP bridge — replaces Python websockify for noVNC deployments, with static file serving.
24 endpoints across all servers. Auth column: ● none, ● conditional, ● required.
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /api/ping | Health check — returns 'ok' as plain text | ● |
| GET | /api/otp?a=<account> | Generate TOTP code via scorpiox-otp CLI | ● |
| GET | {prefix} | Default route — runs index.py when path matches prefix exactly | ● |
| GET | {prefix}{name} | Named route — runs {name}.py from first matching script directory | ● |
| POST | {prefix}{name} | POST route — runs {name}.py with body in temp file or stdin streaming (>10MB) | ● |
| * | * | Fallback route — runs _fallback.py for unmatched paths | ● |
| * | CORS preflight — returns 204 with permissive CORS headers | ● | |
| GET|POST | SSE (text/event-stream) | Server-Sent Events — script outputs chunked text/event-stream | ● |
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /health | Health check | ● |
| GET | /status | Server status with active session count | ● |
| GET | /sessions | List all active sessions | ● |
| GET | /sessions/:id | Get session details by ID | ● |
| GET | /sessions/:id/events | Get session events from ring buffer | ● |
| POST | /sessions/:id/events | Push an event to session ring buffer | ● |
| POST | /sessions/:id/register | Register a new session | ● |
| GET | /sessions/:id/messages | Read messages from session queue | ● |
| POST | /sessions/:id/messages | Send a message to session queue | ● |
| POST | /stop | Graceful server shutdown | ● |
| Method | Path | Description | Auth |
|---|---|---|---|
| WS | /websockify | WebSocket upgrade — bridge to TCP backend (RFC 6455) | ● |
| WS | / | WebSocket upgrade — root path alias | ● |
| GET | /* | Static file serving from web root | ● |
| Protocol | Path | Description | Auth |
|---|---|---|---|
| SMTP | port 25 | SMTP MTA — receive and relay mail with STARTTLS + DKIM | ● |
| SMTP | port 587 | SMTP submission — authenticated relay for local users | ● |
| IMAP | port 993 | IMAP over TLS — mailbox access with Maildir storage | ● |
JWT cookie validation (HMAC-SHA256) — extracts user_id and email from sx_token cookie, passes X_AUTHENTICATED, X_USER_ID, X_USER_EMAIL as env vars to scripts. Skipped if SERVER_JWT_SECRET not configured.
CORS headers on every response — Allow-Origin: *, all methods, all headers, credentials, max-age 86400. OPTIONS preflight returns 204.
CGI environment — sets REQUEST_METHOD, CONTENT_TYPE, CONTENT_LENGTH, HTTP_COOKIE, QUERY_STRING, HTTP_AUTHORIZATION, PATH_INFO, POST_BODY_FILE, SX_STREAMING for Python scripts.
Git auto-deploy — polls a git repository on a configurable interval, auto-pulls changes and serves updated code. Supports PAT authentication.
Request/response size limits — configurable max request and response body sizes (default 200MB each).
Environment variables available to Python CGI scripts in scorpiox-server. Query parameters are also passed as individual env vars.
| Variable | Description |
|---|---|
| REQUEST_METHOD | HTTP method (GET, POST, etc.) |
| CONTENT_TYPE | Request Content-Type header |
| CONTENT_LENGTH | Request body size in bytes |
| HTTP_COOKIE | Raw Cookie header value |
| QUERY_STRING | Raw query string |
| HTTP_AUTHORIZATION | Authorization header value |
| PATH_INFO | Request URL path |
| POST_BODY_FILE | Path to temp file containing POST body (non-streaming mode) |
| SX_STREAMING | Set to '1' when in streaming mode (large POST body piped to stdin) |
| X_AUTHENTICATED | '1' if JWT validated, '0' otherwise |
| X_USER_ID | User ID (sub claim) from validated JWT |
| X_USER_EMAIL | User email from validated JWT |
| *query_params* | Each query parameter key=value is set as an env var |
#!/usr/bin/env python3
# Example: reading CGI env vars in a scorpiox-server script
import os
method = os.environ.get('REQUEST_METHOD', 'GET')
user = os.environ.get('X_USER_EMAIL', 'anonymous')
lang = os.environ.get('lang', 'en') # from ?lang=en query param
print("Content-Type: application/json")
print()
print(f'{"method": "{method}", "user": "{user}"}')
WebSocket-to-TCP bridge for VNC (noVNC). Handles WS handshake (RFC 6455), binary frame encoding/decoding, and bidirectional data relay via epoll. Replaces Python websockify with a zero-dependency C binary.
# Start WebSocket bridge on port 6080 → VNC on port 5900
scorpiox-ws2tcp --listen 6080 --target localhost:5900
# With token authentication
scorpiox-ws2tcp --listen 6080 --target localhost:5900 --token-required
# Serve static files (noVNC HTML/JS) from a directory
scorpiox-ws2tcp --listen 6080 --target localhost:5900 --web /opt/novnc
All configuration is loaded from scorpiox-env.txt or -e command-line overrides.
| Key | Default | Description |
|---|---|---|
| SERVER_PORT | 8080 | HTTP listen port |
| SERVER_ROUTE_PREFIX | /api/platform/websites/ | URL prefix for script routing (use '/' for clean URLs) |
| SERVER_SCRIPT_DIR | . | Comma-separated script directories (first match wins) |
| SERVER_JWT_SECRET | (empty) | JWT HMAC-SHA256 secret (empty = skip JWT validation) |
| SERVER_JWT_ISSUER | https://login.scorpiox.net/ | Expected JWT issuer claim |
| SERVER_JWT_AUDIENCE | https://scorpiox.net/api | Expected JWT audience claim |
| SERVER_JWT_COOKIE | sx_token | Cookie name containing JWT |
| SERVER_MAX_REQUEST_MB | 200 | Maximum request body size in MB |
| SERVER_MAX_RESPONSE_MB | 200 | Maximum response body size in MB |
| SERVER_GIT_REPO | (empty) | Git repository URL for auto-deploy |
| SERVER_GIT_PAT | (empty) | Git personal access token |
| SERVER_GIT_BRANCH | main | Git branch to track |
| SERVER_GIT_POLL_SECS | 60 | Git poll interval in seconds |
| Key | Default | Description |
|---|---|---|
| EMAIL_SMTP_PORT | 25 | SMTP MTA port (0 to disable) |
| EMAIL_SUBMISSION_PORT | 587 | SMTP submission port (0 to disable) |
| EMAIL_IMAP_PORT | 993 | IMAP port (0 to disable) |
| EMAIL_DOMAIN | mail.scorpiox.net | Email domain |
| EMAIL_MAILDIR | /var/mail | Maildir base path |
| EMAIL_TLS_CERT | (empty) | TLS certificate file path |
| EMAIL_TLS_KEY | (empty) | TLS private key file path |
| EMAIL_ACCOUNTS_FILE | (empty) | Accounts file (user:sha256_hash) |
# HTTP server — serve website with JWT auth
SERVER_PORT=8080
SERVER_ROUTE_PREFIX=/
SERVER_SCRIPT_DIR=./website,./api
SERVER_JWT_SECRET=your-secret-here
SERVER_JWT_COOKIE=sx_token
# Git auto-deploy — pull from repo every 30 seconds
SERVER_GIT_REPO=https://git.scorpiox.net/repo.git
SERVER_GIT_BRANCH=main
SERVER_GIT_POLL_SECS=30
# Email server
EMAIL_DOMAIN=mail.scorpiox.net
EMAIL_TLS_CERT=/etc/ssl/certs/mail.pem
EMAIL_TLS_KEY=/etc/ssl/private/mail.key