Local API

The tokspur local API: endpoint, chat completions, streaming, tool calls, authentication, cancellation and error responses.

A terminal connects by cable to a local engine box through a partly inserted plug.

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.

Routes in the tested contract
RoutePurpose
POST /v1/chat/completionsChat requests, streamed or buffered, with tool calls and thinking.
GET /v1/modelsLists the served identifier, tokspur.
GET /healthReadiness, 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.

Read the data boundaries

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.

Client responsibilities
ConditionResponseClient action
Missing or wrong key401Check the configured key and endpoint. Avoid printing the key.
Prompt leaves no room in the context400Shorten the conversation or the tool declarations and keep the tool-call sequence intact.
Unsupported field or value400Remove it from the request. The response does not name the field.
Waiting queue full429Wait for the active generation to finish before trying again.
Worker failed503Stop and start tokspur serve, because the server does not restart the worker.
CancellationConnection closedWait 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.