TokenHub is available as a Docker image, Linux package, and offline installer Download now
Developer Center

A few lines of code. Every LLM.

TokenHub speaks the OpenAI API. Swap in your base_url and API key, and your existing code, SDKs and frameworks can reach cloud models, private local models and your knowledge bases.

Quickstart

Your first call in five minutes

Deploy TokenHub on your own server, then call it with the official OpenAI SDK. Any OpenAI-compatible client works the same way.

  1. Deploy TokenHub

    Grab the Docker image or an installer from the download page and run it on your own server. It listens on port 8080 by default; create the admin account the first time you open http://localhost:8080.

    # Docker example (image name announced at release)
    docker run -d --name tokenhub \
      -p 8080:8080 \
      -v $(pwd)/tokenhub-data:/data \
      <IMAGE_TBD>:2.3.0
  2. Create an API key

    In your own TokenHub admin console, add models (cloud provider keys or local model endpoints), then create a key under "API Keys". Each key can be scoped to a project, a set of models and a token quota. Keys start with th- and are shown in full only once.

    # Keep keys in env vars, never in your repo
    export TOKENHUB_API_KEY="th-your-api-key"
    # Replace with your TokenHub address
    export TOKENHUB_BASE_URL="http://localhost:8080/v1"
  3. Install the SDK

    Use the official OpenAI SDK as is; no extra dependencies. Any HTTP client works too.

    # Python
    pip install openai
    
    # Node.js
    npm install openai
  4. Make your first call

    Set model to a specific model (for example deepseek-chat, qwen-plus or ollama/qwen2.5:7b), or to auto and let your routing policy choose.

    # Replace with your TokenHub address
    curl http://localhost:8080/v1/chat/completions \
      -H "Authorization: Bearer $TOKENHUB_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "deepseek-chat",
        "messages": [
          {"role": "system", "content": "You are a helpful business assistant."},
          {"role": "user", "content": "Describe TokenHub in three sentences."}
        ],
        "temperature": 0.7
      }'
    import os
    from openai import OpenAI
    
    client = OpenAI(
        base_url="http://localhost:8080/v1",  # replace with your TokenHub address
        api_key=os.environ["TOKENHUB_API_KEY"],
    )
    
    resp = client.chat.completions.create(
        model="deepseek-chat",
        messages=[
            {"role": "system", "content": "You are a helpful business assistant."},
            {"role": "user", "content": "Describe TokenHub in three sentences."},
        ],
        temperature=0.7,
    )
    print(resp.choices[0].message.content)
    print(resp.usage)  # prompt / completion / total tokens
    import OpenAI from "openai";
    
    const client = new OpenAI({
      baseURL: "http://localhost:8080/v1", // replace with your TokenHub address
      apiKey: process.env.TOKENHUB_API_KEY,
    });
    
    const resp = await client.chat.completions.create({
      model: "deepseek-chat",
      messages: [
        { role: "system", content: "You are a helpful business assistant." },
        { role: "user", content: "Describe TokenHub in three sentences." },
      ],
      temperature: 0.7,
    });
    
    console.log(resp.choices[0].message.content);
  5. Turn on streaming

    Set stream: true to receive output as Server-Sent Events (SSE). The first tokens arrive sooner, which suits chat interfaces. The final message is data: [DONE].

    curl -N http://localhost:8080/v1/chat/completions \
      -H "Authorization: Bearer $TOKENHUB_API_KEY" \
      -H "Content-Type: application/json" \
      -d '{
        "model": "qwen-plus",
        "stream": true,
        "messages": [
          {"role": "user", "content": "Write an opening line for a product launch"}
        ]
      }'
    
    # Response (excerpt):
    # data: {"choices":[{"index":0,"delta":{"content":"Welcome"}}]}
    # data: {"choices":[{"index":0,"delta":{"content":" everyone"}}]}
    # data: [DONE]
    stream = client.chat.completions.create(
        model="qwen-plus",
        messages=[{"role": "user", "content": "Write an opening line for a product launch"}],
        stream=True,
    )
    
    for chunk in stream:
        if chunk.choices and chunk.choices[0].delta.content:
            print(chunk.choices[0].delta.content, end="", flush=True)
    const stream = await client.chat.completions.create({
      model: "qwen-plus",
      messages: [{ role: "user", content: "Write an opening line for a product launch" }],
      stream: true,
    });
    
    for await (const chunk of stream) {
      process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
    }
  6. Check usage and logs

    Every call's model, latency, tokens and cost are logged in real time. Search them under "Call Logs" in your admin console, or see totals by department and project on the Live Dashboard.

API overview

The OpenAI API you already know

Every endpoint uses JSON with Bearer token auth. Replace the base URL with your TokenHub address.

