Proxy API
The proxy speaks plain JSON over HTTP. The same contract serves the Rowsel app
and any other client (for example a backend tool inside your network).
message, error.message, and error.hint are English so a single contract
serves localized clients — map the stable error.code to localized copy.
Response envelope
Section titled “Response envelope”Success:
{ "status": "ok", "message": "Query executed.", "data": {} }Failure:
{ "status": "error", "message": "The query endpoint only runs read-only SQL.", "error": { "code": "ERR_READ_ONLY_QUERY_REQUIRED", "hint": "Use SELECT or read-only WITH.", "retryable": false }}Endpoints
Section titled “Endpoints”| Method | Path | Purpose |
|---|---|---|
GET | /health | Health check; data includes version. |
POST | /v1/test-connection | Verify database connectivity. |
POST | /v1/schema | Load schemas, tables, views, columns. |
POST | /v1/query | Run one read-only query. |
POST | /v1/execute | Run one DML/DDL/DCL statement (confirm: true). |
POST | /v1/sessions | Create a pooled session. |
DELETE | /v1/sessions/{id} | Close a session. |
Session-scoped query, execute, transaction, and cancel routes live under
/v1/sessions/{id}/….
Connection shape
Section titled “Connection shape”{ "engine": "postgres", "host": "db.internal", "port": 5432, "database": "analytics", "username": "app", "password": "…", "ssl_mode": "require"}ssl_mode is one of disable, prefer, require.
SSH tunnel
Section titled “SSH tunnel”Add a tunnel object to connect through a bastion. connection.host/port
are the database endpoint as seen from the bastion:
{ "engine": "postgres", "host": "db.internal", "port": 5432, "database": "analytics", "username": "app", "password": "…", "ssl_mode": "require", "tunnel": { "type": "ssh", "host": "bastion.example.com", "port": 22, "username": "ubuntu", "auth": { "method": "private_key", "private_key": "-----BEGIN…" }, "host_key_check": "accept_new" }}Query policy
Section titled “Query policy”- A single statement classified as a read. Data-modifying CTEs,
SELECT INTO,SELECT … FOR UPDATE, and multi-statement batches are rejected. - Runs inside
BEGIN READ ONLYwith a server-sidestatement_timeout. - User SQL is wrapped to enforce
LIMIT/OFFSET. - Default page size 200, max 500. Default timeout 10s, max 30s.
Query response
Section titled “Query response”{ "status": "ok", "data": { "columns": [{ "name": "id", "data_type": "INT8", "nullable": false }], "rows": [{ "id": 1004821 }], "page": { "page_size": 200, "offset": 0, "returned": 1, "has_next": false }, "stats": { "elapsed_ms": 84, "limit_enforced": true, "read_only": true } }}Selected error codes
Section titled “Selected error codes”| Code | Meaning |
|---|---|
ERR_AUTH_REJECTED | Database authentication failed. |
ERR_DB_UNREACHABLE | Network/host/port connection failed. |
ERR_READ_ONLY_QUERY_REQUIRED | SQL is not a read query. |
ERR_SQL_INVALID | Syntax, table, or column error. |
ERR_QUERY_TIMEOUT | Proxy timeout exceeded. |
ERR_SSH_TUNNEL_FAILED | SSH tunnel failed before becoming ready. |
The proxy returns SQLSTATE and detail when the database provides them.