Skip to content

Test the API — URLs, auth, Postman

Mint a token against the bundled realm and paste it into curl, Postman, or Swagger UI — every door the hub serves, listed with the role it requires.

Day-to-day work goes through lm; this page is for testing the HTTP API itself. URLs below are the self-host defaults. Behind the TLS proxy everything lives on one https origin, with Keycloak under /realms/*.

The doors

URL Auth What it is
http://localhost:8080/q/health none UP/DOWN with named checks — observability
http://localhost:8080/q/metrics none Prometheus metrics (block /q/* at the proxy on a public origin)
http://localhost:8080/q/openapi none the OpenAPI spec — what Postman imports
http://localhost:8080/q/swagger-ui/ none the try-it console, shipped in the packaged hub
http://localhost:8080/app/ browser login the PWA
http://localhost:8080/api/rag/chat Bearer, lm_user the chat door — semantic or analytic, guards apply
http://localhost:8080/api/entities/… Bearer: reads lm_user; apply and writes lm_admin fused entities, reads scope-bound — entities
http://localhost:8080/api/views Bearer, lm_user saved-view discovery, scope-bound — views
http://localhost:8080/api/platform/… Bearer, lm_integrator (some doors also lm_admin) the integrator surface: connectors, validator, runs, apply
http://localhost:8080/scim/v2/… SCIM bearer token deprovisioning, Pro only — SCIM
http://localhost:8180/realms/lumnik — Keycloak: the issuer, and the token endpoint below

Roles ride in the JWT's groups claim; the catalog is on Roles & permissions. A scope-bound user gets the uniform 403 {"error":"scope not granted"} outside their granted scopes — a feature, not a failure.

Mint a token

The bundled realm ships an integrator user (password: INTEGRATOR_PASSWORD in the .env that up.sh generated) and a public CLI client, lm-cli, that allows the password grant. From the repo root, in curl:

INTEGRATOR_PASSWORD=$(grep '^INTEGRATOR_PASSWORD=' .env | cut -d= -f2-)

TOKEN=$(curl -s "http://localhost:8180/realms/lumnik/protocol/openid-connect/token" \
  -d grant_type=password -d client_id=lm-cli \
  -d username=integrator --data-urlencode password="$INTEGRATOR_PASSWORD" \
  | jq -r .access_token)

# First authenticated smoke test:
curl -s http://localhost:8080/api/platform/health -H "Authorization: Bearer $TOKEN"

The reply lists every installed module (here a Pro hub with the AI switched off):

{"platform":"ok","modules":{"core":{"status":"ok","version":"0.1.0"},"identity":{"status":"ok","version":"0.1.0"},"rag":{"status":"inactive","version":"0.1.0","reason":"disabled:lumnik.ai.enabled"},"llm":{"status":"inactive","version":"0.1.0","reason":"disabled:lumnik.ai.enabled"}},"search":{"status":"not_installed","affectsReadiness":false,"error":null}}

Tokens from the bundled realm live one hour — mint again when a call starts answering 401. Your own IdP may be stricter.

The same thing in Postman

On the collection's Authorization tab, choose OAuth 2.0 and fill:

Field Value
Grant type Password Credentials
Access Token URL http://localhost:8180/realms/lumnik/protocol/openid-connect/token
Client ID lm-cli
Username / Password integrator / the INTEGRATOR_PASSWORD from .env

Get New Access Token → every request in the collection inherits the Bearer, and Postman re-mints it when it expires.

Import the whole API

Postman → Import → URL → http://localhost:8080/q/openapi. Postman builds the collection from the running hub, every endpoint pre-filled. Set the collection auth as above.

Prefer a browser? http://localhost:8080/q/swagger-ui/ is the same spec with a try-it button — paste the token from Mint a token into its Authorize dialog.

Testing as a business user, not an integrator

Everything above authenticates as integrator. To see what a scope-bound user sees (the 403 scope not granted boundaries, the user chat door), mint the token with that user's credentials instead. Scopes explains the binding.