API reference

Chat completions

Send a conversation, get the model's next message. Same request and response shape as the OpenAI Chat Completions API.

http
POST https://www.synaps.chat/api/v1/chat/completions

Request body

modelstringrequired
The model ID, for example deepseek/deepseek-chat. Must be one of the IDs returned by GET /models. Free models end in :free.
messagesarrayrequired
The conversation so far, oldest first. Each item has a role (system, user, assistant or tool) and content. Assistant messages may carry tool_calls; tool messages carry tool_call_id.
streamboolean
Default false. When true, the reply arrives as server-sent events. See Streaming.
max_tokensinteger
Upper limit on generated tokens. Defaults to 4096 when omitted. Lower it to cap the cost of a single request.
temperaturenumber
Sampling temperature, usually between 0 and 2. Lower is more focused, higher is more varied.
top_pnumber
Nucleus sampling. Use either this or temperature, not both.
stopstring | string[]
Up to four sequences where the model stops generating.
frequency_penaltynumber
Penalises tokens that already appeared often. Range −2 to 2.
presence_penaltynumber
Penalises tokens that already appeared at all. Range −2 to 2.
seedinteger
Best-effort determinism on models that support it.
toolsarray
Functions the model may call. See Tool calling.
tool_choicestring | object
auto, none, required, or a specific function.
response_formatobject
{ "type": "json_object" } or a JSON schema, on models that support structured output. See JSON output.
reasoningobject
Reasoning controls for thinking models, for example { "effort": "high" }. Ignored by models that do not reason.

Example request

bash
curl https://www.synaps.chat/api/v1/chat/completions \
  -H "Authorization: Bearer $SYNAPS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek/deepseek-chat",
    "temperature": 0.3,
    "max_tokens": 300,
    "messages": [
      {"role": "system", "content": "Answer in one short paragraph."},
      {"role": "user", "content": "Why do tokens use bonding curves?"}
    ]
  }'

Response

json
{
  "id": "gen-1729760000-AbCdEf",
  "object": "chat.completion",
  "created": 1729760000,
  "model": "deepseek/deepseek-chat",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "A bonding curve sets the price from the supply..."
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 31,
    "completion_tokens": 74,
    "total_tokens": 105,
    "cost": 0.000123
  }
}
choices[].message.contentstring | null
The reply text. null when the model answered only with tool calls.
choices[].message.tool_callsarray
Present when the model wants to call one of your tools.
choices[].finish_reasonstring
stop (finished), length (hit max_tokens), tool_calls, or content_filter.
usage.prompt_tokensinteger
Tokens in your input, as counted by the provider.
usage.completion_tokensinteger
Tokens the model generated, including any reasoning tokens.
usage.costnumber
What you were charged, in USD, including the Synaps fee. This amount was deducted from your balance. It is 0 for free models.

Multi-turn conversations

The API is stateless. To continue a conversation, send the full history every time, including the assistant's previous replies:

python
history = [{"role": "user", "content": "Name a layer-2 chain."}]
first = client.chat.completions.create(model="deepseek/deepseek-chat", messages=history)
history.append({"role": "assistant", "content": first.choices[0].message.content})
history.append({"role": "user", "content": "Who runs it?"})
second = client.chat.completions.create(model="deepseek/deepseek-chat", messages=history)

Images

Models with vision accept image parts in a user message, using the OpenAI content-array format:

json
{
  "role": "user",
  "content": [
    { "type": "text", "text": "What is in this chart?" },
    { "type": "image_url", "image_url": { "url": "https://example.com/chart.png" } }
  ]
}

You can also send an image as a base64 data URL (data:image/png;base64,…). PNG, JPEG, WebP and GIF are accepted. Only models that list image in input_modalities on GET /models can read images; sending one to a text-only model returns an error.

PDFs and documents

Send a PDF as a file part with a base64 data URL. It works with every model: models that read files natively get the PDF as is, and the rest receive its extracted text.

json
{
  "role": "user",
  "content": [
    { "type": "text", "text": "Summarise the key terms in this contract." },
    { "type": "file", "file": { "filename": "contract.pdf", "file_data": "data:application/pdf;base64,JVBERi0x..." } }
  ]
}

For plain text, Markdown, CSV, JSON or code files, put the contents straight into the text of the message. That is cheaper and works with any model.

Generating images

Models that list image in output_modalities can create images. Add "modalities": ["image", "text"] and send the request without streaming:

json
{
  "model": "google/gemini-3.1-flash-image",
  "modalities": ["image", "text"],
  "messages": [{ "role": "user", "content": "A glass orb orbiting a violet planet, studio lighting" }]
}

The images come back on the assistant message as base64 data URLs:

json
{
  "choices": [{
    "message": {
      "role": "assistant",
      "content": "Here is your image.",
      "images": [{ "type": "image_url", "image_url": { "url": "data:image/png;base64,iVBORw0..." } }]
    }
  }],
  "usage": { "prompt_tokens": 14, "completion_tokens": 1290, "cost": 0.0468 }
}

You pay what the model charges for the image plus the usual 20% fee, shown in usage.cost. Model IDs change over time, so pick a current one from GET /models.