Skip to content

HeliosDB HTTP/REST API Reference

HeliosDB Full includes an HTTP gateway next to its wire-protocol listeners. It runs SQL over HTTP and returns JSON, so scripts, serverless functions and tools that cannot load a database driver can still reach the database. The gateway runs inside the heliosdb-full server process; there is nothing extra to install.

This page describes the endpoints the heliosdb-full server serves, how to change the port and bind address, and how requests are authenticated.

The HTTP gateway has no S3/object endpoints (planned): an S3-compatible object API for HeliosDB Full is on the roadmap and is not part of the current release. The /snowflake/, /dbsql/ and /pinecone/ paths answer 501 Not Implemented; those interfaces are planned as well.


Default address

SettingDefaultChange it with
Port8443--http-port <port> or HELIOSDB_HTTP_PORT
Bind address127.0.0.1--bind-addr <address> or HELIOSDB_BIND_ADDR
Enabledyes--no-http turns the gateway off

The listener speaks plain HTTP on port 8443; the port number is only the default, not an indication of TLS. For connections that leave the host, put the gateway behind a TLS-terminating reverse proxy or load balancer (nginx, HAProxy, Envoy, a cloud load balancer) and keep the gateway itself on a private address.

Terminal window
# Local only (default): http://127.0.0.1:8443
heliosdb-full
# Another port
heliosdb-full --http-port 9443
# or
HELIOSDB_HTTP_PORT=9443 heliosdb-full

Binding to a non-loopback address

--bind-addr applies to every listener the server opens (PostgreSQL, HTTP and any protocol you enable). Binding to anything other than a loopback address requires an explicit opt-in, and the server refuses to start without it:

Terminal window
heliosdb-full --bind-addr 0.0.0.0 --allow-external
# or
HELIOSDB_BIND_ADDR=0.0.0.0 HELIOSDB_ALLOW_EXTERNAL=true heliosdb-full

--allow-external accepts 1/0, true/false, yes/no and on/off. Configure an API key (below) and a firewall before you expose the gateway.

Containers

The HeliosDB Full container image (provided during onboarding; it is not on a public registry) already binds 0.0.0.0 inside the container and sets HELIOSDB_ALLOW_EXTERNAL=true. Publish the port you need:

Terminal window
docker run -d --name heliosdb \
--env-file /etc/heliosdb/heliosdb.env \
-p 127.0.0.1:8443:8443 -p 127.0.0.1:5432:5432 \
-v heliosdb-data:/var/lib/heliosdb/data \
<heliosdb-full-image>

/etc/heliosdb/heliosdb.env holds HELIOSDB_SUPERUSER_PASSWORD and HELIOSDB_API_KEY and is readable only by root. To serve HTTP on another port inside the container, add -e HELIOSDB_HTTP_PORT=9443 and publish -p 127.0.0.1:9443:9443.


Authentication

RouteAuthentication
GET /, GET /health, GET /healthz, GET /ready, GET /readyz, GET /status, GET /api/v1/statusNone (probes and server information)
Every other routeAPI key

Set the key on the server with the HELIOSDB_API_KEY environment variable. Clients send it in either header:

Authorization: Bearer <api-key>
X-API-Key: <api-key>

The key is compared in constant time. A request without a valid key receives:

HTTP/1.1 401 Unauthorized
WWW-Authenticate: Bearer
Content-Type: application/json
{"error":"unauthorized"}

When HELIOSDB_API_KEY is not set, every non-public route returns 401. The only way to call them without a key is --auth-mode trust, which the server accepts on a loopback bind only (it refuses to start with trust on an external address). Use it for local development.

The HTTP gateway has one shared key, not per-user accounts: SQL sent over HTTP is not tied to a database role, so treat the key like a superuser password. For per-user logins, connect with a PostgreSQL client and a database role instead.

Keep the key out of shell history and process listings: export it from a secrets manager or an environment file readable only by the service account, for example EnvironmentFile= in a systemd unit or --env-file with Docker.


Endpoints

MethodPathPurpose
GET/health, /healthzLiveness
GET/ready, /readyzReadiness
GET/status, /api/v1/statusServer status
GET/Server name, version and route list
POST/api/v1/query, /queryRun one SQL statement
POST, DELETE/api/v1/sessionsPinned sessions (opt-in, see below)
POST/api/v1/chat/completions, /v1/chat/completionsChat completion through a configured AI provider
POST/api/v1/embeddings, /v1/embeddingsEmbeddings through a configured AI provider
POST/api/v1/audio/transcribe, /api/v1/audio/transcriptions, /v1/audio/transcriptionsSpeech-to-text through a configured AI provider
POST/api/v1/vectors/storesCreate a vector store
POST/api/v1/vectors/stores/{name}/textsAdd texts to a vector store
POST/api/v1/vectors/stores/{name}/search/hybridHybrid (vector + keyword) search
GET, POST/api/v1/agents/memoryList or create agent memory sessions
GET, DELETE/api/v1/agents/memory/{id}Read or delete a memory session
GET/api/v1/agents/memory/{id}/messagesRead messages
POST/api/v1/agents/memory/{id}/messages/batchAppend messages
POST/api/v1/agents/memory/{id}/clear, /summarize, /searchClear, summarize or search a session
GET, POST/api/v1/documents (also POST /api/v1/documents/ingest)List or ingest documents
GET, DELETE/api/v1/documents/{id}Read or delete a document
POST/api/v1/documents/searchSearch documents

