Docs do Nodaro
DocumentaçãoReferência de nósModelosAgentes de IA (MCP)DesenvolvedoresSelf-hostingPesquisa
API REST

Nós

Execute qualquer nó do Nodaro com POST /v1/<node-type>, descubra nós, modelos e valores de seletores e guie o prompt com referências e IDs de direção.

Uma execução de nó chama um nó do Nodaro diretamente, sem montar um workflow: você envia POST /v1/<node-type> com as configurações do nó no corpo. Todos os nós de geração seguem esse formato, de generate-image e generate-video a text-to-speech, e os endpoints de descoberta informam quais nós, modelos e configurações existem. A maioria das execuções de nó é assíncrona: a resposta é um jobId, que você consulta periodicamente até o resultado ficar pronto.

Executar um nó

A rota de um tipo de nó é POST /v1/ seguido do tipo, e o corpo são as configurações do nó em JSON:

POST /v1/generate-image
Authorization: Bearer ndr_…
Content-Type: application/json

{ "prompt": "a lighthouse in a storm, oil painting", "provider": "nano-banana-pro", "aspectRatio": "3:4" }

O que volta depende do nó:

  • Os nós de geração respondem 200 com { "jobId": "…" }. O processamento roda em um worker, e você consulta o job periodicamente com GET /v1/jobs/:id/status até o status ser completed. Veja Jobs.
  • As gerações de imagem e de vídeo podem incluir adjustments, uma lista das configurações que o servidor corrigiu para o modelo escolhido. generate-video também pode incluir warnings. Veja Correções de parâmetros.
  • Os nós inline, como combine-text, retornam o resultado completo na hora, sem jobId.
  • Os extratores, como web-scrape, também respondem na hora. A resposta traz um jobId, para o seu histórico, e também os próprios dados.

Uma geração reserva créditos quando começa. Quando a conta não tem créditos para cobrir a execução, a chamada retorna 402 insufficient_credits.

Nós com um caminho mais longo

A maioria dos nós de texto que chamam um modelo de linguagem segue a mesma regra POST /v1/<node-type>: generate-script, image-critic, qa-check e describe-to-picker. Alguns outros são registrados em um caminho mais longo:

Tipo de nóRota
llm-chatPOST /v1/llm-chat/generate
after-effectsPOST /v1/after-effects/generate
motion-graphicsPOST /v1/motion-graphics/generate
lottie-overlayPOST /v1/lottie-overlay/generate
3d-titlePOST /v1/3d-title/generate
image-to-textPOST /v1/image-to-text/describe
video-composerPOST /v1/scene-graph/generate

O client.nodes.run(type, params) do SDK envia para /v1/<type>, então chame esses nós com client.request('POST', '/v1/llm-chat/generate', { body }).

As rotas de modelo de linguagem aceitam dois campos opcionais:

  • reasoningEffort: none, low, medium, high, xhigh ou max, conforme o modelo. Omita o campo, ou escolha um nível que o modelo não aceita, para usar o padrão do próprio modelo. xhigh e max cobram um nível de crédito acima, com teto no nível premium.
  • advancedMode: true: só para modelos Gemini. A requisição roda na API do próprio fabricante do modelo, a única via em que temperature, maxTokens e toda a faixa de raciocínio têm efeito. Ela cobra um nível de crédito acima, independentemente de reasoningEffort. O nível de crédito tem teto no premium. Um modelo sem essa via retorna 400 advanced_mode_unsupported.

O describe-to-picker responde com o resultado na mesma requisição, e também pode transmitir a resposta como eventos enviados pelo servidor (server-sent events). Veja Descrever para seletor (Describe to Picker). Os campos de generate-script estão em Gerar roteiro (Generate Script).

Exemplo: gerar uma imagem

Iniciar o job

curl -s -X POST https://app.nodaro.ai/v1/generate-image \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
        "prompt": "a knight on a hill at dawn, cinematic",
        "provider": "nano-banana-pro",
        "aspectRatio": "16:9",
        "resolution": "2K"
      }'
{ "jobId": "0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10" }
import { createClient, StaticTokenAuth } from '@nodaro/sdk'

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

const result = await client.nodes.run('generate-image', {
  prompt: 'a knight on a hill at dawn, cinematic',
  provider: 'nano-banana-pro',
  aspectRatio: '16:9',
  resolution: '2K',
})
nodaro nodes run generate-image \
  --param prompt="a knight on a hill at dawn, cinematic" \
  --param provider=nano-banana-pro \
  --param aspectRatio=16:9 \
  --param resolution=2K

Consultar o job periodicamente

Peça o status do job a cada 2 a 5 segundos, até ele ser completed ou failed:

