A LiteLLM OpenAI-compatible endpoint takes three values: the model as openai/ plus an id, the api_base, and a key. This guide fills them with uncensored builds, first in the Python SDK, then in the proxy's config.yaml, with a fallback chain across three builds. Field names come from docs.litellm.ai, read on 25 October 2026.
If builds with the refusals edited out are new to you, start with abliterated vs uncensored, then come back here to wire them up.
How LiteLLM reaches an OpenAI-compatible endpoint
LiteLLM picks a provider from the prefix on the model name. For any server that speaks OpenAI's /chat/completions, the prefix is openai/, followed by that server's own model id. The OpenAI-compatible endpoints doc puts it in one comment: add the prefix "so litellm knows to route to OpenAI".
The same doc says to leave the base URL alone apart from the /v1 suffix. Every uncensored build in this catalog takes the OpenAI wire format, so one prefix covers all of them. Version checked: litellm 1.106.3, the current release on PyPI on 25 October 2026.
The three values LiteLLM needs
- model
- openai/glm-5.3-uncensoredopenai/ plus any id from the models page
- api_base
- https://api.uncensoredllm.ai/v1Ends in /v1; nothing after it
- api_key
- sk-ullm-live-…Created in the console; keep it in ULLM_API_KEY
Create the key in the console. It starts with sk-ullm-, is shown once, and spends a prepaid balance that starts at $10. Model ids are on the uncensored model list.
Call the endpoint from the LiteLLM Python SDK
One call, no config file. The response has the OpenAI shape, so code written for the OpenAI SDK reads it the same way.
import osimport litellm response = litellm.completion( model="openai/glm-5.3-uncensored", api_base="https://api.uncensoredllm.ai/v1", api_key=os.environ["ULLM_API_KEY"], messages=[{"role": "user", "content": "Outline a heist thriller in five beats."}], max_tokens=600,)print(response.choices[0].message.content)Swap the id after openai/ to change builds. Nothing else in the call changes, because every build sits behind the same base URL and key.
A fallback chain across three uncensored builds
The Router takes a list of named deployments and a fallbacks map. Per the reliability doc, a call that still fails after num_retries moves to the next name, and fallbacks run in order.
import osfrom litellm import Router BASE = "https://api.uncensoredllm.ai/v1"KEY = os.environ["ULLM_API_KEY"] def build(model_id): return {"model": f"openai/{model_id}", "api_base": BASE, "api_key": KEY} router = Router( model_list=[ {"model_name": "uncensored-primary", "litellm_params": build("glm-5.3-uncensored")}, {"model_name": "uncensored-second", "litellm_params": build("deepseek-v4-pro-uncensored")}, {"model_name": "uncensored-third", "litellm_params": build("glm-5.3-abliterated")}, ], fallbacks=[{"uncensored-primary": ["uncensored-second", "uncensored-third"]}], num_retries=1,) response = router.completion( model="uncensored-primary", messages=[{"role": "user", "content": "Outline a heist thriller in five beats."}],)print(response.choices[0].message.content)Two details decide whether the chain helps. First, all three entries use the same key, so a 401 or a 402 comes back the same from every build; fallbacks cannot fix those. They help when one build fails on its own: a 404 for an id that left the catalog, a 429, a 5xx or a timeout. Second, the docs page states that a request that fails before the model answers is not charged. A request that falls through is billed once, at the price of the build that answered.
The names are aliases. Your application asks for uncensored-primary and never sees a model id, so moving to another build is one line in the list, not a change to the app. num_retries=1 gives a failing build one more try before the chain moves on. A retry that fails before the model answers is free as well, so the setting costs latency, not money.
The same chain in the LiteLLM proxy config.yaml
The proxy reads the same deployments from a file and serves them on an OpenAI-format endpoint of its own. The os.environ/ form reads a value from the environment, which keeps the key out of the file. The prices under model_info are this catalog's, written into the file when this page rendered, so LiteLLM's spend tracking matches what the API charges.
model_list: - model_name: uncensored-primary litellm_params: model: openai/glm-5.3-uncensored api_base: https://api.uncensoredllm.ai/v1 api_key: os.environ/ULLM_API_KEY model_info: input_cost_per_token: 0.000000282 output_cost_per_token: 0.000000846 - model_name: uncensored-second litellm_params: model: openai/deepseek-v4-pro-uncensored api_base: https://api.uncensoredllm.ai/v1 api_key: os.environ/ULLM_API_KEY model_info: input_cost_per_token: 0.000001 output_cost_per_token: 0.000002 - model_name: uncensored-third litellm_params: model: openai/glm-5.3-abliterated api_base: https://api.uncensoredllm.ai/v1 api_key: os.environ/ULLM_API_KEY model_info: input_cost_per_token: 0.00000225 output_cost_per_token: 0.0000045 router_settings: fallbacks: [{"uncensored-primary": ["uncensored-second", "uncensored-third"]}] litellm_settings: num_retries: 1 request_timeout: 120 general_settings: master_key: os.environ/LITELLM_MASTER_KEYexport ULLM_API_KEY="sk-ullm-live-…"export LITELLM_MASTER_KEY="sk-pick-your-own"litellm --config config.yamlThe proxy listens on port 4000. Point any OpenAI SDK at it with the master key, and ask for uncensored-primary as the model. LiteLLM's custom pricing doc marks the two *_cost_per_token keys as tracking only; they change nothing about what is billed.
Context window and content policy fallbacks
context_window_fallbacks handle LiteLLM's ContextWindowExceededError. The reliability doc requires enable_pre_call_checks: true under router_settings for that check, and without it requests go to the provider whatever their size. The check needs a window to compare against, and the three builds above publish none in the catalog. For a context fallback, add a fourth entry for minimax-m3-uncensored, which lists 262,144 tokens, and map uncensored-primary to it.
content_policy_fallbacks fire on a provider's content-filter error, LiteLLM's ContentPolicyViolationError. Mapping a filtered model on another provider to uncensored-primary sends those requests here. A refusal written into a normal reply is a successful response, not an error, so no fallback sees it.
Which uncensored builds to chain
Put the build you want most first: the backups bill only on the requests that reach them. When this guide was written, all three had been steady since 12 October on the daily real-model check, which sends a fixed prompt to every model each day and records whether the answer still matches. The column below is today's verdict.
| Wire formats | |||||
|---|---|---|---|---|---|
| GLM-5.3 Uncensored | Uncensored | $0.282 | $0.846 | ||
| DeepSeek V4 Pro Uncensored | Uncensored | $1.00 | $2.00 | ||
| GLM-5.3 Abliterated | Abliterated | $2.25 | $4.50 |
| Model id | Role in config.yaml | Daily check | Context window |
|---|---|---|---|
glm-5.3-uncensored | uncensored-primary | Steady since Oct 12 | not published |
deepseek-v4-pro-uncensored | uncensored-second | Steady since Oct 12 | not published |
glm-5.3-abliterated | uncensored-third | Steady since Oct 27 | not published |
Two GLM builds and a DeepSeek build means a family outage on one side still leaves an answer. The rest of each family is on the uncensored GLM and uncensored DeepSeek pages.
What a batch through the chain costs
The worked example: 10,000 requests of 1,200 prompt tokens and 350 reply tokens, all answered by one build.
| Model | 10,000 requests |
|---|---|
| GLM-5.3 Uncensored | $6.35 |
| DeepSeek V4 Pro Uncensored | $19.00 |
| GLM-5.3 Abliterated | $42.75 |
A real month sits close to the first row, plus a backup's price on the requests that fall through to it. Every per-token rate is on the pricing page.
Check the key before LiteLLM
This lists the ids the key can call. It is free; run it before blaming the config.
curl https://api.uncensoredllm.ai/v1/models \ -H "Authorization: Bearer sk-ullm-live-…"A 200 with a list of ids means the key and base URL are right. A 401 says which way the key is wrong:
HTTP 401{"error":{"message":"No API key was sent.","type":"authentication_error","param":null,"code":"invalid_api_key"}}HTTP 401{"error":{"message":"The API key is not valid.","type":"authentication_error","param":null,"code":"invalid_api_key"}}Troubleshooting LiteLLM errors on this endpoint
LiteLLM maps each status to an exception class, per its exception mapping doc: 401 is AuthenticationError, 402 is PaymentRequiredError, 404 is NotFoundError, 429 is RateLimitError.
Not Found on every call
The OpenAI-compatible doc's advice: make sure api_base ends in /v1. Check also that the model name starts with openai/.
404 model_not_found on one build
The id after openai/ is not in the catalog. The chain moves on to the next build; fix the id from the list the curl above prints.
HTTP 404{"error":{"message":"No such model: glm-5.3-uncensord.","type":"not_found_error","param":null,"code":"model_not_found"}}402 insufficient_balance
The prepaid balance is at zero, so every build in the chain answers the same. Top up in the console; a refused request is not charged.
HTTP 402{"error":{"message":"The prepaid balance does not cover this request. Top up at … to continue.","type":"insufficient_quota","param":null,"code":"insufficient_balance"}}Questions
Both ways. It calls OpenAI-compatible endpoints when the model name starts with openai/, and its proxy serves an OpenAI-format endpoint of its own on port 4000.
An API that takes the same requests and returns the same responses as OpenAI's /v1/chat/completions, so a client needs only a base URL, a key and a model id. This one is https://api.uncensoredllm.ai/v1. See the docs page.
Set model to openai/ plus the provider's model id, api_base to its URL ending in /v1, and api_key to its key. Here that is openai/glm-5.3-uncensored and https://api.uncensoredllm.ai/v1.
Services that answer the OpenAI wire format at their own base URL. LiteLLM’s doc also names provider-specific prefixes, such as hosted_vllm, for servers that match one; this API takes plain openai/. See the uncensored model list.
Yes. The proxy speaks the OpenAI format, so the OpenAI Node SDK works with its baseURL set to the proxy and the master key as apiKey.
Only if it knows the prices. The config above writes this catalog’s per-token prices into model_info, which LiteLLM uses for tracking only. See per-token prices.