API reference
This page lists every HTTP endpoint that the v0.1.2 server serves for a text model such as Qwen3.8 Flash Next. Each endpoint was checked against a running server.
Address and model name
Section titled “Address and model name”- The server listens on
127.0.0.1:8080. Change this with--hostand--port. - Requests use the model’s id, for example
huihui-qwen38-flash-next-ud-q4-k-xl-v1.GET /v1/modelslists it, and it listsbubotoo. Both names work. To use another name, set--served-model-name. Any other name returns 404 with the served id in the message. - A request with a
modelthat the server does not serve gets error 404model_not_found. A request with nomodelgets error 400missing_model.
The examples use the base address http://127.0.0.1:8080 and the model name bubo, which always works. See the quickstart to start the server.
Endpoint list
Section titled “Endpoint list”| Method | Path | Purpose |
|---|---|---|
| GET | /health |
Liveness. Also /v1/health and /healthz. |
| GET | /ready |
Readiness and model name. Also /v1/ready and /readyz. |
| GET | /v1/models |
The model that the server serves. Also /models. |
| POST | /v1/chat/completions |
Chat. OpenAI format. |
| POST | /v1/completions |
Text completion. OpenAI format. |
| POST | /v1/responses |
OpenAI Responses format. |
| POST | /v1/messages |
Anthropic Messages format. |
| POST | /completion |
Text completion. llama-server format. |
| POST | /apply-template |
Renders a chat request into the prompt text and returns {"prompt": ...}. llama-server format. |
| GET | /props |
Model name, template and default settings. llama-server format. |
| GET | /slots |
State of the session slot. Also /v1/slots. |
| GET | /metrics |
Prometheus text metrics. Also /v1/metrics. |
These paths exist but answer 501 not_implemented on a text model: POST /v1/embeddings, /v1/rerank, /v1/reranking, /rerank, /infill and the /sdapi/v1/... paths. Any other path answers 404 not_found.
When you serve an audio, image or video model, the server adds the endpoints for that model. This page does not cover them.
Health, ready and models
Section titled “Health, ready and models”curl.exe -s http://127.0.0.1:8080/health# {"status":"ok"}curl.exe -s http://127.0.0.1:8080/ready# {"status":"ready","model":"huihui-qwen38-flash-next-ud-q4-k-xl-v1"}curl.exe -s http://127.0.0.1:8080/v1/models# {"object":"list","data":[{"id":"huihui-qwen38-flash-next-ud-q4-k-xl-v1","object":"model","created":1793047296,"owned_by":"bubo","context_length":200000,"max_model_len":200000,"meta":{"n_ctx":200000},"architecture":{"input_modalities":["text","image"]}},{"id":"bubo","object":"model","created":1793047296,"owned_by":"bubo","context_length":200000,"max_model_len":200000,"meta":{"n_ctx":200000},"architecture":{"input_modalities":["text","image"]}}]}This is the output of Bubo 0.1.2 with Qwen3.8 Flash Next and the default settings. The two entries are the same model under two names.
/ready answers 503 not_ready while the model loads. After a GPU context loss, /health, /ready and every POST answer 503 with "status":"device_lost".
Chat completions
Section titled “Chat completions”POST /v1/chat/completions follows the OpenAI chat format.
@'{"model":"bubo","messages":[{"role":"user","content":"Say hi."}],"max_tokens":32}'@ | curl.exe -s http://127.0.0.1:8080/v1/chat/completions -H "Content-Type: application/json" -d "@-"Main request fields
Section titled “Main request fields”| Field | Meaning |
|---|---|
model |
Required. The served model name. |
messages |
Required. A non-empty array of messages with the roles system, user, assistant and tool. Content is a string or an array of parts, with image parts for models that take images. |
max_tokens, max_completion_tokens |
Limit on generated tokens. A value of -1 or null keeps the server default. Any other value must be a positive integer. |
stream |
true returns server-sent events. |
stream_options |
{"include_usage": true} adds a final usage chunk. |
temperature, top_p, top_k, min_p, seed |
Sampling. |
presence_penalty, frequency_penalty, repeat_penalty, logit_bias |
Penalties and token bias. |
stop |
A string or an array of strings. |
logprobs |
Return token log probabilities. |
tools, tool_choice, parallel_tool_calls |
Function calling. See below. |
response_format |
Use json_schema to force output that matches a schema. |
reasoning_effort |
off, minimal, low, medium, high, xhigh or max. |
thinking |
{"type":"enabled"} or {"type":"disabled"}. |
chat_template_kwargs |
enable_thinking and reasoning_effort. They must agree with the top-level fields. |
n |
Only 1 is accepted. Other values give error 400 unsupported_n. |
Response
Section titled “Response”A non-streaming response has the OpenAI shape:
{ "id": "chatcmpl-…", "object": "chat.completion", "created": 1791893817, "model": "bubo", "choices": [{ "index": 0, "message": { "role": "assistant", "reasoning_content": "The user wants me to say \"hi.\" …", "content": "Hi there! 👋" }, "finish_reason": "length" }], "usage": { "prompt_tokens": 13, "completion_tokens": 32, "total_tokens": 45, … }, "timings": { … }}reasoning_contentholds the reasoning text when thinking is on. Thinking is on by default. Setreasoning_efforttooffto turn it off.finish_reasonisstop,lengthortool_calls.usagealso reportsprompt_tokens_per_second,completion_tokens_per_second, cached tokens, the draft tokens that MTP proposed and accepted, and prompt-cache details inusage.gufo. The cache fields (cache_hit,cache_miss_reason,cache_snapshots_skippedand others) are in options.timingsreports the time of the prompt and of each generated token.
Streaming
Section titled “Streaming”Set "stream": true. The response has the content type text/event-stream. Each event is a line data: {json} followed by an empty line. Each chunk has the object chat.completion.chunk and a delta:
- The first chunk has
delta.role. - Reasoning text arrives in
delta.reasoning_content, and answer text indelta.content. - The last chunk with choices has an empty
deltaand thefinish_reason. It also carriestimings. - With
stream_options.include_usage, one more chunk follows with"choices": []and theusageobject. - The stream ends with
data: [DONE].
Tool calls
Section titled “Tool calls”Send the tools in tools, in the OpenAI function format. When the model calls a function, the message has tool_calls and the finish_reason is tool_calls:
"message": { "role": "assistant", "content": null, "tool_calls": [{ "id": "call_ehs0wunbyv65x5zy3woo", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"Paris\"}" } }]},"finish_reason": "tool_calls"arguments is a JSON string. Send the result back as a message with the role tool and the matching tool_call_id. In a stream, the calls arrive in delta.tool_calls.
Text completions
Section titled “Text completions”POST /v1/completions takes model, prompt and the same sampling fields. The response has the object text_completion and choices[].text.
@'{"model":"bubo","prompt":"The capital of France is","max_tokens":8}'@ | curl.exe -s http://127.0.0.1:8080/v1/completions -H "Content-Type: application/json" -d "@-"Responses
Section titled “Responses”POST /v1/responses takes model, input (a string or an array of items) and max_output_tokens. The response has the object response, a status of completed or incomplete, and an output array. The array holds a reasoning item and a message item with output_text content. The usage object has input_tokens, output_tokens and output_tokens_details.reasoning_tokens.
Tools in a Responses request follow the strict field. When a tool has no strict field, or strict is null, Bubo uses the tool schema as you sent it: optional properties stay optional. strict: true and strict: false act as the field says.
Anthropic messages
Section titled “Anthropic messages”POST /v1/messages takes the Anthropic Messages request: model, max_tokens and messages. The response has type: "message", a content array with thinking and text blocks, a stop_reason (end_turn, max_tokens, stop_sequence or tool_use) and usage with input_tokens and output_tokens.
POST /v1/messages/count_tokens takes the same text, system and tool history as Messages and returns {"input_tokens": N}. It does not generate text. A prompt can be longer than the context, so a client can size it before it trims it. Images are not supported. stream: true gives an error.
Errors on /v1/messages and /v1/messages/count_tokens use the Anthropic body, {"type":"error","error":{"type":...,"message":...},"request_id":...}, with the stable code in an extra code field of the error object. All other routes use the error shape in Errors.
llama-server endpoints
Section titled “llama-server endpoints”POST /completiontakespromptandn_predict, and needs nomodel. The response hascontent,stop,tokens_predicted,tokens_evaluated,timingsandusage.GET /propstakes an optionalmodelquery parameter. The response hasmodel,model_alias,template,model_infoand the default sampling settings.POST /apply-templatetakes the same body as/v1/chat/completionsand needs nomodel. It returns{"prompt": "..."}, the chat rendered as prompt text.streamis ignored.GET /slotsreturns an array with one object for the session slot:id,n_ctx,is_processing,stateand the prompt token counts.GET /metricsreturns Prometheus text. It includesllamacpp:prompt_tokens_total,llamacpp:tokens_predicted_total,llamacpp:prompt_tokens_seconds,llamacpp:predicted_tokens_seconds, the speculative decoding counters,llamacpp:requests_processing,llamacpp:requests_deferredandllamacpp:kv_cache_usage_ratio.
API key
Section titled “API key”Start the server with --api-key KEY. Then every request, health checks included, needs the header:
Authorization: Bearer KEYA missing or wrong key gives 401 with the header WWW-Authenticate: Bearer. Without --api-key, the server asks for no key. Keep --host 127.0.0.1 unless remote clients must connect.
Errors
Section titled “Errors”Errors use this JSON shape. Only /v1/messages and /v1/messages/count_tokens use the Anthropic shape (see Anthropic messages).
{"error":{"message":"model 'nope' is not served by this process","type":"invalid_request_error","code":"model_not_found"}}| Status | type |
Common code values |
|---|---|---|
| 400 | invalid_request_error |
parse_error, missing_model, missing_messages, unsupported_n |
| 401 | authentication_error |
invalid_api_key |
| 404 | invalid_request_error |
model_not_found, not_found |
| 501 | server_error |
not_implemented |
| 503 | server_error |
not_ready, device_lost, insufficient_memory, memory_pressure |
| 507 | server_error |
insufficient_memory_permanent |
The codes insufficient_memory and memory_pressure come from the memory guard. They have a Retry-After: 5 header: free memory, then send the request again. The code insufficient_memory_permanent has no Retry-After header: the request needs more memory than the computer can provide, so shorten the prompt or remove the image.
Debug endpoints, not for normal use
Section titled “Debug endpoints, not for normal use”POST /debug/prompt, GET /debug/cache and GET /debug/settings exist only when the server starts with --debug-hooks and listens on a loopback address. Do not use them in normal operation.
Feedback
Comments on this page use GitHub Discussions. You need a GitHub account to comment. For bugs, open an issue.