Documentation

TDSPRO developer docs

One OpenAI-compatible endpoint for 20+ models. Point your client at the base URL below, send your key, and call any model — no SDK changes.

Base URLhttps://api.tdspro.lol/v1

Overview

TDSPRO is a single, OpenAI-compatible gateway. You get one API key and one base URL that route every request to the right model — with smart routing, automatic fallback, a token-saving cache, per-key budgets, and full usage analytics. Because the API matches the OpenAI spec exactly, any existing client, SDK, or tool works without code changes.

Drop-in compatible

Identical request & response shapes to the OpenAI API. Change the base URL and key — that is it.

Smart routing

Call an alias like fast or smart and we pick the best engine by speed, cost, and uptime.

Honest by design

Every response carries the real model name in the "model" field — never a silent swap.

More than an API

The same key powers a whole platform, not just the endpoint below. Build your own assistants in Agents, work in the chat-plus-canvas workspace, generate visuals in the Studio, compare models in the Arena, embed a support widget, or take it offline with the CLI and desktop app.

Quickstart

Three steps and you are live. The snippets below are complete and runnable — paste your key and go.

  1. 1Create a free API key in your dashboard. It starts with sk-hub-.
  2. 2Set your client base URL to https://api.tdspro.lol/v1.
  3. 3Call any model by alias (smart, fast, code…) or by full name (gpt-4.1).

Pick your language. All three do the same thing.

quickstart.ts
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.tdspro.lol/v1",
  apiKey: process.env.AIHUB_API_KEY, // sk-hub-...
});

const res = await client.chat.completions.create({
  model: "smart",                    // alias → best model for the job
  messages: [{ role: "user", content: "Hello from TDSPRO!" }],
});

console.log(res.choices[0]?.message.content);
quickstart.py
from openai import OpenAI
import os

client = OpenAI(
    base_url="https://api.tdspro.lol/v1",
    api_key=os.environ["AIHUB_API_KEY"],  # sk-hub-...
)

res = client.chat.completions.create(
    model="smart",                        # alias → best model for the job
    messages=[{"role": "user", "content": "Hello from TDSPRO!"}],
)
print(res.choices[0].message.content)
curl
curl https://api.tdspro.lol/v1/chat/completions \
  -H "Authorization: Bearer $AIHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "smart",
    "messages": [{"role": "user", "content": "Hello from TDSPRO!"}]
  }'
Open the full connect guide

Authentication

Authenticate every request with a Bearer token — your TDSPRO key, which starts with sk-hub-. The OpenAI SDKs set this header for you when you pass apiKey.

header
Authorization: Bearer sk-hub-...
env
# Keep keys in environment variables — never in source control.
export AIHUB_API_KEY="sk-hub-..."      # macOS / Linux
$env:AIHUB_API_KEY = "sk-hub-..."      # Windows PowerShell

Key security

  • Store keys in environment variables or a secret manager — never in source control or client-side code.
  • Create a separate key per project or environment, and set a spend cap and rate limit on each from the dashboard.
  • Rotate or revoke a key instantly in the dashboard if it leaks. Old keys stop working immediately.
  • Every request runs over HTTPS (TLS), so your key and payloads are encrypted in transit.

Models & aliases

Call a friendly alias and let smart routing choose the best available model, or pass an exact model name. List everything your key can reach from the /models endpoint.

Capability aliases

These route automatically to the best model for the task — and fall back if one is busy.

fastLowest latency — autocomplete, quick replies, classification.
smartBalanced flagship default for hard, general problems.
codeTuned for writing, fixing, and reviewing code.
visionUnderstands images and screenshots alongside text.
reasoningStep-by-step thinking, planning, and math.
creativeLong-form writing, brainstorming, and ideas.
chatFriendly, balanced everyday conversation.

Named models

Prefer an exact flagship? Call it by name. Flagship-class models — including GPT-4.1 and GPT-4o-class — are available directly.

gpt-4.1Flagship general model.
gpt-4oFast multimodal flagship.

List available models

Returns an OpenAI-style list. Each id can be passed straight into the "model" field.

GET /models
curl https://api.tdspro.lol/v1/models \
  -H "Authorization: Bearer sk-hub-..."
200 OK
{
  "object": "list",
  "data": [
    { "id": "smart",  "object": "model", "owned_by": "ai-hub" },
    { "id": "fast",   "object": "model", "owned_by": "ai-hub" },
    { "id": "code",   "object": "model", "owned_by": "ai-hub" },
    { "id": "vision", "object": "model", "owned_by": "ai-hub" }
    // ...and every named model your key can reach
  ]
}

How to verify the model is real