curl -s https://app.nodaro.ai/v1/jobs/0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10/status \
  -H "Authorization: Bearer $NODARO_API_KEY" | jq -r .data.status

Ler o resultado

Um job de imagem concluído traz a URL da imagem em output_data.imageUrl. Um job de vídeo usa videoUrl, um de áudio usa audioUrl, e muitos jobs também trazem um thumbnailUrl.

{
  "data": {
    "id": "0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10",
    "status": "completed",
    "progress": 100,
    "output_data": { "imageUrl": "https://…/0f1a9c2e.png" },
    "error_message": null
  }
}

O SDK e a CLI podem fazer a consulta periódica por você:

const output = await client.nodes.runAndWait('generate-image', {
  prompt: 'a knight on a hill at dawn, cinematic',
  provider: 'nano-banana-pro',
})
console.log(output.imageUrl)

// Several candidates at once, in input order:
const results = await client.nodes.runMany('generate-image', [
  { prompt: 'a knight on a hill, sunrise' },
  { prompt: 'a knight on a hill, golden hour' },
  { prompt: 'a knight on a hill, blue hour' },
])
for (const { jobId, output } of results) console.log(jobId, output.imageUrl)
nodaro nodes run generate-image \
  --param prompt="a knight on a hill at dawn, cinematic" \
  --param provider=nano-banana-pro \
  --watch --json | jq -r '.output_data.imageUrl'

Por padrão, runAndWait faz a consulta periódica a cada 2.000 ms, por até 15 minutos. Mude isso com pollMs e maxMs, interrompa com um AbortSignal em signal e acompanhe o progresso com onProgress. O método lança erros tipados que você pode capturar com instanceof:

ErroQuando
InsufficientCreditsError, StorageExceededError, JobBlockedErrorA execução foi recusada antes de qualquer job começar.
JobFailedErrorO job terminou como failed ou cancelled. O erro traz o jobId e a mensagem de erro.
JobTimeoutErrorO tempo de maxMs passou. O job não é cancelado e geralmente ainda termina: busque-o depois com client.jobs.get(jobId).
JobAbortedErrorO seu signal foi disparado.
JobHeldErrorO job entrou em pending_review em uma implantação que revisa os resultados. O job não é cancelado: verifique de novo mais tarde.

Na CLI, passe corpos complexos, como arrays ou objetos aninhados, em um arquivo com --params-file body.json. Os valores das flags substituem os do arquivo para a mesma chave, e true, false, null e números são convertidos a partir do texto.

Configurações do nó Gerar imagem

Os campos abaixo são as configurações mais usadas de POST /v1/generate-image. Leia Gerar imagem (Generate Image) para saber o que cada configuração faz no editor, e os modelos de imagem para saber o que cada modelo aceita.

Prop

Type

Uma edição com máscara ou um refinamento custa o mesmo que uma nova geração nesse modelo.

Gerar um vídeo

Duas rotas geram vídeo. POST /v1/generate-video anima a partir de imagens: um quadro inicial em imageUrl, um quadro final opcional em endFrameUrl, ou só referências, nos modelos que as aceitam. POST /v1/text-to-video gera um clipe só a partir de um prompt, então o prompt dela é obrigatório. Quando você omite provider, a rota usa o modelo de vídeo padrão da plataforma.

{
  "imageUrl": "https://…/frame.png",
  "provider": "seedance-2",
  "prompt": "she turns toward the window",
  "duration": 8,
  "resolution": "720p",
  "direction": { "cameraMotion": "dolly-in", "timeOfDay": "dawn" }
}

A resposta é { "jobId": "…" }, com warnings e adjustments quando se aplicam. O job concluído traz output_data.videoUrl.

Prop

Type

Algumas regras mudam conforme o modelo:

  • Na família Seedance 2, resolution e aspectRatio são repassados como estão: um valor que o modelo não aceita é ignorado, nunca recusado. O Seedance 2 é o único com 4k e adaptive. O Seedance 2.5 gera até 30 segundos em uma chamada e, com um quadro inicial, sempre renderiza na proporção desse quadro.
  • O MiniMax Hailuo 3 aceita resolution 2K ou 768P, escritos exatamente assim. GET /v1/nodes/:type lista o valor a enviar em providerResolutionWire.
  • Quadros e referências podem ser combinados no Seedance 2 e no MiniMax Hailuo 3. Quando você envia uma referência junto com um quadro inicial ou final, os quadros viram referências numeradas no prompt, em vez de pontos fixos de início e fim. O Wan 3.0 não consegue enviar os dois, então o quadro é adicionado ao final da lista de referências, e a chamada continua sendo bem-sucedida.
  • Vídeos de referência custam mais. Nos modelos que os cobram, um clipe de referência é precificado pela própria duração mais a duração da saída, então um clipe de origem mais longo reserva mais créditos. O Wan 3.0 cobra apenas os segundos de saída.

