API reference

Streaming

Set stream: true to receive the reply token by token as server-sent events, the same format the OpenAI API uses.

The event format

The response has Content-Type: text/event-stream. Each event is one line starting with data: followed by a JSON chunk. New text arrives in choices[0].delta.content:

text
data: {"id":"gen-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":"A bonding"}}]}

data: {"id":"gen-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"content":" curve sets"}}]}

data: {"id":"gen-…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{},"finish_reason":"stop"}]}

data: {"id":"gen-…","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":31,"completion_tokens":74,"total_tokens":105,"cost":0.000123}}

data: [DONE]
  • The second-to-last chunk carries usage, including cost: the amount charged to your balance.
  • data: [DONE] marks the end of the stream.
  • Lines starting with : are keep-alive comments. Ignore them.

Python

python
stream = client.chat.completions.create(
    model="deepseek/deepseek-chat",
    messages=[{"role": "user", "content": "Write a haiku about block times."}],
    stream=True,
)

for chunk in stream:
    if chunk.choices and chunk.choices[0].delta.content:
        print(chunk.choices[0].delta.content, end="", flush=True)
    if getattr(chunk, "usage", None):
        print("\nCharged (USD):", chunk.usage.cost)

TypeScript

typescript
const stream = await client.chat.completions.create({
  model: "deepseek/deepseek-chat",
  messages: [{ role: "user", content: "Write a haiku about block times." }],
  stream: true,
});

for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
  if (chunk.usage) console.log("\nCharged (USD):", (chunk.usage as any).cost);
}

Plain fetch (no SDK)

javascript
const res = await fetch("https://www.synaps.chat/api/v1/chat/completions", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SYNAPS_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "deepseek/deepseek-chat",
    stream: true,
    messages: [{ role: "user", content: "gm" }],
  }),
});

const reader = res.body.getReader();
const decoder = new TextDecoder();
let buffer = "";
for (;;) {
  const { value, done } = await reader.read();
  if (done) break;
  buffer += decoder.decode(value, { stream: true });
  let i;
  while ((i = buffer.indexOf("\n")) >= 0) {
    const line = buffer.slice(0, i).trim();
    buffer = buffer.slice(i + 1);
    if (!line.startsWith("data:")) continue;
    const data = line.slice(5).trim();
    if (data === "[DONE]") break;
    const chunk = JSON.parse(data);
    process.stdout.write(chunk.choices?.[0]?.delta?.content ?? "");
  }
}

Stopping early

You can close the connection at any time. The provider may already have generated more text than you received, and it bills for what it produced, so Synaps charges the final usage reported by the provider even after you disconnect.

Errors during a stream

If something fails before the first chunk, you get a normal JSON error with an HTTP status (see Errors). If the provider fails mid-stream, a chunk with an error object may arrive instead of more content; treat it as the end of the reply.