Documentation
Quickstart
Connect once, keep your existing SDK. Nothing here needs a code rewrite.
Want to see the effect before wiring anything up? The playground runs the same question through one model twice — raw and compressed — with no account.
Do I call CompresLM or my LLM first?
Call CompresLM only. You do not send a separate request to
OpenAI/Anthropic first. CompresLM is a drop-in proxy: your app talks to
https://compreslm.com/v1, we compress what we can,
then we forward the request to your provider with your key.
The model reply comes back through us in the same OpenAI-compatible shape.
Your app
Same SDK as today. Base URL → CompresLM. CompresLM token + provider key in headers.
CompresLM
Auth. Compress input context. If you set compress_output: true, also reduce completion tokens. Never store your provider key.
Your LLM provider
One upstream call on your account. You pay the provider for tokens; we bill only a share of measured savings.
Back to your app
Standard chat-completion JSON — choices[0].message.content, usage, tools, streaming.
We never store your prompts, completions, or provider key. We only record token counts (before/after) for your dashboard and bill — see Privacy Policy.
Create an account and a token
Sign up at /app, verify your email, then click Generate token. Copy it once — it is shown only at creation time. This token goes in the Authorization header on every request; it identifies your account, not your LLM provider.
Point your client at CompresLM
Change two things in your existing OpenAI-compatible client: the base URL (point it at CompresLM) and add one extra header carrying your own provider key. Everything else — model names you're used to, message format, streaming, tool calls — stays the same.
| Header | Required | Value |
|---|---|---|
| Authorization | Required | Bearer YOUR_COMPRESLM_TOKEN — identifies your CompresLM account. |
| X-LLM-API-Key | Required | Your OpenAI / Anthropic / provider key. Used for this one request only, then discarded — never written to disk or logs. |
| X-LLM-API-Base | Optional | Only for a self-hosted / local model (vLLM, Ollama, etc.) — the URL of your own inference server. |
Python
from openai import OpenAI
client = OpenAI(
base_url="https://compreslm.com/v1",
api_key="YOUR_COMPRESLM_TOKEN",
default_headers={"X-LLM-API-Key": "YOUR_PROVIDER_KEY"},
)
resp = client.chat.completions.create(
model="gpt-4o-mini", # any model name your provider accepts
messages=[{"role": "user", "content": "Summarize nothing — just say hi."}],
)
print(resp.choices[0].message.content)
cURL
curl https://compreslm.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_COMPRESLM_TOKEN" \
-H "X-LLM-API-Key: YOUR_PROVIDER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"messages": [{"role":"user","content":"Hello"}]
}'
JavaScript
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://compreslm.com/v1",
apiKey: "YOUR_COMPRESLM_TOKEN",
defaultHeaders: { "X-LLM-API-Key": "YOUR_PROVIDER_KEY" },
});
const r = await client.chat.completions.create({
model: "gpt-4o-mini", // any model name your provider accepts
messages: [{ role: "user", content: "Hello" }],
});
What you get back
A standard chat-completion response from your provider —
same fields you already parse (choices,
usage, etc.). CompresLM shortens the
prompt by default. With compress_output: true
it also reduces completion tokens — still a normal model answer in the usual
response shape.
Choose your model
Send any model name your provider accepts — the exact string you
already pass today (gpt-4o-mini,
gpt-4.1, o3,
claude-sonnet-4-6, claude-opus-4-1, …).
There is no supported-model list to pick from: we forward the name to your
provider unchanged, on your key. Compression is on by default and does not
change which model answers you.
Any model name — long inputs are compressed before they reach the model, and text carrying numbers, dates, names and identifiers survives far more often than ordinary prose. That is a strong bias, not a guarantee: see Terms, section 12, and pick exact when nothing may be dropped.
Self-hosted models — add
X-LLM-API-Base and prefix the name with the API
flavour your server speaks, e.g. openai/my-llama-3.1-70b,
so we know how to talk to it.
Turn compression off for a single request by
appending -raw to one of the built-in aliases
(gpt-4o-mini-raw, gpt-4o-raw,
claude-sonnet-raw) — sent through byte-for-byte,
useful for A/B-checking output quality. The
*-smart aliases are historical synonyms of the
plain names and keep working.
What to send where
This is the one idea worth five minutes. A request carries two different things, and telling them apart is what makes compression safe:
| You send | What we do with it |
|---|---|
| The material — a contract, a report, retrieved
chunks, chat history, a log a tool just returned. Send it as context. |
Scored against your question, span by span. What the answer needs stays; the rest goes. |
| The question — what you actually want to know. Keep it as the last user message. |
Never compressed. It is the ruler everything else is measured against. |
Put both in one big user message and it still works — we fall back to reading the tail of the message as the question. But that is a guess, and a wrong guess is how compression drops something you needed. Separating them removes the guess.
The same request, both ways
# Guessing — document and question in one message messages=[{"role": "user", "content": contract + "\n\nWhat is the notice period?"}] # Told — the document is context, the question is the message messages=[{"role": "user", "content": "What is the notice period?"}], extra_body={"context": contract}
Python SDKs pass it through extra_body; in
JavaScript and cURL it is just another top-level field:
curl https://compreslm.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_COMPRESLM_TOKEN" \
-H "X-LLM-API-Key: YOUR_PROVIDER_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-4o-mini",
"context": "...the contract, the report, the retrieved chunks...",
"messages": [{"role":"user","content":"What is the termination notice period?"}]
}'
Ask specifically. Compression reads your question to decide what matters, so "what does this say about termination, notice periods and renewal?" protects more of a contract than "summarise this". A vague question is a vague ruler.
Everything the model needs must be in the request. We
fetch nothing on your behalf and remember nothing between calls — if a
fact is not in context or in the messages, the
model will not see it.
Shortening the answer is a separate, opt-in flag —
compress_output, on
the profiles page.