Обзор

Быстрый старт

TokSpan совместим с OpenAI — измените базовый URL, чтобы мгновенно получить доступ к 200+ моделям. Также поддерживаются Claude Code / нативный Anthropic и OpenAI Responses API, а генерация видео Doubao Seedance работает с тем же ключом — см. ниже.

1

Зарегистрируйтесь и войдите

Зарегистрируйтесь по email на нашей странице регистрации.

2

Создайте API-ключ

Создайте sk- ключ на странице API Keys в панели управления.

3

Измените базовый URL

Направьте базовый URL вашего SDK на один из URL ниже и вызывайте с ключом.

4

Обновить/Добавить ID модели

Перейдите в Model Plaza, чтобы получить ID модели, затем обновите его.

Базовые URL API

TokSpan поддерживает несколько протоколов API. Выберите тот, который уже использует ваш SDK — все форматы принимают один и тот же API-ключ и открывают доступ к 200+ моделям.

Совместимый с OpenAI
https://api.tokspan.com/v1

SDK OpenAI уже включает /v1 и автоматически добавляет /chat/completions.

Нативный Anthropic
https://api.tokspan.com

Используйте корневой адрес хоста — Claude Code и SDK Anthropic сами добавляют /v1/messages.

Video Generation API
https://api.tokspan.com/v1/videos

POST /v1/videos создаёт задачу и возвращает её id; опрашивайте статус до готовности видео, затем скачайте результат.

Responses API
https://api.tokspan.com/v1

Использует совместимый с OpenAI базовый URL и вызывает /v1/responses.

Совместимый с OpenAI

python
from openai import OpenAI

client = OpenAI(
    api_key="sk-your-api-key",
    base_url="https://api.tokspan.com/v1",  # ← OpenAI-compatible base URL
)

response = client.chat.completions.create(
    model="MODEL_NAME",  # Replace MODEL_NAME with any model from the catalog
    messages=[{"role": "user", "content": "Hello!"}],
)

print(response.choices[0].message.content)

Нативный Anthropic

python
from anthropic import Anthropic

client = Anthropic(
    api_key="sk-your-api-key",
    base_url="https://api.tokspan.com",  # ← Native Anthropic base URL (host root; SDK appends /v1/messages)
)

response = client.messages.create(
    model="MODEL_NAME",  # Replace MODEL_NAME with any Claude model from the catalog
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
)

print(response.content[0].text)

Video Generation API

python
"""
Doubao Seedance video generation - Python example.

Video generation is asynchronous: submit a task, poll it, then download the
result. Requires `pip install requests`.
"""

import time
from typing import Any, Dict, Optional

import requests

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------
# Site origin only - no trailing slash and no "/v1/videos" (the paths below are
# appended by the code, e.g. f"{BASE_URL}/v1/videos").
BASE_URL = "https://api.tokspan.com"
API_KEY = "YOUR_API_KEY"               # user token from Console -> Tokens
MODEL = "volcengine/doubao-seedance-2-5-v2"

PROMPT = "A ginger cat walking through a sunlit garden, cinematic, shallow depth of field"
SECONDS = 5             # 1-3600; upstream default is about 10s
RESOLUTION = "1080p"    # 480p / 720p / 1080p / 4k; upstream default is 720p
IMAGE_URL = None        # reference image URL for image-to-video; None = text-to-video

POLL_INTERVAL = 10      # seconds between status checks
POLL_TIMEOUT = 15 * 60  # give up after this many seconds

# A trailing slash would produce "https://host//v1/videos", which the gateway
# answers with its HTML front page (HTTP 200), so normalize it away.
BASE_URL = BASE_URL.rstrip("/")

# Available models, with list price per 1M tokens (billed on actual usage):
#   volcengine/doubao-seedance-2-5-v2            $10.19   best quality
#   volcengine/doubao-seedance-2-0-260128         $6.00
#   volcengine/doubao-seedance-2-0-fast-260128    $4.35   fastest, cheapest


def _headers() -> Dict[str, str]:
    """Auth header. `requests` sets Content-Type automatically for json= bodies."""
    return {"Authorization": f"Bearer {API_KEY}"}


def _check(resp: requests.Response, action: str) -> None:
    """Raise a readable error for any non-2xx response.

    Error codes you may hit:
        pre_consume_token_quota_failed  token balance below the pre-charge
        model_not_found                 no channel serves this model
        get_channel_failed              channel selection failed
        fail_to_fetch_task              upstream error (details inside `message`)
    """
    if resp.ok:
        return
    try:
        body = resp.json()
    except ValueError:
        body = {"message": resp.text[:200]}
    err = body.get("error", body) if isinstance(body, dict) else {"message": str(body)}
    raise RuntimeError(
        f"{action} failed: HTTP {resp.status_code} "
        f"[{err.get('code', '')}] {err.get('message', '')}"
    )


def create_video(
    prompt: str,
    model: str = MODEL,
    seconds: Optional[int] = None,
    resolution: Optional[str] = None,
    image_url: Optional[str] = None,
) -> str:
    """Submit a generation task and return its task id."""
    payload: Dict[str, Any] = {"model": model, "prompt": prompt}
    if seconds is not None:
        payload["seconds"] = seconds
    if resolution is not None:
        payload["resolution"] = resolution
    if image_url:
        payload["input_reference"] = image_url   # "image" is an accepted alias

    resp = requests.post(f"{BASE_URL}/v1/videos", headers=_headers(), json=payload, timeout=60)
    _check(resp, "Submit")

    task_id = resp.json()["id"]
    print(f"Submitted task: {task_id}")
    return task_id


