HappyHorse 1.1 API

alibaba/happyhorse-1.1/text-to-videoDa 105 crediti per una clip di 5 secondi· Crea video

HappyHorse 1.1 è una famiglia video di Alibaba con tre endpoint: text-to-video, image-to-video e reference-to-video, che accetta fino a nove immagini di riferimento. I clip durano da 3 a 15 secondi interi a 720p o 1080p, in nove proporzioni tra cui 4:5, 5:4, 21:9 e 9:21.

Lo chiami con il nome di modello alibaba/happyhorse-1.1/text-to-video su POST /jobs/createTask, da 105 crediti per una clip di 5 secondi (1,05 USD). I nuovi account ricevono 30 crediti gratuiti per provarlo prima nel Playground.

  • Crea video
  • Da immagine a video
  • Da riferimenti a video
  • Fino a 1080p
  • Clip da 3 a 15 s
  • Fino a 9 immagini di riferimento
  • 9 formati
Nome del modelloalibaba/happyhorse-1.1/text-to-video
EndpointPOST https://api.popnow.ai/api/v1/jobs/createTask
# 1. Create the task. Keep the Idempotency-Key if you retry after a network error.
export IDEMPOTENCY_KEY="$(uuidgen)"
curl -X POST https://api.popnow.ai/api/v1/jobs/createTask \
  -H "Authorization: Bearer $POPNOW_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: $IDEMPOTENCY_KEY" \
  -d '{
  "model": "alibaba/happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "A slow aerial shot drifting over a misty pine forest at sunrise",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration_seconds": 5
  }
}'

# 2. Copy data.taskId from the response, then poll until state is succeeded, failed, canceled or expired.
TASK_ID="TASK_ID_FROM_RESPONSE"
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
  -H "Authorization: Bearer $POPNOW_API_KEY"

L’input è costruito dallo schema qui sotto, quindi supera la verifica così com’è. Sostituisci prompt e link con i tuoi.

Prezzo

OpzioneCrediti al secondo≈ USD
resolution 720p210,21 USD
resolution 1080p270,27 USD

1 credito = 0,01 $ · Tutte le opzioni e i prezzi: GET /models/alibaba/happyhorse-1.1/text-to-video

Limiti

Durata della clip
3–15 s
Risoluzioni
720p · 1080p
Proporzioni
16:9 · 9:16 · 1:1 · 4:3 · 3:4 · 4:5 +3
Lunghezza del prompt (caratteri)
2,500

Parametri

Questi campi vengono dallo stesso schema con cui verifichiamo ogni richiesta. I campi non elencati vengono rifiutati.

  • promptstringObbligatorio

    Describe the scene, action, camera movement, and timing.

    Intervallo
    1 – 2500 chars
  • aspect_ratiostringFacoltativo

    La forma dell'inquadratura: larga, quadrata o verticale.

    Predefinito
    "16:9"
    Valori ammessi
    "16:9""9:16""1:1""4:3""3:4""4:5""5:4""9:21""21:9"
  • resolutionstringFacoltativoCambia il prezzo

    Dimensione dell'output. Più grande è più nitido e costa di più.

    Predefinito
    "720p"
    Valori ammessi
    "720p""1080p"
  • duration_secondsintegerFacoltativoCambia il prezzo

    Quanto dura la clip. Si paga al secondo.

    Predefinito
    5
    Intervallo
    3 – 15
JSON Schema grezzo
{
  "type": "object",
  "required": [
    "prompt"
  ],
  "properties": {
    "prompt": {
      "type": "string",
      "maxLength": 2500,
      "minLength": 1,
      "description": "Describe the scene, action, camera movement, and timing."
    },
    "resolution": {
      "enum": [
        "720p",
        "1080p"
      ],
      "type": "string",
      "default": "720p",
      "description": "Output video resolution."
    },
    "aspect_ratio": {
      "enum": [
        "16:9",
        "9:16",
        "1:1",
        "4:3",
        "3:4",
        "4:5",
        "5:4",
        "9:21",
        "21:9"
      ],
      "type": "string",
      "default": "16:9",
      "description": "Output aspect ratio."
    },
    "duration_seconds": {
      "type": "integer",
      "default": 5,
      "maximum": 15,
      "minimum": 3,
      "description": "Output duration in seconds. Any integer from 3 to 15 is accepted; longer clips cost proportionally more."
    }
  },
  "additionalProperties": false
}

Un risultato reale di HappyHorse 1.1

