Assets
Complete Asset Upload
Finalize a direct-to-S3 upload into a reusable asset. Call after the upload PUT returns 200. Idempotent: repeated calls return the same finalized asset.
POST
/
v3
/
assets
/
{asset_id}
/
complete
Complete Asset Upload
curl --request POST \
--url https://api.heygen.com/v3/assets/{asset_id}/complete \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"checksum_sha256": "<string>"
}
'import requests
url = "https://api.heygen.com/v3/assets/{asset_id}/complete"
payload = { "checksum_sha256": "<string>" }
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({checksum_sha256: '<string>'})
};
fetch('https://api.heygen.com/v3/assets/{asset_id}/complete', 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/assets/{asset_id}/complete",
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([
'checksum_sha256' => '<string>'
]),
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/assets/{asset_id}/complete"
payload := strings.NewReader("{\n \"checksum_sha256\": \"<string>\"\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.heygen.com/v3/assets/{asset_id}/complete")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"checksum_sha256\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.heygen.com/v3/assets/{asset_id}/complete")
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 \"checksum_sha256\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"asset_id": "<string>",
"url": "<string>",
"mime_type": "<string>",
"size_bytes": 123,
"status": "<string>"
}
}{
"error": {
"code": "invalid_parameter",
"message": "Video not found",
"param": "<string>",
"doc_url": "<string>"
}
}{
"error": {
"code": "authentication_failed",
"message": "Invalid or expired API key. Verify your x-api-key header.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "asset_not_found",
"message": "Asset not found.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "conflict",
"message": "Uploaded object not found yet. Retry after the upload PUT returns 200.",
"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
}
}Authorizations
ApiKeyAuthBearerAuth
HeyGen API key. Obtain from your HeyGen dashboard.
Path Parameters
Unique asset identifier
Body
application/json
Finalize a presigned upload (POST /v3/assets/{asset_id}/complete).
Optional SHA256 (hex) cross-check.
Response
Successful response
Result of finalizing an upload.
Show child attributes
Show child attributes
Previous
Get ai clippingReturns the full job resource including produced clips, statuses, and presigned download URLs.
Next
⌘I
Complete Asset Upload
curl --request POST \
--url https://api.heygen.com/v3/assets/{asset_id}/complete \
--header 'Content-Type: application/json' \
--header 'x-api-key: <api-key>' \
--data '
{
"checksum_sha256": "<string>"
}
'import requests
url = "https://api.heygen.com/v3/assets/{asset_id}/complete"
payload = { "checksum_sha256": "<string>" }
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({checksum_sha256: '<string>'})
};
fetch('https://api.heygen.com/v3/assets/{asset_id}/complete', 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/assets/{asset_id}/complete",
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([
'checksum_sha256' => '<string>'
]),
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/assets/{asset_id}/complete"
payload := strings.NewReader("{\n \"checksum_sha256\": \"<string>\"\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.heygen.com/v3/assets/{asset_id}/complete")
.header("x-api-key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"checksum_sha256\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.heygen.com/v3/assets/{asset_id}/complete")
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 \"checksum_sha256\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"data": {
"asset_id": "<string>",
"url": "<string>",
"mime_type": "<string>",
"size_bytes": 123,
"status": "<string>"
}
}{
"error": {
"code": "invalid_parameter",
"message": "Video not found",
"param": "<string>",
"doc_url": "<string>"
}
}{
"error": {
"code": "authentication_failed",
"message": "Invalid or expired API key. Verify your x-api-key header.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "asset_not_found",
"message": "Asset not found.",
"param": null,
"doc_url": null
}
}{
"error": {
"code": "conflict",
"message": "Uploaded object not found yet. Retry after the upload PUT returns 200.",
"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
}
}
