Quick start
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
Two ways to start — pick one:
Option A — install the Agent Skill package (recommended if you use a coding agent, or just want a ready-made CLI). It ships SKILL.md plus a dependency-free Python CLI that handles auth, base64 encoding, polling, and downloads:
mkdir -p .agents/skills
curl -fsSL https://openapi.visionstory.ai/skills/visionstory-video-api.zip -o visionstory-video-api.zip
unzip -o visionstory-video-api.zip -d .agents/skills && rm visionstory-video-api.zip
Then create a video in one command:
python3 .agents/skills/visionstory-video-api/scripts/visionstory_api.py create-video --avatar-id 4321918387609092991 --text "Hello from VisionStory." --voice-id Alice --output result.mp4
Option B — copy the standalone script at the end of this page. It only needs requests.
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 five steps above as one standalone Python script:
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
- Avatars — create a custom avatar from your own photo.
- Voices — clone your voice and use it in any video.
- AI Video — text-to-video and image-to-video generation.
- For agents — let an AI agent drive the API for you.
- API reference — full schemas, parameters, and error codes.