Para as durações, as resoluções e os preços em créditos de cada modelo, leia os modelos de vídeo ou chame GET /v1/models.

Usar referências

Referências são imagens (e, no vídeo, também clipes e áudio) que o modelo deve seguir. Você pode enviá-las como uma lista simples de URLs ou como referências estruturadas, que a rota numera, rotula e escreve no prompt por você, exatamente como o editor faz com os nós conectados.

Referências estruturadas

POST /v1/generate-image, POST /v1/generate-video, POST /v1/text-to-video e POST /v1/extend-video aceitam connectedReferences. Cada entrada descreve uma imagem:

Prop

Type

Nas rotas de vídeo, a rota transforma essas entradas em referências numeradas:

  • Toda referência que você não menciona é anexada. A URL dela entra na lista de referências, sem duplicatas, e ganha uma linha como @image_1 (reference): <label>. Já uma entrada wired-character passa a fazer parte de uma instrução “Use these characters:”.
  • A lista é cortada no limite do modelo antes da numeração, então um número de referência no prompt nunca aponta para uma imagem que não foi enviada.
  • {image:N:label} no prompt vira “the label from @image_N”, numerado em relação às referências anexadas.
  • {ref:<id>} e {ref:<id>:label} apontam para uma referência pelo id que você deu a ela. A plataforma substitui o token pelo número da referência depois de numerar a lista, então você nunca calcula um número. A lista é numerada nesta ordem: primeiro a lista simples referenceImageUrls, depois os personagens que você não mencionou, depois as outras entradas, na sua ordem. Um token cuja referência não foi anexada, por ter passado do limite ou porque o modelo não aceita referências, vira o rótulo dele; sem rótulo, vira defaultName; sem nenhum dos dois, não vira nada. Ele nunca chega ao modelo como texto bruto.
  • referenceOrder, uma lista de IDs de referências, reordena as referências e as renumera de acordo. POST /v1/generate-image também aceita esse campo.

connectedReferences só envia imagens. referenceVideoUrls e referenceAudioUrls continuam sendo listas simples. Se você omitir connectedReferences, as rotas se comportam como antes: o seu prompt e as suas referenceImageUrls são enviados como estão.

Quais modelos de vídeo aceitam imagens de referência

Família de modelosImagens de referência
Família Seedance 2Até 9
HappyHorse Ref2VAté 9
Gemini Omni, Kling 3 Omni, Grok Imagine image-to-videoAté 7
VEO 3.1 Fast e VEO 3.1 LiteAté 3

Em qualquer outro modelo, os tokens {image:N} são reduzidos aos rótulos e nada é anexado. O VEO 3.1 Quality não está na lista: as referências enviadas com veo3 são ignoradas, e a execução usa os quadros dela.

Vídeo só com referências

Em POST /v1/generate-video, o quadro inicial é opcional quando o modelo aceita pelo menos um dos tipos de referência que você envia, por exemplo o Kling 3 Omni só com referenceImageUrls. Uma execução só com referências no VEO 3.1 Fast ou no Lite muda sozinha para o modo de referência, então você não precisa de generationType. Um tipo de referência que o modelo não consegue usar não conta: referências só de áudio em um modelo que aceita apenas imagens são recusadas com 400.

Um quadro final sozinho é aceito nos modelos que o incorporam às referências: a família Seedance 2, o MiniMax Hailuo 3 e o Wan 3.0. Envie endFrameUrl uma vez, sem repetir a imagem em referenceImageUrls. O pacote @nodaro/shared exporta videoProviderFoldsLoneEndFrame(provider) para que a sua interface use a mesma regra.

Quando uma requisição não tem quadro inicial, nem modo de referência, nem uma referência que o modelo possa usar, a resposta depende do modelo:

  • Um modelo que não consegue gerar vídeo só a partir de texto, como o Kling 3 Omni, o HappyHorse Ref2V ou o Hailuo 2.3, retorna 400 image_required. A mensagem diz se referências funcionariam no lugar. GET /v1/models é a fonte oficial sobre quais são esses modelos.
  • Todos os outros modelos retornam 400 validation_error e indicam POST /v1/text-to-video para um clipe só com prompt.

Estender vídeo