def wait_for_video(task_id: str) -> Dict[str, Any]:
    """Poll until the task finishes: queued -> in_progress -> completed / failed."""
    deadline = time.time() + POLL_TIMEOUT
    while time.time() < deadline:
        resp = requests.get(f"{BASE_URL}/v1/videos/{task_id}", headers=_headers(), timeout=60)
        _check(resp, "Poll")

        data = resp.json()
        status = str(data.get("status", "")).lower()
        print(f"  status={status} progress={data.get('progress', 0)}%")

        if status == "completed":
            return data
        if status in {"failed", "cancelled", "expired"}:
            reason = (data.get("error") or {}).get("message", "unknown reason")
            raise RuntimeError(f"Generation failed: {reason}")

        time.sleep(POLL_INTERVAL)

    raise TimeoutError(f"Timed out after {POLL_TIMEOUT}s, task {task_id} still running")


def download_video(task_id: str, save_path: str) -> str:
    """Download the finished video to `save_path`."""
    resp = requests.get(
        f"{BASE_URL}/v1/videos/{task_id}/content",
        headers=_headers(),
        stream=True,
        timeout=300,
    )
    _check(resp, "Download")

    with open(save_path, "wb") as fh:
        for chunk in resp.iter_content(chunk_size=1 << 16):
            fh.write(chunk)

    print(f"Saved video: {save_path}")
    return save_path


if __name__ == "__main__":
    tid = create_video(PROMPT, seconds=SECONDS, resolution=RESOLUTION, image_url=IMAGE_URL)
    wait_for_video(tid)
    download_video(tid, f"{tid}.mp4")

Биллинг: квота списывается предварительно при отправке (seconds × resolution) и сверяется с фактическим использованием по завершении. 5 сек в 720p ≈ $1.10, 1080p ≈ $2.48, 4k ≈ $9.90. Запрос с балансом ниже предварительного списания отклоняется до создания задачи.

Responses API

python
from openai import OpenAI

client = OpenAI(
    api_key="sk-your-api-key",
    base_url="https://api.tokspan.com/v1",  # ← Same base URL as OpenAI-compatible
)

response = client.responses.create(
    model="MODEL_NAME",  # Replace MODEL_NAME with any model from the catalog
    input="Hello!",
)

print(response.output_text)
Один ключ — все форматы. Все форматы используют один и тот же ключ TokSpan. Баланс и использование общие — просто вызывайте нужную модель.

Использование API TokSpan

SDK не требуется — отправляйте запросы напрямую на совместимый с OpenAI эндпоинт через обычный HTTP:

Все запросы используют одинаковый формат: POST https://api.tokspan.com/v1/chat/completions с вашим API-ключом в заголовке Authorization.

python
import requests

def chat(prompt: str, model: str = "MODEL_NAME"):  # Replace MODEL_NAME with any model from the catalog
    response = requests.post(
        "https://api.tokspan.com/v1/chat/completions",
        headers={
            "Authorization": "Bearer sk-your-api-key",
            "Content-Type": "application/json",
        },
        json={
            "model": model,
            "messages": [{"role": "user", "content": prompt}],
        },
    )
    return response.json()["choices"][0]["message"]["content"]

print(chat("Hello! What models are available?"))
typescript
const chat = async (prompt: string, model = 'MODEL_NAME') => {  // Replace MODEL_NAME with any model from the catalog
  const res = await fetch('https://api.tokspan.com/v1/chat/completions', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk-your-api-key',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      model,
      messages: [{ role: 'user', content: prompt }],
    }),
  });
  const data = await res.json();
  return data.choices[0].message.content;
};
shell
curl -X POST "https://api.tokspan.com/v1/chat/completions" \
  -H "Authorization: Bearer sk-your-api-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_NAME",
    "messages": [{"role": "user", "content": "Hello!"}]
  }'

Кросс-форматная конвертация

TokSpan автоматически конвертирует между различными форматами API за кулисами. Вы всегда отправляете запросы в формате OpenAI Chat Completions — TokSpan выполняет трансляцию в нативный формат upstream-провайдера:

  • OpenAI → Claude Messages API — Системные промпты, многошаговые диалоги и определения инструментов автоматически преобразуются
  • OpenAI → Gemini API — Части контента, настройки безопасности и конфигурация генерации транслируются прозрачно
  • Claude → формат OpenAI — Нативные ответы Claude нормализуются до стандартной структуры ответа Chat Completions

Это означает, что вы можете использовать OpenAI Python/Node SDK, LangChain или любую библиотеку, совместимую с OpenAI, для вызова любой модели — независимо от её нативного формата API.

Ограничение ключей и разрешения

Каждый API-ключ может быть ограничен определёнными разрешениями:

  • Модели: Ограничьте, к каким моделям ключ имеет доступ
  • Лимит расходов: Установите жёсткий лимит квоты — ключ автоматически отключается после исчерпания квоты
  • IP-whitelisting: Разрешите запросы только с определённых IP-диапазонов
Примечание по безопасности: Никогда не раскрывайте API-ключ в клиентском коде. Используйте переменные окружения или защищённый бэкенд-прокси. Все запросы к TokSpan шифруются с помощью TLS 1.3.

Что дальше?