YingTu Logo
Checking Google sign-in…
Back to Seedance workspace
REST API reference

Real-person asset API

The API caller does not sign in to YingTu, but the represented person must complete identity, consent, and liveness checks on the official ByteDance H5 page.

Endpoint

Base URL

https://yingtu.ai
POST /api/seedance-assets/real-persons/verifications
GET /api/seedance-assets/real-persons/verifications/{verification_id}
POST /api/seedance-assets/real-persons
GET /api/seedance-assets/real-persons/{id}

Authentication

The caller does not sign in to YingTu or Google. Authenticate with a LaoZhang API key using Authorization: Bearer <LAOZHANG_API_KEY>.

HeaderRequiredDescription
AuthorizationYesLaoZhang API key using Bearer authentication.
Content-TypePOST onlyCreate operations use application/json.

Request

POST /api/seedance-assets/real-persons/verifications

FieldRequiredDescription
callback_urlYesHTTPS URL opened after the verification flow.
languageNoOfficial H5 language: zh, en, or zh-Hant. Default: zh.

GET /api/seedance-assets/real-persons/verifications/{verification_id}

FieldRequiredDescription
verification_idYesPath parameter returned when the verification was created.

POST /api/seedance-assets/real-persons

FieldRequiredDescription
verification_idYesMust be verified and owned by the same API key.
image_urlYesPublic HTTPS URL of a clear front-facing image of the same person.
nameNoAsset name, up to 64 characters.

Create request

1. POST /verifications
curl --request POST \
  --url https://yingtu.ai/api/seedance-assets/real-persons/verifications \
  --header "Authorization: Bearer $LAOZHANG_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "callback_url": "https://customer.example.com/seedance/verified",
    "language": "en"
  }'
2. GET /verifications/{verification_id}
curl --request GET \
  --url https://yingtu.ai/api/seedance-assets/real-persons/verifications/ver_eyJvcGFxdWUiOiJleGFtcGxlIn0 \
  --header "Authorization: Bearer $LAOZHANG_API_KEY"
3. POST /real-persons
curl --request POST \
  --url https://yingtu.ai/api/seedance-assets/real-persons \
  --header "Authorization: Bearer $LAOZHANG_API_KEY" \
  --header "Content-Type: application/json" \
  --data '{
    "verification_id": "ver_eyJvcGFxdWUiOiJleGFtcGxlIn0",
    "image_url": "https://cdn.example.com/presenter.webp",
    "name": "presenter-a"
  }'

Response example

POST /verifications · 201
HTTP/1.1 201 Created
Content-Type: application/json

{
	  "request_id": "req_01JZEXAMPLE",
	  "verification_id": "ver_eyJvcGFxdWUiOiJleGFtcGxlIn0",
	  "status": "requires_user_action",
	  "verification_url": "https://official-h5.example/?...&lng=en",
	  "callback_url": "https://customer.example.com/seedance/verified",
	  "expires_at": "2026-07-29T05:30:00.000Z"
	}
GET /verifications/{id} · 200 pending
{
  "request_id": "req_01JZEXAMPLE",
  "verification_id": "ver_eyJvcGFxdWUiOiJleGFtcGxlIn0",
  "status": "pending",
  "expires_at": "2026-07-29T05:30:00.000Z"
}
GET /verifications/{id} · 200 verified
{
  "request_id": "req_01JZEXAMPLE",
  "verification_id": "ver_eyJvcGFxdWUiOiJleGFtcGxlIn0",
  "status": "verified",
  "expires_at": "2026-07-29T05:30:00.000Z"
}
POST /real-persons · 409 pending
{
  "error": {
    "code": "verification_pending",
    "message": "The represented person has not completed verification.",
    "request_id": "req_01JZEXAMPLE",
    "retryable": true
  }
}
GET or POST · 410 expired
{
  "error": {
    "code": "verification_expired",
    "message": "The verification session expired. Create a new session.",
    "request_id": "req_01JZEXAMPLE",
    "retryable": false
  }
}
POST /real-persons · 202
{
  "request_id": "req_01JZEXAMPLE",
  "id": "ast_eyJvcGFxdWUiOiJleGFtcGxlIn0",
  "object": "seedance.asset",
  "kind": "real_person",
  "name": "presenter-a",
  "status": "Processing",
  "uri": "asset://asset-20260729-example"
}

Verification callback

GET https://customer.example.com/seedance/verified
	  ?verification_id=ver_eyJvcGFxdWUiOiJleGFtcGxlIn0
  &result_code=10000

result_code=10000 means the official H5 flow completed. Use verification_id from the callback Location for later GET and POST requests: GET still returns HTTP 200 while pending, only an early asset POST returns HTTP 409, and an expired ID returns HTTP 410. The callback never exposes the upstream BytedToken.

Official verification-page languages

The official documentation currently lists lng=zh, lng=en, and lng=zh-Hant. The default is zh. This API applies the language parameter to the returned link.

Recommended mapping: zh→zh, en→en, ru/ja/ko/es→en. Traditional Chinese can use zh-Hant. No official Russian, Japanese, Korean, or Spanish verification page is currently documented.

zh → lng=zh
en → lng=en
ru / ja / ko / es → lng=en
Traditional Chinese → lng=zh-Hant

Code examples

JavaScript · Node.js
const headers = {
  Authorization: `Bearer ${process.env.LAOZHANG_API_KEY}`,
  "Content-Type": "application/json",
};

