자산 그룹 생성(실인물)
curl --request POST \
--url https://api.gravitex.ai/v1/visual-validate/session \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"channel_id": 123
}
'import requests
url = "https://api.gravitex.ai/v1/visual-validate/session"
payload = {
"name": "<string>",
"description": "<string>",
"channel_id": 123
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: '<string>', description: '<string>', channel_id: 123})
};
fetch('https://api.gravitex.ai/v1/visual-validate/session', 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.gravitex.ai/v1/visual-validate/session",
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([
'name' => '<string>',
'description' => '<string>',
'channel_id' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$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.gravitex.ai/v1/visual-validate/session"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"channel_id\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
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.gravitex.ai/v1/visual-validate/session")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"channel_id\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gravitex.ai/v1/visual-validate/session")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"channel_id\": 123\n}"
response = http.request(request)
puts response.read_bodySeedance 2.0(/generations)
자산 그룹 생성(실인물)
POST /v1/visual-validate/session (liveness_face)
POST
/
v1
/
visual-validate
/
session
자산 그룹 생성(실인물)
curl --request POST \
--url https://api.gravitex.ai/v1/visual-validate/session \
--header 'Authorization: <authorization>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"description": "<string>",
"channel_id": 123
}
'import requests
url = "https://api.gravitex.ai/v1/visual-validate/session"
payload = {
"name": "<string>",
"description": "<string>",
"channel_id": 123
}
headers = {
"Authorization": "<authorization>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: '<authorization>', 'Content-Type': 'application/json'},
body: JSON.stringify({name: '<string>', description: '<string>', channel_id: 123})
};
fetch('https://api.gravitex.ai/v1/visual-validate/session', 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.gravitex.ai/v1/visual-validate/session",
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([
'name' => '<string>',
'description' => '<string>',
'channel_id' => 123
]),
CURLOPT_HTTPHEADER => [
"Authorization: <authorization>",
"Content-Type: application/json"
],
]);
$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.gravitex.ai/v1/visual-validate/session"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"channel_id\": 123\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "<authorization>")
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.gravitex.ai/v1/visual-validate/session")
.header("Authorization", "<authorization>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"channel_id\": 123\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.gravitex.ai/v1/visual-validate/session")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = '<authorization>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"description\": \"<string>\",\n \"channel_id\": 123\n}"
response = http.request(request)
puts response.read_body소개
실인물 자산 그룹(group_type: liveness_face)은 자산 그룹 생성으로 생성할 수 없습니다. 먼저 이 엔드포인트를 호출하여 H5 생체 인증을 시작하세요. 사용자가 검증을 완료하면 게이트웨이가 그룹을 저장합니다.
| 라이브러리 | group_type | 생성 방법 |
|---|---|---|
| 가상 | aigc | POST /v1/asset-groups |
| 실인물 | liveness_face | 이 엔드포인트를 통한 H5 검증 |
BytePlus
CreateVisualValidateSession은 name 또는 description을 받지 않습니다. 업스트림 GroupId를 받은 후 게이트웨이가 UpdateAssetGroup을 호출하여 해당 필드를 BytePlus 콘솔에 다시 기록합니다.인증
string
필수
Bearer Token, 예:
Bearer sk-xxxxxxxxxxstring
application/json요청 본문
string
필수
자산 그룹 이름(저장되고 BytePlus 콘솔에 동기화됨)
integer
업스트림 채널 ID; 생략 시 자동 선택
H5 검증 흐름
1. 클라이언트가 검증 시작 → POST /v1/visual-validate/session
↓ { h5_link, state, ... } 반환
2. 클라이언트가 팝업에서 h5_link 열기; 사용자가 검증 완료
↓ BytePlus가 게이트웨이 /asset-validate-callback.html?state=…&bytedToken=…&resultCode=10000으로 리디렉션
3. 콜백 페이지가 /v1/visual-validate/result를 가져옴; group_type=liveness_face 저장
↓ window.opener.postMessage({ type: 'gravitex-asset-validate-result', ok, group_id, … })
4. 클라이언트가 group_id 수신; POST /v1/assets(Image / Video / Audio)로 자산 업로드
POST /v1/visual-validate/result를 직접 호출할 필요가 없습니다. 게이트웨이 콜백 페이지가 state를 자동으로 전달합니다.
예제
curl -X POST "https://api.gravitex.ai/v1/visual-validate/session" \
-H "Authorization: Bearer sk-xxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"name": "Live person A"}'
응답
{
"h5_link": "https://verify.byteplus.com/h5/?token=…&lang=zh-CN&lng=zh",
"state": "<base64url>.<hmac>",
"channel_id": 123,
"byted_token": "bp-token-xxxxxxxx",
"expires_in": 900
}
| 필드 | 설명 |
|---|---|
h5_link | BytePlus H5 생체 인증 URL; 게이트웨이가 기본값으로 lang=zh-CN&lng=zh를 추가 |
state | user / channel / group_name / byted_token에 바인딩된 게이트웨이 발급 HMAC-SHA256 토큰; 콜백 페이지가 결과를 가져오는 데 사용 |
byted_token | 이 검증 세션의 BytePlus 자격 증명; 콜백 시 state 내부 값과 대조 검증 |
channel_id | 선택된 업스트림 채널 |
expires_in | state 토큰 TTL(초), 고정값 900(15분). H5 페이지 수명이 아님—BytePlus H5 링크는 약 120초 동안 유효; 만료 후 이 엔드포인트를 다시 호출 |
클라이언트는 일반적으로 팝업에서
h5_link를 열고 window.message를 수신하기만 하면 됩니다. H5 타임아웃 시 팝업을 닫고 리스너를 제거한 후 POST /v1/visual-validate/session을 다시 호출하여 새 링크를 받으세요. 클라이언트 측 타임아웃 약 130초를 대비책으로 고려하세요.클라이언트 postMessage
콜백 페이지(/asset-validate-callback.html)가 window.opener에 메시지를 전송합니다(targetOrigin = '*'). 콜백 페이지와 부모가 다른 출처인 경우 event.origin만 의존하지 말고 type으로 메시지를 식별하세요.
성공:
{
"type": "gravitex-asset-validate-result",
"ok": true,
"group_id": "group-20260512083014-zyxwv",
"name": "Live person A",
"channel_id": 123,
"group_type": "liveness_face"
}
{
"type": "gravitex-asset-validate-result",
"ok": false,
"result_code": "10003",
"error": "Liveness validation failed: face does not match reference"
}
const popup = window.open(session.h5_link, 'asset-validate', 'width=480,height=720');
const listener = (event) => {
const data = event.data;
if (!data || data.type !== 'gravitex-asset-validate-result') return;
window.removeEventListener('message', listener);
if (data.ok) {
console.log('Asset group created:', data.group_id);
} else {
console.error('Validation failed:', data.error, data.result_code);
}
};
window.addEventListener('message', listener);
다음 단계
- postMessage의
group_id사용(이 엔드포인트의 동기 응답이 아님)하여 자산 생성 호출 - 자산 목록 조회 또는 자산 조회로
status: active까지 폴링 - 비디오 생성 작업 생성에서
asset://로 자산 참조
?group_type=liveness_face)로 그룹 생성을 확인할 수도 있습니다.⌘I
