PicassoIA Video utilise l'identifiant de modèle picassoia/picassoia-video. Texte et image vers vidéo avec audio, des clips de 1 à 20 secondes et une sortie en 480p, 720p ou 1080p.
Appeler l'API
Envoyez vos requêtes à https://api.picassoia.com/v1/models/picassoia/picassoia-video/predictions avec un corps JSON dont l'objet input correspond aux paramètres ci-dessous.
Configuration
Gardez votre API key sur votre serveur, dans une variable d'environnement, et envoyez-la dans l'en-tête Authorization de chaque requête.
export PICASSOIA_API_KEY="pia_sk_…"Paramètres de la Requête
promptstringObligatoire- Par DéfautAucun
- Ce que la sortie doit montrer. Jusqu'à 4000 caractères.
imagestring- Par DéfautAucun
- L'image de départ, ou l'image sur laquelle travailler. Une image PNG, JPEG ou WebP, sous forme d'URL https publique ou d'URL de données de 5 Mo maximum.
resolutionstring- Par Défaut
"480p" - La taille de la sortie. Options : 480p, 720p et 1080p.
durationinteger- Par Défaut
5 - La durée du clip, en secondes. De 1 à 20. Jusqu'à 20 en 480p. Jusqu'à 10 en 720p. Jusqu'à 5 en 1080p.
aspect_ratiostring- Par Défaut
"match_input_image" / "16:9" - La forme de la sortie. Quand match_input_image est proposé, il conserve les proportions de l'image d'entrée, ou de la première s'il y en a plusieurs. Options : match_input_image, 1:1, 16:9, 9:16, 4:3, 3:4, 3:2 et 2:3. Si vous ne l'envoyez pas : match_input_image quand image est envoyé, 16:9 sinon.
save_audioboolean- Par Défaut
true - Conserve la piste audio générée.
seedinteger- Par DéfautAucun
- Définissez-la pour reproduire un résultat ; omettez-la pour un résultat aléatoire.
enhance_promptboolean- Par Défaut
true - Picasso IA réécrit votre prompt pour un meilleur résultat. Votre prompt d'origine reste dans l'entrée.
Modes
Le mode dépend des fichiers que vous envoyez avec le prompt, le cas échéant. Tous les modes utilisent le même point de terminaison.
Exemple de Requête
Texte vers Vidéo
curl -s -X POST https://api.picassoia.com/v1/models/picassoia/picassoia-video/predictions \
-H "Authorization: Bearer $PICASSOIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input":{"prompt":"waves crashing on a rocky shore at night, cinematic"}}'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))
const input = {
prompt: "waves crashing on a rocky shore at night, cinematic"
}
const created = await fetch(`${API}/models/picassoia/picassoia-video/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)
console.log(prediction.output)import os, time, requests
API = "https://api.picassoia.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['PICASSOIA_API_KEY']}"}
payload = {"input": {
"prompt": "waves crashing on a rocky shore at night, cinematic",
}}
response = requests.post(f"{API}/models/picassoia/picassoia-video/predictions", json=payload, 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"])
print(prediction["output"])Image vers Vidéo
curl -s -X POST https://api.picassoia.com/v1/models/picassoia/picassoia-video/predictions \
-H "Authorization: Bearer $PICASSOIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input":{"prompt":"the camera slowly pushes in as the subject turns to smile","image":"https://example.com/portrait.jpg"}}'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))
const input = {
prompt: "the camera slowly pushes in as the subject turns to smile",
image: "https://example.com/portrait.jpg"
}
const created = await fetch(`${API}/models/picassoia/picassoia-video/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)
console.log(prediction.output)import os, time, requests
API = "https://api.picassoia.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['PICASSOIA_API_KEY']}"}
payload = {"input": {
"prompt": "the camera slowly pushes in as the subject turns to smile",
"image": "https://example.com/portrait.jpg",
}}
response = requests.post(f"{API}/models/picassoia/picassoia-video/predictions", json=payload, 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"])
print(prediction["output"])Authentification
Chaque requête doit comporter une API key dans l'en-tête Authorization, sous forme de jeton Bearer. Créez vos clés dans votre compte ; la clé complète n'est affichée qu'une seule fois.
Authorization: Bearer $PICASSOIA_API_KEYFile d'Attente et Interrogation
Chaque prédiction se déroule en trois étapes : la créer, l'interroger jusqu'à ce qu'elle soit terminée, puis lire le résultat.
Envoi
L'API répond 201, généralement en quelques secondes, avec la prédiction à l'état starting, une estimation dans eta et l'URL à interroger dans urls.get. Si la prédiction échoue immédiatement, par exemple quand le filtre de sécurité refuse l'entrée, la réponse reste 201, avec la prédiction à l'état failed et son champ error.
curl -s -X POST https://api.picassoia.com/v1/models/picassoia/picassoia-video/predictions \
-H "Authorization: Bearer $PICASSOIA_API_KEY" \
-H "Content-Type: application/json" \
-d '{"input":{"prompt":"waves crashing on a rocky shore at night, cinematic"}}'const API = 'https://api.picassoia.com/v1'
const headers = {
Authorization: `Bearer ${process.env.PICASSOIA_API_KEY}`,
'Content-Type': 'application/json',
}
const input = {
prompt: "waves crashing on a rocky shore at night, cinematic"
}
const created = await fetch(`${API}/models/picassoia/picassoia-video/predictions`, {
method: 'POST',
headers,
body: JSON.stringify({ input }),
})
let prediction = await created.json()
if (!created.ok) throw new Error(`${prediction.code}: ${prediction.detail}`)
console.log(prediction.id, prediction.status) // api_…, startingimport os, requests
API = "https://api.picassoia.com/v1"
HEADERS = {"Authorization": f"Bearer {os.environ['PICASSOIA_API_KEY']}"}
payload = {"input": {
"prompt": "waves crashing on a rocky shore at night, cinematic",
}}
response = requests.post(f"{API}/models/picassoia/picassoia-video/predictions", json=payload, headers=HEADERS)
prediction = response.json()
if not response.ok:
raise RuntimeError(f"{prediction['code']}: {prediction['detail']}")
print(prediction["id"], prediction["status"]) # api_…, starting{
"id": "api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60",
"model": "picassoia/picassoia-video",
"input": {
"prompt": "waves crashing on a rocky shore at night, cinematic",
"resolution": "480p",
"duration": 5,
"aspect_ratio": "16:9",
"save_audio": true,
"enhance_prompt": true
},
"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": 60,
"next_poll_in_seconds": 30
}
}Interrogation
Interrogez de nouveau urls.get après eta.next_poll_in_seconds : à la moitié du temps estimé, lorsque le temps estimé est atteint, puis toutes les 2 secondes.
# Repeat after eta.next_poll_in_seconds until status is
# succeeded, failed or canceled.
curl -s https://api.picassoia.com/v1/predictions/api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60 \
-H "Authorization: Bearer $PICASSOIA_API_KEY"const sleep = (s) => new Promise((resolve) => setTimeout(resolve, s * 1000))
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()
}import time
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(){
"id": "api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60",
"status": "processing",
"output": null,
"eta": {
"seconds": 30,
"next_poll_in_seconds": 30
}
}Résultat
Quand status vaut succeeded, output contient le résultat. Une prédiction échouée indique sa raison dans error, et une prédiction annulée a été arrêtée avant la fin. Ces trois états sont définitifs.
# The last poll holds the result: "output" when "status" is succeeded,
# "error" when it is failed. With jq, just those three fields:
curl -s https://api.picassoia.com/v1/predictions/api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60 \
-H "Authorization: Bearer $PICASSOIA_API_KEY" | jq '.status, .output, .error'if (prediction.status !== 'succeeded') throw new Error(prediction.error ?? prediction.status)
console.log(prediction.output)if prediction["status"] != "succeeded":
raise RuntimeError(prediction["error"] or prediction["status"])
print(prediction["output"]){
"id": "api_3f9c2b7e8d1a4c6f9e0b1a2c3d4e5f60",
"status": "succeeded",
"output": "https://…/output.mp4",
"error": null,
"completed_at": "2026-10-01T09:30:54.000Z",
"metrics": {
"predict_time": 52.8
},
"eta": null
}Annulation
POST urls.cancel arrête une prédiction encore en file d'attente (tout modèle) ou une image encore en cours de génération ; pour une vidéo déjà en cours de génération, la réponse est 409 not_cancelable.
Les identifiants, horodatages et URL de ces réponses sont des exemples : les vôtres auront leurs propres valeurs.
Sortie
Quand la prédiction réussit, output est l'URL d'une vidéo MP4.
Résultats Réels
Erreurs et Limites
Les erreurs sont des « problem details » JSON avec un code stable, et une erreur 422 nomme chaque champ en cause.
{
"title": "Input validation failed",
"status": 422,
"code": "invalid_input",
"detail": "input.duration: At 1080p the longest clip is 5 seconds.",
"invalid_fields": [
{
"type": "invalid_value",
"field": "input.duration",
"description": "At 1080p the longest clip is 5 seconds."
}
]
}Limites
- 5 prédictions en file d'attente ou en cours d'exécution à la fois par compte
- Corps de requête jusqu'à 10 Mo ; images en URL de données jusqu'à 5 Mo chacune
- Prompt jusqu'à 4000 caractères
- Les champs inconnus sont refusés avec 422 invalid_input
Tarifs
$0 par requête avec un forfait Infinite actif : les prédictions de l'API ne consomment aucun crédit, quels que soient les paramètres.
D'autres fournisseurs facturent à partir de $0.06/s pour un modèle comparable (au 1er octobre 2026).
Tarifs de l'APIJSON Schema
Le même schéma que celui que l'API renvoie via GET /v1/models/picassoia/picassoia-video.
{
"input_schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "object",
"properties": {
"prompt": {
"type": "string",
"minLength": 1,
"maxLength": 4000,
"description": "What happens in the video."
},
"image": {
"type": "string",
"description": "Opening frame (image-to-video): an https URL or a data URL."
},
"resolution": {
"default": "480p",
"description": "480p (up to 20 s), 720p (up to 10 s) or 1080p (up to 5 s).",
"type": "string",
"enum": [
"480p",
"720p",
"1080p"
]
},
"duration": {
"default": 5,
"description": "Length in seconds. The longest clip depends on the resolution.",
"type": "integer",
"minimum": 1,
"maximum": 20
},
"aspect_ratio": {
"description": "Default: match_input_image when there is an image, 16:9 without one.",
"type": "string",
"enum": [
"match_input_image",
"1:1",
"16:9",
"9:16",
"4:3",
"3:4",
"3:2",
"2:3"
]
},
"save_audio": {
"default": true,
"description": "Keep the generated audio track.",
"type": "boolean"
},
"seed": {
"description": "Random seed. Set it to reproduce a result.",
"type": "integer",
"minimum": -9007199254740991,
"maximum": 9007199254740991
},
"enhance_prompt": {
"default": true,
"description": "Let PicassoIA rewrite the prompt for a better video before generating it.",
"type": "boolean"
}
},
"required": [
"prompt"
],
"additionalProperties": false
},
"output_schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"type": "string",
"format": "uri",
"description": "URL of the generated video (MP4)."
}
}