API documentation

A free, OpenAI-compatible LLM API. Create a free account, grab an API key, change one line (base_url) and your existing OpenAI code works.

Get your free API key →

Base URL & authentication

Base URL:

https://dreamprompting.com/api/v1

Every request needs an API key, sent as a Bearer token (the standard OpenAI way):

Authorization: Bearer YOUR_API_KEY

Keys are free. Sign in and create one in a few seconds — no credit card. Your account has a generous daily quota, shared across all of its keys; usage is shown on your account page.

Chat completions

POST /api/v1/chat/completions — OpenAI-compatible.

Request body

FieldTypeNotes
messagesarrayRequired. [{role, content}] with roles system/user/assistant.
modelstringOptional. "auto" (default, failover) or "provider/model". See model selection.
streambooleanOptional. true for Server-Sent Events. See streaming.
temperaturenumberOptional. Passed through to the provider.
max_tokensintegerOptional. Passed through.
context_idstring"new" to start a server-side thread, or an id from a previous response to continue one. See conversation context.
reasoning_effortstringnone|low|medium|high. Controls Gemini thinking. See below.
thinkingbooleanConvenience flag to enable Gemini thinking. See below.

Examples

curl
curl https://dreamprompting.com/api/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "auto",
    "messages": [{"role":"user","content":"Hello!"}]
  }'
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(
    base_url="https://dreamprompting.com/api/v1",
    api_key="YOUR_API_KEY",
)
r = client.chat.completions.create(
    model="auto",
    messages=[{"role":"user","content":"Hi"}],
)
print(r.choices[0].message.content)
JavaScript
const r = await fetch(
  "https://dreamprompting.com/api/v1/chat/completions",
  { method:"POST",
    headers:{"Content-Type":"application/json",
             "Authorization":"Bearer YOUR_API_KEY"},
    body: JSON.stringify({
      model:"auto",
      messages:[{role:"user",content:"Hi"}]
    })});
const d = await r.json();
console.log(d.choices[0].message.content);
Response (200)
{
  "object": "chat.completion",
  "model": "openai/gpt-oss-120b",
  "provider": "groq",
  "choices": [{
    "index": 0,
    "message": {"role":"assistant","content":"Hi!"},
    "finish_reason": "stop"
  }],
  "usage": {"total_tokens": 12}
}

The response includes a non-standard provider field and an X-Served-By header telling you which upstream answered.

Conversation context

By default every call is independent, so a multi-turn chat means resending the whole history each time. Send "context_id": "new" and we keep the thread for you. The response returns a context_id; pass it on later calls and we prepend the earlier turns, so you only send the new message.

1. Start a thread

{
  "model": "auto",
  "context_id": "new",
  "messages": [
    {"role": "user", "content": "My name is Elena."}
  ]
}

// response includes:
// "context_id": "ctx-A1b2C3..."

2. Continue it

{
  "model": "auto",
  "context_id": "ctx-A1b2C3...",
  "messages": [
    {"role": "user", "content": "What is my name?"}
  ]
}

// the model already knows
  • The id is also returned as an X-Context-Id header, which is how you read it when streaming.
  • A thread is tied to the account that created it. Another account cannot read it, even with the id.
  • Long threads are trimmed to about 12,000 tokens. Your system message is always kept, and the newest turns win over the oldest.
  • This does not reduce token usage. Models are stateless, so the history still goes upstream on every turn and still counts toward your token budget. What it saves is the bookkeeping on your side, and it stops a thread growing until no provider will accept it.
  • Omit context_id for one-off calls. Nothing is stored as a thread and behaviour is unchanged.
  • Inspect a thread with GET /api/v1/contexts/{context_id}.
Full conversation context guide →

Model selection & failover

  • "auto" (default): the gateway picks a live provider and automatically fails over to the next if one errors or is rate-limited.
  • "provider/model": pin a specific model, e.g. "groq/openai/gpt-oss-120b" or "google/gemini-3.1-flash-lite". If it fails, the gateway still falls back to other providers.
  • List everything live at /api/v1/models, or browse and test them on the models page.

Streaming (SSE)

Pass "stream": true to receive Server-Sent Events with OpenAI-compatible chat.completion.chunk deltas, terminated by data: [DONE]. The OpenAI SDK's stream=True works unchanged.

