DEV Community

Cover image for How to Build an Async Text-to-Video Workflow with a REST API
Germey
Germey

Posted on Originally published at platform.acedata.cloud

How to Build an Async Text-to-Video Workflow with a REST API

Video generation is easy to demo and surprisingly easy to make unreliable: a browser request waits too long, the user refreshes, and the app loses track of the generated file.

This guide shows a practical way to integrate the Hailuo Videos Generation API as an asynchronous workflow. The goal is not just to send a prompt, but to keep enough state to connect a request, a callback, and the final video_url inside your own product.

What you can do

The documented endpoint is:

  • Base URL: https://api.acedata.cloud
  • Endpoint: POST /hailuo/videos
  • Headers: accept: application/json, authorization: Bearer {token}, and content-type: application/json
  • Action: generate
  • Models: minimax-t2v for text-to-video and minimax-i2v for image-to-video

The main request fields are action, model, prompt, first_image_url, callback_url, and async. The first_image_url field is required when using minimax-i2v, and the documentation notes that Base64 is not supported for that field.

Start with a text-to-video request

For a local test, begin with the same endpoint and a minimal JSON body.

curl -X POST 'https://api.acedata.cloud/hailuo/videos' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "action": "generate",
    "model": "minimax-t2v",
    "prompt": "A quiet city street after rain, reflections on the pavement, slow cinematic camera movement"
  }'
Enter fullscreen mode Exit fullscreen mode

A successful response includes success, task_id, trace_id, and a data array. Each item can include id, model, prompt, video_url, and state.

{
  "success": true,
  "task_id": "baf1034c-684c-46be-ae6d-89ebb89b690d",
  "trace_id": "3221eb74-1a25-447a-ba69-7d9b310e306c",
  "data": [
    {
      "id": "0pv8yhe4fdrge0cmckpv23pd2g",
      "model": "minimax-t2v",
      "prompt": "Internal heat",
      "video_url": "https://platform.cdn.acedata.cloud/.../output.mp4",
      "state": "succeeded"
    }
  ]
}
Enter fullscreen mode Exit fullscreen mode

For an app, store at least task_id, trace_id, prompt, model, state, and video_url.

Add image-to-video without changing your pipeline

The image-to-video path uses the same endpoint and action, but switches the model to minimax-i2v and adds first_image_url.

{
  "action": "generate",
  "model": "minimax-i2v",
  "first_image_url": "https://example.com/first-frame.png",
  "prompt": "Animate the scene with a slow forward camera move and soft natural motion"
}
Enter fullscreen mode Exit fullscreen mode

Because Base64 is not supported for first_image_url, your app should upload the first frame to object storage or another public URL before calling the API. Keeping both modes in the same video_jobs table is usually cleaner than building two systems.

Use callbacks for production-style requests

Video generation may take around 1–2 minutes. Holding a client HTTP request open for that long is fragile, so the API supports asynchronous callbacks through callback_url.

curl -X POST 'https://api.acedata.cloud/hailuo/videos' \
  -H 'accept: application/json' \
  -H 'authorization: Bearer {token}' \
  -H 'content-type: application/json' \
  -d '{
    "action": "generate",
    "model": "minimax-t2v",
    "prompt": "A product prototype floating above a dark desk, subtle light sweep, cinematic 6 second loop",
    "callback_url": "https://example.com/webhooks/hailuo"
  }'
Enter fullscreen mode Exit fullscreen mode

With callback_url, the API immediately returns a JSON object containing task_id. Later, your webhook receives a POST JSON payload containing the same task_id, plus fields such as success, trace_id, data[].id, data[].model, data[].prompt, data[].video_url, and data[].state.

A simple webhook handler can look up the local job by task_id, store trace_id, state, and video_url, then mark the job as finished when state is succeeded.

Handle errors deliberately

The documented error response includes success: false, an error object, and trace_id.

{
  "success": false,
  "error": {
    "code": "api_error",
    "message": "fetch failed"
  },
  "trace_id": "2cf86e86-22a4-46e1-ac2f-032c0f2a4e89"
}
Enter fullscreen mode Exit fullscreen mode

Common codes include invalid_token, too_many_requests, token_mismatched, api_not_implemented, and api_error. Log the full error object with trace_id, but show a short message in the UI. If you retry, create a new local attempt record so you can tell which task_id produced which callback.

A practical integration shape

A minimal database table might look like this:

video_jobs
- id
- task_id
- trace_id
- model
- prompt
- first_image_url
- callback_url
- state
- video_url
- created_at
- finished_at
Enter fullscreen mode Exit fullscreen mode

The key idea is simple: treat video generation as a job, not a one-off request. Submit the prompt, store the returned task_id, and let the callback update the final video_url when it arrives.

If you want the full field reference and original examples, read the Hailuo Videos Generation API documentation: https://platform.acedata.cloud/documents/hailuo-videos-generation-integration

Top comments (0)