Clave de API TTS en Python: configuración, streaming y modo JSON
Esta es una guía en Python para la API detrás de este sitio: guarda la clave, crea un cliente, transmite las respuestas, fuerza la salida JSON y maneja los límites de peticiones. Una advertencia primero: genera texto, no audio.
Actualizado

Puntos clave
- El endpoint es compatible con OpenAI, por lo que el paquete Python openai funciona con base_url configurado en https://api.ttsapihub.com/v1.
- Mantén la clave en una variable de entorno, nunca en el código fuente.
- Se admiten streaming, modo JSON y llamadas a funciones; no hay salida de audio.
- Maneja HTTP 429 con una breve espera y lee X-Balance-USD para rastrear el gasto.
Verifica qué habilita la clave
Las personas que buscan un ejemplo de clave de API TTS en Python suelen querer convertir texto en audio hablado. La clave de este servicio no hace eso. Autentica peticiones a un LLM de texto: POST /v1/chat/completions y GET /v1/models, usando el modelo uncensored. No hay síntesis de voz, ni subida de audio ni embeddings.
Si esto encaja en tu proyecto, por ejemplo porque generas guiones, diálogos o narración que pasas a una herramienta de voz separada, el resto de esta página te da código Python funcional. Si necesitas salida de audio desde la API misma, este no es el servicio adecuado y es mejor saberlo ahora. La documentación enumera el conjunto exacto de funciones.
Una forma práctica de usar la generación de texto en un proyecto de audio es tratarlo como la etapa de escritura. El modelo redacta la narración, reescribe una línea para ajustarse a un límite de tiempo o convierte notas en diálogos con varios hablantes. Tu código Python luego pasa el texto final a la herramienta de voz que uses. Mantener las etapas separadas también significa que puedes cambiar cualquiera de ellas sin tocar la otra, y solo pagas a esta API por las palabras que escribe.
Para seguir la guía necesitas Python 3.9 o superior y una clave. Regístrate en la página de clave de API y reclama el crédito de prueba de $0,50 en un clic; dura 7 días y no requiere tarjeta.
Guarda la clave e instala el paquete
Nunca escribas la clave en un archivo que vayas a hacer commit. Ponla en una variable de entorno y léela en tiempo de ejecución.
# base URL used below: https://api.ttsapihub.com/v1 , model: uncensored
pip install openai
export API_KEY="paste-your-key-here"En PowerShell de Windows, el equivalente es $env:API_KEY = "paste-your-key-here". Para un proyecto, un archivo .env cargado con un paquete como python-dotenv es un patrón común, siempre que .env esté en tu .gitignore.
Si una clave se filtra en un repositorio, trátala como quemada: elimínala del historial si puedes y solicita una nueva. Recuerda que las claves gastan crédito prepago, por lo que una clave filtrada es también una fuga financiera.
Crea el cliente y haz una primera llamada
El paquete oficial acepta un base_url. El resto es la llamada OpenAI habitual.
import os
from openai import OpenAI
client = OpenAI(
base_url="https://api.ttsapihub.com/v1",
api_key=os.environ["API_KEY"],
)
resp = client.chat.completions.create(
model="uncensored",
messages=[
{"role": "system", "content": "You write short narration scripts."},
{"role": "user", "content": "Draft a 40-word intro for a podcast about night trains."},
],
temperature=0.8,
max_tokens=200,
)
print(resp.choices[0].message.content)
print(resp.usage.prompt_tokens, resp.usage.completion_tokens)El objeto usage muestra cuántos tokens usó la llamada, para que puedas calcular el costo: tokens de entrada multiplicados por $0,15 por millón, más tokens de salida multiplicados por $0,50 por millón. Si la llamada anterior usó 60 tokens de entrada y 80 de salida, el costo es $0,000009 más $0,00004, lo que suma $0,000049. Las peticiones fallidas o rechazadas no se cobran.
max_tokens es opcional. Sin él, la generación puede usar lo que quede de la ventana de 100.000 tokens, así que establécelo cuando quieras un límite estricto de longitud y costo.
Transmite la respuesta
El streaming devuelve tokens a medida que se generan usando eventos enviados por el servidor. Configura stream=True e itera.
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])
stream = client.chat.completions.create(
model="uncensored",
messages=[{"role": "user", "content": "Describe a rainy station platform in four sentences."}],
stream=True,
)
parts = []
for chunk in stream:
if not chunk.choices:
continue
delta = chunk.choices[0].delta.content or ""
parts.append(delta)
print(delta, end="", flush=True)
text = "".join(parts)La protección para una lista de choices vacía está ahí porque el evento final de un streaming puede llevar datos de uso y ningún texto. Saltarlo evita un error de índice. Un detalle operativo: una petición en streaming mantiene su slot de concurrencia hasta que termina el streaming. Si inicias muchos streaming en hilos y nunca terminas de leerlos, alcanzarás el límite de concurrencia aunque tu tasa de peticiones sea baja.
Solicita JSON y llama a herramientas
Modo JSON
Configura response_format a un objeto JSON para que la respuesta sea analizable. También indícale en el prompt que quieres JSON; la configuración restringe el formato y el prompt le indica la forma.
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])
resp = client.chat.completions.create(
model="uncensored",
response_format={"type": "json_object"},
messages=[
{"role": "system", "content": "Reply only with JSON: {\"title\": str, \"beats\": [str]}"},
{"role": "user", "content": "Outline a three-beat radio drama about a lost key."},
],
)
data = json.loads(resp.choices[0].message.content)
print(data["title"], len(data["beats"]))Envuelve json.loads en un bloque try de todos modos. Una respuesta que alcance max_tokens puede cortarse en medio de un objeto.
Llamada de herramientas
Pasa tools y opcionalmente tool_choice. Cuando el modelo solicite una herramienta, ejecútala tú mismo y envía el resultado de vuelta como un mensaje con role: "tool".
import json, os
from openai import OpenAI
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])
tools = [{
"type": "function",
"function": {
"name": "word_count",
"description": "Count the words in a text",
"parameters": {
"type": "object",
"properties": {"text": {"type": "string"}},
"required": ["text"],
},
},
}]
messages = [{"role": "user", "content": "How many words are in: the quick brown fox?"}]
first = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
msg = first.choices[0].message
if msg.tool_calls:
call = msg.tool_calls[0]
args = json.loads(call.function.arguments)
result = len(args["text"].split())
messages.append(msg)
messages.append({"role": "tool", "tool_call_id": call.id, "content": str(result)})
final = client.chat.completions.create(model="uncensored", messages=messages, tools=tools)
print(final.choices[0].message.content)Mantén una conversación y vigila el presupuesto de tokens
La API es sin estado. Si quieres un chat que recuerde lo dicho, mantienes la lista de mensajes en tu programa y la envías completa con cada llamada. Una pequeña clase hace el trabajo y es también el lugar adecuado para acotar el historial para que el costo no aumente.
import os
from openai import OpenAI
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"])
history = [{"role": "system", "content": "You are a dialogue writer. Keep replies under 120 words."}]
def say(user_text, keep_last=12):
history.append({"role": "user", "content": user_text})
# keep the system message plus the most recent turns
trimmed = [history[0]] + history[1:][-keep_last:]
resp = client.chat.completions.create(model="uncensored", messages=trimmed, max_tokens=250)
reply = resp.choices[0].message.content
history.append({"role": "assistant", "content": reply})
return reply, resp.usage.total_tokens
print(say("Open a scene in a ticket office at closing time.")[0])Recortar importa más por dinero que por la ventana. El modelo acepta hasta 100.000 tokens en total, pero si cada turno reenvía 30.000 tokens de historial, cada llamada cuesta $0,0045 solo en entrada (30.000 veces $0,15 por millón). Cincuenta de esos turnos suman $0,225 antes de que se cuente un solo token de salida. Mantener los últimos doce turnos, o resumir los anteriores en una nota corta, suele mantener la calidad y recorta la factura drásticamente.
La concurrencia es otro aspecto para el que debes diseñar. Si tu programa atiende a varios usuarios a la vez, un semáforo dimensionado al límite de tu clave (8 para una clave completa, 2 para una de prueba) evita que tropieces con el error de concurrency. Las llamadas por encima del límite esperan en tu propia cola en lugar de fallar, lo cual es más amigable que reintentar en un 429.
Las pruebas también merecen una mención. Escribe un pequeño script que llame a la API con un seed fijo, una temperatura baja y un max_tokens corto, y ejecútalo cada vez que cambies prompts o configuraciones. Un seed y una temperatura baja hacen la salida más repetible, lo que te permite comparar dos versiones de prompt sin ruido. Mantén estas pruebas pequeñas; una prueba que cuesta una fracción de centavo puede ejecutarse en cada commit sin que nadie note la factura.
Finalmente, registra el ID de petición de cada respuesta. Cuando una llamada se comporta de forma extraña, ese ID es la forma más rápida de señalar a soporte la petición exacta.
Maneja límites, errores y saldo
Una clave completa permite 8 peticiones concurrentes y 300 peticiones por minuto. La clave de prueba permite 2 y 60. Exceder el primero devuelve HTTP 429 con el código de error concurrency, y exceder el segundo devuelve 429 con rate_limited. Una sobrecarga temporal también devuelve 429 con un encabezado Retry-After: 5.
El paquete OpenAI reintenta algunos fallos por sí mismo, y puedes aumentar eso con max_retries. Para un trabajo por lotes, añade tu propio límite de trabajo paralelo también, para que te mantengas por debajo del límite de concurrencia en lugar de depender de reintentos.
import os
from openai import OpenAI, RateLimitError
client = OpenAI(base_url="https://api.ttsapihub.com/v1", api_key=os.environ["API_KEY"], max_retries=3)
raw = client.chat.completions.with_raw_response.create(
model="uncensored",
messages=[{"role": "user", "content": "One sentence about trains."}],
max_tokens=60,
)
print("balance:", raw.headers.get("X-Balance-USD"))
print("request id:", raw.headers.get("X-Request-Id"))
print(raw.parse().choices[0].message.content)Los encabezados de respuesta X-Request-Id y X-Balance-USD son útiles en los registros. Cita el ID de la petición cuando contactes a soporte. Los costos se listan en la página de precios: $0,15 por 1M de tokens de entrada y $0,50 por 1M de tokens de salida, con recargas desde $20 hasta $500 y bonificaciones del 5%, 10% y 15% en $50, $100 y $200. Se aceptan tarjetas (Visa, Mastercard, Apple Pay, Google Pay) y cripto (USDT en TRC20, USDC en Base). Los prompts no se usan para entrenamiento. El modelo está destinado a uso adulto lícito y el contenido sexual que involucre a menores de edad nunca está permitido.
Más guías
Preguntas y respuestas
¿Funciona esta clave de API para texto a voz en Python?
No. La clave autentica una API LLM de texto sin salida de audio. Úsala para generar texto y luego pásalo a una herramienta de voz.
¿Qué paquete de Python debo usar?
El paquete oficial openai. Configura base_url en https://api.ttsapihub.com/v1 y model en uncensored.
¿Cómo mantengo la clave fuera del código?
Lee la clave desde una variable de entorno como API_KEY y excluye cualquier archivo .env del control de versiones.
¿Cómo veo cuánto costó una petición?
Lee resp.usage para los recuentos de tokens y el encabezado de respuesta X-Balance-USD para el saldo restante.
¿Qué sucede cuando alcanzas el límite de peticiones?
La API devuelve HTTP 429 con el código rate_limited o concurrency. Espera unos segundos y reintenta; la petición fallida no se cobra.
Tu clave está a un formulario de distancia
Crea una cuenta, copia la clave, cambia la URL base. Esa es toda la configuración.