POST /v1/chat/completions

POST /v1/chat/completions

The OpenAI Chat Completions API. Any OpenAI SDK or tool works when you point its base URL at https://api.abliteratedllm.dev/v1.

Placeholders: $API_BASE is https://api.abliteratedllm.dev/v1, $API_ORIGIN is https://api.abliteratedllm.dev, and $YOUR_KEY is your API key.

Request

curl $API_BASE/chat/completions \
  -H "Authorization: Bearer $YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm-5.3-flash-abliterated",
    "messages": [
      {"role": "system", "content": "You are a noir novelist."},
      {"role": "user", "content": "Open chapter one in three sentences."}
    ],
    "reasoning_effort": "low",
    "max_tokens": 2048,
    "temperature": 0.8
  }'

Abridged response:

{
  "id": "…",
  "object": "chat.completion",
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "Rain hit the window like it owed me money…" },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 31,
    "completion_tokens": 212,
    "total_tokens": 243,
    "prompt_tokens_details": { "cached_tokens": 0 }
  }
}

Parameters

Fields not listed here are passed to the model unchanged, so standard OpenAI parameters work. Sampling parameters are range-checked first: a value outside its range fails with 400 invalid_request before anything is charged.

FieldNotes
modelRequired. Any id from GET /v1/models, currently glm-5.3-flash-abliterated, deepseek-v4.1-flash or deepseek-v4-pro.
messagesRequired. Text only (see below).
max_tokens or max_completion_tokensOutput budget. Default 16384. Lowered to the model's max output (max_output_tokens in GET /v1/models), and to 4096 on trial accounts. A value above the limit is lowered, not rejected.
reasoning_effortPassed through. "low", "medium" or "high" sets how much the model reasons before answering.
streamtrue for server-sent events. Without it, the answer is generated as a stream on our side and returned as one chat.completion when it ends, so a request cut by the time limit or a disconnect is billed for the output generated so far.
stream_optionsinclude_usage is always switched on, so streams always end with a usage chunk.
temperature0 to 2.
top_p0 to 1.
top_k0 to 100.
frequency_penalty, presence_penalty-2 to 2.
stopA string or up to 4 strings.
tools, tool_choice, parallel_tool_callsFunction tools, as in the OpenAI API. A tool whose type isn't "function" fails with 400 invalid_request.
nOnly 1 (the default). Any other value fails with 400 invalid_request; send separate requests for more samples.
response_formatjson_object or json_schema for structured output.
prompt_cache_keyPassed through. Requests that share a key are routed together, which raises prompt cache hits.
userPassed through.

Streaming

With "stream": true the response is a stream of data: lines. Headers are sent as soon as the model accepts the request. Until the first token arrives, the stream carries an SSE comment line, : ping, every 15 seconds, so proxies don't close an idle connection. SSE clients and the OpenAI SDKs ignore comment lines.

: ping

data: {"id":"…","object":"chat.completion.chunk","choices":[{"index":0,"delta":{"role":"assistant","content":"Rain"}}]}

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

data: {"id":"…","object":"chat.completion.chunk","choices":[],"usage":{"prompt_tokens":31,"completion_tokens":212,"total_tokens":243,"prompt_tokens_details":{"cached_tokens":0}}}

data: [DONE]

Usage always arrives in its own final chunk, and that chunk has an empty choices array. Check that choices isn't empty before reading choices[0]:

for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="")
    if chunk.usage:
        print("\n", chunk.usage)

Reasoning

Models that reason before they answer, such as glm-5.3-flash-abliterated, use reasoning_effort to set how much. The model's page under Models says whether it reasons. When the model returns its reasoning, it arrives in reasoning_content: on choices[0].message in a normal response, and on choices[0].delta while streaming. Reasoning tokens are output tokens: they count toward the output budget and are billed at the output price.

Text only

The models accept text. A message with an image, video, audio or file content part fails with 400 unsupported_content before anything is charged. The rejected part types are image_url, input_image, image, video, input_audio and file. Plain string content and text parts are fine. Content nested many levels deep (parts inside parts) fails with 400 invalid_request.

Context length

A prompt longer than the model's context window fails with an error. It is never silently truncated.

Prompt caching

Caching is automatic: when a request starts with the same tokens as a recent one, those tokens are read from cache and billed at the lower cached-input price. usage.prompt_tokens_details.cached_tokens reports how many. To raise hit rates for a long conversation or agent session, send the same prompt_cache_key on every request of that session. We recommend it for any client that sends many requests with a shared prefix.

Billing

cost = (prompt_tokens - cached_tokens) × input price
     + cached_tokens × cached-input price
     + completion_tokens × output price

Prices are per 1M tokens and each term is rounded up to the next $0.000001. Current prices are on GET /v1/models, which also explains holds, aborted streams and failed requests.

Headers

Claude Code's session header, X-Claude-Code-Session-Id, is honored for cache affinity; every other client header is dropped. Every response carries x-request-id.

Errors

Errors use the OpenAI shape, {"error": {"type", "code", "message"}}. The codes are on the Errors page.