Chat completions and streaming
This page takes you from a key to a completed answer, then to tokens arriving live. At the end you will have run a chat completion with curl, streamed one with server-sent events, and know exactly which request fields the API honours.
The value is narrow and concrete: one endpoint that your existing OpenAI-shaped client already speaks.
The endpoint
POST https://platform.synapsex.ai/api/v1/chat/completionsRequired headers:
Authorization: Bearer sk-synapsex-YOUR-API-KEY
Content-Type: application/jsonYour first completion
export SYNAPSEX_API_KEY=sk-synapsex-YOUR-API-KEY
curl -sS https://platform.synapsex.ai/api/v1/chat/completions \
-H "Authorization: Bearer $SYNAPSEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "synapsex-forge-code-14b-v1",
"messages": [{"role": "user", "content": "Hello!"}]
}'The response is an OpenAI chat.completion object. Read the assistant text
from choices[0].message.content:
{
"id": "...",
"object": "chat.completion",
"model": "synapsex-forge-code-14b-v1",
"choices": [
{
"index": 0,
"message": { "role": "assistant", "content": "..." },
"finish_reason": "stop"
}
],
"usage": { "prompt_tokens": 0, "completion_tokens": 0, "total_tokens": 0 }
}That is the documented response shape; the exact field set is whatever an OpenAI-compatible client expects.
Responses from this endpoint that reached the model gateway — successful ones,
streaming or not, and errors forwarded back from the gateway — carry an
X-SynapseX-Request-Id header. Log it when it is there. It is the single most
useful thing to include when you contact support about a specific request.
Requests rejected before the gateway is reached (401, 402, 403 and a malformed
body) do not carry it, and neither does GET /models.
Which request fields are supported?
The API forwards exactly six fields:
| Field | Required | Type | Meaning |
|---|---|---|---|
model | Yes | string | The model id to run. See Models. |
messages | Yes | array | Conversation turns, each {"role": "system" | "user" | "assistant", "content": "…"}. |
stream | No | boolean | true switches the response to server-sent events. |
temperature | No | number | Sampling temperature. |
top_p | No | number | Nucleus sampling. |
max_tokens | No | integer | Upper bound on generated tokens. |
Anything else you put in the body is not forwarded and will simply have no
effect. It is not rejected, it is dropped — which is worse, because the call
succeeds and quietly ignores what you asked for. Do not rely on tools,
tool_choice, response_format, seed, stop, n, logprobs,
presence_penalty, frequency_penalty or user on this endpoint.
Omitting model or messages returns HTTP 400:
{"error":{"message":"model and messages are required","type":"invalid_request_error"}}How to stream a response
Set "stream": true. The response arrives as text/event-stream: a sequence of
chat.completion.chunk frames, each prefixed with data: , terminated by a
final data: [DONE] line.
curl -sS --no-buffer https://platform.synapsex.ai/api/v1/chat/completions \
-H "Authorization: Bearer $SYNAPSEX_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "synapsex-forge-code-14b-v1",
"messages": [{"role": "user", "content": "Count from 1 to 5."}],
"stream": true
}'--no-buffer matters — without it curl waits for the whole body and you lose
the point of streaming.
Each chunk carries an incremental delta at choices[0].delta.content. In Python,
the SDK iterates them for you:
from synapsex_platform import LLMClient
client = LLMClient() # reads SYNAPSEX_API_KEY
stream = client.chat_completions(
model="synapsex-forge-code-14b-v1",
messages=[{"role": "user", "content": "Count from 1 to 5."}],
stream=True,
)
for chunk in stream:
choices = chunk.get("choices") or []
if not choices:
continue
piece = choices[0].get("delta", {}).get("content")
if piece:
print(piece, end="", flush=True)
print()The SDK stops the iteration when it sees [DONE], so you do not have to handle
the sentinel yourself.
Multi-turn conversations
The API is stateless. There is no conversation id and nothing is remembered
between calls — you build the history yourself by appending to messages:
{
"model": "synapsex-forge-code-14b-v1",
"messages": [
{"role": "system", "content": "You are a concise assistant."},
{"role": "user", "content": "What is a qubit?"},
{"role": "assistant", "content": "A qubit is ..."},
{"role": "user", "content": "And what is superposition?"}
]
}Every turn you keep costs tokens on every subsequent request, so trim old turns when the conversation gets long.
First successful call checklist
Four errors block a first call. Each maps to one fix:
| Status | Meaning | Fix |
|---|---|---|
| 401 | Key missing, malformed or deleted | Check the Bearer prefix and that the key still exists in the console |
| 402 | Workspace balance at or below zero | Add credits — this is checked before the model runs |
| 403 | Key lacks the chat:write scope | Create a new key with the default scope |
| 429 | Rate limited | Back off exponentially and cap your retries |
Full bodies and handling code are on API errors and how to handle them.