Local requests
The server listens on the loopback interface only, at http://127.0.0.1:18081/v1 unless you configured another port. It accepts OpenAI-style chat completion requests for the model identifier tokspur.
| Route | Purpose |
|---|---|
POST /v1/chat/completions | Chat requests, streamed or buffered, with tool calls and thinking. |
GET /v1/models | Lists the served identifier, tokspur. |
GET /health | Readiness, with the key like every route. Answers 200 with status ready, or 503 with status worker_failed after a worker failure. |
Clients that require Anthropic Messages or OpenAI Responses can use the optional local gateway. Other routes return 404.
Messages
The default output budget is 8,192 tokens, including thinking, with an explicit limit of 1 to 32,768. n: 1 and boolean parallel_tool_calls are accepted. Setting parallel calls to false caps completed tool calls at 1. A request carries model, the messages array, max_tokens and sampling fields such as temperature, top_p, top_k, min_p and seed. Unknown fields, including stop, are refused with a 400 response that does not name the field. Tool definitions go in tools, and a tool result returns as a tool message carrying the tool_call_id from the assistant's call. The chat template and the tool declarations are part of the prompt, so count them against the 65,536-token context. A prompt that leaves no room to generate is refused with a 400 response. When the prompt fits but the output limit does not, the server lowers the limit to the room left, and the reply ends with finish reason length if it runs out.
Messages can quote conversation control spellings as literal text. The renderer keeps them separate from conversation boundaries. Generated examples of thinking or tool-call tags need code formatting, quoting or a backslash before the opener. Tool arguments stay structured JSON for clients. Parameter text in the pinned model format preserves literal entity spellings and tags. A historical argument containing \n</parameter> cannot be represented in that format and is refused before inference. Tool schemas accept annotations and bounded anyOf alternatives, with recursive validation before calls are returned. Unsupported schema features return 400. Gateway histories may include an optional integer index from 0 to 127 on a tool call. Call IDs and array order identify the call, so repeated index values are allowed. An assistant history may also duplicate its plain reasoning_content in thinking_blocks, with an empty or absent signature. Opaque or mismatched thinking data is refused. A numeric or duration-string keep_alive hint does not change worker lifetime.
Streaming
With "stream": true the response is a server-sent event stream of chat completion chunks, ending with data: [DONE]. Thinking arrives in delta.reasoning_content, separate from delta.content. Each completed tool call arrives after the text in its own delta.tool_calls chunk. The call carries its array index and complete arguments. All calls are validated before the first call is published, and a chunk with the finish reason tool_calls follows. Assemble chunks in order.
Closing the connection cancels the generation. Admission waits for that generation to drain before the next request runs, so confirm cancellation or completion before sending a replacement.
Authentication
Every inference request needs Authorization: Bearer with the key in .tokspur/state/api-key, which configuration generates with mode 0600. A missing or wrong key gets a 401 response. The key grants access to the model endpoint only. File and command permissions remain with the calling agent.
Request handling
Requests are generated in turn, and the next request waits its turn. Any request beyond that is refused with a 429 response rather than queued, and the server never retries a generation on its own.
| Condition | Response | Client action |
|---|---|---|
| Missing or wrong key | 401 | Check the configured key and endpoint. Avoid printing the key. |
| Prompt leaves no room in the context | 400 | Shorten the conversation or the tool declarations and keep the tool-call sequence intact. |
| Unsupported field or value | 400 | Remove it from the request. The response does not name the field. |
| Waiting queue full | 429 | Wait for the active generation to finish before trying again. |
| Worker failed | 503 | Stop and start tokspur serve, because the server does not restart the worker. |
| Cancellation | Connection closed | Wait for the active generation to stop before starting another. |
Automatic retries of generation requests duplicate work. Make retry behaviour explicit in the client and follow the diagnostic guidance.