Documentation

The API is OpenAI-compatible. Change two strings.

If your code already calls an OpenAI-style endpoint, you are changing the base URL and the model name.

01 · Base URL https://poolmill.com/v1
02 · Key as bearer token
03 · Model ID via GET /v1/models

First request

Every sample uses a live model ID from the router, so the docs cannot drift from the API.

 bash
# 1. put your key in the environment
export POOLMILL_API_KEY="pool_..."

# 2. call the OpenAI-compatible endpoint
curl https://poolmill.com/v1/chat/completions \
  -H "Authorization: Bearer $POOLMILL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek/deepseek-v4-flash-vision-exp",
    "messages": [{"role": "user", "content": "Say hello."}]
  }'
 python — openai sdk
from openai import OpenAI

client = OpenAI(
    base_url="https://poolmill.com/v1",
    api_key="pool_...",         # from the console
)

r = client.chat.completions.create(
    model="deepseek/deepseek-v4-flash-vision-exp",
    messages=[{"role": "user", "content": "Say hello."}],
)
print(r.choices[0].message.content)
 javascript — openai sdk
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://poolmill.com/v1",
  apiKey: process.env.POOLMILL_API_KEY, // pool_...
});

const r = await client.chat.completions.create({
  model: "deepseek/deepseek-v4-flash-vision-exp",
  messages: [{ role: "user", content: "Say hello." }],
});
console.log(r.choices[0].message.content);

Chat completions

Standard OpenAI request and response shapes, including temperature, top_p, max_tokens, stop, tools and response_format.

 bash
curl https://poolmill.com/v1/chat/completions \
  -H "Authorization: Bearer $POOLMILL_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "deepseek/deepseek-v4-flash-vision-exp",
    "messages": [
      {"role": "system", "content": "You are terse."},
      {"role": "user", "content": "What is a vector index?"}
    ],
    "max_tokens": 200,
    "temperature": 0.2
  }'

Streaming

Pass "stream": true to receive server-sent events. Any OpenAI-compatible client library handles this transparently.

 python — streaming
from openai import OpenAI

client = OpenAI(base_url="https://poolmill.com/v1", api_key="pool_...")

stream = client.chat.completions.create(
    model="deepseek/deepseek-v4-flash-vision-exp",
    messages=[{"role": "user", "content": "Write a haiku about caching."}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content
    if delta:
        print(delta, end="", flush=True)

Cached input

When a prompt repeats content the provider has seen, those tokens bill at the cached rate — on DeepSeek v4.1 Flash that is 50x cheaper. Read prompt_tokens_details.cached_tokens to see the split.

 json — usage
{
  "usage": {
    "prompt_tokens": 1233,
    "completion_tokens": 5,
    "total_tokens": 1238,
    "prompt_tokens_details": { "cached_tokens": 1024 }
  }
}

Anthropic SDK

Anthropic-shaped requests are accepted at the same endpoint. Use the Anthropic SDK with a custom base URL.

 python — anthropic messages
from anthropic import Anthropic

client = Anthropic(base_url="https://poolmill.com/v1", api_key="pool_...")

msg = client.messages.create(
    model="deepseek/deepseek-v4-flash-vision-exp",
    max_tokens=256,
    stream=True,
    messages=[{"role": "user", "content": "Summarise this release note."}],
)
for event in msg:
    print(event)

Errors

Errors are JSON with an error object, matching the OpenAI shape: 401 bad key, 403 model not in your package, 429 credit exhausted, 5xx safe to retry with backoff.

 json — 429
{
  "error": {
    "message": "Budget has been exceeded! Current cost: 9.5, Max budget: 9.0",
    "type": "budget_exceeded",
    "code": "429"
  }
}

Rate limits

Capacity is pooled upstream. Steady production traffic is unaffected; extreme bursts at peak may surface as 429 or 5xx — retry with exponential backoff.

 python — retry with backoff
import random, time
from openai import OpenAI, APIStatusError

client = OpenAI(base_url="https://poolmill.com/v1", api_key="pool_...")

def complete(**kw):
    for attempt in range(5):
        try:
            return client.chat.completions.create(**kw)
        except APIStatusError as e:
            # 429 = no credit or rate limit; 5xx = upstream capacity
            if e.status_code < 500 and e.status_code != 429:
                raise
            time.sleep(min(2 ** attempt + random.random(), 20))
    raise RuntimeError("giving up after 5 attempts")

Available models

USD per 1M tokens: input / cached input / output, charged against prepaid credit.

ModelInputCachedOutputSave
Qwen3.7 FlashQwen/Qwen3.7-Flash$0.03$0.006$0.135x
Qwen3.8 FlashQwen/Qwen3.8-Flash$0.16$0.016$0.4710x
Qwen3.8 Omni FlashQwen/Qwen3.8-Omni-Flash$0.15$0.016$0.479.4x
Claude Haiku 5 5claude-haiku-5-5$0.10$0.01$0.5010x
Claude Sonnet 5 5claude-sonnet-5-5$2.00$0.10$10.0020x
DeepSeek v4 Flash Vision Expdeepseek/deepseek-v4-flash-vision-exp$0.15$0.003$0.6050x
DeepSeek v4.1 Flashdeepseek/deepseek-v4.1-flash$0.15$0.003$0.6050x
DeepSeek v4.1 Flash Fastdeepseek/deepseek-v4.1-flash-fast$0.16$0.016$0.5810x
GPT 6 Lunagpt-6-luna$0.10$0.01$0.5010x
Meta Muse Spark 1.2 Contributormeta/muse-spark-1.2-contributor$0.10$0.002$0.2050x
Meta Muse Spark 1.3 Contributormeta/muse-spark-1.3-contributor$0.10$0.002$0.2050x
Typesafe Jevtypesafe/jev$0.042$0$0—x
Xiaomi Mimo v2.5xiaomi/mimo-v2.5$0.14$0.0028$0.2850x
Xiaomi Mimo v2.6 Flashxiaomi/mimo-v2.6-flash$0.14$0.0028$0.2850x
Z.ai GLM 5.3 Flashz-ai/glm-5.3-flash$0.15$0.03$0.505x
DeepSeek v4 Flash Vision Expopenrouter/deepseek/deepseek-v4-flash-vision-exp$0.15$0.003$0.6050x
 bash — discover your model ids
export POOLMILL_API_KEY="pool_..."
curl https://poolmill.com/v1/models \
  -H "Authorization: Bearer $POOLMILL_API_KEY"