API reference

Base URLs:

  • Site: https://klunqlabs.com
  • Proxy: https://proxy.klunqlabs.com

Auth model:

  • Management key (sk-… from dashboard) — can manage your v-keys and read your usage.
  • v-key (sk-… minted via management key) — inference only, cannot call management.

The proxy is LiteLLM-based with custom hooks and guardrails, so the management key exposes only the documented subset below — not the full upstream LiteLLM surface. Production does not expose Swagger.


Management — v-keys

All following require Authorization: Bearer $TEAM_MGMT_KEY (the team management key from the dashboard).

POST /key/generate

Create a disposable v-key.

curl -X POST "$PROXY_URL/key/generate" \
  -H "Authorization: Bearer $TEAM_MGMT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key_alias":"vkey-landing","models":["gemma4"],"max_budget":2,"budget_duration":"30d","rpm_limit":100,"tpm_limit":10000}'
# 200 { "key":"sk-…", "token_id":"…", "max_budget":2, ... }

Fields: key_alias required, models (array, empty = all curated models), max_budget, budget_duration (30d/1d/1h), rpm_limit, tpm_limit, max_parallel_requests, expires/duration.

GET /key/list

List keys for your team.

curl -G "$PROXY_URL/key/list" -H "Authorization: Bearer $TEAM_MGMT_KEY"
# → { "keys": [...], "total_count": 42, "total_pages": 5, "current_page": 1 }
# Filter exact alias:
curl -G "$PROXY_URL/key/list" -H "Authorization: Bearer $TEAM_MGMT_KEY" --data-urlencode "key_alias=vkey-landing"

Exact key_alias search is case-sensitive (dashboard search).

GET /key/info?key={sk-…}

Inspect a key.

curl -G "$PROXY_URL/key/info" -H "Authorization: Bearer $TEAM_MGMT_KEY" --data-urlencode "key=$VKEY"

POST /key/update

Update alias, budget or limits.

curl -X POST "$PROXY_URL/key/update" \
  -H "Authorization: Bearer $TEAM_MGMT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"key":"sk-…","key_alias":"vkey-renamed","max_budget":5}'

key_alias cannot be cleared to empty.

POST /key/delete

curl -X POST "$PROXY_URL/key/delete" \
  -H "Authorization: Bearer $TEAM_MGMT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"keys":["sk-…"]}'
# subsequent GET /key/info?key=sk-… → 404

GET /team/info

Read your team.

curl -G "$PROXY_URL/team/info" -H "Authorization: Bearer $TEAM_MGMT_KEY"

Spend — team-scoped

  • GET /team/daily/activity?start_date=YYYY-MM-DD&end_date=YYYY-MM-DD — aggregated per day/model/key. Without params auto-scoped to your team.
  • GET /spend/logs/v2?start_date&end_date&page&page_size — per-request logs [{request_id, model, spend, total_tokens, startTime}], auto-scoped to your team.
  • GET /spend/logs?start_date&end_date — deprecated aggregated variant.
  • POST /spend/calculate {"model":"gemma4","messages":[...],"max_tokens":10}{"cost":0.0} estimator.
curl -G "$PROXY_URL/team/daily/activity" -H "Authorization: Bearer $TEAM_MGMT_KEY" \
  --data-urlencode "start_date=2025-01-01" --data-urlencode "end_date=2026-12-31"
curl -G "$PROXY_URL/spend/logs/v2" -H "Authorization: Bearer $TEAM_MGMT_KEY" \
  --data-urlencode "start_date=2025-01-01" --data-urlencode "end_date=2026-12-31"
curl -X POST "$PROXY_URL/spend/calculate" -H "Authorization: Bearer $TEAM_MGMT_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"gemma4","messages":[{"role":"user","content":"hi"}],"max_tokens":10}'

Inference — with a v-key (widget-only)

The proxy is OpenAI-compatible, but today it only accepts the Klunq Widget’s watermarked prompts. A v-key alone is not enough — every POST /v1/chat/completions must carry the widget’s page-locked system prompt, otherwise the proxy returns 400 Guardrail Violation (see Watermarking). Custom watermarks for other clients are planned; until then use the Klunq Widget integration.

List models (allowed with a v-key):

curl -H "Authorization: Bearer $VKEY" "$PROXY_URL/v1/models"

Errors & status codes

CodeMeaning
200Success (finish_reason:"stop" on page-lock pass)
400Guardrail Violation — page-lock failed (system prompt missing, not first, or watermark absent)
401Missing/invalid key
403Not allowed to call this route
404Team/key not found
500Invalid route or server error

Next: Security

Help improve these docs

Found a gap? The widget is open source — open an issue or PR in the widget repo.