POST /v1/completions

POST /v1/completions

The legacy OpenAI Completions API. You send a raw prompt and the model continues it, with no chat template around it. Any OpenAI SDK or tool works when you point its base URL at https://api.abliteratedllm.dev/v1. For conversations, instructions, tools, images or reasoning output, use POST /v1/chat/completions instead.

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/completions \
  -H "Authorization: Bearer $YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "glm-5.3-flash-abliterated",
    "prompt": "The lighthouse keeper opened the logbook and wrote:",
    "max_tokens": 256,
    "temperature": 0.8
  }'

Abridged response:

{
  "id": "…",
  "object": "text_completion",
  "created": 1793700000,
  "model": "glm-5.3-flash-abliterated",
  "choices": [
    { "index": 0, "text": " Day 41. The fog came in before the gulls did…", "finish_reason": "stop" }
  ],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 187,
    "total_tokens": 199,
    "prompt_tokens_details": { "cached_tokens": 0 }
  }
}

Not on Official DeepSeek API models

DeepSeek's API has no completions endpoint, so a request for a model labelled Official DeepSeek API (variant "official_api" in GET /v1/models) fails with 400 invalid_request before anything is charged. Every other model in GET /v1/models works here.

Parameters

Fields not listed here are passed to the model unchanged. 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 that isn't an Official DeepSeek API model.
promptRequired. A string, or an array of 1 to 4 strings to complete several prompts in one request: each prompt gets its own choice, in order of index. 5 or more prompts, an empty array or a prompt of token ids (numbers) fail with 400 invalid_request. Text only: this endpoint takes no image input.
max_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.
streamtrue for server-sent events. Without it, the answer is generated as a stream on our side and returned as one text_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.
logprobsAn integer from 0 to 5: the log probability of each output token, plus that many of the most likely alternatives, in the format shown under Logprobs below. true with top_logprobs (0 to 5) works too, and returns the chat completions format instead.
echotrue puts the prompt in front of the generated text in text.
suffixText that should follow the completion. Passed through; not every model supports it.
n, best_ofOnly 1 (the default). Any other value fails with 400 invalid_request; to complete several prompts at once, send them as a prompt array.
service_tier"priority" runs the request on the priority tier of a model that has one, at its priority prices (pricing.priority in GET /v1/models). On a model without one it fails with 400 invalid_request. Any other value is ignored. The tier is described on POST /v1/chat/completions.
context_length_exceeded_behavior"truncate" (the default) or "error". See Context length below.
seed, 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":"text_completion","choices":[{"index":0,"text":" Day","logprobs":null,"finish_reason":null}]}

data: {"id":"…","object":"text_completion","choices":[{"index":0,"text":"","logprobs":null,"finish_reason":"stop"}]}

data: {"id":"…","object":"text_completion","choices":[],"usage":{"prompt_tokens":12,"completion_tokens":187,"total_tokens":199,"prompt_tokens_details":{"cached_tokens":0}}}

data: [DONE]

Each chunk carries the next piece of text for one choice, finish_reason arrives on a chunk of its own, and usage always arrives in a final chunk whose choices array is empty. Check that choices isn't empty before reading choices[0]:

from openai import OpenAI

client = OpenAI(base_url="$API_BASE", api_key="$YOUR_KEY")

stream = client.completions.create(
    model="glm-5.3-flash-abliterated",
    prompt="The lighthouse keeper opened the logbook and wrote:",
    max_tokens=256,
    stream=True,
)
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].text, end="")
    if chunk.usage:
        print("\n", chunk.usage)

With an array prompt, each chunk belongs to the choice in its choices[].index, and chunks for different prompts can carry different id values.

Logprobs

An integer logprobs returns the legacy format on each choice: parallel arrays with one entry per output token.

{
  "tokens": [" Day", " 41"],
  "token_logprobs": [-0.21, -1.73],
  "top_logprobs": [{ " Day": -0.21, " The": -2.05 }, { " 41": -1.73, " 12": -1.94 }],
  "text_offset": [51, 55]
}

While streaming, each chunk carries the entries for its own tokens. The non-streaming response joins them per choice.

Context length

The prompt plus the output budget must fit in the model's context window, context_length in GET /v1/models. With the default "context_length_exceeded_behavior": "truncate", the output budget is lowered to the room the prompt leaves; with "error", such a request fails with 400 invalid_request. A prompt that is longer than the context window on its own always fails, and is never cut.

Prompt caching

Caching is automatic, as on chat completions: when a prompt starts with the same tokens as a recent one, those tokens are read from cache and billed at the cached-input price. usage.prompt_tokens_details.cached_tokens reports how many.

Billing

prompt_tokens includes cached tokens, which are billed at the cached-input price:

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. With "service_tier": "priority", the model's priority prices replace its standard ones. Current prices are on GET /v1/models, which also explains holds, aborted streams and failed requests.

Errors

Errors use the OpenAI shape, {"error": {"type", "code", "message"}}. The codes are on the Errors page. Every response carries x-request-id.