POST /v1/extend-video só aceita connectedReferences e referenceImageUrls com provider: "seedance-2-extend". Qualquer outro modelo de extensão os recusa com 400. O limite é de 8 imagens suas, porque o último quadro do clipe de origem ocupa uma vaga de referência, depois das suas, e assim os seus números nunca mudam. Os últimos 2 segundos da origem vão como @video_1 e já estão incluídos no preço da extensão: imagens de referência não adicionam créditos. O nó Estender vídeo (Extend Video) não tem direction nem subject, porque o prompt dele continua um clipe que já tem um visual.

Referências descritas

describedReferences nomeia um assunto que você consegue descrever, mas do qual ainda não tem imagem, como um papel em um roteiro. POST /v1/generate-image, /v1/generate-video, /v1/text-to-video e /v1/extend-video aceitam até 10 entradas { name, description }. O nome pode ter até 80 caracteres, e a descrição, até 2.000.

  • Nada é anexado. Uma referência descrita não ocupa vaga de referência, e a numeração das suas outras referências não muda.
  • Ela chega ao modelo como uma linha de texto: <Name> — <description>. Mantenha o nome no seu prompt, por exemplo Natalie walks down the pier., e a linha diz ao modelo quem é Natalie. Não escreva uma menção com @ para ela: essa sintaxe aponta para uma imagem anexada.
  • Ela funciona sozinha. Envie describedReferences sem nenhuma connectedReferences, o caso comum de uma história escrita antes de existir qualquer personagem.
  • Entradas sem nome ou sem descrição são descartadas, e um nome repetido é escrito uma vez só. Todos os modelos de extensão aceitam referências descritas, porque elas não trazem URL.

Descrições e legendas por uso

  • descriptionOverride, em uma entrada de connectedReferences, diz o que a referência é só nesta execução, em até 2.000 caracteres. Ele preenche a descrição que a instrução da referência já tem, com prioridade sobre a descrição salva. Quando a instrução não tem descrição, ele adiciona uma linha, então o modelo recebe a informação uma vez, nunca duas.
  • referenceVideoCaptions e referenceAudioCaptions, em POST /v1/generate-video e /v1/text-to-video, descrevem os clipes e os áudios de referência, com até 500 caracteres cada. Eles são alinhados por índice: referenceVideoCaptions[0] descreve referenceVideoUrls[0]. Cada um vira uma linha como @video_1: <caption>., e uma entrada vazia pula um clipe sem quebrar o alinhamento.

Mencionar uma referência no prompt

Em POST /v1/generate-image, você pode colocar uma referência dentro da sua frase, em vez de deixá-la na lista do final. Escreva @<name-slug>:<index>, ou @<name-slug>:<index>:<role> para dizer o que aproveitar dela:

{
  "prompt": "a wide shot of @nessie:1 rising beside @dock:2:material",
  "connectedReferences": [
    { "id": "cr-1", "defaultName": "Nessie", "source": "wired-creature", "url": "https://…/nessie.png" },
    { "id": "ob-1", "defaultName": "Dock", "source": "wired-object", "url": "https://…/dock.png" }
  ]
}

O modelo recebe “a wide shot of the creature from reference image A rising beside the material from reference image B”.

  • O slug vem de defaultName, em minúsculas, com cada sequência de outros caracteres trocada por um único -: Old Town vira old-town. Não existe campo de slug para definir.
  • O índice só associa a menção a uma referência. Ele nunca é escrito no prompt, e a própria plataforma numera as referências.
  • Os papéis para imagens (manual e wired-image) são object, person, face, clothes, background, style, pose e texture. Criaturas aceitam creature, anatomy, markings, pose, color e style. Objetos aceitam object, shape, material, color, texture e style. Qualquer outra palavra única passa como foi escrita. Sem papel, vale o defaultRole da entrada.
  • ~lock e ~nolock depois de uma menção, como em @town:1:background~lock, ativam ou desativam o bloqueio de identidade dessa referência para a menção.
  • Os nomes são resolvidos nesta ordem: personagem, local, imagem, criatura, objeto. Um nome compartilhado por um personagem e uma imagem indica o personagem, e, dentro de um mesmo tipo, vale a primeira correspondência.
  • Um nome cujo slug começa com um dígito não pode ser mencionado, por exemplo 3D Render, que vira 3d-render. Renomeie a referência para mencioná-la. Uma menção a uma referência que passou do limite do modelo fica como texto literal.
  • Mencionar uma referência a move da lista do final para o lugar onde você a digitou, e as letras das referências seguintes mudam para acompanhar a frase. Para uma criatura ou um objeto, a menção também substitui a linha que, sem ela, seria adicionada no final.

Bloqueio de referência

referenceLock, em POST /v1/generate-image, adiciona antes da cena a redação testada do Nodaro para fidelidade às referências:

ValorAdicionaUse para
standardInstruções para usar só o que as referências mostram, manter a semelhança e compor as referências juntasComposições a partir de várias referências
multi-personO mesmo, mais regras para nunca alterar nem misturar rostosDois ou mais rostos em uma tomada

Você envia o ID, não o texto: a redação pertence à plataforma e melhora sem que você atualize o cliente. Se você omitir o campo, nenhum bloqueio é adicionado.

Direção cinematográfica por ID

direction descreve a câmera, a luz e o visual com IDs de seletores, em vez de texto corrido. POST /v1/generate-image, POST /v1/generate-video e POST /v1/text-to-video aceitam o campo. O Nodaro escreve no prompt a própria redação testada para cada ID, então uma requisição salva incorpora as melhorias de redação com o tempo, em vez de congelar o texto que o seu cliente escreveu.

{
  "prompt": "a knight on a hill",
  "provider": "nano-banana-pro",
  "direction": {
    "shotSize": "wide-shot",
    "lens": "wide-24mm",
    "lightingStyle": "rembrandt",
    "style": "anime",
    "mood": ["happy", "joyful"]
  }
}

Chaves e a origem dos IDs

Cada chave é um campo de um seletor de Controles criativos. Obtenha os IDs válidos em GET /v1/picker-catalogs/<picker>, os mesmos catálogos que os seletores do editor usam.

ChavesSeletorImagemVídeo
shotSize, angle, coverage, composition, vantageEnquadramento (Framing)SimSim
posePoseSimSim
compositionEffectEfeitos de composição (Composition Effects)SimSim
cameraFormatCâmera / película (Camera / Film Stock)SimSim
lensLente (Lens)SimSim
aperture, shutterSpeed, isoValueConfigurações de exposição (Exposure Settings)SimNão
timeOfDay, lightingStyle, lightingDirection, lightingRatio, colorTemperatureIluminação (Lighting)SimSim
colorLookCor / look (Color / Look)SimSim
atmosphereAtmosfera (Atmosphere)SimSim
postProcessEfeitos de pós-produção (Post-Process Effects)SimNão
styleEstilo (Style)SimSim
moodClima (Mood)SimSim
aestheticEstética (Aesthetic)SimSim
photoGenreGênero fotográfico (Photo Genre)SimNão
photographerFotógrafo (Photographer)SimNão
renderQualityQualidade de renderização (Render Quality)SimNão
settingCenário (Setting)SimSim
eraÉpoca (Era)SimSim
backdropFundo de estúdio (Backdrop)SimSim
cameraMotionMovimento de câmera (Camera Motion)NãoSim
actionFxEfeitos de ação (Action FX)NãoSim
temporalSpeed, temporalFreeze, temporalDirection, temporalShutterEfeitos temporais (Temporal)NãoSim
transitionTransição (Transition)NãoSim
loopSubjectTema de loop (Loop Subject)NãoSim

Uma chave que não se aplica a uma rota é aceita e simplesmente não adiciona nada, então um mesmo mapa de IDs de visual pode ser enviado sem alterações às rotas de imagem e de vídeo.

Valores e limites

  • Um ID ou uma lista. As chaves de escolha múltipla (mood, aesthetic, photographer, atmosphere, postProcess, composition e lightingStyle) aceitam IDs até o limite de cada uma, e os IDs excedentes são descartados. Uma chave de escolha única que recebe uma lista usa a primeira entrada.
  • Dois limites resultam em recusa com 400 validation_error: mais de 8 entradas em uma chave e um ID com mais de 100 caracteres.
  • Ausente não é vazio. Uma chave ausente significa nenhuma indicação, nunca um valor padrão. Uma string vazia ou uma lista vazia não adiciona nada.
  • Chaves e IDs desconhecidos são ignorados, não recusados. Um cliente mais novo em um servidor mais antigo recebe menos indicações em vez de um erro, então atualize o servidor antes de um cliente que envia chaves novas.
  • Pacotes de catálogo personalizados. Em uma implantação que registra os próprios pacotes de catálogo, GET /v1/picker-catalogs lista os IDs que um pacote adiciona. Esses IDs são aceitos, mas não adicionam redação a direction.

Onde entram as palavras

As cláusulas são adicionadas depois do seu prompt, em uma seção [style]. A linha de filme traz cameraFormat, colorLook, style e era, e a linha de cena traz as outras chaves de visual:

a knight on a hill

[style]:
<film line>
<scene line>
  • A ordem dentro de uma linha é a ordem fixa da plataforma, não a ordem das suas chaves. Uma cláusula repetida por duas chaves é escrita uma vez só.
  • Uma linha vazia é omitida. Quando nenhuma chave adiciona nada, não há seção nenhuma, e o seu prompt chega ao modelo sem alterações.
  • Nas rotas de vídeo, as chaves de movimento funcionam de outro jeito. Elas adicionam um termo profissional curto, como cross-dissolve, e ficam no corpo do prompt, depois do seu texto, porque o movimento faz parte da tomada. cameraMotion vem primeiro. Só as chaves de visual vão para a seção [style].