Every response carries the real model name in the "model" field — we NEVER swap it for a cheaper one. Want to be sure? Compare the answer or behavior with the same model on its official API; the model name in the response will match. In Chat and Arena we surface that exact name on every reply, with a "Verify" button that shows the raw response so you can read the field yourself.

  1. 1Send any request and read the "model" field in the JSON response — that is the engine that actually answered.
  2. 2Aliases (smart, fast…) resolve to a concrete model name; that resolved name is what you see in "model".
  3. 3Run the same prompt against that model on its official API and compare — same name, same family of behavior.

Endpoints

The core OpenAI surface is supported. All paths are relative to the base URL and require the Authorization header.

POST/chat/completionsChat & tool calling. Streaming supported via "stream": true.
POST/embeddingsVector embeddings for search, clustering & RAG.
POST/images/generationsGenerate images from a text prompt.
GET/modelsList the models and aliases your key can call.
GET/meYour key’s plan, usage, and remaining quota.

Chat completions

Request

POST /chat/completions
curl https://api.tdspro.lol/v1/chat/completions \
  -H "Authorization: Bearer sk-hub-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "smart",
    "messages": [
      { "role": "system", "content": "You are concise." },
      { "role": "user",   "content": "Explain HTTP in one sentence." }
    ],
    "temperature": 0.7,
    "max_tokens": 256
  }'

Response

200 OK
{
  "id": "chatcmpl-...",
  "object": "chat.completion",
  "model": "gpt-4o",                 // the real model that answered
  "choices": [
    {
      "index": 0,
      "message": { "role": "assistant", "content": "..." },
      "finish_reason": "stop"
    }
  ],
  "usage": { "prompt_tokens": 23, "completion_tokens": 14, "total_tokens": 37 }
}

The "model" field in the response is the real engine that answered — useful for logging and cost attribution.

Embeddings

POST /embeddings
curl https://api.tdspro.lol/v1/embeddings \
  -H "Authorization: Bearer sk-hub-..." \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-embedding-001",
    "input": "The quick brown fox"
  }'

Returns an OpenAI-style data array of float vectors. Use them for semantic search and RAG.

Streaming

Set "stream": true to receive tokens as they are generated over Server-Sent Events (SSE), exactly like the OpenAI API. The stream ends with a [DONE] sentinel. The OpenAI SDKs handle this for you — just iterate the response.

With the SDK

stream.py
from openai import OpenAI

client = OpenAI(base_url="https://api.tdspro.lol/v1", api_key="sk-hub-...")

stream = client.chat.completions.create(
    model="smart",
    messages=[{"role": "user", "content": "Write a haiku about caching."}],
    stream=True,
)
for chunk in stream:
    delta = chunk.choices[0].delta.content or ""
    print(delta, end="", flush=True)

Raw SSE wire format

text/event-stream
data: {"choices":[{"delta":{"content":"Hello"}}]}

data: {"choices":[{"delta":{"content":" world"}}]}

data: {"choices":[{"delta":{},"finish_reason":"stop"}]}

data: [DONE]

Each event is a data: line with a JSON delta. Concatenate the delta.content fields to rebuild the message.

Errors & status codes

Errors use standard HTTP status codes and a consistent JSON shape, so OpenAI-style error handling works unchanged.

Error shape

error.json
{
  "error": {
    "type": "rate_limit_exceeded",
    "message": "You hit your per-key rate limit. Retry shortly.",
    "code": 429
  }
}

Status codes

200OKSuccess. For streams, tokens arrive as SSE.
400Bad requestMalformed JSON or invalid parameters. Check your payload.
401UnauthorizedMissing or invalid key. Re-check the Authorization header.
402Payment requiredOut of quota or budget. Top up or raise the cap.
403ForbiddenKey is disabled or the request was blocked by policy.
404Not foundUnknown model id or endpoint path.
429Rate limitedToo many requests. Back off and retry — see below.
5xxServer errorTransient upstream issue. Retry with backoff.

Retry on 429 & 5xx

On a 429 or transient 5xx, retry with exponential backoff. Automatic fallback often resolves it before you even see the error.

retry.js
async function withRetry(fn, tries = 4) {
  for (let i = 0; i < tries; i++) {
    try {
      return await fn();
    } catch (e) {
      // Retry only on 429 and transient 5xx.
      const status = e?.status ?? e?.response?.status;
      if (![429, 500, 502, 503].includes(status) || i === tries - 1) throw e;
      await new Promise((r) => setTimeout(r, 2 ** i * 500)); // 0.5s, 1s, 2s, 4s
    }
  }
}

Rate limits & quotas

Rate limits and budgets are set per key in your dashboard, not hard-coded globally — so you control them. Limits scale with your plan.

Per-key rate limit

