Skip to content

OpenAI-compatible chat ​

Use POST /v1/chat/completions and GET /v1/models with the OpenAI Python or JavaScript SDK by changing the base URL and API key. This is text Chat Completions compatibility, not support for every OpenAI endpoint or capability.

Authentication and models ​

Use the same console API key: Authorization: Bearer sk-your-key. The model list contains currently available text models and their public IDs. Use the returned id; do not use a display name. Prices and voice IDs remain available in /v1/chat/catalog.

bash
curl https://api.coldstart.win/v1/models -H "Authorization: Bearer sk-your-key"
json
{"object":"list","data":[{"id":"chat-standard","object":"model","created":0,"owned_by":"girllab"}]}

Requests and conversation history ​

Each request supplies the complete messages array in order. Supported roles: system, developer, user, assistant, tool. Content may be a string or an array of { "type": "text", "text": "..." } parts. No server history or default persona is added. Each turn must include the required system instructions and relevant history.

bash
curl https://api.coldstart.win/v1/chat/completions \
  -H "Authorization: Bearer sk-your-key" \
  -H "Content-Type: application/json" \
  -d '{"model":"chat-standard","messages":[{"role":"system","content":"You are a helpful assistant."},{"role":"user","content":"Hello!"}],"max_tokens":256}'
json
{
  "id": "chatcmpl_example",
  "object": "chat.completion",
  "created": 1792540800,
  "model": "chat-standard",
  "choices": [{"index": 0, "message": {"role": "assistant", "content": "Hello!", "refusal": null}, "logprobs": null, "finish_reason": "stop"}],
  "usage": {"prompt_tokens": 12, "completion_tokens": 3, "total_tokens": 15}
}

Supported parameters ​

model and a non-empty messages array are required. Optional: stream (default false), temperature (0–2), top_p (0–1), max_tokens or max_completion_tokens (integer 1–8192, mutually exclusive), stop (one string or 1–4 strings), presence_penalty and frequency_penalty (−2–2), seed (safe integer), n (only 1). Omitted generation settings use the service defaults; effects of sampling parameters depend on the selected model. stream_options: {"include_usage": true} is only valid with stream: true. Optional null values use defaults. The HTTP JSON body limit is 15 MiB; token context limits depend on the model.

Streaming and usage ​

Streaming uses data-only SSE, with no custom event: delta or event: completed. Read choices[0].delta.content, then the final finish_reason (stop, length or content_filter, tool_calls) and data: [DONE]. With include_usage: true, an extra chunk with choices: [] and the final usage precedes [DONE]; other chunks have usage: null. Without it, streaming chunks omit usage. All chunks share a local completion ID, creation time and public model ID.

json
{"model":"chat-standard","messages":[{"role":"user","content":"Hello!"}],"stream":true,"stream_options":{"include_usage":true}}
text
data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1792540800,"model":"chat-standard","choices":[{"index":0,"delta":{"role":"assistant","content":""},"logprobs":null,"finish_reason":null}],"usage":null}

data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1792540800,"model":"chat-standard","choices":[{"index":0,"delta":{"content":"Hello!"},"logprobs":null,"finish_reason":null}],"usage":null}

data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1792540800,"model":"chat-standard","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null}

data: {"id":"chatcmpl_example","object":"chat.completion.chunk","created":1792540800,"model":"chat-standard","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":3,"total_tokens":15}}

data: [DONE]

Errors and supported scope ​

Errors use { "error": { "message": "...", "type": "invalid_request_error", "param": null, "code": "invalid_request" } }. HTTP 400 means invalid or unsupported input; 401 invalid key, 402 insufficient credits, 429 rate limiting, 503 temporary service failure, and 504 timeout. Errors are sanitized. Before streaming begins, failures use an HTTP JSON error; after it begins, a data: {"error": ...} frame ends the stream without a success marker. Do not treat a partial response as completed. First-text timeout: 90 seconds; idle timeout: 60 seconds, reset by each text delta. Non-streaming requests time out after 60 seconds.

Unsupported: image/audio inputs, hosted search, hosted code execution, legacy functions / function_call, custom tools, log probabilities, multiple candidates, store, the Responses API, and other unlisted parameters. Requests are rejected rather than silently ignored. Use /v1/chat/speech for speech.

Billing and SDK examples ​

The same balance, public model prices and input/output token billing apply. Credits are reserved before generation and settled using reported usage; unused reservations are released. Generation failure, invalid usage or a disconnect before settlement releases the reservation. Cancellation after a successful settlement does not undo the charge. Calls appear in Usage history and the admin dashboard; the standard JSON response contains usage, not a custom billing field. Repeating a request may incur another charge; no idempotency is provided.

bash
pip install openai
npm install openai
python
import os
from openai import OpenAI

client = OpenAI(api_key=os.environ["KARMAN_API_KEY"], base_url="https://api.coldstart.win/v1", max_retries=0)
print([model.id for model in client.models.list().data])
model = os.environ["KARMAN_MODEL"]
messages = [{"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Hello!"}]
reply = client.chat.completions.create(model=model, messages=messages, max_tokens=256)
print(reply.choices[0].message.content)

