[{"data":1,"prerenderedAt":92},["ShallowReactive",2],{"guides-openai-compatible-api":3},{"collection":4,"slug":5,"path":6,"title":7,"seoTitle":8,"description":9,"summary":10,"primaryKeyword":11,"cluster":12,"published":13,"updated":13,"reviewed":13,"readingMinutes":14,"html":15,"toc":16,"wordCount":33,"sources":34,"faq":63,"related":70,"tested":87,"internalLinks":91},"guides","openai-compatible-api","\u002Fguides\u002Fopenai-compatible-api\u002F","OpenAI-compatible LLM APIs, and where they differ","OpenAI-Compatible LLM API: What Changes Between Providers","What OpenAI-compatible means for uncensored LLM APIs: base URLs, ignored parameters, reasoning fields, usage in streams, tool calls, plus a script to probe any endpoint.","An OpenAI-compatible API accepts the chat-completions request format, so the official SDKs work after changing the base URL and key. Compatibility stops at the shape of the request: providers differ in which parameters they apply, how they return reasoning, whether usage arrives in streams, and how they cap output. Probe an endpoint before relying on any of these.","openai compatible uncensored llm api","api-features","2026-11-14",3,"\u003Ch2 id=\"what-compatible-covers\">What “compatible” covers\u003C\u002Fh2>\n\u003Cp>The OpenAI chat-completions format has become the common interface for hosted and local language models. A compatible server accepts \u003Ccode>POST \u002Fchat\u002Fcompletions\u003C\u002Fcode> with a \u003Ccode>model\u003C\u002Fcode> and a list of \u003Ccode>messages\u003C\u002Fcode>, returns a \u003Ccode>choices\u003C\u002Fcode> array, and can stream the reply as server-sent events. That is enough for the official Python and Node SDKs, and for most tools built on them, to work after you change two settings: the base URL and the key.\u003C\u002Fp>\n\u003Cp>Everything else is up to the provider. Two servers can accept the same request and treat half of its parameters differently. The table below shows the differences that matter most, as each provider documents them.\u003C\u002Fp>\n\u003Ch2 id=\"where-providers-differ\">Where providers differ\u003C\u002Fh2>\n\u003Cdiv class=\"table-wrap\" role=\"region\" aria-label=\"Scrollable table\" tabindex=\"0\">\n\u003Ctable>\n\u003Cthead>\n\u003Ctr>\n\u003Cth>Area\u003C\u002Fth>\n\u003Cth>What varies\u003C\u002Fth>\n\u003Cth>Example from documentation\u003C\u002Fth>\n\u003C\u002Ftr>\n\u003C\u002Fthead>\n\u003Ctbody>\n\u003Ctr>\n\u003Ctd>Base URL\u003C\u002Ftd>\n\u003Ctd>The path before \u003Ccode>\u002Fchat\u002Fcompletions\u003C\u002Fcode>\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>\u002Fv1\u003C\u002Fcode> (Featherless, llama.cpp, vLLM) vs \u003Ccode>\u002Fapi\u002Fv1\u003C\u002Fcode> (Venice, OpenRouter, MolochAI)\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Ignored parameters\u003C\u002Ftd>\n\u003Ctd>Accepted without error but not applied\u003C\u002Ftd>\n\u003Ctd>MolochAI drops \u003Ccode>stop\u003C\u002Fcode>, \u003Ccode>n\u003C\u002Fcode>, \u003Ccode>seed\u003C\u002Fcode>, \u003Ccode>frequency_penalty\u003C\u002Fcode>, \u003Ccode>presence_penalty\u003C\u002Fcode>, \u003Ccode>top_k\u003C\u002Fcode>, \u003Ccode>logprobs\u003C\u002Fcode> and \u003Ccode>logit_bias\u003C\u002Fcode>\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>JSON mode\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>response_format\u003C\u002Fcode> honoured or not\u003C\u002Ftd>\n\u003Ctd>MolochAI ignores it; Venice and OpenRouter flag support per model\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Output cap\u003C\u002Ftd>\n\u003Ctd>\u003Ccode>max_tokens\u003C\u002Fcode> respected, capped, or replaced\u003C\u002Ftd>\n\u003Ctd>MolochAI replaces it with the plan’s output cap of 9,000 tokens\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Usage in streams\u003C\u002Ftd>\n\u003Ctd>Always, on request, or never\u003C\u002Ftd>\n\u003Ctd>MolochAI always includes it in the final chunk; OpenAI-style servers send it when \u003Ccode>stream_options.include_usage\u003C\u002Fcode> is set\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Tool calls while streaming\u003C\u002Ftd>\n\u003Ctd>Arguments in fragments or whole\u003C\u002Ftd>\n\u003Ctd>MolochAI sends arguments whole; the OpenAI format allows fragments\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Reasoning text\u003C\u002Ftd>\n\u003Ctd>In \u003Ccode>content\u003C\u002Fcode>, in a separate field, or hidden\u003C\u002Ftd>\n\u003Ctd>vLLM returns it in \u003Ccode>message.reasoning\u003C\u002Fcode>, according to the dealignai GLM-5.3-Flash card; other servers inline \u003Ccode>&lt;think&gt;\u003C\u002Fcode> blocks\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003Ctr>\n\u003Ctd>Model ids\u003C\u002Ftd>\n\u003Ctd>Repo names, provider names, or aliases\u003C\u002Ftd>\n\u003Ctd>Featherless uses Hugging Face repo ids; Venice and MolochAI use their own ids\u003C\u002Ftd>\n\u003C\u002Ftr>\n\u003C\u002Ftbody>\n\u003C\u002Ftable>\n\u003C\u002Fdiv>\n\u003Cp>Two practical consequences. First, a parameter you rely on for correctness, such as \u003Ccode>stop\u003C\u002Fcode> or \u003Ccode>response_format\u003C\u002Fcode>, must be tested on each provider, because a silent ignore looks like success. Second, if your code reads reasoning, it needs to look in more than one place.\u003C\u002Fp>\n\u003Ch2 id=\"probe-an-endpoint-before-you-depend-on-it\">Probe an endpoint before you depend on it\u003C\u002Fh2>\n\u003Cp>This script sends two small requests and reports what the endpoint returned: whether your model is listed, the finish reason and usage of a plain request, where reasoning text appears, and whether usage arrives in a stream.\u003C\u002Fp>\n\u003Cdiv class=\"code-block\" data-lang=\"python\">\u003Cspan class=\"sr-only\">python code\u003C\u002Fspan>\u003Cpre tabindex=\"0\">\u003Ccode class=\"language-python\">&quot;&quot;&quot;Probe an OpenAI-compatible endpoint and report what it actually returns.\n\nChecks: model list, a plain completion, usage, a streamed completion, whether\nusage arrives in the stream, and where reasoning text appears. Sends two\nsmall requests, so it costs a few hundred tokens.\n&quot;&quot;&quot;\nimport os\n\nfrom openai import OpenAI, APIStatusError\n\nclient = OpenAI(base_url=os.environ[&quot;LLM_BASE_URL&quot;], api_key=os.environ[&quot;LLM_API_KEY&quot;], timeout=60.0, max_retries=1)\nMODEL = os.environ[&quot;LLM_MODEL&quot;]\nreport = []\n\n\ndef check(name, fn):\n    try:\n        report.append((name, &quot;ok&quot;, fn()))\n    except APIStatusError as e:\n        report.append((name, f&quot;HTTP {e.status_code}&quot;, e.message[:120]))\n    except Exception as e:  # report anything else instead of stopping\n        report.append((name, &quot;error&quot;, f&quot;{type(e).__name__}: {e}&quot;[:120]))\n\n\ndef models():\n    ids = [m.id for m in client.models.list().data]\n    found = &quot;listed&quot; if MODEL in ids else &quot;NOT listed&quot;\n    return f&quot;{len(ids)} models; {MODEL} {found}&quot;\n\n\ndef plain():\n    r = client.chat.completions.create(model=MODEL, messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;Reply with the word ok.&quot;}], max_tokens=50)\n    msg = r.choices[0].message\n    extra = msg.model_extra or {}\n    reasoning = [k for k in (&quot;reasoning&quot;, &quot;reasoning_content&quot;) if extra.get(k)]\n    usage = f&quot;{r.usage.prompt_tokens} in \u002F {r.usage.completion_tokens} out&quot; if r.usage else &quot;no usage&quot;\n    where = f&quot;reasoning in field {reasoning[0]}&quot; if reasoning else (&quot;reasoning inline in content&quot; if &quot;&lt;think&gt;&quot; in (msg.content or &quot;&quot;) else &quot;no separate reasoning&quot;)\n    return f&quot;finish_reason={r.choices[0].finish_reason}; {usage}; {where}&quot;\n\n\ndef streamed():\n    chunks, usage = 0, None\n    stream = client.chat.completions.create(\n        model=MODEL, messages=[{&quot;role&quot;: &quot;user&quot;, &quot;content&quot;: &quot;Count from one to five.&quot;}], max_tokens=60,\n        stream=True, stream_options={&quot;include_usage&quot;: True},\n    )\n    with stream:\n        for chunk in stream:\n            chunks += 1\n            usage = chunk.usage or usage\n    return f&quot;{chunks} chunks; usage {'present' if usage else 'absent'} in stream&quot;\n\n\ncheck(&quot;GET \u002Fmodels&quot;, models)\ncheck(&quot;chat completion&quot;, plain)\ncheck(&quot;streaming&quot;, streamed)\n\nwidth = max(len(n) for n, _, _ in report)\nfor name, status, detail in report:\n    print(f&quot;{name:&lt;{width}}  {status:&lt;8}  {detail}&quot;)\n\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>Against the mock server in our repository it printed:\u003C\u002Fp>\n\u003Cdiv class=\"code-block\" data-lang=\"text\">\u003Cspan class=\"sr-only\">text code\u003C\u002Fspan>\u003Cpre tabindex=\"0\">\u003Ccode class=\"language-text\">GET \u002Fmodels      ok        1 models; mock-model listed\nchat completion  ok        finish_reason=stop; 6 in \u002F 10 out; no separate reasoning\nstreaming        ok        11 chunks; usage present in stream\n\u003C\u002Fcode>\u003C\u002Fpre>\u003C\u002Fdiv>\n\u003Cp>Run it with your own \u003Ccode>LLM_BASE_URL\u003C\u002Fcode>, \u003Ccode>LLM_API_KEY\u003C\u002Fcode> and \u003Ccode>LLM_MODEL\u003C\u002Fcode>. The requests are tiny, so the cost is a few hundred tokens.\u003C\u002Fp>\n\u003Ch2 id=\"parameters-to-treat-with-care\">Parameters to treat with care\u003C\u002Fh2>\n\u003Cul>\n\u003Cli>\u003Cstrong>\u003Ccode>max_tokens\u003C\u002Fcode>.\u003C\u002Fstrong> Providers cap output per reply. Send what you need, then check \u003Ccode>finish_reason\u003C\u002Fcode> for \u003Ccode>length\u003C\u002Fcode>.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>temperature\u003C\u002Fcode> and \u003Ccode>top_p\u003C\u002Fcode>.\u003C\u002Fstrong> Usually honoured, but defaults differ by provider and by model. Set them explicitly if results must be repeatable.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>seed\u003C\u002Fcode>.\u003C\u002Fstrong> Rarely guaranteed with open-weight serving stacks, and ignored by some providers. Do not build tests that depend on identical outputs.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>\u003Ccode>response_format\u003C\u002Fcode>.\u003C\u002Fstrong> Where it is ignored, ask for JSON in the prompt and validate the result with a schema library; retry on parse failure.\u003C\u002Fli>\n\u003Cli>\u003Cstrong>Model-specific options.\u003C\u002Fstrong> Some models take extra parameters, such as \u003Ccode>reasoning_effort\u003C\u002Fcode>, and their cards document pitfalls. The GLM-5.3-Flash card says the parameter defaults to its deepest mode when missing; one variant’s card adds that a small \u003Ccode>max_tokens\u003C\u002Fcode> at that setting can return an empty reply.\u003C\u002Fli>\n\u003C\u002Ful>\n\u003Ch2 id=\"when-compatibility-is-not-enough\">When compatibility is not enough\u003C\u002Fh2>\n\u003Cp>If you need features outside chat completions, such as embeddings, file uploads, batch jobs or the newer Responses API, check that the provider implements them; many do not. And compatibility says nothing about what is being served. Two endpoints that accept \u003Ccode>qwen3.8-27b-uncensored\u003C\u002Fcode> and \u003Ccode>huihui-ai\u002FHuihui-Qwen3.8-27B-abliterated\u003C\u002Fcode> might serve different weights. The \u003Ca href=\"\u002Fapi\u002F\">API overview\u003C\u002Fa> separates providers that name the exact repo from those that serve their own builds.\u003C\u002Fp>\n",[17,21,24,27,30],{"id":18,"text":19,"level":20},"what-compatible-covers","What “compatible” covers",2,{"id":22,"text":23,"level":20},"where-providers-differ","Where providers differ",{"id":25,"text":26,"level":20},"probe-an-endpoint-before-you-depend-on-it","Probe an endpoint before you depend on it",{"id":28,"text":29,"level":20},"parameters-to-treat-with-care","Parameters to treat with care",{"id":31,"text":32,"level":20},"when-compatibility-is-not-enough","When compatibility is not enough",628,[35,39,43,47,51,55,59],{"title":36,"publisher":37,"url":38},"Chat Completions API reference","OpenAI","https:\u002F\u002Fplatform.openai.com\u002Fdocs\u002Fapi-reference\u002Fchat",{"title":40,"publisher":41,"url":42},"OpenAI compatibility","MolochAI","https:\u002F\u002Fmolochai.dev\u002Fdocs\u002Fopenai-compatibility",{"title":44,"publisher":45,"url":46},"Venice public model list","Venice","https:\u002F\u002Fapi.venice.ai\u002Fapi\u002Fv1\u002Fmodels?type=text",{"title":48,"publisher":49,"url":50},"OpenRouter model list","OpenRouter","https:\u002F\u002Fopenrouter.ai\u002Fapi\u002Fv1\u002Fmodels",{"title":52,"publisher":53,"url":54},"llama.cpp HTTP server","GitHub (ggml-org)","https:\u002F\u002Fgithub.com\u002Fggml-org\u002Fllama.cpp\u002Fblob\u002Fmaster\u002Ftools\u002Fserver\u002FREADME.md",{"title":56,"publisher":57,"url":58},"OpenAI-Compatible Server","vLLM documentation","https:\u002F\u002Fdocs.vllm.ai\u002Fen\u002Flatest\u002Fserving\u002Fopenai_compatible_server.html",{"title":60,"publisher":61,"url":62},"dealignai\u002FGLM-5.3-Flash-UNCENSORED-FP8 (serving notes)","Hugging Face","https:\u002F\u002Fhuggingface.co\u002Fdealignai\u002FGLM-5.3-Flash-UNCENSORED-FP8",[64,67],{"q":65,"a":66},"If an API is OpenAI-compatible, will my existing app work unchanged?","The requests will usually succeed. Whether features such as JSON mode, seeds, stop sequences or tool calls behave the same depends on the provider, so test the features you rely on.",{"q":68,"a":69},"Is the Responses API supported?","Most providers of open-weight models implement chat completions only. Check each provider's documentation; MolochAI, for example, says the Responses API is not available.",[71,75,79,83],{"path":72,"title":73,"description":74},"\u002Fapi\u002F","Uncensored AI API options","Who serves which weights, and how compatible each API is.",{"path":76,"title":77,"description":78},"\u002Fguides\u002Fpython-uncensored-llm-api\u002F","Call an uncensored LLM API from Python","Call an uncensored or open-weight LLM from Python with the OpenAI SDK: environment variables, first request, streaming, error handling, retries and provider switching.",{"path":80,"title":81,"description":82},"\u002Fguides\u002Fstreaming-llm-responses\u002F","Streaming LLM responses with server-sent events","How LLM API streaming works: the server-sent events format, parsing chunks, the final usage chunk, cancelling a stream, timeouts and errors that arrive mid-stream.",{"path":84,"title":85,"description":86},"\u002Fapi\u002Fproviders\u002F","API providers","Provider profiles with published features and limits.",{"summary":88,"ranOn":13,"environment":89,"liveEndpoint":90},"The probe script on this page was run against the mock OpenAI-compatible server in this site's repository and produced the report shown. It was not run against the providers named in the tables, whose entries come from their documentation.","Python 3.12.4, openai 3.51.0 for Python",false,[72],1794622336928]