Skip to content

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.

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
}
}
MethodPathPurpose
GET/healthHealth check; data includes version.
POST/v1/test-connectionVerify database connectivity.
POST/v1/schemaLoad schemas, tables, views, columns.
POST/v1/queryRun one read-only query.
POST/v1/executeRun one DML/DDL/DCL statement (confirm: true).
POST/v1/sessionsCreate a pooled session.
DELETE/v1/sessions/{id}Close a session.

Session-scoped query, execute, transaction, and cancel routes live under /v1/sessions/{id}/….

{
"engine": "postgres",
"host": "db.internal",
"port": 5432,
"database": "analytics",
"username": "app",
"password": "",
"ssl_mode": "require"
}

ssl_mode is one of disable, prefer, require.

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"
}
}
  • 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 ONLY with a server-side statement_timeout.
  • User SQL is wrapped to enforce LIMIT/OFFSET.
  • Default page size 200, max 500. Default timeout 10s, max 30s.
{
"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 }
}
}
CodeMeaning
ERR_AUTH_REJECTEDDatabase authentication failed.
ERR_DB_UNREACHABLENetwork/host/port connection failed.
ERR_READ_ONLY_QUERY_REQUIREDSQL is not a read query.
ERR_SQL_INVALIDSyntax, table, or column error.
ERR_QUERY_TIMEOUTProxy timeout exceeded.
ERR_SSH_TUNNEL_FAILEDSSH tunnel failed before becoming ready.

The proxy returns SQLSTATE and detail when the database provides them.