# Executar nós

> Execute qualquer nó do Nodaro em TypeScript, sem workflow: descubra os tipos, inicie execuções, aguarde resultados e passe referências e direção de câmera.

Source: https://nodaro.ai/pt-BR/docs/developers/sdk/nodes

**`client.nodes`** lista os tipos de nó que um servidor do Nodaro aceita e executa qualquer um deles diretamente, sem montar um workflow. Uma execução envia os seus parâmetros para o endpoint do nó, `POST /v1/<type>`, e retorna um job que você pode aguardar. É o mesmo caminho que a [CLI](https://nodaro.ai/docs/developers/cli) usa em `nodaro nodes run` e que as ferramentas MCP do Nodaro usam. Veja [Executar um único nó](https://nodaro.ai/docs/developers/api/nodes) para a visão REST.

## Métodos
| Método | O que faz |
| --- | --- |
| [`nodes.list()`](#list) | Lista todos os tipos de nó, com os modelos e o custo em créditos de cada um |
| [`nodes.get(type)`](#gettype) | Lê um tipo de nó |
| [`nodes.run(type, params?, options?)`](#runtype-params-options) | Inicia um nó e retorna o ID do job imediatamente |
| [`nodes.runAndWait(type, params?, opts?)`](#runandwaittype-params-opts) | Inicia um nó, consulta o job periodicamente e retorna a saída |
| [`nodes.runMany(type, paramsList, opts?)`](#runmanytype-paramslist-opts) | Inicia várias execuções de um nó ao mesmo tempo e aguarda todas |

## client.nodes
### list()
Lista todos os tipos de nó que o servidor aceita. O servidor pode manter a resposta em cache por 5 minutos. A chamada não custa nada e não exige escopos.

```ts
list(): Promise<{ data: NodeDescriptor[] }>
```

```ts
const { data: nodes } = await client.nodes.list()

const imageGenerators = nodes.filter((n) => n.category === "ai-image")
const takesReferences = nodes.filter((n) => n.capabilities?.includes("supports-reference-image"))
```

Cada `NodeDescriptor` tem estes campos:

| Campo | Tipo | Descrição |
| --- | --- | --- |
| `type` | `string` | O tipo na API, como `generate-image`. Passe-o para `run()`. |
| `label` | `string` | O nome do nó no editor. |
| `category` | `string` | A categoria, como `ai-image`, `ai-video`, `ai-audio`, `ai-text`, `processing` ou `parameter`. |
| `description` | `string` | Uma descrição de uma linha. |
| `outputType` | `string` | `text`, `image`, `video`, `audio`, `data` ou `none`. |
| `creditCost` | `number \| string` | O custo em créditos cobrado por uma execução, o mesmo número do botão **Executar** do nó: um número quando é fixo, ou uma faixa como `"3-682"` quando depende do modelo. No **Cortar vídeo** (Trim Video), no **Vídeo em loop** (Loop Video) e no **Combinar vídeos** (Combine Videos), ele é, em vez disso, o preço de um bloco de 5 segundos, e uma execução custa um certo número de blocos. Só no Nodaro Cloud. |
| `providers` | `string[]` | Os IDs dos modelos que o nó pode executar, para o parâmetro `provider`. |
| `capabilities` | `string[]` | Flags como `supports-reference-image` ou `supports-end-frame`. |
| `inputSchema` | `{ fields }` | Os campos de entrada que você pode definir, cada um com `key`, `type`, `required` e `options`. |
| `maxDurationSec` | `number` | A maior duração que o nó aceita, quando ele tem um limite. |
| `providerResolutions` | `Record<string, string[]>` | As resoluções que cada modelo aceita, quando elas variam. |

As instalações self-hosted Community e Business não têm sistema de créditos, então os descritores delas omitem `creditCost`.

### get(type)
Lê o descritor de um tipo de nó.

```ts
get(type: string): Promise<{ data: NodeDescriptor }>
```

<TypeTable
type={{
type: { type: 'string', required: true, description: "O tipo do nó na API, como generate-image ou generate-video." },
}}
/>

```ts
const { data: node } = await client.nodes.get("generate-video")
console.log(node.providers)  // every video model id
console.log(node.creditCost) // Nodaro Cloud only
```

Para mostrar os preços ao lado dos modelos, passe `node.providers` para [`client.credits.modelCosts()`](https://nodaro.ai/docs/developers/sdk/models-and-credits).

### run(type, params?, options?)
Inicia um nó e retorna imediatamente. O corpo é enviado para `POST /v1/<type>`, a rota que todo nó de geração usa. Os nomes dos campos correspondem aos campos de entrada do nó.

```ts
run(type: string, params?: Record<string, unknown>, options?: { idempotencyKey?: string }): Promise<RunNodeResult>
```

<TypeTable
type={{
type: { type: 'string', required: true, description: "O tipo do nó na API, como generate-image, image-to-video ou text-to-speech." },
params: { type: 'Record<string, unknown>', default: '{}', description: "O corpo da requisição. generate-image, generate-video, text-to-video e assemble-narrated-video têm parâmetros tipados, listados abaixo." },
idempotencyKey: { type: 'string', description: "Enviada como o cabeçalho Idempotency-Key. Reutilize o mesmo valor ao repetir uma requisição que esgotou o tempo, para que a execução não seja iniciada nem cobrada duas vezes." },
}}
/>

```ts
const result = await client.nodes.run("generate-image", {
prompt: "A snow leopard in the mountains",
provider: "nano-banana-2",
})

if ("jobId" in result) {
const { data: job } = await client.jobs.getStatus(result.jobId)
console.log(job.status)
}
```

**O que volta.** A maioria dos tipos de nó é assíncrona: o resultado traz um `jobId`, e um worker faz a geração. Consulte [`client.jobs.getStatus(jobId)`](https://nodaro.ai/docs/developers/sdk/jobs-and-executions) periodicamente até o job terminar, ou use `runAndWait()`. Alguns tipos de nó inline, como `combine-text`, retornam o resultado completo imediatamente, sem `jobId`. Verifique se há um `jobId` para decidir o que fazer.

**Correções de parâmetros.** Nos tipos de nó de imagem (`generate-image`, `image-to-image` e `edit-image`), o servidor pode corrigir um valor que o modelo escolhido não aceita. A execução continua com o valor corrigido, e os créditos reservados correspondem a ele. O resultado então traz `adjustments`, com uma entrada por campo corrigido:

```ts
const result = await client.nodes.run("generate-image", {
prompt: "A snow leopard",
provider: "gpt-image-2",
aspectRatio: "3:2",
})
if ("adjustments" in result && result.adjustments?.length) {
for (const a of result.adjustments) {
console.warn(`${a.field}: ${a.from} -> ${a.to ?? "(dropped)"} (${a.reason})`)
}
}
```

Cada ajuste tem `field` (`aspectRatio`, `resolution`, `quality` ou `duration`), `from`, `to` e `reason`. `adjustments` não aparece quando nada mudou.

Lança `InsufficientCreditsError` quando a conta não consegue pagar, `StorageExceededError` quando o armazenamento está cheio e `JobBlockedError` quando uma política de conteúdo da implantação recusa a requisição. Veja [Erros](https://nodaro.ai/docs/developers/sdk/errors).

### runAndWait(type, params?, opts?)
Executa um nó assíncrono até o fim. O método chama `run()`, pega o `jobId` e consulta [`client.jobs.getStatus()`](https://nodaro.ai/docs/developers/sdk/jobs-and-executions) periodicamente até o job terminar. Ele resolve com a saída do job quando o status é `completed`.

```ts
runAndWait(type: string, params?: Record<string, unknown>, opts?: RunAndWaitOptions): Promise<NodeJobOutput>
```

<TypeTable
type={{
type: { type: 'string', required: true, description: "O tipo do nó na API." },
params: { type: 'Record<string, unknown>', default: '{}', description: "O corpo da requisição, como em run()." },
signal: { type: 'AbortSignal', description: "Interrompe a espera e rejeita com JobAbortedError. O job em si continua em execução." },
onProgress: { type: '(status: JobStatusResult) => void', description: "Chamada com o status do job a cada consulta. status.progress vai de 0 a 100 quando o modelo informa o progresso." },
pollMs: { type: 'number', default: '2000', description: "O intervalo entre as consultas, em milissegundos." },
maxMs: { type: 'number', default: '900000', description: "Quanto tempo esperar no total, em milissegundos, antes de JobTimeoutError." },
idempotencyKey: { type: 'string', description: "Enviada com a requisição de execução. Reutilize-a ao repetir a mesma requisição." },
}}
/>

```ts
const output = await client.nodes.runAndWait(
"generate-video",
{ prompt: "Rain falls on a neon street at night", provider: "seedance-2-fast", duration: 4 },
{ onProgress: (s) => console.log(`${s.progress ?? 0}%`) },
)
console.log(output.videoUrl, output.thumbnailUrl)
```

A saída é um `NodeJobOutput`: `imageUrl` para nós de imagem, `videoUrl` e `thumbnailUrl` para nós de vídeo, `audioUrl` para nós de áudio, além de quaisquer outros campos que o nó grave. O nó [**Separação de áudio** (Audio Separation)](https://nodaro.ai/docs/nodes/audio/audio-separation), por exemplo, adiciona uma URL por stem, como `vocalUrl` e `instrumentalUrl`.

O método lança estes erros tipados:

| Erro | Quando |
| --- | --- |
| `InsufficientCreditsError`, `StorageExceededError`, `JobBlockedError` | A requisição de execução foi recusada, antes de qualquer consulta. |
| `JobFailedError` | O job terminou como `failed` ou `cancelled`. O erro traz o `jobId` e a mensagem de erro do job. |
| `JobTimeoutError` | O tempo de `maxMs` passou. O job não é cancelado. |
| `JobAbortedError` | O seu `signal` disparou. O job não é cancelado. |
| `JobHeldError` | O job está retido para revisão humana, em implantações com política de conteúdo. |

**Recuperações lentas.** Às vezes um modelo entrega o resultado depois que o worker já desistiu dele. O job então fica em `processing` com `recovering: true` enquanto a plataforma o recupera, o que pode levar dezenas de minutos em modelos lentos. Se um `JobTimeoutError` encerrar a sua espera, busque o job mais tarde com `client.jobs.get(jobId)` ou aumente `maxMs`.

### runMany(type, paramsList, opts?)
Inicia várias execuções de um tipo de nó ao mesmo tempo e aguarda todas, por exemplo para gerar uma grade de candidatos. Cada entrada é executada por `runAndWait()`.

```ts
runMany(type: string, paramsList: Record<string, unknown>[], opts?: RunAndWaitOptions): Promise<RunManyResult[]>
```

<TypeTable
type={{
type: { type: 'string', required: true, description: "O tipo do nó na API, usado em todas as execuções." },
paramsList: { type: 'Record<string, unknown>[]', required: true, description: "Um corpo de requisição por execução." },
opts: { type: 'RunAndWaitOptions', description: "O signal, o onProgress, o pollMs e o maxMs compartilhados por todas as execuções. Um signal compartilhado interrompe o lote inteiro." },
}}
/>

```ts
const results = await client.nodes.runMany("generate-image", [
{ prompt: "A snow leopard at sunrise" },
{ prompt: "A snow leopard at golden hour" },
{ prompt: "A snow leopard at blue hour" },
])
for (const { jobId, output } of results) console.log(jobId, output.imageUrl)
```

O método resolve quando todas as execuções terminam, com um `{ jobId, output }` por entrada, na mesma ordem da lista que você passou. Ele rejeita assim que qualquer execução falha, com os mesmos erros de `runAndWait()`. Para escolher o melhor resultado depois, passe as URLs para [`client.reduce.run()`](https://nodaro.ai/docs/developers/sdk/llm-and-reduce).

## Parâmetros tipados
Quatro tipos de nó têm parâmetros tipados, então o seu editor de código completa e verifica os campos deles. Todos os outros tipos de nó recebem um objeto simples; os campos são os campos de entrada do nó, listados em `inputSchema` e na página do nó na [Referência de nós](https://nodaro.ai/docs/nodes). Os nós de cena 3D também têm parâmetros tipados: veja [Cenas 3D](https://nodaro.ai/docs/developers/sdk/scenes-3d).

| Tipo de nó | Tipo do parâmetro | Página do nó |
| --- | --- | --- |
| `generate-image` | `GenerateImageParams` | [**Gerar imagem** (Generate Image)](https://nodaro.ai/docs/nodes/image/generate-image) |
| `generate-video` | `GenerateVideoParams` | [**Gerar vídeo** (Generate Video)](https://nodaro.ai/docs/nodes/video/generate-video) |
| `text-to-video` | `TextToVideoParams` | [Gerar vídeo](https://nodaro.ai/docs/nodes/video/generate-video) |
| `assemble-narrated-video` | `AssembleNarratedVideoParams` | [**Montar vídeo narrado** (Assemble Narrated Video)](https://nodaro.ai/docs/nodes/video/assemble-narrated-video) |

Todo objeto de parâmetros tipados também aceita outros campos da rota. O servidor valida o corpo completo.

### GenerateImageParams
<TypeTable
type={{
prompt: { type: 'string', description: "O que a imagem mostra." },
provider: { type: 'string', description: "O ID do modelo, como nano-banana-2 ou gpt-image-2. Omita-o para usar o modelo padrão do nó." },
negativePrompt: { type: 'string', description: "O que o modelo deve evitar." },
referenceImageUrls: { type: 'string[]', description: "URLs de imagens de referência, adicionadas depois de connectedReferences." },
connectedReferences: { type: 'ConnectedReference[]', description: "Referências com rótulo, do jeito que o editor as conecta. Veja Referências abaixo." },
describedReferences: { type: 'DescribedReference[]', description: "Até 10 assuntos que você consegue nomear e descrever, mas dos quais não tem imagem." },
referenceOrder: { type: 'string[]', description: "IDs de referência na ordem em que o modelo deve vê-las." },
direction: { type: 'object', description: "Direção cinematográfica como IDs de seletor. Veja Direção abaixo." },
}}
/>

### GenerateVideoParams
A via de imagem para vídeo: um quadro inicial, um quadro final opcional e referências.

<TypeTable
type={{
prompt: { type: 'string', description: "O que acontece no clipe. Opcional quando há um quadro inicial." },
provider: { type: 'string', description: "O ID do modelo, como seedance-2-fast ou kling-3.0." },
imageUrl: { type: 'string', description: "O quadro inicial." },
endFrameUrl: { type: 'string', description: "O quadro final, nos modelos que aceitam um." },
frameFit: { type: '"original" | "ratio" | "resolution"', default: '"resolution"', description: "Como um quadro inicial ou final é ajustado. resolution redimensiona o quadro para o tamanho que o modelo renderiza, ratio ajusta só a proporção, e original envia o quadro sem alteração." },
frameDelivery: { type: '"auto" | "frame" | "reference"', default: '"auto"', description: "Se o quadro é enviado como um quadro inicial de verdade ou como uma imagem de referência identificada como o quadro de abertura. auto escolhe por modelo." },
referenceImageUrls: { type: 'string[]', description: "Imagens de referência." },
referenceVideoUrls: { type: 'string[]', description: "Vídeos de referência, nos modelos que os aceitam." },
referenceAudioUrls: { type: 'string[]', description: "Áudio de referência, nos modelos que o aceitam." },
referenceVideoCaptions: { type: 'string[]', description: "Uma legenda por vídeo de referência, na mesma ordem." },
referenceAudioCaptions: { type: 'string[]', description: "Uma legenda por clipe de áudio de referência, na mesma ordem." },
connectedReferences: { type: 'ConnectedReference[]', description: "Referências com rótulo." },
describedReferences: { type: 'DescribedReference[]', description: "Assuntos nomeados sem imagem." },
referenceOrder: { type: 'string[]', description: "A ordem das referências." },
direction: { type: 'object', description: "Direção cinematográfica e de movimento como IDs de seletor." },
}}
/>

### TextToVideoParams
A via de vídeo só com prompt, `POST /v1/text-to-video`. O prompt é obrigatório, e os quadros inicial e final ficam com o `generate-video`. Um modelo sem modo de texto para vídeo responde `400 image_required`.

<TypeTable
type={{
prompt: { type: 'string', required: true, description: "O que acontece no clipe." },
provider: { type: 'string', description: "O ID do modelo." },
duration: { type: 'number', description: "A duração em segundos. Os valores permitidos dependem do modelo." },
sound: { type: 'boolean', description: "Áudio nativo, nos modelos que renderizam som." },
negativePrompt: { type: 'string', description: "O que evitar." },
aspectRatio: { type: 'string', description: "O formato do quadro, como 16:9." },
resolution: { type: 'string', description: "A resolução, como 720p." },
seed: { type: 'number', description: "Uma seed fixa, nos modelos que aceitam uma." },
referenceImageUrls: { type: 'string[]', description: "Imagens de referência." },
referenceVideoUrls: { type: 'string[]', description: "Vídeos de referência." },
referenceAudioUrls: { type: 'string[]', description: "Áudio de referência." },
direction: { type: 'object', description: "Direção cinematográfica e de movimento como IDs de seletor." },
subject: { type: 'object', description: "IDs de seletores de assunto, como uma pessoa ou um animal, colocados antes do texto da direção." },
}}
/>

### AssembleNarratedVideoParams
Junta blocos de vídeo com narração em um único vídeo. A execução é cobrada pelo número de blocos e custa 44 créditos: 3 unidades, mais uma unidade a cada 6 blocos ou fração de 6. Veja [Montar vídeo narrado](https://nodaro.ai/docs/nodes/video/assemble-narrated-video) para saber como cada bloco é ajustado à sua narração.

<TypeTable
type={{
blocks: { type: '{ videoUrl: string; audioUrl?: string }[]', required: true, description: "De 1 a 60 blocos, na ordem de reprodução." },
voiceVolume: { type: 'number', default: '100', description: "O volume da narração, de 0 a 200." },
clipAudioVolume: { type: 'number', default: '40', description: "O volume do áudio dos próprios clipes, de 0 a 200." },
maxSlowdown: { type: 'number', default: '1.5', description: "Quanto um clipe pode ser desacelerado para caber na narração, de 1 a 2." },
trimStartFrames: { type: 'number', default: '0', description: "Quadros a cortar do início de cada clipe, de 0 a 120." },
trimEndFrames: { type: 'number', default: '0', description: "Quadros a cortar do fim de cada clipe, de 0 a 120." },
}}
/>

## Referências
`generate-image`, `generate-video` e `text-to-video` aceitam referências do jeito que o editor as conecta. O servidor as transforma em diretivas numeradas no prompt, como `@image_1`, então você não precisa escrever “Image 1 is...”.

- **`connectedReferences`** é uma lista de entradas `ConnectedReference`, o formato de referência conectada do editor, exportado pelo SDK. O servidor remove duplicatas e mantém quantas o modelo aceitar. `referenceOrder` define a ordem delas pelo ID.
- **Bloqueio de identidade.** Uma entrada pode trazer `identityLock: { enabled: true, text? }`. O servidor então adiciona uma linha curta que diz ao modelo para manter a identidade dessa referência. `text` substitui o texto padrão, e `{ref}` dentro dele representa o nome da referência. O bloqueio vem desativado por padrão.
- **`describedReferences`** recebe até 10 entradas `{ name, description }` para assuntos que você consegue nomear, mas dos quais não tem imagem, como um papel em um roteiro. Cada uma vira uma linha `Name — description.` no prompt. Mantenha o nome no texto do prompt, para que o modelo saiba quem é.
- **`descriptionOverride`** em uma entrada de referência substitui a descrição armazenada dela só nesta execução.
- **Legendas para referências de vídeo e áudio.** `referenceVideoCaptions` e `referenceAudioCaptions` seguem a ordem de `referenceVideoUrls` e `referenceAudioUrls`. Cada legenda aparece no prompt como `@video_1: caption.` ou `@audio_1: caption.`.
- **Mencione uma referência de imagem no prompt.** No `generate-image`, dê um nome a uma referência e mencione-a como `@<name>:<index>` ou `@<name>:<index>:<role>`, por exemplo `@town:1:background`. A menção insere essa referência, ou o papel dela, naquele ponto do prompt. `~lock` e `~nolock` funcionam como nas menções de personagem.

Veja [Papéis de referência](https://nodaro.ai/docs/guides/reference-roles) para os papéis que você pode usar e [Personagens consistentes](https://nodaro.ai/docs/guides/consistent-characters) para trabalhar com identidade.

## Direção
`generate-image`, `generate-video` e `text-to-video` aceitam um objeto `direction` com **IDs** de seletor em vez de palavras. O Nodaro escreve no prompt um texto testado para cada ID, então o seu código envia IDs e o texto continua sempre atualizado.

```ts
await client.nodes.runAndWait("generate-image", {
prompt: "A detective waits under a street lamp",
direction: { shotSize: "wide-shot", timeOfDay: "golden-hour", mood: "suspicious" },
})
```

- As **chaves** são dimensões de seletor, como `shotSize`, `lightingStyle`, `style`, `mood`, `photographer` ou `era`. As rotas de vídeo adicionam chaves de movimento, como `cameraMotion`, `actionFx`, `transition`, `loopSubject` e as chaves `temporal`.
- Os **valores** são um ID ou um array de IDs. Uma dimensão que aceita vários valores mantém no máximo o próprio limite e descarta o resto. A requisição só é recusada acima de 8 valores por chave ou de 100 caracteres por ID.
- **Chaves e IDs desconhecidos são ignorados**, não recusados. Um `direction` vazio deixa o seu prompt inalterado.
- **Um único mapa serve para imagens e vídeo.** Uma chave só de imagem fixa enviada a uma execução de vídeo é aceita e não adiciona nada.
- `extend-video` não recebe `direction`, porque o prompt dele continua um clipe existente.

Leia os IDs válidos em [`client.pickerCatalogs`](https://nodaro.ai/docs/developers/sdk/pickers-and-prompts). Veja [Catálogos de seletores](https://nodaro.ai/docs/developers/picker-catalogs) para todas as dimensões.

## Nós de modelo de linguagem
`run(type, params)` envia para `/v1/<type>`. Entre os nós de modelo de linguagem, essa rota só existe para `generate-script`, `image-critic`, `qa-check` e `describe-to-picker`. Os outros nós de modelo de linguagem usam um caminho mais longo, então chame-os com [`client.request()`](https://nodaro.ai/docs/developers/sdk/client#requestmethod-path-options):

| Tipo de nó | Endpoint |
| --- | --- |
| `llm-chat` | `/v1/llm-chat/generate` |
| `after-effects` | `/v1/after-effects/generate` |
| `motion-graphics` | `/v1/motion-graphics/generate` |
| `lottie-overlay` | `/v1/lottie-overlay/generate` |
| `3d-title` | `/v1/3d-title/generate` |
| `image-to-text` | `/v1/image-to-text/describe` |
| `video-composer` | `/v1/scene-graph/generate` |

```ts
await client.nodes.run("generate-script", {
prompt: "A 3-scene product launch script for a smart water bottle",
reasoningEffort: "high",
})
```

- **`reasoningEffort`** é `"none"`, `"low"`, `"medium"`, `"high"`, `"xhigh"` ou `"max"`, conforme o modelo. Omita-o, ou envie um nível que o modelo não aceita, para usar o padrão do modelo. `xhigh` e `max` cobram um nível de créditos acima, até o nível premium. Veja o nó [**Prompt**](https://nodaro.ai/docs/nodes/automate/prompt) para os modelos e os níveis de cada um.
- **`advancedMode: true`** executa um modelo Gemini diretamente na API do fabricante. Só ali `temperature`, `maxTokens` e toda a faixa de esforço têm efeito completo. O modo cobra um nível de créditos acima, somado a qualquer aumento por esforço. O nível de créditos tem como teto o nível premium. Um modelo sem essa opção responde `400 advanced_mode_unsupported`.
- **O streaming não é encapsulado.** O SDK não lê a resposta em streaming do nó Prompt. Para ela, use `fetch` com um stream legível.

## Regras específicas de modelos
Alguns modelos de vídeo aceitam valores que os outros não aceitam. A página de cada modelo lista todas as opções e os preços.

- **[Seedance 2](https://nodaro.ai/docs/models/video/seedance-2)** aceita `resolution: "4k"` e `aspectRatio: "adaptive"` ou `"21:9"`. O [Seedance 2 Fast](https://nodaro.ai/docs/models/video/seedance-2-fast) e o [Seedance 2 Mini](https://nodaro.ai/docs/models/video/seedance-2-mini) renderizam só em 480p ou 720p.
- **[Seedance 2.5](https://nodaro.ai/docs/models/video/seedance-2-5)** renderiza em 480p, 720p ou 1080p, gera até 30 segundos em uma chamada e aceita 30 referências de imagem, 10 de vídeo e 10 de áudio. Com um quadro inicial, ele usa a proporção desse quadro e recusa um `aspectRatio` explícito.
- **[MiniMax Hailuo 3](https://nodaro.ai/docs/models/video/minimax-h3)** (`minimax-h3`) aceita 9 referências de imagem, 3 de vídeo e 3 de áudio com `resolution: "2K"` (o padrão) ou `"768P"`. Qualquer outro valor é renderizado e cobrado como 2K.
- **[Wan 3.0](https://nodaro.ai/docs/models/video/wan-3-0)** (`wan-3` e o mais rápido `wan-3-prime`) aceita 10 referências de imagem, 5 de vídeo e 5 de áudio. As listas de referências não podem ser combinadas com `imageUrl` nem com `endFrameUrl`. `duration` é um número inteiro de 2 a 30, e `resolution` é `480p`, `720p` ou `1080p`.
- **[Gemini Omni Flash](https://nodaro.ai/docs/models/video/gemini-omni-flash)** aceita a mesma requisição que o [Gemini Omni](https://nodaro.ai/docs/models/video/gemini-omni): durações de 4, 6, 8 ou 10 segundos, de 720p a 4K, e só 16:9 ou 9:16.

**Texto para fala.** Quando você omite `provider`, o nó [**Texto para fala** (Text to Speech)](https://nodaro.ai/docs/nodes/audio/text-to-speech) usa o [ElevenLabs v3](https://nodaro.ai/docs/models/audio/elevenlabs-v3) para textos de até 3.000 caracteres. Textos mais longos passam para o [ElevenLabs Turbo v2.5](https://nodaro.ai/docs/models/audio/elevenlabs-turbo-v2-5), cujo limite é de 40.000 caracteres, para não serem cortados. Um `provider` que você indicar é sempre usado.

## Scrapers e outros nós de entrada
Os nós de entrada são executados do mesmo jeito. Um scraper, como o nó [**Extrair da web** (Web Scrape)](https://nodaro.ai/docs/nodes/automate/web-scrape), responde imediatamente: o resultado traz um `jobId` para o seu histórico e os próprios dados, então você pode usá-los sem consultas periódicas. Os campos da requisição são os campos de entrada do nó, listados em `inputSchema`.

## Frequently asked questions

### Como gero uma imagem com o SDK do Nodaro?

Chame client.nodes.runAndWait com o tipo de nó generate-image e um prompt. A chamada resolve com a saída do job, cujo imageUrl é a imagem gerada.

### Qual é a diferença entre run e runAndWait?

run inicia o nó e retorna um jobId imediatamente. runAndWait inicia o nó, consulta o job a cada 2 segundos e resolve com a saída quando o job é concluído.

### Quanto tempo o runAndWait espera?

Até 15 minutos, por padrão. Altere esse tempo com a opção maxMs. Esgotar o tempo não cancela o job, que normalmente ainda é concluído no servidor.

### Quais tipos de nó posso executar?

Chame client.nodes.list() para ver todos os tipos que o servidor aceita, com a categoria, o tipo de saída, os modelos e o custo em créditos de cada um. Todo nó da Referência de nós tem um tipo na API.

### Como evito pagar duas vezes quando repito uma requisição?

Passe uma idempotencyKey nas opções de run ou runAndWait e reutilize a mesma chave ao repetir a requisição. A plataforma retorna a primeira execução em vez de iniciar uma segunda.