Any other path returns 404 with {"error":"Not found","path":"..."}.

Health and status

Terminal window
curl -s http://127.0.0.1:8443/health
# {"status":"healthy","version":"x.y.z"}
curl -s http://127.0.0.1:8443/ready
# {"ready":true}
curl -s http://127.0.0.1:8443/status
# {"status":"running","version":"x.y.z","protocols":["postgresql","mysql","http"]}

/health and /ready need no key, so you can use them directly as container health checks and load-balancer probes. The protocols list in /status is a fixed summary; the server log and SHOW PROTOCOLS (from psql) show which listeners are actually open.

Run SQL: POST /api/v1/query

Send one statement in the query field of a JSON body:

Terminal window
curl -s -X POST http://127.0.0.1:8443/api/v1/query \
-H "Authorization: Bearer $HELIOSDB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"query": "SELECT id, name FROM customers WHERE id = 1"}'

Successful result:

{
"success": true,
"columns": [
{"name": "id", "type": "integer"},
{"name": "name", "type": "text"}
],
"rows": [[1, "Acme"]],
"row_count": 1
}

Column type is one of integer, float, boolean or text; other SQL types are reported as text and their values are returned as JSON strings. NULL is JSON null. DDL and DML return an empty columns/rows and the affected row count in row_count.

A SQL error is returned with HTTP status 200 and success: false, so check the success field rather than only the status code:

{"success": false, "error": "relation \"no_such_table\" does not exist"}

A missing or malformed body returns 400 with a hint:

{"error": "Missing 'query' field", "hint": "Send JSON body: {\"query\": \"SELECT 1\"}"}

Notes:

  • The body field is query. Bind parameters are not part of the HTTP API; build statements with values your application has validated, or use a PostgreSQL driver when you need server-side parameter binding.
  • Each request runs on a pooled PostgreSQL handler that is reset afterwards, so BEGIN, temporary tables and SET do not carry over to the next request. A BEGIN over plain HTTP is refused. Use a pinned session (next section) for multi-statement transactions.
  • Responses carry Access-Control-Allow-Origin: *.
  • The pool size is set with --http-pg-pool-size / HELIOSDB_HTTP_PG_POOL_SIZE (default 16; 0 builds a handler per request).

Pinned sessions: /api/v1/sessions

A pinned session keeps one dedicated PostgreSQL session for an HTTP client across requests, so transactions, temporary tables and SET work over HTTP. Start the server with --http-sessions to enable it; without it these routes return 501 (sessions_disabled).

Terminal window
# 1. Create a session
curl -s -X POST http://127.0.0.1:8443/api/v1/sessions \
-H "Authorization: Bearer $HELIOSDB_API_KEY"
# {"session":"<node>.<token>","node":"<node>","expires_in_secs":300,
# "idle_in_transaction_timeout_secs":60,"max_lifetime_secs":3600,"in_transaction":false}
# 2. Run statements on it
curl -s -X POST http://127.0.0.1:8443/api/v1/query \
-H "Authorization: Bearer $HELIOSDB_API_KEY" \
-H "X-HeliosDB-Session: $SESSION" \
-d '{"query": "BEGIN"}'
# ... more statements with the same header ...
curl -s -X POST http://127.0.0.1:8443/api/v1/query \
-H "Authorization: Bearer $HELIOSDB_API_KEY" \
-H "X-HeliosDB-Session: $SESSION" \
-d '{"query": "COMMIT"}'
# 3. End it (an open transaction is rolled back)
curl -s -X DELETE http://127.0.0.1:8443/api/v1/sessions \
-H "Authorization: Bearer $HELIOSDB_API_KEY" \
-H "X-HeliosDB-Session: $SESSION"

Responses on a pinned session add "in_transaction": true|false. The token travels only in the X-HeliosDB-Session header, never in the URL or body, and the server stores only its SHA-256 hash.

Flag (environment variable)DefaultMeaning
--http-sessionsoffEnable pinned sessions
--http-max-sessions (HELIOSDB_HTTP_MAX_SESSIONS)256Sessions per node
--http-max-sessions-per-principal (HELIOSDB_HTTP_MAX_SESSIONS_PER_PRINCIPAL)32Sessions per API key
--http-session-idle-timeout-secs (HELIOSDB_HTTP_SESSION_IDLE_TIMEOUT_SECS)300Idle time before the session ends
--http-session-idle-in-txn-timeout-secs (HELIOSDB_HTTP_SESSION_IDLE_IN_TXN_TIMEOUT_SECS)60Idle time while a transaction is open (work is rolled back)
--http-session-max-lifetime-secs (HELIOSDB_HTTP_SESSION_MAX_LIFETIME_SECS)3600Maximum session age
--http-session-reap-interval-ms (HELIOSDB_HTTP_SESSION_REAP_INTERVAL_MS)1000Reaper interval; also the Retry-After of a 429
--http-session-concurrency wait|reject (HELIOSDB_HTTP_SESSION_CONCURRENCY)waitA second concurrent request on one token waits, or gets 409
--http-session-bind-ipoffAlso bind each session to the client IP that created it
--node-id (HELIOSDB_NODE_ID)hostnameNode id carried in each token, for load-balancer routing

