HTTP API
The same engine that powers the browser tools is also a public HTTP service. Use it from scripts, CI pipelines, monitoring jobs, or your own internal tools. Endpoints are unauthenticated for the public actions below; account-scoped endpoints (history, share-links, API keys) require a session cookie.
Base URL. Hosted: https://pgconfigurator.cybertec.at/api/v1. Self-hosted: whatever you put behind your proxy (the bundled docker-compose exposes it at :8080).
POST /api/v1/analyze
Send an EXPLAIN plan (text, JSON, or YAML) as the request body. Returns the parsed plan tree, computed findings, and per-node diagnostics.
curl -X POST https://pgconfigurator.cybertec.at/api/v1/analyze \ -H "Content-Type: text/plain" \ --data-binary @plan.txt
Response (truncated)
{
"plan": { "root": { "type": "Seq Scan", ... }, "executionTimeMS": 117 },
"findings": [
{ "severity": "warn", "title": "Filter on big discards 500000 rows, 80000 kept",
"detail": "...", "fix": "...", "impact": "...", "nodePath": [0,1,0] }
],
"analyzed": true
}POST /api/v1/generate
Compute a recommended PostgreSQL configuration for a server profile. Request body is the same Input shape the Tune tool uses.
curl -X POST https://pgconfigurator.cybertec.at/api/v1/generate \
-H "Content-Type: application/json" \
-d '{
"workload": "OLTP",
"pgVersion": 18,
"hardware": { "ramBytes": 34359738368, "vCPUs": 8, "storage": "NVMe" },
"maxConns": 200,
"standbys": 1
}'Response shape
{
"input": { ... },
"recommendations": [
{ "name": "shared_buffers", "category": "Memory",
"default": "128MB", "suggested": "8GB",
"risk": "restart",
"why": "25% of RAM is the well-tested starting point...",
"related": ["effective_cache_size", "work_mem"] },
...
]
}POST /api/v1/render
Turn an Input into a specific output format (fullpostgresql.conf, ALTER SYSTEM script, Ansible vars, Patroni YAML, initdb command, or a Markdown runbook).
curl -X POST https://pgconfigurator.cybertec.at/api/v1/render \
-H "Content-Type: application/json" \
-d '{ "input": { "workload": "OLTP", "pgVersion": 18, "hardware": {"ramBytes":34359738368,"vCPUs":8,"storage":"NVMe"} }, "format": "alter_system" }'Valid format values: conf, alter_system, ansible, patroni, patroni_full, initdb, markdown.
POST /api/v1/narrate
Ask the configured AI provider for a short plain-English summary of an Analysis (the JSON returned by /analyze). Returns 503 when no provider is configured — self-hosters set the CYBERTEC_LLM_KEY env var on the API service to enable it.
# First analyze, then narrate
ANALYSIS=$(curl -sX POST https://pgconfigurator.cybertec.at/api/v1/analyze \
-H "Content-Type: text/plain" --data-binary @plan.txt)
curl -X POST https://pgconfigurator.cybertec.at/api/v1/narrate \
-H "Content-Type: application/json" \
-d "{ \"analysis\": $(jq -c -R . <<< "$ANALYSIS") }"Response
{ "summary": "This plan reads the orders table sequentially and..." }POST /api/v1/describe
Turn a free-form natural-language description ("a busy SaaS app on a 32 GB cloud box, lots of small writes") into the structured Input you can feed to /generate. Also AI-gated; same 503 behavior when not configured.
curl -X POST https://pgconfigurator.cybertec.at/api/v1/describe \
-H "Content-Type: application/json" \
-d '{ "description": "OLTP API on a 32 GB / 8 vCPU NVMe box, 1 hot standby" }'Errors
Errors come back as JSON with a single error field:
{ "error": "invalid input: ..." }Common status codes:
- 400 — malformed input (bad JSON, missing field, unparseable plan).
- 413 — payload exceeds the per-route limit (analyze caps plan size).
- 429 — public-API rate limit (per-IP).
- 502 — AI provider unavailable / upstream error.
- 503 — AI provider not configured on this deployment.
Self-hosting
The API runs as ./bin/api (or in the supplied Docker image). See tuning and the repo's SELF-HOSTING.md for the env var list. Nothing about the API requires the hosted service — same code, same behavior, same license (PostgreSQL License).
Want a client library?
The Go module ships with the engine itself — github.com/cybertec-postgresql/pgconfigurator_v2/pkg/pgplan and .../pkg/pgconfigare usable directly, with no HTTP round-trip. A TypeScript client wrapping these endpoints is on the roadmap (it's a thin layer over fetch — see the request shapes above).