curl -X POST "https://api.hooked.so/v1/avatar/create/generate" \
-H "x-api-key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{ "description": "28 year old woman with curly hair in a bright kitchen, holding a coffee", "name": "Maya" }'
const headers = { "x-api-key": process.env.HOOKED_API_KEY, "Content-Type": "application/json" };
const started = await fetch("https://api.hooked.so/v1/avatar/create/generate", {
method: "POST",
headers,
body: JSON.stringify({ description: "28 year old woman with curly hair in a bright kitchen, holding a coffee", name: "Maya" }),
}).then((r) => r.json());
let avatar = started.data;
while (avatar.status === "PROCESSING") {
await new Promise((resolve) => setTimeout(resolve, 5000));
avatar = (await fetch(`https://api.hooked.so/v1/avatar/${avatar.id}`, { headers }).then((r) => r.json())).data;
}
console.log(avatar.status, avatar.id);
import os, time
import requests
headers = {"x-api-key": os.environ["HOOKED_API_KEY"]}
avatar = requests.post(
"https://api.hooked.so/v1/avatar/create/generate",
headers=headers,
json={"description": "28 year old woman with curly hair in a bright kitchen, holding a coffee", "name": "Maya"},
).json()["data"]
while avatar["status"] == "PROCESSING":
time.sleep(5)
avatar = requests.get(f"https://api.hooked.so/v1/avatar/{avatar['id']}", headers=headers).json()["data"]
print(avatar["status"], avatar["id"])
{
"success": true,
"message": "Avatar generation started",
"data": {
"id": "cm7a1v9t20003ab12cd34ef56",
"name": "Maya",
"type": "AI",
"gender": "Female",
"age": "Adult",
"image": null,
"status": "PROCESSING",
"situation": [],
"emotions": [],
"skinTone": "medium",
"isCustom": true,
"source": "custom",
"createdAt": "2026-10-05T09:12:44.000Z",
"usedCredits": 4
}
}
{
"success": false,
"message": "description: Required"
}
Generate Avatar
Generate one of your team’s own avatars from a description
curl -X POST "https://api.hooked.so/v1/avatar/create/generate" \
-H "x-api-key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{ "description": "28 year old woman with curly hair in a bright kitchen, holding a coffee", "name": "Maya" }'
const headers = { "x-api-key": process.env.HOOKED_API_KEY, "Content-Type": "application/json" };
const started = await fetch("https://api.hooked.so/v1/avatar/create/generate", {
method: "POST",
headers,
body: JSON.stringify({ description: "28 year old woman with curly hair in a bright kitchen, holding a coffee", name: "Maya" }),
}).then((r) => r.json());
let avatar = started.data;
while (avatar.status === "PROCESSING") {
await new Promise((resolve) => setTimeout(resolve, 5000));
avatar = (await fetch(`https://api.hooked.so/v1/avatar/${avatar.id}`, { headers }).then((r) => r.json())).data;
}
console.log(avatar.status, avatar.id);
import os, time
import requests
headers = {"x-api-key": os.environ["HOOKED_API_KEY"]}
avatar = requests.post(
"https://api.hooked.so/v1/avatar/create/generate",
headers=headers,
json={"description": "28 year old woman with curly hair in a bright kitchen, holding a coffee", "name": "Maya"},
).json()["data"]
while avatar["status"] == "PROCESSING":
time.sleep(5)
avatar = requests.get(f"https://api.hooked.so/v1/avatar/{avatar['id']}", headers=headers).json()["data"]
print(avatar["status"], avatar["id"])
{
"success": true,
"message": "Avatar generation started",
"data": {
"id": "cm7a1v9t20003ab12cd34ef56",
"name": "Maya",
"type": "AI",
"gender": "Female",
"age": "Adult",
"image": null,
"status": "PROCESSING",
"situation": [],
"emotions": [],
"skinTone": "medium",
"isCustom": true,
"source": "custom",
"createdAt": "2026-10-05T09:12:44.000Z",
"usedCredits": 4
}
}
{
"success": false,
"message": "description: Required"
}
Overview
Generates an avatar from a description, the same way Generate with AI does in the dashboard: one portrait with the image model you pick, which then becomes the avatar. The call answers202 at once with the avatar in PROCESSING; the portrait takes about 20-60 seconds. Poll Get Avatar until status is COMPLETED (use the id as avatarId) or FAILED.
| Field | Default | Values |
|---|---|---|
model | gpt_image_2 | An id of GET /v1/catalog/image-models |
aspectRatio | ratio_9_16 | ratio_9_16, ratio_1_1, ratio_16_9 |
artStyle | realistic | A library id of GET /v1/catalog/visual-styles (anime, claymation, …). Custom styles are not accepted |
curl -X POST "https://api.hooked.so/v1/avatar/create/generate" \
-H "x-api-key: your_api_key_here" \
-H "Content-Type: application/json" \
-d '{ "description": "28 year old woman with curly hair in a bright kitchen, holding a coffee", "name": "Maya" }'
const headers = { "x-api-key": process.env.HOOKED_API_KEY, "Content-Type": "application/json" };
const started = await fetch("https://api.hooked.so/v1/avatar/create/generate", {
method: "POST",
headers,
body: JSON.stringify({ description: "28 year old woman with curly hair in a bright kitchen, holding a coffee", name: "Maya" }),
}).then((r) => r.json());
let avatar = started.data;
while (avatar.status === "PROCESSING") {
await new Promise((resolve) => setTimeout(resolve, 5000));
avatar = (await fetch(`https://api.hooked.so/v1/avatar/${avatar.id}`, { headers }).then((r) => r.json())).data;
}
console.log(avatar.status, avatar.id);
import os, time
import requests
headers = {"x-api-key": os.environ["HOOKED_API_KEY"]}
avatar = requests.post(
"https://api.hooked.so/v1/avatar/create/generate",
headers=headers,
json={"description": "28 year old woman with curly hair in a bright kitchen, holding a coffee", "name": "Maya"},
).json()["data"]
while avatar["status"] == "PROCESSING":
time.sleep(5)
avatar = requests.get(f"https://api.hooked.so/v1/avatar/{avatar['id']}", headers=headers).json()["data"]
print(avatar["status"], avatar["id"])
{
"success": true,
"message": "Avatar generation started",
"data": {
"id": "cm7a1v9t20003ab12cd34ef56",
"name": "Maya",
"type": "AI",
"gender": "Female",
"age": "Adult",
"image": null,
"status": "PROCESSING",
"situation": [],
"emotions": [],
"skinTone": "medium",
"isCustom": true,
"source": "custom",
"createdAt": "2026-10-05T09:12:44.000Z",
"usedCredits": 4
}
}
{
"success": false,
"message": "description: Required"
}
Errors
| Status | When |
|---|---|
| 400 | Invalid JSON, description: Required (up to 2,000 characters), or an invalid name, model, aspectRatio or artStyle |
| 401 | Missing or invalid API key |
| 402 | BYOK without its keys, no live plan, or not enough credits. Nothing was created or charged |
| 403 | The team does not have the Hooked app product |
PROCESSING after 15 minutes) leaves the avatar FAILED and gives the credits back. Delete it with Delete Avatar and try again.Authorizations
Headers
Makes the request safe to retry. 1-255 printable ASCII characters, one per operation (your job id, or a UUID you store), reused on every retry. Within 24 hours the same key with the same body answers with the first response and the header Idempotent-Replayed: true, without running or charging again. Keys are scoped to your team and the endpoint. 5xx answers and refusals before anything ran (401, 402, 403, 409, 429) are not kept. See Idempotency.
1 - 255^[\x20-\x7E]+$Body
Who the avatar is and where: age, gender, look, what they are doing, the setting. For example 28 year old woman with curly hair in a bright kitchen, holding a coffee.
2000The avatar's name. Defaults to the first words of description.
60Image model: an id of GET /v1/catalog/image-models.
ratio_9_16, ratio_1_1, ratio_16_9 Visual style: a library id of GET /v1/catalog/visual-styles (realistic, anime, ...). Custom styles are not accepted.