La API de PicassoIA te permite ejecutar los modelos de imagen y vídeo de PicassoIA desde tu propio código:
- Creas una predicción para un modelo.
- Consultas la predicción periódicamente hasta que termina.
- Lees las URL de salida.
- URL base:
https://api.picassoia.com/v1 - Formato: peticiones y respuestas en JSON, UTF-8.
- Precio: por ahora, las predicciones de la API son gratuitas. No consumen créditos.
- Quién puede usarla: las cuentas con el plan Infinite.
Contenido
- Autenticación
- Inicio rápido
- Modelos
- Endpoints
- El objeto de predicción
- Sondeo y ETA
- Cancelación
- Errores
- Límites
Autenticación
Cada petición necesita una API key en la cabecera Authorization:
Authorization: Bearer pia_sk_…- Crear una API key. Crea tus API keys en picassoia.com, en la sección API keys de tu cuenta.
- La API key completa se muestra una sola vez, al crearla. Guárdala en un lugar seguro.
- Una cuenta puede tener 2 API keys a la vez. Para hacer sitio, revoca una.
- Revocar una API key. Una API key revocada deja de funcionar al instante.
- Usa las API keys solo en el servidor. Cualquiera que tenga una API key puede ejecutar predicciones con tu cuenta, así que nunca la incluyas en una página web ni en una app móvil. La API no envía cabeceras CORS, por lo que los navegadores no pueden llamarla directamente.
- Cambios de plan. Tus API keys se conservan aunque cambie tu plan. Sin un plan Infinite, al crear una predicción la respuesta es
403 plan_required. Podrás seguir consultando, listando y cancelando tus predicciones.
Inicio rápido
1. Crea una predicción:
curl -s -X POST https://api.picassoia.com/v1/models/picassoia/picassoia-image/predictions \
-H "Authorization: Bearer $PICASSOIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input": {"prompt": "a lighthouse at sunset, oil painting", "aspect_ratio": "16:9"}}'La respuesta (201 Created) es una predicción en el estado starting:
{
"id": "api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60",
"model": "picassoia/picassoia-image",
"input": {
"prompt": "a lighthouse at sunset, oil painting",
"aspect_ratio": "16:9",
"num_outputs": 1,
"output_format": "jpg",
"output_quality": 80
},
"output": null,
"error": null,
"status": "starting",
"created_at": "2026-10-01T09:30:00.000Z",
"started_at": null,
"completed_at": null,
"metrics": { "predict_time": null },
"urls": {
"get": "https://api.picassoia.com/v1/predictions/api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60",
"cancel": "https://api.picassoia.com/v1/predictions/api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60/cancel"
},
"eta": { "seconds": 12, "next_poll_in_seconds": 6 }
}2. Consúltala periódicamente (espera eta.next_poll_in_seconds entre llamadas) hasta que status sea succeeded, failed o canceled:
curl -s https://api.picassoia.com/v1/predictions/api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60 \
-H "Authorization: Bearer $PICASSOIA_API_KEY"3. Lee la salida:
{
"id": "api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60",
"status": "succeeded",
"output": ["https://…/lighthouse.jpg"],
"metrics": { "predict_time": 6.4 },
"eta": null
}(Aquí se omiten los demás campos.)
Node.js (fetch)
const API = 'https://api.picassoia.com/v1'
const headers = {
Authorization: `Bearer ${process.env.PICASSOIA_API_KEY}`,
'Content-Type': 'application/json',
}
const sleep = (s) => new Promise((resolve) => setTimeout(resolve, s * 1000))
async function run(model, input) {
const created = await fetch(`${API}/models/${model}/predictions`, {
method: 'POST',
headers,
body: JSON.stringify({ input }),
})
let prediction = await created.json()
if (!created.ok) throw new Error(`${prediction.code}: ${prediction.detail}`)
while (!['succeeded', 'failed', 'canceled'].includes(prediction.status)) {
await sleep(prediction.eta?.next_poll_in_seconds ?? 2)
prediction = await (await fetch(prediction.urls.get, { headers })).json()
}
if (prediction.status !== 'succeeded') throw new Error(prediction.error ?? prediction.status)
return prediction.output
}
const video = await run('picassoia/seedance-2.5-lite', {
prompt: 'a paper boat sailing down a rainy street',
duration: 5,
})
console.log(video) // "https://…/video.mp4"Python (requests)
import os, time, requests
API = "https://api.picassoia.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['PICASSOIA_API_KEY']}"}
def run(model, input):
response = requests.post(f"{API}/models/{model}/predictions", json={"input": input}, headers=HEADERS)
prediction = response.json()
if not response.ok:
raise RuntimeError(f"{prediction['code']}: {prediction['detail']}")
while prediction["status"] not in ("succeeded", "failed", "canceled"):
time.sleep((prediction.get("eta") or {}).get("next_poll_in_seconds", 2))
prediction = requests.get(prediction["urls"]["get"], headers=HEADERS).json()
if prediction["status"] != "succeeded":
raise RuntimeError(prediction["error"] or prediction["status"])
return prediction["output"]
images = run("picassoia/picassoia-image-editor-pro", {
"prompt": "put the cat from image 1 on the sofa from image 2",
"images": ["https://example.com/cat.png", "https://example.com/sofa.jpg"],
})
print(images) # ["https://…/result.webp"]Modelos
El esquema exacto de cada modelo también se sirve como JSON Schema: GET /v1/models/{owner}/{name} devuelve input_schema (con todos los campos, sus límites y sus valores por defecto) y output_schema.
Imágenes como entrada. Los campos de imagen aceptan cualquiera de estos dos tipos de valor:
- una URL https accesible públicamente;
- una data URL:
data:image/png;base64,…, tambiénimage/jpegoimage/webp, de hasta 5 MB cada una.
Las imágenes deben ser PNG, JPEG o WebP. PicassoIA guarda su propia copia de cada una, así que el input de la predicción muestra la URL de esa copia. Usa URL para cualquier imagen de más de unos cientos de KB: el cuerpo completo de la petición está limitado a 10 MB.
Los campos desconocidos se rechazan, para que una errata no acabe usando en silencio un valor por defecto. La respuesta es 422 invalid_input.
picassoia/picassoia-image
Salida: una lista de 1 o 2 URL de imágenes.
picassoia/picassoia-image-editor-pro
Salida: una lista de 1 o 2 URL de imágenes.
picassoia/picassoia-video
Salida: una URL de MP4 (una cadena).
picassoia/seedance-2.5-lite
Salida: una URL de MP4 (una cadena).
Endpoints
Modelo
{
"id": "picassoia/seedance-2.5-lite",
"owner": "picassoia",
"name": "seedance-2.5-lite",
"title": "Seedance 2.5 Lite",
"description": "Text or image to video with synchronized audio: …",
"input_schema": { "type": "object", "properties": { "…": {} }, "required": ["prompt"], "additionalProperties": false },
"output_schema": { "type": "string", "format": "uri" }
}Crear una predicción
POST /v1/models/{owner}/{name}/predictions con el cuerpo { "input": { … } }.
- La API responde en cuanto el modelo acepta el trabajo, normalmente en pocos segundos, con la predicción en el estado
starting. Nunca espera al resultado. - Si la predicción falla de inmediato, la respuesta sigue siendo
201, con la predicción en el estadofailedy suerror. Esto ocurre, por ejemplo, cuando el filtro de seguridad rechaza la entrada. - Si no se ha creado ninguna predicción, la respuesta es un error: entrada no válida, plan insuficiente, demasiadas predicciones en curso, servicio no disponible.
Listar predicciones
GET /v1/predictions devuelve tus predicciones de la API, 50 por página, de la más reciente a la más antigua, incluidas las de todas tus API keys.
nextes la URL de la página siguiente (…/v1/predictions?cursor=…), onullen la última página.previoussiempre esnull.- Las predicciones que hayas eliminado en picassoia.com no aparecen.
Una predicción es visible desde cualquiera de tus API keys, y nunca para nadie más.
El objeto de predicción
Estados.
La distinción entre starting y processing es una estimación, calculada a partir de la posición en la cola en el momento de la creación. Una predicción nueva siempre está en starting. Los tres últimos estados son definitivos: una predicción que está en uno de ellos ya no vuelve a cambiar.
Errores de una predicción fallida. El error de una predicción fallida es uno de estos mensajes:
- El filtro de seguridad ha rechazado la entrada o la salida. El mensaje termina en
(SAFETY_CHECKER_PICASSO_FILTER_S4). The prediction failed. You can try again.The prediction timed out. You can try again.La predicción no terminó en un plazo de 3 horas.
Salidas. Las URL de salida están alojadas en PicassoIA. Descarga los archivos que quieras conservar.
Sondeo y ETA
eta.next_poll_in_seconds te indica cuándo merece la pena hacer la siguiente consulta:
- A la mitad del tiempo estimado.
- Cuando se alcanza el tiempo estimado.
- Después, cada 2 segundos.
Ejemplo con una estimación de 10 s: consulta a los 5 s, luego a los 10 s y, a partir de ahí, cada 2 s. Consultar con más frecuencia no te dará el resultado antes.
Cancelación
POST /v1/predictions/{id}/cancel:
Una predicción cancelada libera al instante su plaza entre tus 5 predicciones en curso.
Errores
Los errores se devuelven como problem details en JSON, con un code estable añadido para uso programático:
{
"title": "Too many predictions in progress",
"detail": "This account can have up to 5 predictions queued or running at once, shared by its API keys and MCP connections, and 5 are. Wait for one to finish and try again.",
"status": 429,
"code": "concurrency_limit",
"retry_after": 10,
"limit": 5,
"running": 5
}invalid_fields. Una respuesta 422 enumera todos los campos con errores:
{
"title": "Input validation failed",
"status": 422,
"code": "invalid_input",
"detail": "input.duration: At 720p the longest clip is 10 seconds.",
"invalid_fields": [
{ "type": "invalid_value", "field": "input.duration", "description": "At 720p the longest clip is 10 seconds." }
]
}