Quando o prompt é longo demais

Cada modelo aceita um prompt até um comprimento próprio. Um direction completo pode, sozinho, passar de um limite pequeno, por exemplo 3.000 caracteres no Seedream, do lado da imagem, e 1.000 caracteres no Kling, do lado do vídeo. Quando isso acontece, o Nodaro remove as cláusulas de direção uma de cada vez, a partir do final da sua ordem fixa, até o prompt caber. Nada mais é removido antes delas:

  • As cláusulas de assunto só são removidas depois de todas as cláusulas de direção.
  • O seu texto, as suas referências e as frases que as vinculam, as menções com @ e as linhas Style: e Avoid: sempre ficam.
  • Só quando o prompt ainda não cabe, sem nenhuma indicação restante, o final do texto é cortado, com ... no fim.

Nas rotas de vídeo, o orçamento de caracteres também conta as instruções de referência que a rota adiciona, que nunca são removidas. Em um modelo sem configuração de prompt negativo, o seu negativePrompt é adicionado como uma linha Avoid: cujo espaço é reservado primeiro, então um prompt negativo longo custa cláusulas de indicação, não texto. O texto opcional de injectCharacterContext é adicionado depois dessa etapa e não entra no orçamento.

O job registra o que aconteceu. input_data.prompt é o que o modelo recebeu, input_data.userPrompt é o texto que você enviou (uma string vazia quando você enviou só direction), e input_data.direction são os seus IDs, como foram enviados.

Direção salva em um nó

Um nó Gerar imagem em um workflow salvo pode guardar o mesmo objeto direction nos dados dele, escrito pela API, pelo MCP ou por um app que cria workflows. O editor respeita esse objeto em toda execução e na prévia do prompt final. Os IDs salvos se somam a qualquer seletor de Enquadramento, Iluminação ou Estilo conectado: a indicação do seletor conectado vem primeiro, depois os IDs salvos. As predefinições e as exportações de workflow mantêm os IDs junto com o resto do nó.

Descrever o assunto por ID

subject é a mesma ideia para quem está na tomada: a pessoa, como ela está produzida e os objetos de cena no quadro. POST /v1/generate-image, POST /v1/generate-video e POST /v1/text-to-video aceitam o campo:

{
  "prompt": "on the seawall at dusk",
  "provider": "nano-banana-pro",
  "subject": {
    "type": "woman",
    "age": "age-30s",
    "ethnicity": "east-asian",
    "hairBase": "base-short-straight",
    "makeup": "makeup-smoky",
    "outerwear": "outerwear-trench",
    "heldProp": "smartphone"
  }
}
  • As chaves são os campos dos seletores Pessoa (Person) e Figurino e beleza (Styling), como type, age, ethnicity, faceShape, hairColor, skinTone, makeup, outfit, outerwear e footwear. Há também três chaves de objetos: heldProp (Objeto na mão (Held Prop)), material (Material) e animal (Animal). GET /v1/picker-catalogs/person e /styling listam todos os campos e IDs.
  • subject e direction nunca se sobrepõem. As chaves de um e de outro são separadas, então uma escolha nunca adiciona duas cláusulas. pose pertence a direction.
  • customAge é o único número. Envie "age": "age-custom" com "customAge": 34 para uma idade exata em anos. O valor é arredondado e mantido entre 0 e 120.
  • As listas têm limites por chave. jewelry, wardrobeState e distinctiveFeature aceitam 3 IDs. ethnicity, regionalAesthetic, hairColor, eyeColor, lipState, eyeState, skinTexture, hairState, heldProp e material aceitam 2. Todas as outras chaves, inclusive animal, aceitam 1. Os IDs excedentes são descartados.
  • Limites que resultam em recusa: mais de 8 entradas em uma chave, um ID com mais de 100 caracteres, mais de 128 chaves ou uma chave com mais de 64 caracteres retornam 400 validation_error.
  • Chaves desconhecidas são removidas, e IDs desconhecidos são ignorados. input_data.subject, no job, registra exatamente os IDs que foram usados.
  • As cláusulas de assunto fazem parte do seu texto, antes das cláusulas de direção e nunca na seção [style]. Pessoa vira uma cláusula, Figurino e beleza vira outra, e escolhas sobrepostas são escritas uma vez só. Na rota de imagem, cada escolha adiciona a cláusula completa; as rotas de vídeo adicionam o termo curto, porque o quadro inicial já mostra quem é o assunto.

