curl -X POST https://api.vibepeak.ai/v1/families \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6c8f2e1a-3b4d-4e5f-9a0b-1c2d3e4f5a6b" \
-d '{
"name": "The Garcia Family",
"members": [
{ "role": "mother", "type": "adult", "age": "35-40", "ethnicity": "hispanic", "physical": "medium build, long dark hair", "clothing": "casual blouse" },
{ "role": "father", "type": "adult", "age": "38-45", "ethnicity": "hispanic", "physical": "athletic build, short dark hair", "clothing": "casual polo shirt" },
{ "role": "daughter", "type": "child", "age": "8-10", "ethnicity": "hispanic", "physical": "long dark hair, bright smile" }
],
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/families', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({
name: 'The Garcia Family',
members: [
{ role: 'mother', type: 'adult', age: '35-40', ethnicity: 'hispanic', physical: 'medium build, long dark hair', clothing: 'casual blouse' },
{ role: 'father', type: 'adult', age: '38-45', ethnicity: 'hispanic', physical: 'athletic build, short dark hair', clothing: 'casual polo shirt' },
{ role: 'daughter', type: 'child', age: '8-10', ethnicity: 'hispanic', physical: 'long dark hair, bright smile' }
],
webhook_url: 'https://yourserver.com/webhooks/vibepeak'
})
});
const family = await response.json();
console.log(`Family created: ${family.family_id} (task: ${family.task_id})`);
import requests
import uuid
response = requests.post(
'https://api.vibepeak.ai/v1/families',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json',
'Idempotency-Key': str(uuid.uuid4())
},
json={
'name': 'The Garcia Family',
'members': [
{'role': 'mother', 'type': 'adult', 'age': '35-40', 'ethnicity': 'hispanic', 'physical': 'medium build, long dark hair', 'clothing': 'casual blouse'},
{'role': 'father', 'type': 'adult', 'age': '38-45', 'ethnicity': 'hispanic', 'physical': 'athletic build, short dark hair', 'clothing': 'casual polo shirt'},
{'role': 'daughter', 'type': 'child', 'age': '8-10', 'ethnicity': 'hispanic', 'physical': 'long dark hair, bright smile'}
],
'webhook_url': 'https://yourserver.com/webhooks/vibepeak'
}
)
family = response.json()
print(f"Family created: {family['family_id']} (task: {family['task_id']})")
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task_id": "task_fam456xyz",
"status": "generating",
"livemode": true,
"_links": {
"self": "/v1/families/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task": "/v1/tasks/task_fam456xyz"
}
}
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task_id": "task_fam456xyz",
"status": "generating",
"livemode": false,
"_links": {
"self": "/v1/families/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task": "/v1/tasks/task_fam456xyz"
}
}
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "pending_avatars"
}
{
"error": {
"code": "PLAN_NOT_ALLOWED",
"message": "Families are available on the Pro, Max and Enterprise plans. Upgrade your plan to use this feature.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_MEMBER_LIMIT_EXCEEDED",
"message": "A family must have between 1 and 6 members.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_LIMIT_REACHED",
"message": "You have reached the maximum number of families for your plan. Delete an existing family to create a new one.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid or has been revoked",
"request_id": "req_xyz123"
}
}
Families
Create Family
Create a custom family with AI-generated avatars for consistent casting across videos
POST
/
v1
/
families
curl -X POST https://api.vibepeak.ai/v1/families \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6c8f2e1a-3b4d-4e5f-9a0b-1c2d3e4f5a6b" \
-d '{
"name": "The Garcia Family",
"members": [
{ "role": "mother", "type": "adult", "age": "35-40", "ethnicity": "hispanic", "physical": "medium build, long dark hair", "clothing": "casual blouse" },
{ "role": "father", "type": "adult", "age": "38-45", "ethnicity": "hispanic", "physical": "athletic build, short dark hair", "clothing": "casual polo shirt" },
{ "role": "daughter", "type": "child", "age": "8-10", "ethnicity": "hispanic", "physical": "long dark hair, bright smile" }
],
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/families', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({
name: 'The Garcia Family',
members: [
{ role: 'mother', type: 'adult', age: '35-40', ethnicity: 'hispanic', physical: 'medium build, long dark hair', clothing: 'casual blouse' },
{ role: 'father', type: 'adult', age: '38-45', ethnicity: 'hispanic', physical: 'athletic build, short dark hair', clothing: 'casual polo shirt' },
{ role: 'daughter', type: 'child', age: '8-10', ethnicity: 'hispanic', physical: 'long dark hair, bright smile' }
],
webhook_url: 'https://yourserver.com/webhooks/vibepeak'
})
});
const family = await response.json();
console.log(`Family created: ${family.family_id} (task: ${family.task_id})`);
import requests
import uuid
response = requests.post(
'https://api.vibepeak.ai/v1/families',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json',
'Idempotency-Key': str(uuid.uuid4())
},
json={
'name': 'The Garcia Family',
'members': [
{'role': 'mother', 'type': 'adult', 'age': '35-40', 'ethnicity': 'hispanic', 'physical': 'medium build, long dark hair', 'clothing': 'casual blouse'},
{'role': 'father', 'type': 'adult', 'age': '38-45', 'ethnicity': 'hispanic', 'physical': 'athletic build, short dark hair', 'clothing': 'casual polo shirt'},
{'role': 'daughter', 'type': 'child', 'age': '8-10', 'ethnicity': 'hispanic', 'physical': 'long dark hair, bright smile'}
],
'webhook_url': 'https://yourserver.com/webhooks/vibepeak'
}
)
family = response.json()
print(f"Family created: {family['family_id']} (task: {family['task_id']})")
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task_id": "task_fam456xyz",
"status": "generating",
"livemode": true,
"_links": {
"self": "/v1/families/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task": "/v1/tasks/task_fam456xyz"
}
}
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task_id": "task_fam456xyz",
"status": "generating",
"livemode": false,
"_links": {
"self": "/v1/families/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task": "/v1/tasks/task_fam456xyz"
}
}
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "pending_avatars"
}
{
"error": {
"code": "PLAN_NOT_ALLOWED",
"message": "Families are available on the Pro, Max and Enterprise plans. Upgrade your plan to use this feature.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_MEMBER_LIMIT_EXCEEDED",
"message": "A family must have between 1 and 6 members.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_LIMIT_REACHED",
"message": "You have reached the maximum number of families for your plan. Delete an existing family to create a new one.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid or has been revoked",
"request_id": "req_xyz123"
}
}
Creates a family: a reusable cast of AI-generated people. Once ready, reference the family’s
With
You can also fetch the family directly with Get Family at any point to check its
See Error Handling for more details.
id as the selected_family_id parameter on Create Living Property Video to keep the same cast consistent across every scene of a video, instead of AI casting different people scene to scene.
Creating a family is free: it always charges 0 credits, regardless of how many members you request.
Family creation requires a Pro, Max, or Enterprise plan.
Request Body
string
required
Display name for the family.Length: 1-80 characters
object[]
required
The members that make up the family’s cast.Length: 1-6 members. Requests outside this range are rejected with
FAMILY_MEMBER_LIMIT_EXCEEDED.Show Member properties
Show Member properties
string
required
Broad age category.Allowed values:
adult, child, seniorGuides how the member is depicted in generated scenes.string
Short descriptive label for this member’s role in the family, e.g.
father, mother, daughter, grandmother. This guides avatar generation and how the member is referred to internally.string
Free-text age or age range to guide avatar generation, e.g.
35-40.string
Free-text ethnicity to guide avatar generation.
string
Free-text physical description to guide avatar generation, e.g.
athletic build, short dark hair.string
Free-text clothing description to guide avatar generation, e.g.
casual button-down shirt.boolean
default:"true"
Whether to start AI avatar generation immediately.
true(default): generation starts right away. The family is created with statusgeneratingand atask_idyou can poll or receive a webhook for.false: the family is created with statuspending_avatarsand no generation is triggered. A pending family cannot be selected for video generation until it has portraits, and there is no separate endpoint to trigger generation later, so most integrations should keep the default.
string
HTTPS URL to receive a webhook notification when avatar generation completes. Only used when
generate_avatars is true.See Webhooks for payload format and verification details.Webhook URLs must use HTTPS and cannot point to private/internal networks (SSRF protection).
string
Optional idempotency key. Retrying a request with the same key returns the original result instead of creating a duplicate family.
Response
Withgenerate_avatars: true (default), returns a 202 Accepted response with a task to poll:
string
required
Unique identifier for the newly created family.
string
required
Unique identifier for the avatar generation task. Poll it via Get Task, or use
webhook_url for a notification instead.string
required
Initial family status. Always
generating for this response shape.boolean
required
true for live (vpk_live_) requests; false for test-mode (vpk_test_) requests. See Test Mode.object
required
HATEOAS links for navigation.
self: URL to fetch the family (/v1/families/{family_id})task: URL to poll for the avatar generation task (/v1/tasks/{task_id})
generate_avatars: false, returns a 201 Created response instead, with no generation task:
string
required
Unique identifier for the newly created family.
string
required
Always
pending_avatars for this response shape.curl -X POST https://api.vibepeak.ai/v1/families \
-H "Authorization: Bearer vpk_live_xxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 6c8f2e1a-3b4d-4e5f-9a0b-1c2d3e4f5a6b" \
-d '{
"name": "The Garcia Family",
"members": [
{ "role": "mother", "type": "adult", "age": "35-40", "ethnicity": "hispanic", "physical": "medium build, long dark hair", "clothing": "casual blouse" },
{ "role": "father", "type": "adult", "age": "38-45", "ethnicity": "hispanic", "physical": "athletic build, short dark hair", "clothing": "casual polo shirt" },
{ "role": "daughter", "type": "child", "age": "8-10", "ethnicity": "hispanic", "physical": "long dark hair, bright smile" }
],
"webhook_url": "https://yourserver.com/webhooks/vibepeak"
}'
const response = await fetch('https://api.vibepeak.ai/v1/families', {
method: 'POST',
headers: {
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json',
'Idempotency-Key': crypto.randomUUID()
},
body: JSON.stringify({
name: 'The Garcia Family',
members: [
{ role: 'mother', type: 'adult', age: '35-40', ethnicity: 'hispanic', physical: 'medium build, long dark hair', clothing: 'casual blouse' },
{ role: 'father', type: 'adult', age: '38-45', ethnicity: 'hispanic', physical: 'athletic build, short dark hair', clothing: 'casual polo shirt' },
{ role: 'daughter', type: 'child', age: '8-10', ethnicity: 'hispanic', physical: 'long dark hair, bright smile' }
],
webhook_url: 'https://yourserver.com/webhooks/vibepeak'
})
});
const family = await response.json();
console.log(`Family created: ${family.family_id} (task: ${family.task_id})`);
import requests
import uuid
response = requests.post(
'https://api.vibepeak.ai/v1/families',
headers={
'Authorization': 'Bearer vpk_live_xxxxx',
'Content-Type': 'application/json',
'Idempotency-Key': str(uuid.uuid4())
},
json={
'name': 'The Garcia Family',
'members': [
{'role': 'mother', 'type': 'adult', 'age': '35-40', 'ethnicity': 'hispanic', 'physical': 'medium build, long dark hair', 'clothing': 'casual blouse'},
{'role': 'father', 'type': 'adult', 'age': '38-45', 'ethnicity': 'hispanic', 'physical': 'athletic build, short dark hair', 'clothing': 'casual polo shirt'},
{'role': 'daughter', 'type': 'child', 'age': '8-10', 'ethnicity': 'hispanic', 'physical': 'long dark hair, bright smile'}
],
'webhook_url': 'https://yourserver.com/webhooks/vibepeak'
}
)
family = response.json()
print(f"Family created: {family['family_id']} (task: {family['task_id']})")
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task_id": "task_fam456xyz",
"status": "generating",
"livemode": true,
"_links": {
"self": "/v1/families/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task": "/v1/tasks/task_fam456xyz"
}
}
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task_id": "task_fam456xyz",
"status": "generating",
"livemode": false,
"_links": {
"self": "/v1/families/3fa85f64-5717-4562-b3fc-2c963f66afa6",
"task": "/v1/tasks/task_fam456xyz"
}
}
{
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"status": "pending_avatars"
}
{
"error": {
"code": "PLAN_NOT_ALLOWED",
"message": "Families are available on the Pro, Max and Enterprise plans. Upgrade your plan to use this feature.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_MEMBER_LIMIT_EXCEEDED",
"message": "A family must have between 1 and 6 members.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "FAMILY_LIMIT_REACHED",
"message": "You have reached the maximum number of families for your plan. Delete an existing family to create a new one.",
"request_id": "req_xyz123"
}
}
{
"error": {
"code": "INVALID_API_KEY",
"message": "The provided API key is invalid or has been revoked",
"request_id": "req_xyz123"
}
}
Polling for Completion
Poll the returnedtask_id via Get Task. Once status is completed, the task’s result contains the generated family assets:
{
"task_id": "task_fam456xyz",
"status": "completed",
"livemode": true,
"created_at": "2026-07-09T10:00:00Z",
"completed_at": "2026-07-09T10:02:30Z",
"result": {
"family_id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"reference_image_urls": [
"https://media.vibepeak.ai/families/garcia-family-mother.jpg",
"https://media.vibepeak.ai/families/garcia-family-father.jpg",
"https://media.vibepeak.ai/families/garcia-family-daughter.jpg"
],
"card_image_url": "https://media.vibepeak.ai/families/garcia-family-card.jpg"
}
}
status.
Generation runs one portrait at a time and then composes the group card, so
expect roughly 1-3 minutes per member. Poll every 10-15 seconds, or use
webhook_url and skip polling entirely.Error Codes
| Code | Status | Description |
|---|---|---|
VALIDATION_ERROR | 400 | Invalid request parameters |
MISSING_API_KEY | 401 | No Authorization header was sent |
INVALID_API_KEY | 401 | The API key is invalid or has been revoked |
PLAN_NOT_ALLOWED | 403 | Your plan doesn’t allow family creation (requires Pro, Max, or Enterprise) |
FAMILY_MEMBER_LIMIT_EXCEEDED | 422 | members must contain between 1 and 6 entries |
FAMILY_LIMIT_REACHED | 422 | You already have the maximum of 5 active families |
Credits
This endpoint always charges 0 credits.Next Steps
- Poll for status: Use Get Task (or Get Family) to check generation progress
- Wait for webhook: If configured, receive a
task.completednotification when the avatars are ready - Use in a video: Pass the family’s
idasselected_family_idon Create Living Property Video