PromptThe giant hand gently sets the orange jelly building down into the candy city block, the jelly wobbles as it lands, tiny jelly buses roll along the streets and the lilac fountain bubbles; tilt-shift miniature look, slow camera drift, no text.
La stessa richiesta tramite API
{
  "model": "alibaba/happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "The giant hand gently sets the orange jelly building down into the candy city block, the jelly wobbles as it lands, tiny jelly buses roll along the streets and the lilac fountain bubbles; tilt-shift miniature look, slow camera drift, no text.",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration_seconds": 5
  }
}

Risposte, polling e callback

Tutti i modelli funzionano allo stesso modo: crei un task, poi lo interroghi o aspetti la callback.

Prima il prezzo

cURL
curl -X POST https://api.popnow.ai/api/v1/jobs/quote \
  -H "Authorization: Bearer $POPNOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
  "model": "alibaba/happyhorse-1.1/text-to-video",
  "input": {
    "prompt": "A slow aerial shot drifting over a misty pine forest at sunrise",
    "aspect_ratio": "16:9",
    "resolution": "720p",
    "duration_seconds": 5
  }
}'

Stesso corpo di createTask. Restituisce l’addebito previsto e quello massimo possibile, senza eseguire nulla.

Accettata

HTTP
HTTP/1.1 202 Accepted

{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "task_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "state": "queued"
  },
  "request_id": "req_example_create"
}

HTTP 202 significa che il task è stato accettato e i crediti sono riservati, non ancora addebitati. L’addebito finale non supera mai la riserva.

Controlla lo stato

cURL
curl "https://api.popnow.ai/api/v1/jobs/recordInfo?taskId=$TASK_ID" \
  -H "Authorization: Bearer $POPNOW_API_KEY"

Controlla ogni pochi secondi allungando via via l’intervallo e fermati quando state è succeeded, failed, canceled o expired.

Task completato

JSON
{
  "code": 200,
  "msg": "success",
  "data": {
    "taskId": "task_01k3m8x9q2z4v7n5p6r8s0t1w3",
    "model": "alibaba/happyhorse-1.1/text-to-video",
    "state": "succeeded",
    "output": {
      "assets": [
        {
          "url": "https://cdn.popnow.ai/tasks/task_01k3m8x9q2z4v7n5p6r8s0t1w3/output.mp4?signature=FROM_RESPONSE",
          "expiresAt": "2026-10-17T12:20:00Z",
          "mime": "video/mp4",
          "width": 1280,
          "height": 720,
          "durationSeconds": 5
        }
      ]
    },
    "settled": true
  },
  "request_id": "req_example_record"
}

Scarica dall’url prima di expiresAt. Ti serve un link nuovo più tardi? Chiedilo con POST /common/download-url.

Verifica una callback

Node.js
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
import express from "express";

const app = express();
// express.raw keeps the exact bytes that were signed; express.json would not match.
app.post("/hooks/popnow", express.raw({ type: "application/json" }), (req, res) => {
  const timestamp = req.header("X-Webhook-Timestamp");
  const signature = req.header("X-Webhook-Signature") ?? "";
  const body = JSON.parse(req.body.toString("utf8"));
  const taskId = body.data?.taskId ?? body.task_id;
  const digest = createHash("sha256").update(req.body).digest("hex");
  const expected = createHmac("sha256", process.env.POPNOW_WEBHOOK_SECRET)
    .update(`${taskId}.${timestamp}.${digest}`)
    .digest("base64");
  const ok = expected.length === signature.length && timingSafeEqual(Buffer.from(expected), Buffer.from(signature));
  // Check the signature first, then reject anything older than five minutes.
  if (!ok || Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return res.status(401).end();
  res.status(200).end(); // answer fast, then fetch the task and store its files
});

Con callBackUrl impostata ti inviamo il task completato. Verifica la firma sul corpo grezzo prima di fidarti.

Invia un file locale

cURL
curl -X POST https://api.popnow.ai/api/v1/common/upload-url \
  -H "Authorization: Bearer $POPNOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"contentType": "image/png", "bytes": 482113}'

# PUT the file bytes to data.uploadUrl with every header in data.headers, then commit it:
curl -X POST https://api.popnow.ai/api/v1/files/$FILE_ID/commit \
  -H "Authorization: Bearer $POPNOW_API_KEY"
# The commit returns a popnow://f/... reference. Put it in any image, video or
# audio field of the task input instead of a public https URL.

I link https pubblici funzionano così come sono. I file locali passano prima da upload-url e commit.