Descobrir nós

GET /v1/nodes lista todos os tipos de nó que o servidor conhece, e GET /v1/nodes/:type retorna um deles. Os dois são públicos, não precisam de token e ficam em cache por 5 minutos. Um tipo desconhecido retorna 404 not_found.

curl -s https://app.nodaro.ai/v1/nodes/generate-image | jq .data
const { data: nodes } = await client.nodes.list()
const imageNodes = nodes.filter((n) => n.category === 'ai-image')

const { data: generateImage } = await client.nodes.get('generate-image')
console.log(generateImage.providers)
nodaro nodes list --category ai-image
nodaro nodes get generate-image
{
  "data": {
    "type": "generate-image",
    "label": "Generate Image",
    "category": "ai-image",
    "description": "Generate an image from a text prompt using an AI provider.",
    "outputType": "image",
    "creditCost": "3-682",
    "providers": ["nano-banana-pro", "gpt-image-2", "gpt-image-2-5-flare", "seedream-5-pro", "z-image"],
    "capabilities": ["supports-reference-image", "supports-aspect-ratio"],
    "inputSchema": {
      "fields": [
        { "key": "prompt", "type": "text", "required": true },
        { "key": "provider", "type": "select", "options": ["nano-banana-pro", "gpt-image-2"] },
        { "key": "aspectRatio", "type": "select" },
        { "key": "promptPrefix", "type": "text" },
        { "key": "promptSuffix", "type": "text" }
      ]
    }
  }
}
CampoSignificado
typeO tipo do nó, que também é a rota: POST /v1/<type>.
label, category, descriptionComo o editor nomeia e agrupa o nó.
outputTypetext, image, video, audio, data ou none.
creditCostO custo do nó em créditos, ou a faixa de custo. É o preço cobrado por uma execução, o mesmo número do botão Executar do nó. 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: as edições sem créditos omitem o campo.
providersOs IDs de modelo que o nó aceita em provider.
capabilitiesFlags de recursos, como supports-reference-image.
inputSchema.fieldsAs configurações do nó, com o tipo, se são obrigatórias e as opções.

Todo nó que recebe um prompt também lista promptPrefix e promptSuffix: texto adicionado antes e depois do prompt. Veja Texto antes e depois do prompt. Nós com limites por modelo trazem campos extras:

CampoSignificado
maxDurationSecA duração máxima que o nó aceita.
sparseProvidersModelos com poucas durações de segmento. Um valor entre elas é ajustado para a mais próxima.
providerResolutionsAs resoluções de cada modelo, por exemplo { "minimax-h3": ["2K", "768P"] }.
providerResolutionWireO valor exato a enviar para cada resolução, por exemplo 768P, e não 768p, para o nível mais barato do MiniMax Hailuo 3.
soundtrackNo Gerar vídeo Pro (Generate Video Pro): o servidor aceita a entrada soundtrack de áudio original.

O descritor cresce com o tempo, então ignore os campos que você não conhece. Os mesmos dados alimentam a referência de nós.

Descobrir modelos

GET /v1/models retorna o catálogo de modelos, agrupado por tipo e por fabricante. Ele é público, fica em cache por 5 minutos e traz os mesmos dados que a ferramenta list_models do MCP retorna.

curl -s "https://app.nodaro.ai/v1/models?kind=video&mode=i2v" | jq '.totalModels'
const catalog = await client.models.list({ kind: 'video', mode: 'i2v' })
for (const section of catalog.sections)
  for (const family of section.families)
    for (const m of family.models) console.log(m.id)
nodaro models list --kind video --mode i2v

A resposta é { sections, recommendations, totalModels }. Cada modelo traz os próprios recursos (modes, features, aspectRatios, resolutions, durations), o pricing em créditos por variante no Nodaro Cloud e promptTips curtas. Ele também traz doctrineCovered, que só é true quando existe um guia de prompts com fontes para a família do modelo. Os créditos de pricing são o preço cobrado por uma execução, o mesmo número do botão Executar no editor.

ParâmetroValoresFiltra por
kindimage, video ou audioUm tipo de mídia
modePor exemplo, t2i, i2v, t2v, tts, video-analysisUma operação
familyUm fabricante, por exemplo Google ou BytedanceUm fabricante
featuredOnlytrueModelos em destaque

As páginas de modelos mostram o mesmo catálogo.

Descobrir valores de seletores

Os seletores de Controles criativos têm catálogos públicos de IDs válidos, os valores que direction e subject aceitam:

