API contract
The plnt playground implements a subset of the OpenAI API — just the surface the plnt.work chat panel and any OpenAI client SDK actually need. This document is the canonical spec; the pytest suite tests/test_site_contract.py mechanically enforces it.
Base URL: https://playground.plnt.work (prod) · http://127.0.0.1:8080 (local plnt playground up).
Endpoints
Section titled “Endpoints”| Method | Path | Purpose |
|---|---|---|
GET | /healthz | Liveness. Always 200 once up. |
GET | /readyz | Readiness. 503 if no models. |
GET | /v1/models | List registered models. |
POST | /v1/chat/completions | Chat completion (± SSE stream). |
GET | / | Service banner + link to /docs. |
GET | /docs | Swagger UI (FastAPI auto-gen). |
GET /v1/models
Section titled “GET /v1/models”{ "object": "list", "data": [ { "id": "plnt-mock-7b", "object": "model", "created": 1784017752, "owned_by": "plnt", "runtime": "mock", "backend": "mock" } ]}The runtime and backend fields are plnt-specific extensions — an OpenAI client will ignore them. The site uses runtime to badge each model card.
POST /v1/chat/completions
Section titled “POST /v1/chat/completions”Request:
{ "model": "plnt-mock-7b", "messages": [ {"role": "system", "content": "You are helpful."}, {"role": "user", "content": "hello"} ], "stream": false, "max_tokens": 256, "temperature": 0.7, "top_p": 1.0}model— required. Must appear in/v1/models.messages— required, ≥ 1.stream— defaultfalse. Set totruefor SSE.max_tokens— default256, range1..8192.temperature— default0.7, range0.0..2.0.top_p— default1.0, range0.0..1.0.
Non-streaming response (stream: false):
{ "id": "chatcmpl-45dca0d6a9cd470bb4d2b8b4", "object": "chat.completion", "created": 1784017753, "model": "plnt-mock-7b", "choices": [ { "index": 0, "message": {"role": "assistant", "content": "..."}, "finish_reason": "stop" } ], "usage": { "prompt_tokens": 4, "completion_tokens": 42, "total_tokens": 46 }}finish_reason is "stop" | "length" | "error".
Streaming response (stream: true) — Server-Sent Events, text/event-stream:
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"role":"assistant"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"content":"Hello "},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{"content":"world"},"finish_reason":null}]}
data: {"id":"chatcmpl-...","object":"chat.completion.chunk","created":...,"model":"...","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}
data: [DONE]Frame invariants (asserted in tests/test_site_contract.py):
- Content-Type is
text/event-stream. - First frame’s
delta.roleis"assistant". - Interior frames carry
delta.contentdeltas — clients concatenate them. - Last real frame sets
choices[0].finish_reason. - Stream terminates with
data: [DONE].
Errors
Section titled “Errors”| Status | When |
|---|---|
| 400 | Malformed body (pydantic validation). |
| 404 | model not in /v1/models. |
| 502 | Upstream backend (HTTPBackend) errored or timed out. |
| 503 | Registry empty (/readyz only). |
Errors are JSON: {"detail": "..."}, matching FastAPI’s default.
None. The playground is a public demo surface. If you need to lock it down later, the cleanest layer is a Cloudflare Access policy on the ingress; the pod itself stays auth-free.
Versioning
Section titled “Versioning”- Chart version bumped in
plnt/charts/playground-api/Chart.yaml. - API version — this contract is v1 (the
/v1/...path prefix). A v2 path prefix would ship alongside v1, not replace it. - Breaking changes to
/v1/...require a corresponding update totests/test_site_contract.pyAND the plnt-siteapi.ts. That’s the guard against silent breakage.
Not implemented (won’t fix)
Section titled “Not implemented (won’t fix)”These OpenAI endpoints are deliberately not served:
POST /v1/completions— legacy completions. Use chat.POST /v1/embeddings— out of playground scope.POST /v1/files,POST /v1/fine_tuning/*— model lifecycle is a Helm concern.POST /v1/images/*,POST /v1/audio/*— different playground, different day.