A requests-per-minute ceiling you set per key. Exceeding it returns 429; just retry shortly.

Spend cap & quota

Set a hard monthly budget or request quota per key. Hitting it returns 402 until you raise it or the period resets.

Plan limits

Free keys are capped at ~50 requests/day; paid plans raise both rate and volume. See pricing for exact numbers.

Live usage

Track remaining quota any time via GET /me or the dashboard — no surprises at the end of the month.

Caching & token savings

Identical requests are served from a token-saving cache, so repeat traffic costs less and returns instantly. It is the same model and the same answer — you simply pay for fewer of them.

Instant repeats

A cache hit skips inference entirely and returns in milliseconds.

Lower bill

Cached responses do not re-bill tokens — your repeat traffic gets cheaper automatically.

Same model, honestly

The cached response carries the same real model name as the original — no swaps.

Caching keys on the exact request (model + messages + parameters). Change any field — temperature, a message — and you get a fresh generation.

Examples

Copy-paste starters for the most common tools. Replace sk-hub-... with your key.

Python
from openai import OpenAI
import os

client = OpenAI(
    base_url="https://api.tdspro.lol/v1",
    api_key=os.environ["AIHUB_API_KEY"],  # sk-hub-...
)

res = client.chat.completions.create(
    model="smart",                        # alias → best model for the job
    messages=[{"role": "user", "content": "Hello from TDSPRO!"}],
)
print(res.choices[0].message.content)
JS / Node
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://api.tdspro.lol/v1",
  apiKey: process.env.AIHUB_API_KEY,
});

const r = await client.chat.completions.create({
  model: "code",                       // tuned for programming
  messages: [{ role: "user", content: "Write a debounce() in TypeScript." }],
});
console.log(r.choices[0].message.content);
curl
curl https://api.tdspro.lol/v1/chat/completions \
  -H "Authorization: Bearer $AIHUB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "smart",
    "messages": [{"role": "user", "content": "Hello from TDSPRO!"}]
  }'
opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "aihub": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "TDSPRO",
      "options": {
        "baseURL": "https://api.tdspro.lol/v1",
        "apiKey": "sk-hub-..."
      },
      "models": {
        "smart": { "name": "TDSPRO — Flagship" },
        "fast":  { "name": "TDSPRO — Fast" },
        "code":  { "name": "TDSPRO — Code" }
      }
    }
  },
  "model": "aihub/smart"
}

Drop this into opencode.json. Only the baseURL, key, and model ids are ours.

Cursor settings
Settings → Models → OpenAI API Key
  Override OpenAI Base URL:  https://api.tdspro.lol/v1
  OpenAI API Key:            sk-hub-...
  Custom model name:         smart   (also add: fast, code, vision)

Cursor → Settings → Models. Turn on “Override OpenAI Base URL”, paste the base URL and your key, then add a model named smart.

For Claude Code, MCP, and one-line installers, see the connect guide.

FAQ

Is the API really OpenAI-compatible?+

Yes. The request and response shapes match the OpenAI spec, so the official OpenAI SDKs and any compatible tool work by changing only the base URL and key.

Do you ever swap my model for a cheaper one?+

Never. Every response carries the real model name in the "model" field. We save you money only through caching identical requests — which return the same model.

What is an alias vs a model name?+

An alias (like smart or fast) is a capability that smart-routes to the best available model and falls back if one is busy. A model name (like gpt-4.1) pins one specific model.

How do I stream responses?+

Set "stream": true. Tokens arrive as Server-Sent Events ending in [DONE]. The OpenAI SDKs iterate this for you automatically.

Where do I find my rate limit and quota?+

Both are per-key and visible in your dashboard, or via GET /me. You set the spend cap and rate limit yourself.

Can I self-host?+

The public endpoint is the simplest path. If you run your own instance, point your client at your local base URL instead — everything else stays the same.

Troubleshooting

401 Unauthorized

Your key is missing, mistyped, or revoked. Confirm the header is exactly “Authorization: Bearer sk-hub-...” and copy a fresh key from the dashboard.

404 model not found

The model id is unknown. Use an alias (smart, fast, code) or a listed name from GET /models.

429 rate limited

You exceeded your per-key rate limit. Back off and retry with exponential delay, or raise the limit on the dashboard.

402 out of quota

Your key hit its spend cap or quota. Top up, raise the cap, or wait for the period to reset.

Empty or cut-off response

Raise max_tokens, or stream the response so long outputs arrive incrementally.

SDK ignores the base URL

Make sure baseURL/base_url ends in /v1 and you restarted the process after setting the env var.

Get help

Stuck or have a question? We respond fast — usually within a few hours.

Or reach us directly — Telegram is fastest: Telegram @tdspro_admin · [email protected]