Create Talking Avatar
curl --request POST \
--url https://api.hooked.so/v1/project/create/talking-avatar \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"script": "Check out this amazing product! It’s super easy to use and I love the results.",
"avatarId": "2",
"caption": {
"preset": "wrap1",
"alignment": "bottom",
"disabled": false
},
"webhook": "https://yoursite.com/webhook",
"metadata": {
"campaignId": "campaign_id",
"variant": "A"
}
}
'import requests
url = "https://api.hooked.so/v1/project/create/talking-avatar"
payload = {
"script": "Check out this amazing product! It’s super easy to use and I love the results.",
"avatarId": "2",
"caption": {
"preset": "wrap1",
"alignment": "bottom",
"disabled": False
},
"webhook": "https://yoursite.com/webhook",
"metadata": {
"campaignId": "campaign_id",
"variant": "A"
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
script: 'Check out this amazing product! It’s super easy to use and I love the results.',
avatarId: '2',
caption: {preset: 'wrap1', alignment: 'bottom', disabled: false},
webhook: 'https://yoursite.com/webhook',
metadata: {campaignId: 'campaign_id', variant: 'A'}
})
};
fetch('https://api.hooked.so/v1/project/create/talking-avatar', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hooked.so/v1/project/create/talking-avatar",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'script' => 'Check out this amazing product! It’s super easy to use and I love the results.',
'avatarId' => '2',
'caption' => [
'preset' => 'wrap1',
'alignment' => 'bottom',
'disabled' => false
],
'webhook' => 'https://yoursite.com/webhook',
'metadata' => [
'campaignId' => 'campaign_id',
'variant' => 'A'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hooked.so/v1/project/create/talking-avatar"
payload := strings.NewReader("{\n \"script\": \"Check out this amazing product! It’s super easy to use and I love the results.\",\n \"avatarId\": \"2\",\n \"caption\": {\n \"preset\": \"wrap1\",\n \"alignment\": \"bottom\",\n \"disabled\": false\n },\n \"webhook\": \"https://yoursite.com/webhook\",\n \"metadata\": {\n \"campaignId\": \"campaign_id\",\n \"variant\": \"A\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hooked.so/v1/project/create/talking-avatar")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"script\": \"Check out this amazing product! It’s super easy to use and I love the results.\",\n \"avatarId\": \"2\",\n \"caption\": {\n \"preset\": \"wrap1\",\n \"alignment\": \"bottom\",\n \"disabled\": false\n },\n \"webhook\": \"https://yoursite.com/webhook\",\n \"metadata\": {\n \"campaignId\": \"campaign_id\",\n \"variant\": \"A\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hooked.so/v1/project/create/talking-avatar")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"script\": \"Check out this amazing product! It’s super easy to use and I love the results.\",\n \"avatarId\": \"2\",\n \"caption\": {\n \"preset\": \"wrap1\",\n \"alignment\": \"bottom\",\n \"disabled\": false\n },\n \"webhook\": \"https://yoursite.com/webhook\",\n \"metadata\": {\n \"campaignId\": \"campaign_id\",\n \"variant\": \"A\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"videoId": "vid_talking_avatar_abc123xyz",
"projectId": "proj_ugc_abc123xyz",
"status": "STARTED"
},
"message": "Talking avatar successfully created"
}
{
"success": false,
"message": "script: Script must be at least 1 character"
}
{
"success": false,
"message": "avatarId: Avatar \"invalid_id\" not found."
}
Videos
Talking Avatar
Create talking avatar videos with AI avatars
POST
/
v1
/
project
/
create
/
talking-avatar
Create Talking Avatar
curl --request POST \
--url https://api.hooked.so/v1/project/create/talking-avatar \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"script": "Check out this amazing product! It’s super easy to use and I love the results.",
"avatarId": "2",
"caption": {
"preset": "wrap1",
"alignment": "bottom",
"disabled": false
},
"webhook": "https://yoursite.com/webhook",
"metadata": {
"campaignId": "campaign_id",
"variant": "A"
}
}
'import requests
url = "https://api.hooked.so/v1/project/create/talking-avatar"
payload = {
"script": "Check out this amazing product! It’s super easy to use and I love the results.",
"avatarId": "2",
"caption": {
"preset": "wrap1",
"alignment": "bottom",
"disabled": False
},
"webhook": "https://yoursite.com/webhook",
"metadata": {
"campaignId": "campaign_id",
"variant": "A"
}
}
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
script: 'Check out this amazing product! It’s super easy to use and I love the results.',
avatarId: '2',
caption: {preset: 'wrap1', alignment: 'bottom', disabled: false},
webhook: 'https://yoursite.com/webhook',
metadata: {campaignId: 'campaign_id', variant: 'A'}
})
};
fetch('https://api.hooked.so/v1/project/create/talking-avatar', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.hooked.so/v1/project/create/talking-avatar",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'script' => 'Check out this amazing product! It’s super easy to use and I love the results.',
'avatarId' => '2',
'caption' => [
'preset' => 'wrap1',
'alignment' => 'bottom',
'disabled' => false
],
'webhook' => 'https://yoursite.com/webhook',
'metadata' => [
'campaignId' => 'campaign_id',
'variant' => 'A'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"x-api-key: <api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.hooked.so/v1/project/create/talking-avatar"
payload := strings.NewReader("{\n \"script\": \"Check out this amazing product! It’s super easy to use and I love the results.\",\n \"avatarId\": \"2\",\n \"caption\": {\n \"preset\": \"wrap1\",\n \"alignment\": \"bottom\",\n \"disabled\": false\n },\n \"webhook\": \"https://yoursite.com/webhook\",\n \"metadata\": {\n \"campaignId\": \"campaign_id\",\n \"variant\": \"A\"\n }\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("x-api-key", "<api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.hooked.so/v1/project/create/talking-avatar")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"script\": \"Check out this amazing product! It’s super easy to use and I love the results.\",\n \"avatarId\": \"2\",\n \"caption\": {\n \"preset\": \"wrap1\",\n \"alignment\": \"bottom\",\n \"disabled\": false\n },\n \"webhook\": \"https://yoursite.com/webhook\",\n \"metadata\": {\n \"campaignId\": \"campaign_id\",\n \"variant\": \"A\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.hooked.so/v1/project/create/talking-avatar")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"script\": \"Check out this amazing product! It’s super easy to use and I love the results.\",\n \"avatarId\": \"2\",\n \"caption\": {\n \"preset\": \"wrap1\",\n \"alignment\": \"bottom\",\n \"disabled\": false\n },\n \"webhook\": \"https://yoursite.com/webhook\",\n \"metadata\": {\n \"campaignId\": \"campaign_id\",\n \"variant\": \"A\"\n }\n}"
response = http.request(request)
puts response.read_body{
"success": true,
"data": {
"videoId": "vid_talking_avatar_abc123xyz",
"projectId": "proj_ugc_abc123xyz",
"status": "STARTED"
},
"message": "Talking avatar successfully created"
}
{
"success": false,
"message": "script: Script must be at least 1 character"
}
{
"success": false,
"message": "avatarId: Avatar \"invalid_id\" not found."
}
Try it out! Use the API playground on the right to test the Talking Avatar endpoint directly.
Overview
Talking Avatar creates videos of an AI avatar speaking your script. The voice, lip movement and gestures are generated natively by the video model: you pick the avatar and write the script, nothing else. This format is ideal for:- Testimonial-style videos
- Social media content
- Personal video messages
- Quick video updates
- Product presentations
The script is split into short clips and each clip is generated with the avatar speaking on camera. There is no
voiceId and no lipsync model to choose: the avatar comes with its voice.Endpoint
POST /v1/project/create/talking-avatar
Required Fields
string
required
The script for the avatar to speak (1-10,000 characters). Write naturally as if a real person is speaking.
string
required
Avatar ID from
/v1/avatar/list. Choose an avatar that matches your target audience.Optional Fields
string
Video name (max 100 characters)
string
Music ID from
/v1/music/list for background music.object
Caption settings for the video
Show Caption Object
Show Caption Object
string
default:"tiktok"
Caption preset style. Available presets:
default, beast, umi, tiktok, wrap1, wrap2, ariel, hooked, classic, active, bubble, glass, comic, glow, pastel, neon, retroTV, red, marker, modern, blue, vivid.string
default:"bottom"
Caption position on the video:
top, middle, or bottomboolean
default:"false"
Set to
true to hide captions on the videoobject
deprecated
Accepted for backwards compatibility and ignored. The avatar’s speech is generated by the video model together with the picture, so there is no separate voice track to tune.
string
HTTPS URL to receive completion notification (max 500 characters). Highly recommended for production use.
object
Custom metadata object (max 5KB). Store any additional data you need to associate with this video.
{
"campaignId": "summer2024",
"customField": "any value"
}
Request Examples
Basic Talking Avatar
{
"script": "Check out this amazing product! It's super easy to use and I love the results.",
"avatarId": "2"
}
Complete Talking Avatar
{
"name": "Welcome Video",
"script": "Hey there! Thanks for checking out our channel. We create awesome content every week, so make sure to subscribe and hit that notification bell!",
"avatarId": "2",
"caption": {
"preset": "tiktok",
"alignment": "bottom",
"disabled": false
},
"musicId": "music_upbeat_01",
"webhook": "https://yoursite.com/webhook",
"metadata": {
"channelId": "my-channel",
"videoType": "welcome"
}
}
Response
{
"success": true,
"data": {
"videoId": "vid_talking_avatar_abc123xyz",
"projectId": "proj_ugc_abc123xyz",
"status": "STARTED"
},
"message": "Talking avatar successfully created"
}
{
"success": false,
"message": "script: Script must be at least 1 character"
}
{
"success": false,
"message": "avatarId: Avatar \"invalid_id\" not found."
}
Webhook Notification
When your video is ready, we’ll POST to your webhook URL:Webhook Payload
{
"status": "COMPLETED",
"data": {
"videoId": "vid_talking_avatar_abc123xyz",
"status": "COMPLETED",
"url": "https://cdn.hooked.so/videos/abc123xyz.mp4",
"shareUrl": "https://cdn.hooked.so/shared/abc123xyz.mp4",
"metadata": {
"projectId": "proj_ugc_abc123xyz",
"channelId": "my-channel"
}
},
"message": "Video completed"
}
Your webhook endpoint must return a
200 status code. We’ll retry up to 3 times if the request fails.Caption Presets
Available caption presets for thecaption.preset field:
| Preset | Description |
|---|---|
default | Default caption style with bold text and shadow effects |
beast | Bold uppercase style with Komika font |
umi | Yellow glowing text style |
tiktok | Viral & trendy style, perfect for social media |
wrap1 | Wrapped style with red background highlight |
wrap2 | Wrapped style with blue background highlight (uppercase) |
ariel | Bold uppercase style with purple highlight |
hooked | Brand style with purple background |
classic | Clean, simple captions with black background |
active | Green background with bold text |
bubble | White background bubble style |
glass | Glassmorphic transparency effect |
comic | Comic Sans font with colorful style |
glow | Pink and orange glow effects |
pastel | Soft pastel pink background |
neon | Green neon glow effect |
retroTV | Retro TV style with cyan glow |
red | Red glow effect with white text |
marker | Yellow marker/highlighter style |
modern | Contemporary white background style |
blue | Blue background style |
vivid | Vibrant pink background with uppercase text |
Best Practices
Write Naturally
Scripts should sound conversational. Use contractions, pauses, and natural speech patterns.
Put the Tone in the Script
The avatar reads what you write, the way you write it. Exclamation marks, pauses and short sentences shape the delivery.
Pick the Avatar for the Audience
Voice and look come together with the avatar, so choose the one that matches who the video is for.
Keep It Concise
Shorter videos (15-60 seconds) tend to perform better on social media.
Use Webhooks
Always use webhooks in production instead of polling for video status.
Error Handling
| Error | Description | Solution |
|---|---|---|
script: Script must be at least 1 character | Missing or empty script | Add the script field with your content |
avatarId: Avatar not found | Invalid avatar ID | Use a valid avatar ID from /v1/avatar/list |
webhook: Must be a valid HTTPS URL | Invalid webhook URL | Ensure webhook URL starts with https:// |
Not enough credits | Insufficient credits | Top up your account credits |
Next Steps
List Avatars
Browse available avatars
List Voices
Find the perfect voice
List Videos
View all your created videos
Webhooks Guide
Learn how to handle webhook notifications
Authorizations
Body
application/json
The script for the avatar to speak (1-10,000 characters)
Required string length:
1 - 10000Avatar ID from /v1/avatar/list
Maximum string length:
30Video name (max 100 characters)
Maximum string length:
100Music ID from /v1/music/list for background music
Maximum string length:
30Show child attributes
Show child attributes
Deprecated. Accepted for backwards compatibility and ignored: the avatar's speech is generated by the video model together with the picture.
HTTPS URL to receive completion notification
Maximum string length:
500Custom metadata object (max 5KB)