Skip to content

HTTP API

ParticleDB exposes a lightweight HTTP surface on the same port as the built-in status page. The current server implements JSON SQL execution, KV helpers, health endpoints, Prometheus metrics, and SSE streaming for incremental results.

http://localhost:8080

Configure it with:

Terminal window
particledb start --http-addr 0.0.0.0:8080
PathMethodPurpose
/v1/sqlPOSTExecute one SQL statement and return JSON rows
/v1/sql/streamPOSTStream SQL results as Server-Sent Events
/v1/tablesGETList public tables
/v1/kv/getPOSTRead a single KV row by key
/v1/kv/setPOSTUpsert a KV row
/v1/kv/deletePOSTDelete a KV row
/v1/versionGETReturn server name/version metadata
/healthGETLegacy plain-text health check (OK)
/health/liveGETLiveness probe JSON
/health/readyGETReadiness probe JSON
/health/deepGETDeep health JSON
/metricsGETPrometheus text metrics

There is no /query, /bulk, or /tables/:name route in the current server.

Terminal window
curl -X POST http://localhost:8080/v1/sql \
-H "Content-Type: application/json" \
-d '{"sql":"SELECT 1 AS ok"}'

Response:

{
"rows": [
{ "ok": 1 }
],
"row_count": 1,
"columns": ["ok"]
}

The server also accepts a plain-text body if you want to post raw SQL:

Terminal window
printf 'SELECT 1 AS ok' | curl -X POST http://localhost:8080/v1/sql --data-binary @-
Terminal window
curl -X POST http://localhost:8080/v1/sql \
-H "Content-Type: application/json" \
-d '{"sql":"CREATE TABLE events (id BIGINT PRIMARY KEY, name TEXT)"}'
curl -X POST http://localhost:8080/v1/sql \
-H "Content-Type: application/json" \
-d '{"sql":"INSERT INTO events (id, name) VALUES (1, ''signup'')"}'
curl -X POST http://localhost:8080/v1/sql \
-H "Content-Type: application/json" \
-d '{"sql":"SELECT id, name FROM events"}'

The HTTP handler currently executes the sql string directly. It does not bind a separate JSON params array the way the PG wire or gRPC clients do. For HTTP calls today, send the final SQL text you want executed.

The server can stream incremental results as Server-Sent Events (SSE).

Terminal window
curl -N -X POST http://localhost:8080/v1/sql/stream \
-H "Content-Type: application/json" \
-d '{"sql":"SELECT * FROM events"}'

The stream emits event: frames such as:

event: row
data: {"id":1,"name":"signup"}
event: done
data: {"full_text":"...","elapsed_ms":1.2}

Use this transport today for browser-friendly incremental results. The repo contains WebSocket protocol definitions, but the default HTTP server currently exposes SSE, not a live WebSocket upgrade endpoint.

Terminal window
curl http://localhost:8080/v1/tables

Response:

{
"tables": ["events", "products"]
}

The current route returns table names only.

The KV endpoints are simple HTTP wrappers over SQL. They assume a table with a key column and a value column already exists.

Create one:

CREATE TABLE kv_store (
key TEXT PRIMARY KEY,
value TEXT
);
Terminal window
curl -X POST http://localhost:8080/v1/kv/set \
-H "Content-Type: application/json" \
-d '{"table":"kv_store","key":"user:1001","value":"{\"name\":\"Alice\"}"}'
{
"ok": true
}
Terminal window
curl -X POST http://localhost:8080/v1/kv/get \
-H "Content-Type: application/json" \
-d '{"table":"kv_store","key":"user:1001"}'
{
"key": "user:1001",
"value": "{\"name\":\"Alice\"}"
}

If the key is missing, the server returns 404 with an error field.

Terminal window
curl -X POST http://localhost:8080/v1/kv/delete \
-H "Content-Type: application/json" \
-d '{"table":"kv_store","key":"user:1001"}'
{
"ok": true
}
Terminal window
curl http://localhost:8080/health

Response:

OK
{
"status": "alive",
"uptime_seconds": 42
}
{
"status": "ready",
"tables_loaded": 3,
"connections_active": 1,
"connections_max": 100,
"connections_available": 99
}
{
"status": "healthy",
"ready": true
}
Terminal window
curl http://localhost:9090/metrics

By default metrics are served from the dedicated metrics port, not the main HTTP port:

Terminal window
particledb start --metrics-port 9090
Terminal window
curl http://localhost:8080/v1/version
{
"name": "ParticleDB",
"version": "0.1.0",
"protocol": "pg-wire"
}

The built-in HTTP server responds with permissive CORS headers:

  • Access-Control-Allow-Origin: *
  • Access-Control-Allow-Methods: GET, POST, OPTIONS
  • Access-Control-Allow-Headers: Content-Type

It also answers generic OPTIONS requests with 204 No Content.

  • The built-in HTTP server is plain HTTP today. Terminate TLS at your reverse proxy or ingress if you need HTTPS.
  • The current /v1/* routes do not perform the PG/gRPC-style username/password auth flow. For production, put the HTTP port behind your normal network perimeter, reverse proxy, or API gateway.