DGX Spark · documentation

API

docs/api.md Last pushed 3 September 2026

The server speaks the OpenAI chat-completions protocol on http://127.0.0.1:8000/v1. Any OpenAI-compatible client works; point it at that base URL with any (or no) API key.

Endpoints

Path What
GET /health {"status": "healthy"} once the model is loaded — ./run.sh serve waits on it
GET /v1/models lists deepseek-v4-flash-0731
POST /v1/chat/completions chat, streaming or not, tools, reasoning
POST /v1/completions raw completions (you supply the formatted prompt)
GET /v1/model the loaded model's parameters (context length, draft, etc.)

Plain chat

curl -s http://127.0.0.1:8000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{
    "model": "deepseek-v4-flash-0731",
    "messages": [{"role": "user", "content": "Explain unified memory in three sentences."}]
  }' | jq -r '.choices[0].message.content'

No sampling parameters sent → DeepSeek's recommended temperature 1.0 / top_p 1.0.

Streaming

curl -sN http://127.0.0.1:8000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{
    "model": "deepseek-v4-flash-0731",
    "stream": true,
    "stream_options": {"include_usage": true},
    "messages": [{"role": "user", "content": "Write a limerick about a lighthouse."}]
  }'

Chunks arrive one per draft step — around six tokens every ~150 ms — so text appears in small even bursts rather than one token at a time. The final chunk carries usage with prompt_tokens, completion_tokens, and the server's own completion_tokens_per_sec.

Sampling

"temperature": 0

Send your own temperature / top_p when you want them; unset means DeepSeek's 1.0 / 1.0. Speed does not hinge on this: code and structured output stream at 50–57 tok/s and free prose at ~30 tok/s whichever temperature you pick, because the speculative draft is accepted on predictable text and rejected on open-ended text. Use 0 where you would use greedy anyway (extraction, classification, strict formats) and the default for long open-ended writing, where greedy decoding can loop on this model.

Thinking

curl -s http://127.0.0.1:8000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{
    "model": "deepseek-v4-flash-0731",
    "messages": [{"role": "user", "content": "Is 2^61 - 1 prime? Reason carefully."}],
    "chat_template_kwargs": {"thinking": true, "reasoning_effort": "high"}
  }' | jq '{reasoning: .choices[0].message.reasoning_content, answer: .choices[0].message.content}'

reasoning_effort: low (default when thinking is on), high, max. Streaming responses carry reasoning as delta.reasoning_content before the first delta.content. Budget for it: a high answer to a hard question is routinely several thousand reasoning tokens.

Clients that only know the OpenAI-style fields work too. Any of these turn thinking on, without chat_template_kwargs:

"reasoning_effort": "high"
"enable_thinking": true
"reasoning": {"effort": "high"}

reasoning_effort at the top level: none and low keep thinking off, medium turns it on with no effort text, high and max add DeepSeek's effort text; xhigh is accepted as max. An explicit chat_template_kwargs.thinking always wins over the derived value.

Tool calling

Standard OpenAI tools / tool_choice. The server parses the model's DSML block into tool_calls:

curl -s http://127.0.0.1:8000/v1/chat/completions \
  -H 'content-type: application/json' \
  -d '{
    "model": "deepseek-v4-flash-0731",
    "messages": [{"role": "user", "content": "What is the weather in Lisbon right now?"}],
    "tools": [{"type": "function", "function": {
      "name": "get_weather",
      "description": "Current weather for a city",
      "parameters": {"type": "object", "properties": {"city": {"type": "string"}}, "required": ["city"]}
    }}]
  }' | jq '.choices[0] | {finish_reason, tool_calls: .message.tool_calls}'
{
  "finish_reason": "tool_calls",
  "tool_calls": [{"id": "…", "type": "function",
                  "function": {"name": "get_weather", "arguments": "{\"city\": \"Lisbon\"}"}}]
}

Send the result back as a {"role": "tool", "tool_call_id": …, "content": …} message and continue. In streaming mode the call arrives as delta.tool_calls. DeepSeek suggests top_p: 0.95 for agentic use. Note that with tools in the prompt the model is eager to use them — a note-taking tool offered alongside "write me a story" will get called — so attach tools to the requests that need them, not to every request.

Python

from openai import OpenAI
client = OpenAI(base_url="http://127.0.0.1:8000/v1", api_key="none")

r = client.chat.completions.create(
    model="deepseek-v4-flash-0731",
    messages=[{"role": "user", "content": "Summarise the attached RFC in five bullets.\n\n" + rfc_text}],
    temperature=0,
    extra_body={"chat_template_kwargs": {"thinking": True}},
)
print(r.choices[0].message.reasoning_content)
print(r.choices[0].message.content)

Long prompts

Up to 393,216 tokens per request. Prefill runs at roughly 550–800 tok/s, so a 100k-token prompt takes about two minutes before the first token and a 300k-token prompt about six. Set your client's timeout accordingly, and send long conversations in the same order each turn so the prefix cache serves the unchanged prefix.

Concurrency

max_batch_size: 1: one request generates at a time; the rest wait in a queue and are served in order. A client that sees a slow time-to-first-token while another request is running is seeing the queue, not the model — see configuration.md for max_batch_size: 2.

Every number here was measured. Open an issue if one looks wrong.

All documentation