Session errors:

StatusCodeMeaning
400session_malformedThe token is not well formed
403session_forbiddenToken used with another API key, or from another IP with --http-session-bind-ip
404session_unknownNo such session
409session_not_localThe token belongs to another node (the body names it)
409session_busyAnother request is running on the token and concurrency is reject
410session_expiredThe session timed out
429too_many_sessionsA session limit was reached (Retry-After is set)
500session_lostThe session ended because of an internal error
501sessions_disabledThe server was started without --http-sessions

Behind a load balancer, route requests that carry X-HeliosDB-Session to the node named in the token (the part before the first .), or use sticky sessions.

AI routes

The chat, embeddings and audio routes forward requests to an AI provider configured on the server. The vector store, agent memory and document routes store their data in HeliosDB and call the provider for embeddings.

Environment variablePurpose
HELIOSDB_AI_PROVIDERopenai (default), anthropic or ollama
HELIOSDB_AI_API_KEYProvider API key
HELIOSDB_AI_API_BASEProvider base URL (defaults to the provider’s public endpoint)
HELIOSDB_AI_CHAT_MODEL, HELIOSDB_AI_EMBED_MODELModel names
HELIOSDB_AI_ALLOW_PRIVATE_NETWORK1 allows an http:// or private-network base URL, for a local Ollama
HELIOSDB_AI_HOST_ALLOWLISTComma-separated host names allowed as the base URL
HELIOSDB_AI_RATE_LIMIT, HELIOSDB_AI_RATE_WINDOW_SECSRequests per tenant per window (default 60 per 60 s; 0 disables)

Requests are counted per tenant, taken from the X-HeliosDB-Tenant header (default when absent). Over the limit, the route returns 429 with Retry-After. The chat route accepts the OpenAI-style body (messages, optional model, temperature, max_tokens, stream); with "stream": true the response is server-sent events.

Terminal window
curl -s -X POST http://127.0.0.1:8443/api/v1/chat/completions \
-H "Authorization: Bearer $HELIOSDB_API_KEY" \
-H "Content-Type: application/json" \
-d '{"messages":[{"role":"user","content":"Summarise last week'\''s orders"}]}'

Snowflake, Databricks and Pinecone paths

Requests under /snowflake/, /dbsql/ and /pinecone/ are answered with 501 Not Implemented by the heliosdb-full HTTP listener. Use POST /api/v1/query or a PostgreSQL client for SQL access.


Rate limits

LimitDefaultSetting
New connections per client IP500 per minute (burst 100), all listeners--conn-rate-limit <per-minute> (HELIOSDB_CONN_RATE_LIMIT)
SQL queries per client IPnot limited--query-rate-limit <per-second> (HELIOSDB_QUERY_RATE_LIMIT); applies to POST /api/v1/query and the PostgreSQL wire
AI requests per tenant60 per 60 sHELIOSDB_AI_RATE_LIMIT, HELIOSDB_AI_RATE_WINDOW_SECS
Concurrent connections, all protocols10000--max-connections (HELIOSDB_MAX_CONNECTIONS)

A query over the limit returns 429 Too Many Requests with a Retry-After header. Setting the environment variable HELIOSDB_RATE_LIMITING=false turns the connection and query limiters off (not recommended for production). The --rate-limiting command-line flag can only switch them on, which is already the default: --rate-limiting false and --rate-limiting=false are rejected by the argument parser.


Client examples

Python

import os
import requests
BASE = os.environ.get("HELIOSDB_HTTP_URL", "http://127.0.0.1:8443")
HEADERS = {"Authorization": f"Bearer {os.environ['HELIOSDB_API_KEY']}"}
def query(sql: str) -> dict:
r = requests.post(f"{BASE}/api/v1/query", json={"query": sql}, headers=HEADERS, timeout=30)
r.raise_for_status()
body = r.json()
if not body.get("success"):
raise RuntimeError(body.get("error"))
return body
result = query("SELECT COUNT(*) AS n FROM orders")
print(result["rows"][0][0])

JavaScript / TypeScript

const BASE = process.env.HELIOSDB_HTTP_URL ?? "http://127.0.0.1:8443";
async function query(sql: string) {
const res = await fetch(`${BASE}/api/v1/query`, {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.HELIOSDB_API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({ query: sql }),
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const body = await res.json();
if (!body.success) throw new Error(body.error);
return body;
}

Shell health check

Terminal window
curl -fsS http://127.0.0.1:8443/health > /dev/null || echo "HeliosDB is down"

  • Connecting to HeliosDB — PostgreSQL, MySQL and other wire-protocol clients
  • Configuration reference
  • Run heliosdb-full --help for every flag and its environment variable, and heliosdb-full --show-features for the listeners and features in your build