---
title: "LiteLLM OpenAI-compatible endpoint for uncensored models"
canonical: https://uncensoredllm.ai/guides/litellm
generated: 2026-10-27T08:11:51.311Z
source: https://uncensoredllm.ai/guides/litellm
base_url: https://api.uncensoredllm.ai/v1
---

# LiteLLM with an uncensored OpenAI-compatible endpoint

LiteLLM OpenAI-compatible endpoint setup for uncensored builds: openai/ plus the model id and api_base, in the SDK and in config.yaml, with a fallback chain.

Steps checked October 25, 2026 · prices as of October 27, 2026

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](https://uncensoredllm.ai/blog/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](https://docs.litellm.ai/docs/providers/openai_compatible) 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-uncensored openai/ plus any id from the models page
- api_base: https://api.uncensoredllm.ai/v1 Ends 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](https://app.uncensoredllm.ai/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](https://uncensoredllm.ai/models).

## 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.

```python
import os
import 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](https://docs.litellm.ai/docs/proxy/reliability), a call that still fails after `num_retries` moves to the next name, and fallbacks run in order.

```python
import os
from 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](https://uncensoredllm.ai/docs) 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_KEY
```

```bash
export ULLM_API_KEY="sk-ullm-live-…"
export LITELLM_MASTER_KEY="sk-pick-your-own"
litellm --config config.yaml
```

The 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`](https://uncensoredllm.ai/models/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](https://uncensoredllm.ai/proof), which sends a fixed prompt to every model each day and records whether the answer still matches. The column below is today's verdict.

| Model | Build | Input $/M | Output $/M | Context | Wire formats |
| --- | --- | --- | --- | --- | --- |
| [GLM-5.3 Uncensored](https://uncensoredllm.ai/models/glm-5.3-uncensored) glm-5.3-uncensored | Uncensored | $0.282 | $0.846 |  | openai |
| [DeepSeek V4 Pro Uncensored](https://uncensoredllm.ai/models/deepseek-v4-pro-uncensored) deepseek-v4-pro-uncensored | Uncensored | $1.00 | $2.00 |  | openai |
| [GLM-5.3 Abliterated](https://uncensoredllm.ai/models/glm-5.3-abliterated) glm-5.3-abliterated | Abliterated | $2.25 | $4.50 |  | openai |

Prices per million tokens, read from the live catalog on 2026-10-27.

| Model id | Role in config.yaml | Daily check | Context window |
| --- | --- | --- | --- |
| [`glm-5.3-uncensored`](https://uncensoredllm.ai/models/glm-5.3-uncensored) | `uncensored-primary` | Steady since Oct 12 | not published |
| [`deepseek-v4-pro-uncensored`](https://uncensoredllm.ai/models/deepseek-v4-pro-uncensored) | `uncensored-second` | Steady since Oct 12 | not published |
| [`glm-5.3-abliterated`](https://uncensoredllm.ai/models/glm-5.3-abliterated) | `uncensored-third` | Steady since Oct 27 | not published |

Windows from the live catalog on 2026-10-27; verdicts from /proof at render.

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](https://uncensoredllm.ai/uncensored/glm) and [uncensored DeepSeek](https://uncensoredllm.ai/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](https://uncensoredllm.ai/models/glm-5.3-uncensored) | $6.35 |
| [DeepSeek V4 Pro Uncensored](https://uncensoredllm.ai/models/deepseek-v4-pro-uncensored) | $19.00 |
| [GLM-5.3 Abliterated](https://uncensoredllm.ai/models/glm-5.3-abliterated) | $42.75 |

Computed at render from the catalog prices on 2026-10-27: requests × 1,200 × input price, plus requests × 350 × output price.

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](https://uncensoredllm.ai/pricing).

## Check the key before LiteLLM

This lists the ids the key can call. It is free; run it before blaming the config.

```bash
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"}}
```

Both bodies as the API returned them on 25 October 2026.

## 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

### Is LiteLLM OpenAI compatible?

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.

### What is an OpenAI-compatible API endpoint?

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.

### How do I use LiteLLM with an OpenAI-compatible provider?

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.

### What are OpenAI-compatible providers?

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.

### Can I call the LiteLLM proxy from JavaScript?

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.

### Does LiteLLM track spend on these models?

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.

[Get a key](https://app.uncensoredllm.ai/console) Prepaid from $10, no subscription.

## New models and price changes, once a month.

New uncensored builds with their prices, price moves, and what the daily model check found.
