VisionStory OpenAPI
Get API key

Generate your first talking-avatar video in five steps. The whole flow is: get a key, set up a client, submit a script, poll, download.

1. Get your API key

Sign up and create an API key at visionstory.ai/openapi (available on Pro plans and up). Send it with every request in the X-API-Key header:

X-API-Key: sk-vs-xxxxxxxxxxxxxxxxxxx

Keep the key on your server and never expose it in browser code or a public repository. The examples below read it from an environment variable:

export VISIONSTORY_API_KEY="sk-vs-xxxxxxxxxxxxxxxxxxx"

2. Set up your client

Call the REST API with curl or any HTTP client. The full script below uses requests; SDK, CLI, MCP, and Agent Skill documentation is maintained in the VisionStory developer portal.

3. Create your first video

Submit a text script with a public avatar and a public voice. The request returns a video_id immediately — generation happens asynchronously:

curl -s -H "X-API-Key: $VISIONSTORY_API_KEY" -H "Content-Type: application/json" -d '{"model_id": "vs_character_v4", "avatar_id": "4321918387609092991", "text_script": {"text": "Hello World, this is my first test video.", "voice_id": "Alice", "speech_rate": "normal"}, "aspect_ratio": "9:16", "resolution": "720p"}' https://openapi.visionstory.ai/api/v1/video
{
  "data": {
    "video_id": "7241059991822401536"
  }
}

Before building a production integration, discover current IDs instead of hardcoding them: GET /api/v1/models, GET /api/v1/avatars, and GET /api/v1/voices. To use your own audio instead of text, send an audio_script (with audio_url or base64 inline_data) in place of text_script — never both.

4. Poll until the video is ready

Query the task every 5 seconds until it reaches a final state:

curl -s -H "X-API-Key: $VISIONSTORY_API_KEY" "https://openapi.visionstory.ai/api/v1/video?video_id=7241059991822401536"
status Meaning
queued Accepted, waiting for a worker
creating Generating
created Done — video_url is ready
failed Generation failed — stop polling and inspect the error

Avoid polling faster than every 5 seconds, and give up after about 10 minutes.

5. Download the result

When the status is created, the response carries a video_url. Completed videos are retained for 7 days — download the file if you need permanent storage:

curl -sL -o result.mp4 "<video_url from the response>"

Full script

The same five steps with requests:

import requests
import time
import os

headers = {"X-API-Key": os.environ["VISIONSTORY_API_KEY"]}

# Submit the video generation task
payload = {
    "model_id": "vs_character_v4",
    "avatar_id": "4321918387609092991",
    "text_script": {
        "text": "Hello World, this is my first test video.",
        "voice_id": "Alice",  # select voice_id from GET /api/v1/voices
        "speech_rate": "normal"
    },
    "aspect_ratio": "9:16",
    "resolution": "720p"
}
response = requests.post("https://openapi.visionstory.ai/api/v1/video", json=payload, headers=headers)
response.raise_for_status()
video_id = response.json()["data"]["video_id"]

# Poll every 5 seconds until the task finishes (10 minute timeout)
video_data = None
for _ in range(120):
    time.sleep(5)
    response = requests.get("https://openapi.visionstory.ai/api/v1/video", params={"video_id": video_id}, headers=headers)
    response.raise_for_status()
    data = response.json()["data"]
    if data["status"] == "created":
        video_data = data
        break
    if data["status"] == "failed":
        raise RuntimeError(f"Video {video_id} generation failed")
if video_data is None:
    raise TimeoutError(f"Video {video_id} timed out")

# Download the result (videos are retained for 7 days)
video = requests.get(video_data["video_url"], timeout=120)
with open("result.mp4", "wb") as f:
    f.write(video.content)
print("saved result.mp4")

Next steps