Personagens
Crie, atualize, arquive e restaure personagens via REST, gere candidatos a retrato, expressões, ângulos e clipes de movimento e aprove o retrato-âncora.
A API de personagens automatiza tudo o que o Estúdio de personagens faz. Você cria um personagem, gera candidatos a retrato, aprova um deles como retrato-âncora e adiciona expressões, ângulos, poses, variações de iluminação e clipes de movimento. Os nós de imagem e de vídeo então reaproveitam o personagem, para que a mesma pessoa tenha a mesma aparência em todas as tomadas.
As rotas funcionam em todas as edições. Elas aceitam um token Bearer: um token de API pessoal (ndr_…), um token de app OAuth (ndr_app_…) ou o token da sua sessão na Community Edition. Toda rota se limita a quem chama: você só vê e altera os seus próprios personagens. Veja Autenticação.
Endpoints
| Método | Caminho | O que faz |
|---|---|---|
GET | /v1/characters | Lista os seus personagens, uma página por vez. |
GET | /v1/characters/:id | Retorna um personagem com os jobs dele em andamento. |
POST | /v1/characters | Cria um personagem, ou atualiza um quando o corpo tem um id. |
POST | /v1/characters/:id/duplicate | Copia um personagem para um novo, com o sufixo (copy) no nome. |
DELETE | /v1/characters/:id | Arquiva um personagem. Ele pode ser restaurado. |
POST | /v1/characters/:id/restore | Restaura um personagem arquivado. |
GET | /v1/characters/:id/usage | Conta e lista os workflows que usam o personagem. |
POST | /v1/generate-character | Gera de 1 a 10 candidatos a retrato. |
POST | /v1/generate-character-asset | Gera uma expressão, pose, ângulo ou variação de iluminação. |
POST | /v1/generate-character-motion | Anima o personagem em um clipe de movimento. |
POST | /v1/characters/:id/approve-portrait | Aprova um candidato como retrato e escreve a descrição do personagem. |
POST | /v1/characters/:id/llm-caption | Escreve a descrição de novo a partir do retrato atual. |
Treinar um modelo dedicado com um personagem é um recurso do Nodaro Cloud com rotas próprias. Veja Treinamento de personagem.
O que um personagem contém
Um personagem é uma identidade salva. Os campos abaixo voltam de GET /v1/characters/:id em camelCase.
| Campo | O que contém |
|---|---|
id, name | O identificador e o nome de exibição. Os nomes são únicos por conta, sem diferenciar maiúsculas de minúsculas. |
description, gender, style, baseOutfit | Notas de identidade que moldam todas as imagens geradas do personagem. |
seedPrompt | Um prompt curto que enquadra o retrato, com até 4.000 caracteres. |
sourceImageUrl | O retrato-âncora. É definido quando você aprova um candidato. |
canonicalDescription | Uma descrição visual de cerca de 80 a 120 palavras, escrita pelo Nodaro quando o retrato é aprovado. Os prompts que fazem referência ao personagem a incluem. |
expressions, poses, angles, bodyAngles, lightingVariations, motions | Os grupos de mídias. Cada entrada é { name, url }. |
referencePhotos | Até 20 fotos reais, cada uma marcada com o enquadramento. |
realLifeRefsByVariant, referenceVideosByVariant | Fotos ou clipes de referência extras para uma variação, por exemplo a expressão smile. |
person, wardrobe | Escolhas estruturadas de aparência e de figurino, definidas na página Seletores do Estúdio de personagens. |
voice, personality | A voz e a personalidade do personagem. |
identityLock | Com que rigor as mídias geradas mantêm o rosto: off, soft ou strict. O padrão é off. |
deletedAt | Definido quando o personagem é arquivado. |
Os grupos de mídias
Cada grupo guarda variações do retrato-âncora. Você pode dar qualquer nome a uma variação; estes são os nomes predefinidos.
| Grupo | O que mostra | Variações predefinidas |
|---|---|---|
expressions | Cabeça e ombros, com outra emoção | neutral, smile, angry, surprised, sad, talking, laughing, disgusted, fearful, smirk, crying |
angles | Cabeça e ombros de outro ângulo de câmera | front, 3/4 left, left profile, right profile, 3/4 right |
bodyAngles | Corpo inteiro de outro ângulo, com os braços relaxados | front, 3/4 left, left profile, right profile, 3/4 right, back |
poses | Corpo inteiro em outra postura | standing, walking, sitting, running, crouching, pointing, fighting stance, jumping, turning |
lightingVariations | A mesma pose sob outra luz | daylight, night, dramatic |
motions | Clipes de vídeo do personagem em movimento | Qualquer rótulo, por exemplo walking ou head turn |
Listar personagens
GET /v1/characters retorna uma página dos seus personagens, dos mais recentes para os mais antigos. Continue pedindo páginas até nextCursor ser null: uma única resposta nunca traz “todos os personagens” de uma conta que passa do tamanho da página.
| Parâmetro de consulta | O que faz |
|---|---|
limit | Linhas por página. O padrão é 100 e o máximo é 500. |
cursor | O nextCursor da página anterior. |
projectId | Só os personagens de um projeto. |
archived | true lista os personagens arquivados em vez dos ativos. |
CURSOR=""
while :; do
PAGE=$(curl -s "https://app.nodaro.ai/v1/characters?limit=100${CURSOR:+&cursor=$CURSOR}" \
-H "Authorization: Bearer $NODARO_API_KEY")
echo "$PAGE" | jq -r '.characters[] | "\(.id) \(.name)"'
CURSOR=$(echo "$PAGE" | jq -r '.nextCursor // empty')
[ -z "$CURSOR" ] && break
doneimport { createClient, StaticTokenAuth } from '@nodaro/sdk'
const client = createClient({
baseUrl: 'https://app.nodaro.ai',
auth: new StaticTokenAuth(process.env.NODARO_API_KEY!),
})
const all = []
let cursor: string | undefined
do {
const page = await client.characters.list({ limit: 100, cursor })
all.push(...page.characters)
cursor = page.nextCursor ?? undefined
} while (cursor)nodaro characters list --limit 100 --json
nodaro characters list --archived{
"characters": [
{
"id": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94",
"name": "Kira",
"description": "young protagonist with auburn hair",
"sourceImageUrl": "https://cdn.nodaro.ai/characters/kira-portrait.png",
"expressions": [{ "name": "smile", "url": "https://cdn.nodaro.ai/characters/kira-smile.png" }]
}
],
"nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTA5LTIwVDEwOjAwOjAxWiJ9"
}O cursor é opaco. Envie de volta apenas um nextCursor que o servidor deu a você, e nunca guarde um cursor de uma versão para outra. Um cursor malformado gera 400 validation_error, não uma volta silenciosa para a primeira página. Os personagens criados enquanto você pagina não são incluídos; comece de novo sem cursor para vê-los.
Criar ou atualizar um personagem
POST /v1/characters cria um personagem quando o corpo não tem id e atualiza o personagem quando tem. Uma criação precisa de nodeId e name. nodeId vincula o personagem a um nó do canvas; use qualquer rótulo, como "scripted", quando criar o personagem por código.
Em uma atualização, só os campos que você envia são gravados. Os campos omitidos mantêm os valores, então um salvamento nunca sobrescreve grupos de mídias que um job em execução está preenchendo. Envie um grupo de mídias só quando quiser substituí-lo.
curl -X POST https://app.nodaro.ai/v1/characters \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"nodeId": "scripted",
"name": "Kira",
"description": "young protagonist with auburn hair",
"style": "realistic",
"seedPrompt": "kira portrait, warm natural lighting"
}'const { id } = await client.characters.create({
nodeId: 'scripted',
name: 'Kira',
description: 'young protagonist with auburn hair',
style: 'realistic',
seedPrompt: 'kira portrait, warm natural lighting',
})
await client.characters.update(id, { gender: 'female', identityLock: 'soft' })nodaro characters create --name "Kira" \
--description "young protagonist with auburn hair" \
--style realistic --seed-prompt "kira portrait, warm natural lighting"
nodaro characters update <id> --gender female{ "id": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94", "name": "Kira" }Prop
Type
person e wardrobe moldam só as gerações do retrato e das mídias do próprio personagem. Eles usam os mesmos catálogos do seletor Pessoa (Person). Veja Catálogos de seletores.
Quando um workflow é executado, a voice do personagem preenche qualquer nó Texto para fala (Text to Speech) conectado depois do personagem: a voz, o tipo de voz e o modelo recomendado. Um valor definido no próprio nó Texto para fala tem prioridade.
Gerar candidatos a retrato
POST /v1/generate-character inicia um job por candidato e retorna os IDs deles na hora. Consulte cada job periodicamente com a API de jobs até ele estar completed.
Com attachToCharacterId, o primeiro candidato a terminar vira o retrato do personagem. Para um único candidato, isso é tudo de que você precisa. Para vários candidatos, aprove o que preferir; a aprovação substitui o retrato.
curl -X POST https://app.nodaro.ai/v1/generate-character \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Kira",
"seedPrompt": "kira portrait, warm natural lighting",
"count": 4,
"attachToCharacterId": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94"
}'const { jobIds } = await client.characters.generate({
name: 'Kira',
seedPrompt: 'kira portrait, warm natural lighting',
count: 4,
attachToCharacterId: id,
})nodaro characters generate <id> --count 4 \
--seed-prompt "kira portrait, warm natural lighting" --watch{
"jobId": "a1c4e8f2-5b3d-4e6a-8f7c-2d9b1e0a3c5f",
"jobIds": [
"a1c4e8f2-5b3d-4e6a-8f7c-2d9b1e0a3c5f",
"b7d2f9a1-6c4e-4a8b-9d3f-3e0c2f1b4d6a",
"c3e5a7b9-8d1f-4c2e-a6b8-4f1d3a2c5e7b",
"d9f1b3c5-2e4a-4d6f-b8c1-5a2e4b3d6f8c"
]
}Prop
Type
quality e resolution definem o preço do job exatamente como no Gerar imagem (Generate Image): uma execução em 4K ou de alta qualidade custa mais que o mesmo modelo no nível básico. Um valor que o modelo não aceita é trocado pelo mais próximo que ele aceita, nunca recusado, e os créditos seguem o valor trocado. Essas rotas não retornam uma lista adjustments; leia o valor que foi executado no input_data do job, em GET /v1/jobs/:id.
Gerar uma variação de expressão, ângulo, pose ou iluminação
POST /v1/generate-character-asset gera uma variação do retrato-âncora e retorna { jobId }. Para adicionar o resultado ao personagem, envie os três campos de anexo: attachToCharacterId, attachToColumn e attachName. Quando o job termina, o worker acrescenta { name: attachName, url } a esse grupo.
curl -X POST https://app.nodaro.ai/v1/generate-character-asset \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Kira",
"assetType": "expressions",
"variant": "smile",
"attachToCharacterId": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94",
"attachToColumn": "expressions",
"attachName": "smile"
}'await client.characters.generateAsset({
name: 'Kira',
assetType: 'bodyAngles',
variant: 'front',
attachToCharacterId: id,
attachToColumn: 'body_angles',
attachName: 'front',
})nodaro characters generate-asset <id> --asset-type expressions --variant smile --watch| Campo | O que faz |
|---|---|
name | Obrigatório. O nome do personagem. |
assetType | Obrigatório. expressions, poses, lighting, headAngles, angles (igual a headAngles), bodyAngles ou custom. |
variant | Obrigatório. A variação a gerar, de 1 a 100 caracteres, por exemplo smile ou 3/4 left. |
description | Uma descrição de uma frase desta variação, com até 1.000 caracteres. Quando você anexa a um personagem e omite este campo, o Nodaro rascunha uma a partir da descrição canônica do personagem. |
sourceImageUrl | A imagem a variar, normalmente o retrato aprovado. |
provider, quality, resolution | O modelo de imagem e o nível de saída dele, com preço igual ao do Gerar imagem. |
aspectRatio | 1:1, 3:4, 16:9 ou 9:16. O padrão depende do tipo: 1:1 para expressões, 9:16 para poses e ângulos do corpo e 3:4 para os demais. |
attachToCharacterId, attachToColumn, attachName | Para onde vai o resultado. attachToColumn é expressions, poses, angles, body_angles ou lighting_variations. Uma variação custom precisa indicar a coluna. |
Quando você anexa a variação a um personagem, as fotos reais salvas na chave da variação em realLifeRefsByVariant são enviadas com a requisição automaticamente.
Animar o personagem
POST /v1/generate-character-motion transforma uma imagem fixa do personagem em um clipe de vídeo e retorna { jobId }. Com attachToCharacterId e attachName, o clipe é acrescentado ao grupo motions quando termina.
Quando você anexa a um personagem, o Nodaro escolhe o quadro inicial nesta ordem:
- O
sourceImageUrlque você envia, que sempre tem prioridade. - A entrada
frontdebodyAngles. Um quadro de corpo inteiro fica muito melhor animado do que um retrato de cabeça e ombros. - Qualquer outra entrada de
bodyAngles, da mais recente para a mais antiga. - O retrato-âncora.
Para obter os melhores clipes, gere um ângulo do corpo front antes do primeiro movimento.
curl -X POST https://app.nodaro.ai/v1/generate-character-motion \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Kira",
"motionPrompt": "slow head turn left, soft smile",
"provider": "kling",
"attachToCharacterId": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94",
"attachName": "head turn"
}'await client.characters.generateMotion({
name: 'Kira',
motionPrompt: 'slow head turn left, soft smile',
provider: 'kling',
attachToCharacterId: id,
attachName: 'head turn',
})nodaro characters generate-motion <id> \
--motion-prompt "slow head turn left, soft smile" --attach-name "head turn" --watch| Campo | O que faz |
|---|---|
name | Obrigatório. O nome do personagem. |
motionPrompt | Obrigatório. O que se move e como, de 1 a 2.000 caracteres. |
provider | O modelo de vídeo: kling (o padrão), kling-turbo, kling-3.0, wan-i2v ou wan-2.7-i2v. |
sourceImageUrl | O quadro inicial. Obrigatório quando você não anexa a um personagem. |
description, motionDescription | Uma descrição visual (até 1.000 caracteres) e uma descrição do movimento (até 500). O Nodaro rascunha as duas quando você anexa e as omite. |
aspectRatio | 1:1, 3:4, 16:9 ou 9:16. O padrão é 9:16, um clipe vertical de corpo inteiro. |
attachToCharacterId, attachName | O personagem e o nome do clipe em motions. |
Estes modelos podem animar um personagem. O preço é o preço de imagem para vídeo do modelo:
| Modelo | Desenvolvedor | Modos | Créditos | Detalhes |
|---|---|---|---|---|
| Kling 2.6 | Kuaishou | Imagem para vídeo, Texto para vídeo | a partir de 152 | Kling 2.6 I2V — movimento muito realista. Clipes de 5 ou 10 s, com áudio nativo opcional. |
| Kling 2.5 Turbo Pro | Kuaishou | Imagem para vídeo, Texto para vídeo | a partir de 121 | Kling mais rápido — boa qualidade por um custo menor. Aceita quadro final. |
| Kling 3.0 | Kuaishou | Imagem para vídeo, Texto para vídeo | a partir de 297 | Kling 3.0 premium — duração variável de 3 a 15 s, áudio nativo, 720P/1080P. |
| Wan 2.6 I2V | Alibaba | Imagem para vídeo | a partir de 193 | Wan 2.6 de imagem para vídeo — 5, 10 ou 15 s em 720p/1080p. |
| Wan 2.7 I2V | Alibaba | Imagem para vídeo | 207 | Wan 2.7 de imagem para vídeo — de 2 a 15 s em 720p/1080p, com suporte a quadro inicial e final. |
Aprovar um retrato
POST /v1/characters/:id/approve-portrait define um candidato concluído como o retrato-âncora. Na mesma chamada, o Nodaro analisa o retrato e escreve canonicalDescription, o texto que os prompts seguintes usam para descrever o personagem. Sem essa descrição, um personagem varia muito mais de uma cena para outra.
O candidato precisa ser um job completed que pertence a você. Se a escrita da descrição falhar, o retrato continua definido e canonicalDescription fica null; chame POST /v1/characters/:id/llm-caption para tentar de novo. As duas rotas podem ser repetidas com segurança. Aprovar é gratuito. Cada chamada de llm-caption custa 8 créditos, e uma chamada com falha (502) é reembolsada.
curl -X POST https://app.nodaro.ai/v1/characters/3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94/approve-portrait \
-H "Authorization: Bearer $NODARO_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "candidateJobId": "b7d2f9a1-6c4e-4a8b-9d3f-3e0c2f1b4d6a" }'const { portraitUrl, canonicalDescription } =
await client.characters.approvePortrait(id, jobIds[1])
if (canonicalDescription === null) {
await client.characters.recaption(id)
}nodaro characters approve-portrait <id> --job <jobId>
nodaro characters recaption <id>{
"portraitUrl": "https://cdn.nodaro.ai/characters/kira-portrait-2.png",
"canonicalDescription": "Kira is a woman in her mid-twenties with shoulder-length auburn hair, green eyes and light freckles..."
}llm-caption retorna { canonicalDescription }. A rota responde 400 no_portrait quando o personagem ainda não tem retrato e 502 quando não foi possível escrever a descrição.
Arquivar, restaurar e copiar um personagem
- Arquivar.
DELETE /v1/characters/:idarquiva o personagem e retorna{ success: true, archived: true }. O personagem sai da lista padrão, masGET /v1/characters/:idcontinua retornando o personagem, então os workflows que o usam continuam funcionando. No Nodaro Cloud, arquivar também cancela um treinamento em andamento, reembolsa os créditos dele e remove o modelo treinado. - Restaurar.
POST /v1/characters/:id/restoreretorna{ id, name }. Quando um personagem ativo já tem o mesmo nome, o Nodaro adiciona o sufixo(restored)e retorna o novo nome. - Excluir para sempre. Nenhuma rota da API exclui um personagem permanentemente. Use a visualização de arquivados na biblioteca do editor.
- Copiar.
POST /v1/characters/:id/duplicateretorna{ id, name }de um novo personagem com o sufixo(copy). A cópia compartilha as URLs das mídias do original até você gerá-las de novo. - Uso.
GET /v1/characters/:id/usageretorna{ workflowCount, workflows: [{ id, name }] }. Verifique o uso antes de arquivar um personagem.
| Ação | curl | TypeScript SDK | CLI |
|---|---|---|---|
| Arquivar | DELETE /v1/characters/:id | client.characters.delete(id) | nodaro characters delete <id> |
| Restaurar | POST /v1/characters/:id/restore | client.characters.restore(id) | nodaro characters restore <id> |
| Copiar | POST /v1/characters/:id/duplicate | client.characters.duplicate(id) | nodaro characters duplicate <id> |
| Uso | GET /v1/characters/:id/usage | client.characters.usage(id) | nodaro characters usage <id> |
Um fluxo completo: criar, gerar, aprovar e adicionar variações
Criar o personagem
POST /v1/characters com nodeId, name e um seedPrompt. Guarde o id retornado.
Gerar candidatos a retrato
POST /v1/generate-character com count: 4 e attachToCharacterId. Consulte periodicamente cada job pelo ID até ele estar completed ou failed.
Aprovar o seu favorito
POST /v1/characters/:id/approve-portrait com o ID do job desse candidato. O retrato e a descrição canônica são definidos.
Adicionar variações e movimento
Gere um ângulo do corpo front e, depois, expressões e poses com POST /v1/generate-character-asset, e clipes com POST /v1/generate-character-motion.
Usar o personagem em outras gerações
Depois que as mídias existirem, envie as URLs delas como imagens de referência para o Gerar imagem ou o Gerar vídeo (Generate Video). Por exemplo, leia a entrada smile de expressions e envie a URL dela como referência com o seu prompt. URLs explícitas são a opção mais simples no código, porque não dependem de como um workflow está conectado. Veja Executar um único nó para os campos da requisição.
Em um workflow, conecte o nó Personagem (Character Asset) ao nó de imagem ou de vídeo, ou mencione o personagem no prompt com @, por exemplo @kira:1:smile. Papéis de referência explica a sintaxe das menções, e Personagens consistentes, o método completo.
Uso pelo MCP
Os assistentes de IA usam as mesmas rotas por meio destas ferramentas. Arquivar e restaurar não estão disponíveis pelo MCP, de propósito.
| Ferramenta | O que faz |
|---|---|
list_characters, get_character | Encontra um personagem e lê as URLs das mídias dele. |
create_character, update_character | Cria um personagem ou muda os campos de identidade dele. |
generate_character | Gera um retrato (kind: "main") ou uma variação (kind: "asset"). |
generate_character_motion | Anima o personagem em um clipe. |
approve_portrait, recaption_character | Aprova um retrato ou escreve a descrição dele de novo. |
Veja a Referência das ferramentas MCP.
Créditos
No Nodaro Cloud, a geração de personagens usa os mesmos preços em créditos dos nós correspondentes.
| Rota | Preço |
|---|---|
POST /v1/generate-character | O preço do modelo de imagem vezes count, reservado para todos os candidatos antes de o primeiro job começar. |
POST /v1/generate-character-asset | O preço do modelo de imagem, por variação. |
POST /v1/generate-character-motion | O preço de imagem para vídeo do modelo de vídeo, por clipe. |
approve-portrait | Gratuito. |
llm-caption | 8 créditos por chamada. |
A página de cada modelo informa o preço exato. Veja Créditos.
Erros
Os erros usam o envelope padrão, { "error": { "code", "message" } }. Veja Erros.
| Status | Código | Significado |
|---|---|---|
400 | validation_error | Um campo está ausente ou é inválido, um cursor está malformado, ou uma requisição de geração não tem seedPrompt, description nem referencePhotos. |
400 | no_portrait | llm-caption foi chamado antes de o personagem ter um retrato. |
401 | unauthorized | O token está ausente, é inválido ou foi revogado. |
402 | insufficient_credits | Só no Nodaro Cloud. A conta não cobre a reserva. |
404 | not_found | Nenhum personagem ou job com esse ID pertence a você. |
409 | name_taken | Outro personagem ativo já tem esse nome. |
502 | — | Não foi possível escrever a descrição canônica. O retrato não muda. Tente de novo. |
Perguntas frequentes
Páginas relacionadas
Estúdio de personagens
Personagens consistentes
Treinamento de personagem
Personagem
Jobs
Última atualização
Webhooks
Inicie workflows de qualquer sistema pela URL de um Gatilho de webhook, agende-os pela API e envie os resultados ao seu servidor com a Saída de webhook.
Objetos
API REST de objetos: crie e arquive adereços e produtos, gere e aprove a imagem principal e gere variações de material e ângulo e clipes de movimento.