MétodoCaminhoO que retorna
GET/v1/picker-catalogsTodos os seletores: nodeType, label, kind, o campo ou os campos, optionCount e imageCount.
GET/v1/picker-catalogs/:nodeTypeAs opções de um seletor. ?detail=full adiciona a description e o promptHint de cada opção, ?category= filtra um seletor de campo único, e ?field= retorna um campo de um seletor de vários campos.
GET/v1/catalogsTodos os catálogos em uma chamada, como a implantação os organizou. data só aparece quando a implantação registrou pacotes de catálogo.
POST/v1/text-to-picker“AI Fill”: escolhe IDs para vários seletores a partir de uma descrição de cena em texto livre. Consome créditos.

Toda opção traz id, label e term (a frase curta para usar em um prompt), além de imageUrl quando a opção tem imagem. Os catálogos também vêm como dados no pacote npm @nodaro/prompts. Leia Catálogos de seletores para ver os formatos completos. No terminal: nodaro pickers list, nodaro pickers get mood --full e nodaro pickers analyze "<text>".

Saída estruturada de LLM

POST /v1/llm/structured faz uma chamada a um modelo de linguagem cuja resposta é forçada a seguir um JSON Schema que você fornece, validada e retornada como objeto. A cobrança é em créditos, conforme o nível do modelo.

{
  "system": "You write production plans.",
  "input": "A rainy chase through Rome.",
  "jsonSchema": {
    "type": "object",
    "properties": { "title": { "type": "string" } },
    "required": ["title"]
  }
}

A resposta é { jobId, output, usage: { inputTokens, outputTokens } }, em que output tem o formato do seu schema.

  • Campos: system, input, jsonSchema e, opcionalmente, schemaName (até 64 caracteres), llmModel, reasoningEffort, maxRetries, origin, advancedMode, temperature e maxTokens. system e input aceitam até 100.000 caracteres cada, e input precisa de pelo menos um.
  • Modelo: sem llmModel, a chamada roda no Gemini 3.6 Flash.
  • Schema: a raiz precisa ser um schema de objeto simples, com até 64 KB e 20 níveis de profundidade. Ele pode usar properties, required, additionalProperties, items, os tipos básicos, enum, const, os limites numéricos e de comprimento, multipleOf, exclusiveMinimum e description. anyOf e oneOf só são aceitos abaixo da raiz. not, if, then, else, as palavras-chave dependent, $ref externo e combinadores na raiz retornam 400. Um anyOf de ramos required abaixo da raiz é aceito, mas não é aplicado, então verifique você mesmo as regras que envolvem vários campos.
  • Novas tentativas: maxRetries, de 0 a 3, com padrão 2, é quantas vezes uma resposta inválida volta ao modelo com o erro de validação.
  • Amostragem: maxTokens vale em toda chamada e não pode passar do limite do próprio modelo. temperature é ignorado, a menos que você também envie advancedMode: true, que cobra um nível de crédito acima, com teto no premium.
  • Duração: a chamada é síncrona e pode levar vários minutos. Cada tentativa pode levar até 240 segundos em cada uma das duas vias, então o pior caso é de 24 minutos com o maxRetries padrão e de 32 minutos com o máximo. Aumente o timeout do seu cliente HTTP ou use a forma de job abaixo. O timeoutMs padrão do SDK, de 60 segundos, é curto demais.
  • Erros: 400 validation_error, 401, 402, 500 internal_error, 502 llm_error depois que as novas tentativas se esgotam, e 503 provider_unavailable.

No SDK, chame client.llm.structured(body).

Como job

POST /v1/llm/structured/jobs recebe o mesmo corpo e responde { jobId } na hora. Consulte periodicamente GET /v1/jobs/:id/status: em completed, output_data é { output, inputTokens, outputTokens }, e em failed, error_message diz o motivo. Encontre os seus rascunhos de novo com GET /v1/jobs?type=llm-structured&origin=<your app>. Três campos extras são aceitos:

  • label: um nome de exibição para o job, com até 120 caracteres.
  • videoUrl: gera o rascunho a partir de um vídeo. Primeiro o vídeo é analisado, em um job separado que também é seu, pelo preço da análise de vídeo, e a análise é adicionada ao seu input. Durante a execução, output_data.stage é analyzing e depois drafting.
  • videoAnalysis: { llmModel?, selectionMode? } para essa análise.

Cancelar o rascunho com POST /v1/jobs/:id/cancel também cancela uma análise em andamento. Uma análise recusada libera todos os créditos reservados para o rascunho. Em uma instalação que envia as chamadas de modelo de linguagem para o nodaro.ai, a forma de job retorna 503 provider_unavailable: nesse caso, use a chamada síncrona. No SDK, chame client.llm.structuredJob(body).

Perguntas frequentes

Última atualização

Nesta página