curl -N https://dreamprompting.com/api/v1/chat/completions \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"auto","messages":[{"role":"user","content":"Hi"}],"stream":true}'

Gemini "thinking" control

Google's Gemini models can spend extra tokens "thinking" before answering. This is powerful for hard problems but slower and heavier for everyday calls. On DreamPrompting, Gemini defaults to the lightweight gemini-3.1-flash-lite model with thinking turned OFF, so you get fast, cheap, predictable answers by default.

To enable thinking, opt in per request in either of two ways:

1. Standard reasoning_effort

{
  "model": "google/gemini-2.5-flash",
  "messages": [...],
  "reasoning_effort": "medium"
}

2. Convenience flag

{
  "model": "google/gemini-2.5-flash",
  "messages": [...],
  "thinking": true
}

Values for reasoning_effort: none (off, default), low, medium, high. This applies only to Gemini; other providers ignore it.

Other endpoints

  • GET /api/v1/models — list live models.
  • GET /api/v1/quota — your remaining rate-limit quota.
  • BODY allow_fallback: false — pin the request to the model you named. If it is unavailable you get 503 model_unavailable instead of a different model answering in its place. Needs an explicit model; it means nothing with auto. Useful for a bot that tells its users which model it is.
  • BODY identify: false — drop the one-line note we add to the system prompt telling the model which model and provider it actually is. It is there because a model's weights do not record which endpoint is serving them, so without it a Llama answering through Groq will often claim to be ChatGPT. Skipped automatically when you ask for JSON output.
  • POST /api/v1/classify — one question, a fixed set of answers. Body: {input, choices}, plus optional model. Returns the chosen label and its index. In practice confidence comes back null today: a probability needs token logprobs, only NVIDIA of our providers reports them, and the models it will actually serve this account are reasoning models whose first token is a thought rather than an answer. The field is there and fills in the moment a provider supports it, and method tells you which way the answer was read. It writes the "reply with one letter" prompt for you, which is where almost all of the speed comes from: measured over 60 questions, an unconstrained prompt took 1,401ms against 142ms for a constrained one. The probability is reported raw and calibrated is always false: on a small model it was 0.896 when right and 0.839 when wrong, so do not threshold on it without checking it against your own labels. See the measurements.
  • POST /api/v1/unwatermark — strip watermarks and invisible Unicode from source code and report every removal by codepoint and line. Body: {code}, plus optional trailing, punctuation, homoglyphs and inspect. Costs no tokens. See the invisible character remover.
  • POST /api/v1/tokenize — count tokens before you spend them. No API key needed. Body: {text} or {messages}, plus optional encoding and split. See the token calculator.
  • POST /api/chat — stateful chat with server-side history (used by the chat page). Body: {seed, message, model?, thinking?}.
  • GET /api/chat/history?seed=... — retrieve a chat thread.

Rate limits & budgets

Tokens are the real budget, since that is what the upstream free tiers meter. Requests are a secondary backstop.

LimitValueScope
Burst100 / minuteper IP
Tokens500,000 / 24hper account, rolling
Requests5,000 / 24hper account, rolling
Response length8,192 tokensper request, max_tokens capped to this
Input size32,000 tokensper request, larger returns 413

Every response includes X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Check your remaining budgets any time at GET /api/v1/quota, which reports both requests and tokens, or on your account page. Both 24 hour budgets free up on a rolling window rather than resetting at midnight. Need a higher limit? Just ask and we will raise it, or lift it entirely by adding your own provider key: requests served on a key you supply are routed through your account with that provider and are not counted against this quota.

Errors

Errors use the OpenAI shape and appropriate HTTP status codes:

{"error": {"message": "Rate limit reached (100 requests/minute)...", "type": "rate_limit_error"}}

Common: 400 invalid request, 401 missing/invalid API key, 429 rate limited or daily quota reached, 502 all providers failed, 503 no providers configured.

Getting a 403 with error code: 1010?

That block comes from our CDN, not the API — it rejects generic default User-Agents (e.g. Python's urllib). The fix is one header: send any descriptive User-Agent that identifies your app, e.g. User-Agent: my-app/1.0. The OpenAI SDKs, curl and Python requests already send one and are unaffected.

Building an agent or MCP tool?