const begin = await fetch("https://yingtu.ai/api/seedance-assets/real-persons/verifications", {
  method: "POST",
  headers,
  body: JSON.stringify({
    callback_url: "https://customer.example.com/seedance/verified",
    language: "en",
  }),
});

if (!begin.ok) throw new Error(await begin.text());
const session = await begin.json();
const verificationUrl = session.verification_url;
// Deliver verificationUrl only to the represented person's authenticated UI.
// Do not log or persist this short-lived URL.

// After the represented person finishes the official H5 flow:
const callbackVerificationId =
  "<verification_id received at your callback URL>";
const verified = await fetch(
  `https://yingtu.ai/api/seedance-assets/real-persons/verifications/${callbackVerificationId}`,
  { headers: { Authorization: headers.Authorization } },
).then((response) => response.json());

if (verified.status === "verified") {
  const asset = await fetch("https://yingtu.ai/api/seedance-assets/real-persons", {
    method: "POST",
    headers,
    body: JSON.stringify({
      verification_id: callbackVerificationId,
      image_url: "https://cdn.example.com/presenter.webp",
      name: "presenter-a",
    }),
  }).then((response) => response.json());
  console.log(asset);
}
Python · requests
import os
import requests

endpoint = "https://yingtu.ai/api/seedance-assets/real-persons"
verification_endpoint = f"{endpoint}/verifications"
headers = {"Authorization": f"Bearer {os.environ['LAOZHANG_API_KEY']}"}

session = requests.post(
    verification_endpoint,
    headers=headers,
    json={
        "callback_url": "https://customer.example.com/seedance/verified",
        "language": "en",
    },
    timeout=30,
)
session.raise_for_status()
verification = session.json()
verification_url = verification["verification_url"]
# Deliver verification_url only to the represented person's authenticated UI.
# Do not log or persist this short-lived URL.

# Run this after the represented person completes the official H5 flow.
callback_verification_id = "<verification_id received at your callback URL>"
status = requests.get(
    f"{verification_endpoint}/{callback_verification_id}",
    headers=headers,
    timeout=30,
)
status.raise_for_status()

if status.json()["status"] == "verified":
    asset = requests.post(
        endpoint,
        headers=headers,
        json={
            "verification_id": callback_verification_id,
            "image_url": "https://cdn.example.com/presenter.webp",
            "name": "presenter-a",
        },
        timeout=60,
    )
    asset.raise_for_status()
    print(asset.json())

Retrieve asset status

curl --request GET \
	  --url https://yingtu.ai/api/seedance-assets/real-persons/ast_eyJvcGFxdWUiOiJleGFtcGxlIn0 \
	  --header "Authorization: Bearer $LAOZHANG_API_KEY"
Status response
HTTP/1.1 200 OK
Content-Type: application/json

{
	  "request_id": "req_01JZEXAMPLE",
	  "id": "ast_eyJvcGFxdWUiOiJleGFtcGxlIn0",
  "object": "seedance.asset",
  "kind": "real_person",
  "status": "Active",
  "uri": "asset://asset-20260729-example",
	  "created_at": "2026-07-29T05:00:00Z",
	  "updated_at": "2026-07-29T05:01:00Z"
}
Failed · HTTP 200
{
  "request_id": "req_01JZEXAMPLE",
  "id": "ast_eyJvcGFxdWUiOiJleGFtcGxlIn0",
  "object": "seedance.asset",
  "kind": "real_person",
  "status": "Failed",
  "uri": "asset://asset-20260729-example",
  "failure": {
    "code": "InvalidImage",
    "message": "The image did not pass upstream validation."
  }
}

Errors

HTTP statusError codeDescriptionRetryable
400invalid_requestThe request body, field, or parameter value is invalid.No
401invalid_api_keyThe API key is missing, invalid, or disabled.No
403resource_not_ownedThe verification or asset is not owned by this API key, or the public ID is invalid.No
403capability_unavailablePrivate portrait-asset entitlement is not enabled for the service account.No
409verification_pendingReturned only by POST /real-persons while verification is pending; a GET status check still returns HTTP 200 with status=pending.Yes
410verification_expiredA GET verification-status or POST /real-persons request used a verification_id older than the 30-minute lifetime.No
413payload_too_largeThe JSON request body exceeds 16 KB.No
415unsupported_media_typeA POST request did not use application/json.No
429rate_limit_exceededThe API key has reached its request limit.Yes
500internal_errorThe service could not complete the request.No
502upstream_errorThe upstream asset or verification service returned an error.Yes
503authentication_unavailableAPI-key validation is temporarily unavailable.Yes
503service_unavailableThe asset API server configuration is temporarily unavailable.Yes
Error object
{
  "error": {
    "code": "invalid_request",
	    "message": "image_url is required.",
    "request_id": "req_01JZEXAMPLE",
    "retryable": false
  }
}

Rate limits and tracing

Each API key can make up to 12 create-operation POST requests per hour; GET status requests are not counted. Upstream entitlement may add limits. A limited request returns 429 with Retry-After in seconds.

Every success and error response includes request_id. Include it in support requests, but never send your complete API key.

X-RateLimit-Limit: <limit>
X-RateLimit-Remaining: <remaining>
X-RateLimit-Reset: <unix-seconds>
Retry-After: <seconds>