stream = client.chat.completions.create(model=model, messages=messages, max_tokens=256,
    stream=True, stream_options={"include_usage": True})
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="", flush=True)
    if chunk.usage:
        print("\n", chunk.usage)
javascript
import OpenAI from "openai";

const client = new OpenAI({ apiKey: process.env.KARMAN_API_KEY, baseURL: "https://api.coldstart.win/v1", maxRetries: 0 });
const models = await client.models.list();
console.log(models.data.map(model => model.id));
const stream = await client.chat.completions.create({
  model: process.env.KARMAN_MODEL,
  messages: [{ role: "user", content: "Hello!" }],
  stream: true,
  stream_options: { include_usage: true }
});
for await (const chunk of stream) {
  process.stdout.write(chunk.choices[0]?.delta.content ?? "");
  if (chunk.usage) console.log("\n", chunk.usage);
}

Agent tools and structured output ​

Check models[].capabilities in /v1/chat/catalog: tool_calling, parallel_tool_calls, json_mode, structured_outputs. These are model-specific. Unsupported capabilities return HTTP 400 before generation. Tools run in your application; the API does not execute functions or retain agent memory.

Use tools (up to 128 function definitions), tool_choice (auto, none, required, or a named function), and parallel_tool_calls (boolean, requires tools). Each function accepts name, description, JSON Schema parameters, and optional strict. A tool response contains message.tool_calls; content may be null. Append the assistant message unchanged, then one role: "tool" message per call with its matching tool_call_id. Return all results before the next model turn, including failures as tool results. Keep unique call IDs and preserve conversation order.

For streaming, accumulate choices[0].delta.tool_calls by index, concatenate function.arguments fragments, and retain id, type, and function.name when present. Arguments may span multiple chunks. Execute only after finish_reason: "tool_calls" and a successful stream ending; never execute truncated (length) or failed output. Tool deltas also reset the 60-second idle timeout; the first output timeout is 90 seconds. Validate function names and arguments, enforce permissions, and limit agent rounds in your application.

response_format accepts text, json_object, or json_schema with json_schema: {name, schema, strict, description?}. In JSON mode, explicitly request JSON in the prompt. For strict schemas, mark all properties required and set additionalProperties: false; nullable fields can represent optional values. Do not combine JSON Schema output with parallel_tool_calls: true. Always handle refusal, length, and errors before parsing. Schemas constrain structure, not factual accuracy. Tool definitions, arguments and results contribute to token billing; every model round is billed separately.

Complete tool loop ​

python
import os, json
from openai import OpenAI

client = OpenAI(api_key=os.environ["KARMAN_API_KEY"],
                base_url="https://api.coldstart.win/v1", max_retries=0)
model = os.environ["KARMAN_MODEL"]
tools = [{"type": "function", "function": {
    "name": "lookup_memory", "description": "Read a saved preference.",
    "parameters": {"type": "object", "properties": {"topic": {"type": "string"}},
                   "required": ["topic"], "additionalProperties": False},
    "strict": True
}}]
messages = [{"role": "user", "content": "What food do I like? Use my saved memory."}]

for _ in range(4):
    reply = client.chat.completions.create(
        model=model, messages=messages, tools=tools,
        tool_choice="auto", parallel_tool_calls=False, max_tokens=512)
    choice = reply.choices[0]
    message = choice.message
    if message.refusal or choice.finish_reason not in ("stop", "tool_calls"):
        raise RuntimeError("Incomplete or refused response")
    messages.append(message.model_dump(exclude_none=True))
    if not message.tool_calls:
        print(message.content)
        break
    for call in message.tool_calls:
        try:
            if call.function.name != "lookup_memory":
                raise ValueError("Unknown function")
            args = json.loads(call.function.arguments)
            if not isinstance(args, dict) or set(args) != {"topic"} or not isinstance(args["topic"], str):
                raise ValueError("Invalid arguments")
            result = {"topic": args["topic"], "preference": "apples"}
        except (ValueError, TypeError):
            result = {"error": "Invalid tool request"}
        messages.append({"role": "tool", "tool_call_id": call.id,
                         "content": json.dumps(result)})
else:
    raise RuntimeError("Agent round limit reached")

Structured output example ​

python
reply = client.chat.completions.create(
    model=model,
    messages=[{"role": "user", "content": "I like apples. Extract this preference as JSON."}],
    response_format={"type": "json_schema", "json_schema": {
        "name": "memory", "strict": True,
        "schema": {"type": "object", "properties": {"preference": {"type": "string"}},
                   "required": ["preference"], "additionalProperties": False}
    }}, max_tokens=256)
choice = reply.choices[0]
if choice.finish_reason != "stop" or choice.message.refusal:
    raise RuntimeError("Incomplete or refused response")
memory = json.loads(choice.message.content)
print(memory)
© 2026 GirlLab. All rights reserved.