Visión General
Inicio Rápido
TokSpan es compatible con OpenAI — cambia la URL base para acceder a más de 200 modelos al instante. También se admiten Claude Code / Anthropic nativo y la API Responses de OpenAI, y la generación de video con Doubao Seedance funciona con la misma clave; consulta más abajo.
Crea una clave API
Genera tu clave sk- en la página de API Keys del Panel.
Cambia tu URL base
Apunta la URL base de tu SDK a una de las URLs de abajo y llama con tu clave.
Actualizar/Agregar ID de modelo
Ve a Model Plaza para obtener el ID del modelo y luego actualízalo.
URLs base de la API
TokSpan habla varios protocolos de API. Elige el que tu SDK ya usa — todos los formatos aceptan la misma clave API y acceden a más de 200 modelos.
https://api.tokspan.com/v1El SDK de OpenAI ya incluye /v1 y agrega /chat/completions automáticamente.
https://api.tokspan.comUsa la raíz del host — Claude Code y el SDK de Anthropic agregan /v1/messages por sí mismos.
https://api.tokspan.com/v1/videosPOST /v1/videos crea una tarea y devuelve su id; consulta el estado hasta que el video esté listo y luego descarga el contenido.
https://api.tokspan.com/v1Reutiliza la URL base compatible con OpenAI y llama a /v1/responses.
Compatible con OpenAI
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)Nativo de Anthropic
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
"""
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")Facturación: la cuota se cobra por adelantado al enviar (seconds × resolution) y se concilia con el uso real al completarse. 5s en 720p ≈ $1.10, 1080p ≈ $2.48, 4k ≈ $9.90. Un token con saldo inferior al cargo previo se rechaza antes de crear la tarea.
Responses API
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)Uso de la API de TokSpan
Sin SDK — envía solicitudes directamente al endpoint compatible con OpenAI con HTTP puro:
Todas las solicitudes usan el mismo formato: POST https://api.tokspan.com/v1/chat/completions con tu clave API en el encabezado Authorization.
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?"))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;
};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!"}]
}'Conversión entre formatos
TokSpan convierte automáticamente entre diferentes formatos de API de forma transparente. Tú siempre envía solicitudes en el formato OpenAI Chat Completions: TokSpan se encarga de la traducción al formato nativo del proveedor upstream:
- OpenAI → Claude Messages API: los prompts de sistema, la conversación de múltiples turnos y las definiciones de herramientas se reasignan automáticamente
- OpenAI → Gemini API: las partes de contenido, la configuración de seguridad y los parámetros de generación se traducen de forma transparente
- Claude → formato OpenAI: las respuestas nativas de Claude se normalizan a la estructura estándar de respuesta de Chat Completions
Esto significa que puedes usar el SDK de OpenAI para Python/Node, LangChain o cualquier biblioteca compatible con OpenAI para llamar a cualquier modelo, independientemente de tu formato de API nativo.
Alcance y permisos de claves
Cada clave API puede tener un alcance limitado a permisos específicos:
- Modelos: Restringe a qué modelos puede acceder la clave
- Límite de gasto: Establece un límite de cuota fijo; la clave se desactiva automáticamente cuando se agota su cuota
- Lista blanca de IP: Solo permite solicitudes desde rangos de IP específicos
¿Qué sigue?
- Explore el catálogo completo de modelos: más de 200 modelos en más de 50 proveedores
- Conozca el failover automático para resiliencia en producción
- Descubra las integraciones de SDK para Python, JavaScript y más
- Lea la referencia de la API de Chat Completions con todos los parámetros