SDK de Python
El SDK oficial de Python para SpicyAPI (spicyapi) — instálalo, cotiza y lanza tu primera generación, sube un archivo local, verifica webhooks y consulta todos los códigos de error.
spicyapi es el SDK oficial de Python para SpicyAPI. Pone la generación de imagen, video y audio detrás de un único objeto cliente: adjunta tu clave de API, convierte la envoltura de la respuesta en diccionarios normales, espera a que una tarea termine con esperas crecientes sensatas, sube archivos locales en una sola llamada y verifica las firmas de los webhooks en tiempo constante.
Necesita Python 3.11 o posterior y no tiene ninguna dependencia en tiempo de ejecución. Es una decisión deliberada: este paquete entra en un árbol de dependencias que ya es tuyo, y cada restricción que añade es una oportunidad más de conflicto.
¿Es la herramienta adecuada?
| Quieres… | Usa |
|---|---|
| Llamar a SpicyAPI desde tu propio código de Python | Este SDK |
| Llamarla desde Node.js o TypeScript | El SDK de TypeScript |
| Llamarla desde Go, PHP o Java | El SDK de Go, de PHP o de Java |
| Generar cosas desde una terminal, sin escribir código | La CLI |
| Que un asistente de IA llame a SpicyAPI por ti | El servidor MCP y el Agent Skill |
| Usar un modelo de chat o de texto | La biblioteca oficial openai, anthropic o google-genai apuntando a SpicyAPI; consulta Texto y streaming |
Instálalo
pip install spicyapiDespués guarda tu clave en el entorno, para que no aparezca nunca ni en tu código ni en el archivo de historial de tu terminal:
export SPICY_API_KEY="sk-spicy-..."Tu primer resultado
Pide el precio, decide, crea la tarea, espera y lee los archivos. Cotizar es gratis y no retiene nada.
import os, uuid
from spicyapi import SpicyClient, output_assets
client = SpicyClient() # lee SPICY_API_KEY del entorno
model = client.get_model("MODEL_ID_FROM_CATALOG")
quote = client.quote_task(model=model["model"], input_data={"prompt": "a lantern in fog"})
print(quote["estimatedCost"], quote["maxCharge"]) # decide antes de gastar
task = client.create_task(
model=model["model"],
input_data={"prompt": "a lantern in fog"},
idempotency_key=str(uuid.uuid4()),
quote_id=quote["quoteId"],
expected_cost=quote["estimatedCost"],
)
final = client.wait_for_terminal(task["taskId"])
for asset in output_assets(final): # función del módulo, no un método
print(asset["url"])MODEL_ID_FROM_CATALOG es un marcador de posición. Saca un ID real del catálogo autenticado —client.list_models(), que es GET /api/v1/models— y nunca de memoria ni de una página antigua: los modelos se añaden, se pausan y se retiran. Construye input_data a partir del inputSchema del propio modelo, que devuelve list_models(include_schema=True); cada modelo acepta campos distintos.
Los importes llegan como cadenas decimales en dólares estadounidenses, nunca como números en coma flotante, porque un flotante binario no puede guardar con exactitud la mayoría de los importes decimales. Compáralos y súmalos con decimal.Decimal. En esta API no hay créditos ni puntos por ninguna parte.
wait_for_terminal devuelve el control en cualquier estado terminal. Un estado terminal no es un estado correcto: comprueba final["state"] antes de leer la salida.
Algunos endpoints responden con texto en lugar de con archivos. Lee primero output_text(final) cuando el modelo produzca una transcripción o una descripción; un cliente que solo recorre la lista de archivos da por vacía una tarea que ha salido perfectamente.
Empieza desde un archivo local
La generación de imagen a video, la sustitución de personas y la edición de imágenes necesitan que tu material esté antes de nuestro lado. upload_file hace en una sola llamada la subida en tres pasos —ticket, PUT al almacenamiento y confirmación— y devuelve un URI spicy://. Ese URI es lo que va en la entrada.
uploaded = client.upload_file("/path/to/reference.png")
task = client.create_task(
model="MODEL_ID_FROM_CATALOG",
input_data={"image": uploaded["uri"], "prompt": "slow dolly in"},
idempotency_key=str(uuid.uuid4()),
)Una URL HTTPS accesible públicamente puede ir directamente en la entrada y no necesita ninguna subida. Se aceptan imágenes de hasta 10 MiB, y audio y video de hasta 90 MiB; lo demás está en Carga y descarga de medios.
Webhooks
verify_webhook es una función del módulo, así que el manejador de una solicitud puede usarla sin construir un cliente. Compara en tiempo constante y solo revisa la marca de tiempo después de que la firma sea válida.
from spicyapi import verify_webhook
delivery = verify_webhook(
raw_body=request.body, # los bytes exactos, antes de analizarlos
signature=request.headers["X-Webhook-Signature"],
timestamp=request.headers["X-Webhook-Timestamp"],
payload_version=request.headers["X-Webhook-Payload-Version"],
secret=os.environ["SPICY_WEBHOOK_SECRET"],
)Verifica los bytes en bruto. Un json.loads seguido de un json.dumps los cambia, y la firma ya no volverá a coincidir jamás. Las entregas se reintentan, así que deduplica por el ID de entrega. El formato completo de las entregas y el calendario de reintentos están en Webhooks.
Errores
Cada fallo lanza SpicyApiError, que lleva status, code, request_id y retry_after_seconds. Ramifica según code, nunca según el texto del mensaje: los mensajes se traducen, los códigos no.
El estado HTTP 503 lo comparten tres códigos de negocio distintos, así que leer solo el estado HTTP no basta para decidir qué hacer:
| code | Qué significa | Qué hacer |
|---|---|---|
40003 | los bytes subidos no coinciden con su ticket | empieza de cero con un ticket nuevo |
40004 | ningún despliegue atiende esa combinación de parámetros | cambia el parámetro que nombra el mensaje |
40201 | saldo insuficiente | añade fondos |
40901 | el precio cambió antes de que se creara la tarea | vuelve a cotizar y conserva la misma clave de idempotencia |
503 | una dependencia no está disponible durante un momento | espera lo que indique Retry-After |
50301 | ahora mismo el modelo no tiene ningún despliegue ni precio utilizable | actualiza el catálogo y no insistas a lo loco |
50302 | una generación síncrona falló aguas arriba y se reembolsó | reintenta con una clave de idempotencia nueva |
err.recovery devuelve esa misma orientación en tiempo de ejecución. Cita el request_id cuando escribas a soporte. Todos los códigos están en Errores.
Dos cosas que te ahorrarán dinero
Usa una sola clave de idempotencia por envío. Reutilízala en cada reenvío de ese envío, también después de un tiempo de espera agotado o de una conexión cortada. Que se pierda una respuesta no demuestra que la tarea no se haya creado: una clave nueva convierte un resultado desconocido en una segunda tarea de pago. Consulta Idempotencia.
Una tarea que sale bien se cobra, aunque el resultado te decepcione. Cotiza primero cuando el precio importe; quote_task no retiene nada y no crea nada.
Lo que este paquete no hace
- Modelos de texto. Hablan los formatos de OpenAI, Anthropic y Gemini, así que las bibliotecas oficiales
openai,anthropicygoogle-genaiya funcionan: apúntalas ahttps://api.spicyapi.ai/v1con la misma clave. Consulta Texto y streaming. - Aplicaciones de navegador, móviles y de escritorio. No metas nunca esta clave dentro de una aplicación: una clave compilada en un cliente es una clave pública. Llama desde tu servidor.
- Elegir un modelo o rellenar sus campos. Te entrega el catálogo y el esquema de cada modelo; tú decides qué enviar.
- Cancelar una tarea. Cuando una tarea se acepta, se ejecuta hasta el final. Detener tu programa solo detiene tu espera.
Código fuente
El paquete tiene licencia MIT y se desarrolla en abierto en github.com/spicyapi-ai/spicy-python. Su README es el recorrido completo más corto por el cliente; esta página añade los conceptos que lo rodean.
Siguientes pasos
Catálogo de modelos y esquemas
Cómo leer el inputSchema de un modelo y elegir entradas válidas
Tareas asíncronas
Estados de las tareas, sondeo y qué significa cada campo
Cotizaciones y compatibilidad
Consulta el precio exacto de una solicitud antes de pagarlo
Webhooks
Formato de las entregas, calendario de reintentos y verificación de la firma
Errores
Todos los códigos de error y cuáles vale la pena reintentar
SDK de Go
El mismo flujo desde Go, solo con la biblioteca estándar
SDK de TypeScript
Guía paso a paso del SDK de TypeScript @spicyapi/sdk para instalarlo, conseguir tu primer resultado y consultar cada método, opción y error explicados con palabras sencillas. Los SDK de Python, Go, PHP y Java tienen cada uno su propia página.
SDK de Go
El SDK oficial de Go para SpicyAPI (github.com/spicyapi-ai/spicy-go) — instálalo, cotiza y lanza tu primera generación, sube un archivo local, recorre tu historial de tareas y trata todos los códigos de error.