Base URL http://localhost:8080/v1
Auth Authorization: Bearer th-…
Format application/json · SSE
TokenHub API endpoints
CapabilityMethodPathDescription
Model calls (OpenAI-compatible)
Chat CompletionsPOST/chat/completionsChat completion with streaming, tool calls and multimodal input (model-dependent)
EmbeddingsPOST/embeddingsText embeddings from cloud or local embedding models
RerankPOST/rerankReorder candidate documents by relevance, typically after RAG retrieval
ModelsGET/modelsList every model the current key can call
GET/models/{model_id}Get one model's details, context length and unit price
TokenHub extensions
Knowledge BasesGET/knowledge_basesList the knowledge bases you can access
POST/knowledge_bases/{kb_id}/documentsUpload documents for automatic parsing, chunking and embedding
POST/knowledge_bases/{kb_id}/searchHybrid search that returns passages with source citations
DELETE/knowledge_bases/{kb_id}/documents/{doc_id}Delete a document and its vectors
UsageGET/usageToken usage and cost by time range, project and model

* Extension fields and paths are subject to the official API docs. Pass a knowledge_base parameter to the chat endpoint to turn on RAG.

Local model guide

Register your in-house inference servers

Any inference server with an OpenAI-compatible API can be connected. Once registered, local models share the same API, permissions and metering as cloud models.

  1. Pull models on the inference serverThis example uses Qwen2.5 7B and the bge-m3 embedding model.
  2. Allow network accessOllama only listens on localhost by default. Set OLLAMA_HOST before starting it.
  3. Add the models in TokenHubIn the admin console, go to "Model Integration → Add local model", choose Ollama and enter its address. TokenHub detects the available models.
  4. Call them like any other modelUse model names in name/model form, exactly as you would for cloud models.
# ① Pull models
ollama pull qwen2.5:7b
ollama pull bge-m3

# ② Listen on the LAN and start
OLLAMA_HOST=0.0.0.0:11434 ollama serve

# ③ TokenHub local model config (equivalent YAML)
provider: ollama
name: local-qwen
base_url: http://10.0.0.21:11434
models:
  - qwen2.5:7b
  - bge-m3          # also used as the knowledge base embedding model

# ④ Call with model="local-qwen/qwen2.5:7b"

* Commands and config are illustrative; adjust IPs, models and field names to your environment and the released version. Xinference, LM Studio, SGLang and similar servers connect the same way as an "OpenAI-compatible service".

SDKs & tools

Works with the stack you already use

Because TokenHub is OpenAI-compatible, mainstream SDKs, frameworks and AI app platforms connect by changing only the base URL and key.

SDK

Official OpenAI SDKs

Python · Node.js · Go · Java and more

Set base_url / baseURL and your API key. No dependency changes.

LC

LangChain

Python · JS

Point ChatOpenAI and OpenAIEmbeddings at TokenHub to build chains and agents.

LI

LlamaIndex

Python

Connect through the OpenAI-like LLM and embedding classes and keep your existing indexes and retrieval.

Di

Dify

AI app platform

Add an "OpenAI-API-compatible" model provider and let TokenHub handle permissions and metering.

OW

Open WebUI and other chat clients

Self-hosted chat UIs

Configure an OpenAI-compatible connection to give staff one entry point, with quotas and audits in TokenHub.

{ }

Any HTTP client

curl · requests · fetch

Standard REST + SSE that any language can call, no special SDK required.

* These tools connect via the OpenAI-compatible protocol. TokenHub has no official partnership with these projects; names and trademarks belong to their respective owners.

Error codes

Errors and how to handle them

Error responses follow the OpenAI format, so your existing error handling keeps working.

TokenHub API error codes
HTTPCodeMeaningWhat to do
400invalid_requestMissing or malformed parametersCheck the request body and field types
400context_length_exceededInput exceeds the model's context windowTrim messages or use a long-context model
401invalid_api_keyKey is invalid, expired or disabledCheck the key's status in the admin console
403permission_deniedNo access to this model or knowledge baseAsk an admin to grant access
404model_not_foundModel doesn't exist or isn't enabledCall /models for the available list
429rate_limit_exceededRequest or token rate limit hitRetry with exponential backoff
429quota_exceededProject or key quota used upRequest a higher quota; retrying won't help
500internal_errorGateway internal errorContact support with the request_id
502upstream_errorUpstream model service returned an errorRetry, or configure a fallback model
503model_unavailableModel temporarily unavailable (including offline local servers)Enable automatic failover
504upstream_timeoutUpstream response timed outRaise the timeout or switch to streaming

Sample error response

{
  "error": {
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "message": "Project request rate limit exceeded",
    "request_id": "req_8f2c…"
  }
}
  • Only retry on 429 (rate limits) and 5xx
  • Use exponential backoff and honor the Retry-After header
  • Log the request_id to find the call in your logs

Start building your first AI app

Download TokenHub for free, run it on your own server, and call cloud and local models through one API in minutes.