# Criaturas

> Crie e gerencie animais e criaturas via REST: gere imagens principais, ângulos, poses, variações e clipes de movimento, e dê uma voz à criatura.

Source: https://nodaro.ai/pt-BR/docs/developers/api/creatures

A **API de criaturas** gerencia animais e outros seres não humanos com uma aparência fixa: um animal de estimação, um dragão, um mascote. Uma criatura tem uma imagem principal aprovada, uma descrição escrita e imagens de variações. Os nós de imagem e de vídeo reaproveitam a criatura para que ela tenha a mesma aparência em todas as tomadas. As criaturas funcionam como os [objetos](https://nodaro.ai/docs/developers/api/objects), com três acréscimos: uma `species` em texto livre, painéis com nome e uma voz opcional.

As rotas funcionam em todas as edições e 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. Veja [Autenticação](https://nodaro.ai/docs/developers/api/authentication). A CLI não tem comandos de criaturas; use REST, o SDK ou o MCP.

## Endpoints
| Método | Caminho | O que faz |
| --- | --- | --- |
| `GET` | `/v1/creatures` | Lista as suas criaturas. |
| `GET` | `/v1/creatures/:id` | Retorna uma criatura com os jobs dela em andamento. |
| `POST` | `/v1/creatures` | Cria uma criatura, ou atualiza uma quando o corpo tem um `id`. |
| `DELETE` | `/v1/creatures/:id` | Arquiva uma criatura. Ela pode ser restaurada. |
| `DELETE` | `/v1/creatures/:id?permanent=true` | Exclui para sempre uma criatura arquivada e os arquivos dela. |
| `POST` | `/v1/creatures/:id/restore` | Restaura uma criatura arquivada. |
| `POST` | `/v1/generate-creature` | Gera de 1 a 10 candidatos a imagem principal. |
| `POST` | `/v1/generate-creature-asset` | Gera um ângulo, uma pose, uma variação ou uma variação personalizada. |
| `POST` | `/v1/generate-creature-motion` | Anima a imagem principal em um clipe de movimento. |
| `POST` | `/v1/creatures/:id/approve-main-image` | Aprova um candidato como imagem principal e escreve a descrição da criatura. |
| `POST` | `/v1/creatures/:id/llm-caption` | Escreve a descrição de novo a partir da imagem principal atual. |

## O que uma criatura contém
| Campo | O que contém |
| --- | --- |
| `id`, `name`, `description` | O identificador, o nome de exibição e as notas de identidade. |
| `species` | Texto livre, por exemplo `dragon`, `wolf` ou `tabby cat`. É o assunto do prompt da imagem principal. |
| `category`, `style` | A categoria em texto livre e o estilo visual: `realistic`, `anime`, `3d-pixar` ou `illustration`. |
| `sourceImageUrl` | A imagem principal âncora, definida quando você aprova um candidato. |
| `canonicalDescription` | Uma descrição visual de cerca de 80 a 120 palavras, escrita pelo Nodaro quando a imagem principal é aprovada. |
| `styleLock` | Se as variações são geradas a partir da imagem principal. `true` por padrão. |
| `angles`, `poses`, `variations`, `motionClips` | Os grupos de mídias. Cada entrada é `{ name, url }`; `motionClips` guarda vídeos. |
| `boards` | Até 24 painéis com nome: folhas de referência densas, uma para cada visual ou clima. |
| `voice` | A voz da criatura, ou `null`. |
| `referencePhotos` | Até 20 fotos do painel de inspiração, cada uma `{ kind, url }`. `kind` é `front`, `side`, `detail`, `context`, `moodBoard` ou `other`. |
| `pendingJobs` | Só em `GET /v1/creatures/:id`: os jobs de variações ainda em execução. |

## Listar e ler criaturas
`GET /v1/creatures` retorna as suas criaturas ativas. A rota aceita os mesmos parâmetros da lista de objetos: `archived=true`, `projectId` e um `limit` opcional (no máximo 500) com `cursor`. Sem `limit`, você recebe a lista completa. Com ele, recebe uma página e um `nextCursor` para enviar de volta até ele ser `null`.

`GET /v1/creatures/:id` retorna uma criatura. Uma criatura arquivada retorna `404 not_found`.

**curl**

```bash
curl "https://app.nodaro.ai/v1/creatures?limit=50" \
  -H "Authorization: Bearer $NODARO_API_KEY"
```

**TypeScript SDK**

```ts

const client = createClient({
baseUrl: 'https://app.nodaro.ai',
auth: new StaticTokenAuth(process.env.NODARO_API_KEY!),
})

const { creatures, nextCursor } = await client.creatures.list({ limit: 50 })
const { creatures: archived } = await client.creatures.listArchived()
```

## Criar ou atualizar uma criatura
`POST /v1/creatures` cria uma criatura quando o corpo não tem `id` e a atualiza quando tem. Uma criação precisa de `nodeId` e `name`; use qualquer rótulo em `nodeId`, como `"scripted"`, quando não houver um nó no canvas. Uma criação retorna `{ id }`, e uma atualização retorna `{ id, updatedAt }`.

Em uma atualização, só os campos que você envia são gravados. Uma atualização nunca grava os grupos de mídias, mas `boards` é você quem define: envie a lista inteira para substituí-la. Envie `expectedUpdatedAt` para que a atualização seja recusada com `409 concurrent_modification` quando alguém tiver alterado a criatura depois que você a leu.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/creatures \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
"nodeId": "scripted",
"name": "Ember",
"species": "red dragon",
"description": "Young dragon with copper scales and a chipped left horn",
"style": "realistic"
}'
```

**TypeScript SDK**

```ts
const { id } = await client.creatures.create({
nodeId: 'scripted',
name: 'Ember',
species: 'red dragon',
description: 'Young dragon with copper scales and a chipped left horn',
style: 'realistic',
})

await client.creatures.update(id, {
voice: { voiceId: 'Callum', voiceName: 'Callum', traits: 'gravelly, slow', voiceType: 'premade' },
})
```

<TypeTable
type={{
id: { type: 'string (uuid)', description: 'A criatura a atualizar. Omita para criar uma criatura.' },
nodeId: { type: 'string', description: 'Obrigatório na criação. O nó do canvas ao qual a criatura pertence, ou qualquer rótulo quando não há nenhum.' },
name: { type: 'string', description: 'Obrigatório na criação.' },
species: { type: 'string', description: 'O que a criatura é, em texto livre.' },
description: { type: 'string', description: 'O que torna a criatura única.' },
category: { type: 'string', description: 'Texto livre.' },
style: { type: 'string', description: 'realistic, anime, 3d-pixar ou illustration.' },
styleLock: { type: 'boolean', description: 'Gera as variações a partir da imagem principal aprovada.', default: 'true' },
referencePhotos: { type: 'array', description: 'Até 20 fotos { kind, url } do painel de inspiração.' },
voice: { type: 'object | null', description: '{ voiceId, voiceName, traits, voiceType?, ttsProvider? }. Envie null na atualização para limpar.' },
boards: { type: 'array', description: 'Só na atualização. Até 24 painéis { name, url }. Substitui a lista inteira.' },
canonicalDescription: { type: 'string', description: 'Substitui a descrição escrita.' },
projectId: { type: 'string (uuid)', description: 'O projeto em que a criatura fica guardada.' },
expectedUpdatedAt: { type: 'string (ISO 8601)', description: 'Na atualização: recusa a gravação com 409 quando a criatura mudou desde esse carimbo de data e hora.' },
}}
/>

### Painéis
Um painel é uma folha de referência densa da criatura para um visual ou um clima. Renderize um painel com a predefinição `generate-image/creature-board` do [**Gerar imagem** (Generate Image)](https://nodaro.ai/docs/nodes/image/generate-image) e salve a URL dele em `boards`. Veja [Predefinições](https://nodaro.ai/docs/developers/api/presets) e [Painéis de referência e grades de consistência](https://nodaro.ai/docs/guides/reference-boards).

## Gerar imagens principais e variações
`POST /v1/generate-creature` inicia um job por candidato e retorna `jobIds`; uma requisição de um único candidato também retorna `jobId`. Com `attachToCreatureId` e `count` igual a 1, o resultado vira a imagem principal quando o job termina. Com vários candidatos, nada é anexado; aprove o que preferir.

`POST /v1/generate-creature-asset` gera uma variação e retorna `{ jobId }`. `assetType` é `angles`, `poses`, `variations` ou `custom`. Envie `attachToCreatureId`, `attachToColumn` (`angles`, `poses` ou `variations`) e `attachName` para acrescentar o resultado a um grupo; uma variação `custom` precisa indicar a coluna.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/generate-creature \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
"name": "Ember",
"species": "red dragon",
"count": 1,
"attachToCreatureId": "0b8d6f4a-2c1e-4b9d-8f3a-7e5c1d9b3f2a"
}'

curl -X POST https://app.nodaro.ai/v1/generate-creature-asset \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
"name": "Ember",
"assetType": "poses",
"variant": "wings spread",
"attachToCreatureId": "0b8d6f4a-2c1e-4b9d-8f3a-7e5c1d9b3f2a",
"attachToColumn": "poses",
"attachName": "wings spread"
}'
```

**TypeScript SDK**

```ts
const { jobIds } = await client.creatures.generate({
name: 'Ember',
species: 'red dragon',
count: 4,
})

await client.creatures.generateAsset({
name: 'Ember',
assetType: 'poses',
variant: 'wings spread',
attachToCreatureId: id,
attachToColumn: 'poses',
attachName: 'wings spread',
})
```

| Campo | Rota | O que faz |
| --- | --- | --- |
| `name` | as duas | Obrigatório. O nome da criatura. |
| `species`, `description`, `category`, `style` | as duas | A identidade da criatura. |
| `count` | imagem principal | Candidatos a gerar, de 1 a 10. O padrão é 1. |
| `assetType`, `variant` | variação | Obrigatórios. O tipo de variação e o nome dela. |
| `provider` | as duas | O ID do modelo de imagem. Omita para usar o modelo padrão. |
| `sourceImageUrl` | as duas | Uma imagem para usar como ponto de partida ou para variar. |
| `seedPromptHint` | as duas | Um trecho de prompt a incorporar ao prompt, por exemplo uma escolha do seletor [**Animal**](https://nodaro.ai/docs/nodes/creative-controls/animal). |

## Animar a imagem principal
`POST /v1/generate-creature-motion` transforma uma imagem da criatura em um clipe, como um loop em repouso, uma caminhada à espreita ou um ataque, e retorna `{ jobId }`. `sourceImageUrl` é obrigatório. Com `attachToCreatureId` e `attachName`, o clipe é acrescentado a `motionClips`.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/generate-creature-motion \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
"name": "Ember",
"motionPrompt": "slow idle breathing, tail sways, smoke curls from the nostrils",
"sourceImageUrl": "https://cdn.nodaro.ai/creatures/ember-main.png",
"attachToCreatureId": "0b8d6f4a-2c1e-4b9d-8f3a-7e5c1d9b3f2a",
"attachName": "idle"
}'
```

**TypeScript SDK**

```ts
await client.creatures.generateMotion({
name: 'Ember',
motionPrompt: 'slow idle breathing, tail sways, smoke curls from the nostrils',
sourceImageUrl: ember.sourceImageUrl!,
provider: 'kling-turbo',
duration: 5,
attachToCreatureId: id,
attachName: 'idle',
})
```

| Campo | O que faz |
| --- | --- |
| `name`, `motionPrompt`, `sourceImageUrl` | Obrigatórios. O nome da criatura, o movimento e o quadro inicial. |
| `provider` | `kling-turbo` (o padrão), `kling`, `kling-3.0`, `minimax`, `hailuo-2.3`, `wan-i2v`, `seedance` ou `bytedance-lite`. |
| `duration` | A duração do clipe em segundos. Precisa ser uma duração que o modelo oferece; omita para usar o padrão do modelo. |
| `aspectRatio` | `1:1` (o padrão), `3:4`, `16:9`, `9:16` ou `4:3`. |
| `refineFromVideoUrl` | Um clipe existente para refinar com o novo prompt, em vez de começar de novo a partir da imagem. |
| `attachToCreatureId`, `attachName` | A criatura e o nome do clipe em `motionClips`. |

| Model | Maker | Modes | Credits | Details |
| --- | --- | --- | --- | --- |
| [Kling 2.5 Turbo Pro](https://nodaro.ai/docs/models/video/kling-2-5-turbo-pro) | Kuaishou | Image to video, Text to video | a partir de 121 | Faster Kling — good quality at lower cost. Supports end frame. |
| [Kling 2.6](https://nodaro.ai/docs/models/video/kling-2-6) | Kuaishou | Image to video, Text to video | a partir de 152 | Kling 2.6 I2V — strong motion realism. 5s/10s, optional native audio. |
| [Kling 3.0](https://nodaro.ai/docs/models/video/kling-3-0) | Kuaishou | Image to video, Text to video | a partir de 297 | Premium Kling 3.0 — variable 3-15s duration, native audio, 720P/1080P. |
| [Hailuo 02 I2V Pro](https://nodaro.ai/docs/models/video/hailuo-02-i2v-pro) | MiniMax | Image to video, Text to video | 158 | Hailuo 02 Pro — strong photoreal motion, fixed 5-second clips. Supports end frame. |
| [Hailuo 2.3 Standard](https://nodaro.ai/docs/models/video/hailuo-2-3-standard) | MiniMax | Image to video | a partir de 83 | Cheaper Hailuo 2.3 tier — good baseline quality. |
| [Wan 2.6 I2V](https://nodaro.ai/docs/models/video/wan-2-6-i2v) | Alibaba | Image to video | a partir de 193 | Wan 2.6 image-to-video — 5/10/15s at 720p/1080p. |
| [Bytedance Lite I2V](https://nodaro.ai/docs/models/video/bytedance-lite-i2v) | Bytedance | Image to video, Text to video | 63 | Cheapest Bytedance video tier with end-frame support. |

`seedance` (Seedance 1.5 Pro) é um modelo mais antigo. As rotas ainda o aceitam, mas o catálogo de modelos (`GET /v1/models`) não o lista mais, por isso a tabela não tem uma linha para ele.

## Aprovar uma imagem principal
`POST /v1/creatures/:id/approve-main-image` com `{ candidateJobId, expectedUpdatedAt? }` define um candidato concluído como imagem principal e escreve `canonicalDescription` na mesma chamada. A rota retorna `{ sourceImageUrl, canonicalDescription }`. Quando a escrita da descrição falha, a imagem principal continua definida e a descrição fica vazia; o SDK retorna `null`.

`POST /v1/creatures/:id/llm-caption` escreve a descrição de novo e retorna `{ canonicalDescription }`. A rota responde `502` quando não consegue escrever a descrição e `400 main_image_required` quando ainda não há imagem principal. 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**

```bash
curl -X POST https://app.nodaro.ai/v1/creatures/0b8d6f4a-2c1e-4b9d-8f3a-7e5c1d9b3f2a/approve-main-image \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "candidateJobId": "1c9e7a5b-3d2f-4c8e-9a4b-8f6d2e1a4c3b" }'
```

**TypeScript SDK**

```ts
const ember = await client.creatures.get(id)
const approved = await client.creatures.approveMainImage(id, jobIds[0], ember.updatedAt)
if (approved.canonicalDescription === null) await client.creatures.recaption(id)
```

## Arquivar, restaurar e excluir uma criatura
| Ação | curl | TypeScript SDK |
| --- | --- | --- |
| Arquivar | `DELETE /v1/creatures/:id` | `client.creatures.delete(id)` |
| Restaurar | `POST /v1/creatures/:id/restore` | `client.creatures.restore(id)` |
| Excluir para sempre | `DELETE /v1/creatures/:id?permanent=true` | `client.creatures.permanentDelete(id)` |

Arquivar retorna `{ success: true, archived: true }`, e repetir a ação não muda nada. Restaurar retorna `{ id, name }`, com o sufixo `(restored)` quando uma criatura ativa tem o mesmo nome. Excluir para sempre só funciona em uma criatura arquivada (caso contrário, `400 not_archived`) e remove a criatura e todos os arquivos a que ela faz referência.

## Fazer uma criatura falar
Nenhuma rota específica de criatura é necessária. Gere a fala com a voz da criatura e, depois, sincronize os lábios da imagem principal com ela:

### Gerar a fala
Execute o nó [**Texto para fala** (Text to Speech)](https://nodaro.ai/docs/nodes/audio/text-to-speech) com o `voice.voiceId` da criatura como `voice`, e com o `voice.ttsProvider` e o `voice.voiceType` dela quando estiverem definidos.

### Sincronizar os lábios da imagem principal
Execute o nó [**Sincronização labial** (Lip Sync)](https://nodaro.ai/docs/nodes/video/lip-sync) com o `sourceImageUrl` da criatura como `imageUrl` e a fala como `audioUrl`.

```ts
const speech = await client.nodes.runAndWait('text-to-speech', {
text: 'I knocked the vase off the shelf. I regret nothing.',
voice: ember.voice!.voiceId,
provider: ember.voice!.ttsProvider,
voiceType: ember.voice!.voiceType,
})

const clip = await client.nodes.runAndWait('lip-sync', {
imageUrl: ember.sourceImageUrl!,
audioUrl: speech.audioUrl,
provider: 'kling-avatar',
})
```

Veja [Executar um único nó](https://nodaro.ai/docs/developers/api/nodes) para `nodes.runAndWait` e as rotas `POST /v1/<node-type>` diretas.

## Colocar uma criatura em uma tomada
No [Gerar imagem](https://nodaro.ai/docs/nodes/image/generate-image), envie a criatura como uma referência estruturada com `source: "wired-creature"`. A criatura é anexada automaticamente, com um texto que preserva a anatomia, as marcas e a coloração dela. Você também pode citá-la no prompt: `@ember:1` a coloca onde você digitar. Um papel escolhe o que aproveitar da imagem, por exemplo `@ember:1:markings`. Os papéis são `creature`, `anatomy`, `markings`, `pose`, `color` e `style`.

```json
{
"prompt": "a wide shot of @ember:1 landing on the castle wall",
"connectedReferences": [
{ "id": "cr-1", "defaultName": "Ember", "source": "wired-creature", "url": "https://cdn.nodaro.ai/creatures/ember-main.png" }
]
}
```

Em um workflow, conecte em vez disso o nó [**Animal/criatura** (Animal/Creature Asset)](https://nodaro.ai/docs/nodes/assets/creature) ao nó de imagem ou de vídeo.

## Uso pelo MCP
| Ferramenta | O que faz |
| --- | --- |
| `list_creatures`, `get_creature` | Encontra uma criatura e lê as URLs das variações e a voz dela. |
| `generate_creature` | Gera uma imagem principal (`kind: "main"`) ou uma variação (`kind: "asset"`). |
| `approve_creature_main_image`, `recaption_creature` | Aprova uma imagem principal ou escreve a descrição dela de novo. |
| `generate_creature_motion` | Anima a imagem principal. |

Veja a [Referência das ferramentas MCP](https://nodaro.ai/docs/mcp/tools).

## Créditos
No Nodaro Cloud, uma requisição de imagem principal custa o preço do modelo de imagem vezes `count`, reservado antes de o primeiro job começar. Uma variação custa o preço do modelo de imagem, e um clipe de movimento, o preço de imagem para vídeo do modelo de vídeo. A aprovação e a descrição dela são gratuitas. Cada chamada de llm-caption custa 8 créditos, e uma chamada com falha é reembolsada.

## Erros
| Status | Código | Significado |
| --- | --- | --- |
| `400` | `validation_error` | Um campo está ausente ou é inválido, ou `duration` não é uma duração que o modelo oferece. |
| `400` | `not_archived` | Uma exclusão permanente foi enviada para uma criatura que não está arquivada. |
| `400` | `main_image_required` | `llm-caption` foi chamado antes de a criatura ter uma imagem principal. |
| `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` | Nenhuma criatura ativa com esse ID pertence a você. |
| `409` | `concurrent_modification` | `expectedUpdatedAt` não corresponde mais. Leia a criatura de novo, mescle as mudanças e tente de novo. |
| `502` | — | Não foi possível escrever a descrição canônica. Tente de novo. |

## Frequently asked questions

### Qual é a diferença entre uma criatura e um objeto?

Uma criatura é um animal ou um ser não humano. Ela tem uma espécie em texto livre, um grupo de poses em vez de materiais, painéis com nome e uma voz opcional. Fora isso, as criaturas funcionam como os objetos, com as mesmas rotas para criar, gerar, aprovar e arquivar.

### Como faço uma criatura falar?

Dê uma voz à criatura, gere a fala com o nó Texto para fala usando essa voz e, depois, execute o nó Sincronização labial com a imagem principal da criatura e a fala. Nenhuma rota específica de criatura é necessária.

### Quais modelos podem animar uma criatura?

Os mesmos oito modelos de vídeo dos objetos, pelos IDs de provedor kling-turbo (o padrão), kling, kling-3.0, minimax, hailuo-2.3, wan-i2v, seedance e bytedance-lite. Cada clipe custa o preço de imagem para vídeo desse modelo.

### Existe um comando da CLI para criaturas?

Não. Use as rotas REST, o SDK para TypeScript (client.creatures) ou as ferramentas de criaturas pelo MCP.
