Set Template Variables
Declares the complete set of variables for a template, replacing whatever was declared before. This is a full replacement, not a patch: every variable you want to keep must be included in every call, and any variable omitted is removed (text placeholders are restored to their default text). Character, voice, image, video and audio variables bind to an element by element_id; use the elements list from GET /v3/templates/ to find IDs, and each element takes at most one such variable. Text variables are created with match: every occurrence of that exact text in the template’s script and on-screen text (or only in element_ids) becomes a placeholder, with the matched text as the default. Declare a text variable without match to keep placeholders that already exist. Returns the updated template detail.
curl --request PUT \
--url https://api.heygen.com/v3/templates/{template_id}/variables \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"variables": {
"company": {
"match": "Acme",
"type": "text"
},
"first_name": {
"element_ids": [
"t81c0d4b"
],
"match": "John",
"type": "text"
},
"hero_image": {
"element_id": "i77e5f60",
"type": "image"
},
"narration_voice": {
"element_id": "t81c0d4b",
"type": "voice"
},
"presenter": {
"element_id": "a3f9c2e1",
"type": "character"
}
}
}
'import requests
url = "https://api.heygen.com/v3/templates/{template_id}/variables"
payload = { "variables": {
"company": {
"match": "Acme",
"type": "text"
},
"first_name": {
"element_ids": ["t81c0d4b"],
"match": "John",
"type": "text"
},
"hero_image": {
"element_id": "i77e5f60",
"type": "image"
},
"narration_voice": {
"element_id": "t81c0d4b",
"type": "voice"
},
"presenter": {
"element_id": "a3f9c2e1",
"type": "character"
}
} }
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
variables: {
company: {match: 'Acme', type: 'text'},
first_name: {element_ids: ['t81c0d4b'], match: 'John', type: 'text'},
hero_image: {element_id: 'i77e5f60', type: 'image'},
narration_voice: {element_id: 't81c0d4b', type: 'voice'},
presenter: {element_id: 'a3f9c2e1', type: 'character'}
}
})
};
fetch('https://api.heygen.com/v3/templates/{template_id}/variables', 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.heygen.com/v3/templates/{template_id}/variables",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'variables' => [
'company' => [
'match' => 'Acme',
'type' => 'text'
],
'first_name' => [
'element_ids' => [
't81c0d4b'
],
'match' => 'John',
'type' => 'text'
],
'hero_image' => [
'element_id' => 'i77e5f60',
'type' => 'image'
],
'narration_voice' => [
'element_id' => 't81c0d4b',
'type' => 'voice'
],
'presenter' => [
'element_id' => 'a3f9c2e1',
'type' => 'character'
]
]
]),
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.heygen.com/v3/templates/{template_id}/variables"
payload := strings.NewReader("{\n \"variables\": {\n \"company\": {\n \"match\": \"Acme\",\n \"type\": \"text\"\n },\n \"first_name\": {\n \"element_ids\": [\n \"t81c0d4b\"\n ],\n \"match\": \"John\",\n \"type\": \"text\"\n },\n \"hero_image\": {\n \"element_id\": \"i77e5f60\",\n \"type\": \"image\"\n },\n \"narration_voice\": {\n \"element_id\": \"t81c0d4b\",\n \"type\": \"voice\"\n },\n \"presenter\": {\n \"element_id\": \"a3f9c2e1\",\n \"type\": \"character\"\n }\n }\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.heygen.com/v3/templates/{template_id}/variables")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"variables\": {\n \"company\": {\n \"match\": \"Acme\",\n \"type\": \"text\"\n },\n \"first_name\": {\n \"element_ids\": [\n \"t81c0d4b\"\n ],\n \"match\": \"John\",\n \"type\": \"text\"\n },\n \"hero_image\": {\n \"element_id\": \"i77e5f60\",\n \"type\": \"image\"\n },\n \"narration_voice\": {\n \"element_id\": \"t81c0d4b\",\n \"type\": \"voice\"\n },\n \"presenter\": {\n \"element_id\": \"a3f9c2e1\",\n \"type\": \"character\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.heygen.com/v3/templates/{template_id}/variables")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"variables\": {\n \"company\": {\n \"match\": \"Acme\",\n \"type\": \"text\"\n },\n \"first_name\": {\n \"element_ids\": [\n \"t81c0d4b\"\n ],\n \"match\": \"John\",\n \"type\": \"text\"\n },\n \"hero_image\": {\n \"element_id\": \"i77e5f60\",\n \"type\": \"image\"\n },\n \"narration_voice\": {\n \"element_id\": \"t81c0d4b\",\n \"type\": \"voice\"\n },\n \"presenter\": {\n \"element_id\": \"a3f9c2e1\",\n \"type\": \"character\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "77e650952c024c6188a35e23e7088617",
"name": "Quarterly Update",
"thumbnail_url": "<string>",
"aspect_ratio": "16:9",
"created_at": 1711929600,
"updated_at": 1711929600,
"variables": {},
"source_video_id": "<string>",
"scene_ids": [
"<string>"
],
"scenes": [
{
"scene_id": "<string>",
"script": "<string>",
"variables": [
{
"name": "<string>",
"variable_type": "<string>"
}
]
}
],
"elements": [
{
"element_id": "<string>",
"element_type": "avatar",
"scene_id": "<string>",
"bindable_as": [
"text"
],
"current": {
"avatar_look_id": "<string>",
"character_type": "avatar",
"voice_id": "<string>",
"text": "<string>",
"url": "<string>",
"play_style": "<string>",
"volume": 123
},
"variable": "<string>",
"text_variables": [
"<string>"
]
}
]
}
}{
"error": {
"code": "variable_match_not_found",
"message": "Text 'Acme' for variable 'company' was not found in the template.",
"param": "variables.company.match",
"doc_url": null
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid or expired API key. Verify your x-api-key header.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "resource_access_denied",
"message": "Template creation is restricted by your workspace settings. Ask a workspace admin to allow it.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "template_not_found",
"message": "Template not found.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Retry after the duration specified in the Retry-After header.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "service_unavailable",
"message": "The template's element metadata could not be read, so the character variable was not stored. Retry the request.",
"param": null,
"doc_url": null
}
}Authorizations
HeyGen API key. Obtain from your HeyGen dashboard.
Path Parameters
Unique template identifier
Body
Request body for PUT /v3/templates/{template_id}/variables.
Full replacement: the body is the complete variable set after the call. A variable that exists on the template but is missing here is removed.
The complete variable set, keyed by variable name (letters, digits, underscores; must start with a letter or underscore; at most 64 characters). An empty object removes every variable.
Show child attributes
Show child attributes
{
"company": { "match": "Acme", "type": "text" },
"first_name": {
"element_ids": ["t81c0d4b"],
"match": "John",
"type": "text"
},
"hero_image": { "element_id": "i77e5f60", "type": "image" },
"narration_voice": { "element_id": "t81c0d4b", "type": "voice" },
"presenter": {
"element_id": "a3f9c2e1",
"type": "character"
}
}
Response
Successful response
Template detail including its variable schema, scenes, and bindable elements.
Show child attributes
Show child attributes
curl --request PUT \
--url https://api.heygen.com/v3/templates/{template_id}/variables \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"variables": {
"company": {
"match": "Acme",
"type": "text"
},
"first_name": {
"element_ids": [
"t81c0d4b"
],
"match": "John",
"type": "text"
},
"hero_image": {
"element_id": "i77e5f60",
"type": "image"
},
"narration_voice": {
"element_id": "t81c0d4b",
"type": "voice"
},
"presenter": {
"element_id": "a3f9c2e1",
"type": "character"
}
}
}
'import requests
url = "https://api.heygen.com/v3/templates/{template_id}/variables"
payload = { "variables": {
"company": {
"match": "Acme",
"type": "text"
},
"first_name": {
"element_ids": ["t81c0d4b"],
"match": "John",
"type": "text"
},
"hero_image": {
"element_id": "i77e5f60",
"type": "image"
},
"narration_voice": {
"element_id": "t81c0d4b",
"type": "voice"
},
"presenter": {
"element_id": "a3f9c2e1",
"type": "character"
}
} }
headers = {
"x-api-key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {'x-api-key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
variables: {
company: {match: 'Acme', type: 'text'},
first_name: {element_ids: ['t81c0d4b'], match: 'John', type: 'text'},
hero_image: {element_id: 'i77e5f60', type: 'image'},
narration_voice: {element_id: 't81c0d4b', type: 'voice'},
presenter: {element_id: 'a3f9c2e1', type: 'character'}
}
})
};
fetch('https://api.heygen.com/v3/templates/{template_id}/variables', 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.heygen.com/v3/templates/{template_id}/variables",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'variables' => [
'company' => [
'match' => 'Acme',
'type' => 'text'
],
'first_name' => [
'element_ids' => [
't81c0d4b'
],
'match' => 'John',
'type' => 'text'
],
'hero_image' => [
'element_id' => 'i77e5f60',
'type' => 'image'
],
'narration_voice' => [
'element_id' => 't81c0d4b',
'type' => 'voice'
],
'presenter' => [
'element_id' => 'a3f9c2e1',
'type' => 'character'
]
]
]),
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.heygen.com/v3/templates/{template_id}/variables"
payload := strings.NewReader("{\n \"variables\": {\n \"company\": {\n \"match\": \"Acme\",\n \"type\": \"text\"\n },\n \"first_name\": {\n \"element_ids\": [\n \"t81c0d4b\"\n ],\n \"match\": \"John\",\n \"type\": \"text\"\n },\n \"hero_image\": {\n \"element_id\": \"i77e5f60\",\n \"type\": \"image\"\n },\n \"narration_voice\": {\n \"element_id\": \"t81c0d4b\",\n \"type\": \"voice\"\n },\n \"presenter\": {\n \"element_id\": \"a3f9c2e1\",\n \"type\": \"character\"\n }\n }\n}")
req, _ := http.NewRequest("PUT", 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.put("https://api.heygen.com/v3/templates/{template_id}/variables")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"variables\": {\n \"company\": {\n \"match\": \"Acme\",\n \"type\": \"text\"\n },\n \"first_name\": {\n \"element_ids\": [\n \"t81c0d4b\"\n ],\n \"match\": \"John\",\n \"type\": \"text\"\n },\n \"hero_image\": {\n \"element_id\": \"i77e5f60\",\n \"type\": \"image\"\n },\n \"narration_voice\": {\n \"element_id\": \"t81c0d4b\",\n \"type\": \"voice\"\n },\n \"presenter\": {\n \"element_id\": \"a3f9c2e1\",\n \"type\": \"character\"\n }\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.heygen.com/v3/templates/{template_id}/variables")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["x-api-key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"variables\": {\n \"company\": {\n \"match\": \"Acme\",\n \"type\": \"text\"\n },\n \"first_name\": {\n \"element_ids\": [\n \"t81c0d4b\"\n ],\n \"match\": \"John\",\n \"type\": \"text\"\n },\n \"hero_image\": {\n \"element_id\": \"i77e5f60\",\n \"type\": \"image\"\n },\n \"narration_voice\": {\n \"element_id\": \"t81c0d4b\",\n \"type\": \"voice\"\n },\n \"presenter\": {\n \"element_id\": \"a3f9c2e1\",\n \"type\": \"character\"\n }\n }\n}"
response = http.request(request)
puts response.read_body{
"data": {
"id": "77e650952c024c6188a35e23e7088617",
"name": "Quarterly Update",
"thumbnail_url": "<string>",
"aspect_ratio": "16:9",
"created_at": 1711929600,
"updated_at": 1711929600,
"variables": {},
"source_video_id": "<string>",
"scene_ids": [
"<string>"
],
"scenes": [
{
"scene_id": "<string>",
"script": "<string>",
"variables": [
{
"name": "<string>",
"variable_type": "<string>"
}
]
}
],
"elements": [
{
"element_id": "<string>",
"element_type": "avatar",
"scene_id": "<string>",
"bindable_as": [
"text"
],
"current": {
"avatar_look_id": "<string>",
"character_type": "avatar",
"voice_id": "<string>",
"text": "<string>",
"url": "<string>",
"play_style": "<string>",
"volume": 123
},
"variable": "<string>",
"text_variables": [
"<string>"
]
}
]
}
}{
"error": {
"code": "variable_match_not_found",
"message": "Text 'Acme' for variable 'company' was not found in the template.",
"param": "variables.company.match",
"doc_url": null
}
}{
"error": {
"code": "unauthorized",
"message": "Invalid or expired API key. Verify your x-api-key header.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "resource_access_denied",
"message": "Template creation is restricted by your workspace settings. Ask a workspace admin to allow it.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "template_not_found",
"message": "Template not found.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Retry after the duration specified in the Retry-After header.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "service_unavailable",
"message": "The template's element metadata could not be read, so the character variable was not stored. Retry the request.",
"param": null,
"doc_url": null
}
}
