# SDK para TypeScript

> Instale o @nodaro/sdk, autentique-se com um token de API e execute nós e workflows do Nodaro em TypeScript, no Node.js, no navegador e em runtimes de edge.

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

O **SDK do Nodaro para TypeScript** é o cliente tipado da API REST do Nodaro, publicado no npm como `@nodaro/sdk`. Ele executa nós avulsos e workflows inteiros, espera os resultados e gerencia personagens, vozes, mídias e muito mais. Funciona no Node.js, no navegador e em runtimes de edge, e todo erro da API chega como uma classe de erro tipada que você pode capturar.

## Instalação
```bash
npm install @nodaro/sdk
```

- O pacote é open source, sob a licença Apache-2.0. Veja o [@nodaro/sdk no npm](https://www.npmjs.com/package/@nodaro/sdk) e o [código-fonte no GitHub](https://github.com/nodaroai/app.nodaro.ai/tree/main/packages/client).
- Ele traz builds em ES module e CommonJS, com definições de tipo do TypeScript.
- Ele precisa do Node.js 20 ou mais recente. Também roda em qualquer runtime com `fetch` e `URL` globais: navegadores modernos, React Native, Cloudflare Workers, Deno e Bun.
- Ele instala junto outros dois pacotes do Nodaro: `@nodaro/shared`, com os tipos de dados da API e o catálogo de modelos, e `@nodaro/prompts`, com os helpers de prompt.
- `@supabase/supabase-js` e `@supabase/ssr` são dependências peer opcionais. Instale-os apenas para um app de navegador que faz o login dos usuários com o Supabase, por meio de `supabaseAuth` ou `@nodaro/sdk/supabase`.
- A [CLI do Nodaro](https://nodaro.ai/docs/developers/cli) é construída sobre este SDK, então um comando da CLI e uma chamada do SDK chegam aos mesmos endpoints.

## Obter um token de API
### Criar o token
Entre no [Nodaro](https://app.nodaro.ai), abra **Configurações › Tokens de API** e clique em **Criar token**.

### Copiar o token na hora
O token começa com `ndr_` e é mostrado apenas uma vez. O Nodaro guarda apenas um hash dele, então um token perdido não pode ser mostrado de novo. Nesse caso, crie um novo.

### Manter o token fora do código
Guarde o token em uma variável de ambiente, como `NODARO_TOKEN`, ou no seu gerenciador de segredos. Nunca o coloque em código do lado do cliente.

Um token pessoal age como você. Para agir em nome de outras pessoas, por exemplo em um app ao qual muitos usuários se conectam, use [OAuth](https://nodaro.ai/docs/developers/oauth) em vez disso. A página [Autenticação](https://nodaro.ai/docs/developers/sdk/auth) compara todas as opções.

## Fazer a primeira chamada
```ts

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

const { data: nodes } = await client.nodes.list()
console.log(`${nodes.length} node types available`)
```

`client.nodes.list()` não custa nada e não precisa de escopos, então é um bom primeiro teste da conexão. Em uma instalação self-hosted, defina `baseUrl` como o endereço da sua instância. Em um app de navegador servido pela mesma origem que o Nodaro, use uma string vazia. A página [Cliente](https://nodaro.ai/docs/developers/sdk/client) lista todas as opções de `createClient`.

## Gerar uma imagem e depois um vídeo
```ts
const image = await client.nodes.runAndWait("generate-image", {
prompt: "A snow leopard resting on a rock at sunrise",
provider: "nano-banana-2",
})
console.log(image.imageUrl)

const video = await client.nodes.runAndWait("generate-video", {
prompt: "The snow leopard slowly turns its head toward the camera",
imageUrl: image.imageUrl,
provider: "seedance-2-fast",
duration: 4,
})
console.log(video.videoUrl)
```

`runAndWait` inicia a execução, consulta-a periodicamente e resolve com a saída do job: `imageUrl` para imagens, `videoUrl` para vídeo e `audioUrl` para áudio. A primeira chamada executa o nó [**Gerar imagem** (Generate Image)](https://nodaro.ai/docs/nodes/image/generate-image) no [Nano Banana 2](https://nodaro.ai/docs/models/image/nano-banana-2). A segunda anima essa imagem com o nó [**Gerar vídeo** (Generate Video)](https://nodaro.ai/docs/nodes/video/generate-video) no [Seedance 2 Fast](https://nodaro.ai/docs/models/video/seedance-2-fast).

Omita `provider` para usar o modelo padrão do nó. A página de cada nó lista os modelos que ele pode executar e os preços em créditos deles, e `client.models.list()` retorna o mesmo catálogo pelo código. Veja [Modelos e créditos](https://nodaro.ai/docs/developers/sdk/models-and-credits).

## Como as execuções funcionam
A geração é assíncrona. Uma requisição inicia um **job** em um worker e retorna na hora. O resultado chega segundos ou minutos depois.

| Você chama | Você recebe | O que fazer em seguida |
| --- | --- | --- |
| `client.nodes.run(type, params)` | `{ jobId }` | Consulte `client.jobs.getStatus(jobId)` periodicamente até o status ser `completed`, `failed` ou `cancelled`. |
| `client.nodes.runAndWait(type, params, opts)` | A saída do job | Nada. O SDK consulta o status a cada 2 segundos, por até 15 minutos. |
| `client.nodes.runMany(type, paramsList, opts)` | Um `{ jobId, output }` por requisição | Nada. As execuções começam juntas e resolvem na ordem da entrada. |
| `client.workflows.run(id)` | `{ executionId, status }` | Consulte `client.executions.get(executionId)` periodicamente até a execução terminar. |

Alguns tipos de nó, como o [**Combinar texto** (Combine Text)](https://nodaro.ai/docs/nodes/automate/combine-text), são executados dentro da própria requisição e retornam o resultado diretamente, sem `jobId`. A página [Executar nós](https://nodaro.ai/docs/developers/sdk/nodes) explica todos os métodos de execução, e [Jobs e execuções](https://nodaro.ai/docs/developers/sdk/jobs-and-executions) explica os status.

### Mostrar o progresso e deixar o usuário parar de esperar
```ts

const controller = new AbortController()
stopButton.onclick = () => controller.abort()

try {
const clip = await client.nodes.runAndWait(
"generate-video",
{ prompt: "Waves roll onto a black sand beach", provider: "seedance-2-fast", duration: 4 },
{
signal: controller.signal,
onProgress: (status) => setProgressBar(status.progress ?? 0),
},
)
showVideo(clip.videoUrl)
} catch (err) {
if (err instanceof JobAbortedError && err.jobId) {
await client.jobs.cancel(err.jobId)
} else {
throw err
}
}
```

`onProgress` recebe o status do job a cada consulta, com `progress` de 0 a 100 quando o modelo informa o progresso. Abortar o sinal só interrompe a espera. O job continua em execução até você cancelá-lo com `client.jobs.cancel(jobId)`, o que também reembolsa os créditos que ele tinha reservado.

Mostre cada resultado assim que ele chegar. Em um fluxo de duas etapas, exiba a imagem enquanto a etapa do vídeo ainda está em execução.

## Escolher como autenticar
| Provedor | Use quando | Origem do token |
| --- | --- | --- |
| `StaticTokenAuth` | Código de servidor com um token fixo | Um token de API (`ndr_...`) ou um token de acesso OAuth (`ndr_app_...`) |
| `CallbackAuth` | Você mesmo renova ou rotaciona os tokens | A sua função, chamada antes de cada requisição |
| `supabaseAuth` | Um app de navegador cujos usuários entram na mesma instância do Nodaro | A sessão ativa do usuário |

Cada requisição pede um token ao provedor e o envia como `Authorization: Bearer <token>`. Quando o provedor retorna `null`, a requisição sai sem o cabeçalho. Veja [Autenticação](https://nodaro.ai/docs/developers/sdk/auth) para conhecer cada provedor e as regras específicas do navegador.

## Tratar erros
Todo método lança uma subclasse tipada de `NodaroError` quando a API responde com um erro. Capture primeiro as classes específicas e `NodaroError` por último.

```ts

InsufficientCreditsError,
NodaroError,
RateLimitedError,
UnauthorizedError,
} from "@nodaro/sdk"

try {
await client.workflows.run(workflowId)
} catch (err) {
if (err instanceof InsufficientCreditsError) {
showPaywall({ required: err.required, available: err.available })
} else if (err instanceof UnauthorizedError) {
askForANewToken()
} else if (err instanceof RateLimitedError) {
retryLater()
} else if (err instanceof NodaroError) {
console.error(`API error ${err.status} (${err.code}): ${err.message}`)
} else {
throw err // a network failure, not an API answer
}
}
```

Todo `NodaroError` tem um `message`, um `code` estável, como `insufficient_credits`, e o `status` HTTP. A página [Erros](https://nodaro.ai/docs/developers/sdk/errors) lista todas as classes e quando cada uma é lançada.

## Receitas comuns
### Executar um workflow e esperar o resultado
`client.workflows.run()` inicia uma **execução**, que executa uma vez cada nó do workflow, e retorna na hora. Consulte `client.executions.get()` periodicamente até o status ser final.

```ts
const { executionId } = await client.workflows.run(workflowId)

for (;;) {
const { data } = await client.executions.get(executionId)
console.log(`${data.completedNodes}/${data.totalNodes} nodes done`)

if (["completed", "failed", "cancelled", "timed_out"].includes(data.status)) {
if (data.status !== "completed") throw new Error(data.errorMessage ?? data.status)
console.log(`Done. Used ${data.totalCreditsUsed} credits.`)
break
}
await new Promise((resolve) => setTimeout(resolve, 2_000))
}
```

Passe `{ nodeIds: [...] }` como segundo argumento para executar apenas alguns nós. Veja [Workflows e projetos](https://nodaro.ai/docs/developers/sdk/workflows).

### Gerar vários candidatos de uma vez
```ts
const results = await client.nodes.runMany("generate-image", [
{ prompt: "A lighthouse at dawn, watercolor" },
{ prompt: "A lighthouse at dusk, watercolor" },
{ prompt: "A lighthouse in a storm, watercolor" },
])
for (const { jobId, output } of results) console.log(jobId, output.imageUrl)
```

`runMany` rejeita quando qualquer execução falha. Para deixar um modelo escolher o melhor resultado, passe as URLs para [`client.reduce.run()`](https://nodaro.ai/docs/developers/sdk/llm-and-reduce).

### Enviar um arquivo e usá-lo
```ts
const upload = await client.uploads.upload(file) // a File, in the browser or Node.js
const portrait = await client.nodes.runAndWait("generate-image", {
prompt: "The same person as a watercolor portrait",
referenceImageUrls: [upload.url],
})
```

O upload retorna uma `url` pública que você pode passar para qualquer nó que receba a URL de uma imagem, de um vídeo ou de um áudio. Veja [Mídia e uploads](https://nodaro.ai/docs/developers/sdk/media-and-uploads).

### Verificar o preço antes de executar
```ts
const { total } = await client.credits.balance()
const { data: prices } = await client.credits.modelCosts(["nano-banana-pro", "nano-banana-pro:4K"])

if (total < prices["nano-banana-pro:4K"]) showPaywall()
```

Preços e saldos existem no Nodaro Cloud. Veja [Modelos e créditos](https://nodaro.ai/docs/developers/sdk/models-and-credits) e [Créditos](https://nodaro.ai/docs/concepts/credits).

### Melhorar um prompt antes de gerar
```ts
const { prompt } = await client.promptHelper.enhance({
nodeType: "generate-image",
prompt: "snow leopard on a rock",
})
```

O [Assistente de prompt](https://nodaro.ai/docs/developers/sdk/pickers-and-prompts) reescreve uma ideia rascunhada como um prompt detalhado para o nó que você indicar. Cada chamada custa créditos.

## Usar o SDK com um assistente de programação com IA
- **Plugin do Claude Code.** Execute `/plugin marketplace add nodaroai/app.nodaro.ai` e depois `/plugin install nodaro`. O plugin adiciona uma skill que conhece os padrões, os modelos e os créditos do SDK, e conecta o servidor MCP hospedado do Nodaro. Veja [Skills para agentes](https://nodaro.ai/docs/developers/agent-skills).
- **Outros assistentes.** O README do pacote no npm começa com uma introdução curta escrita para assistentes de programação. Cole-a no Cursor ou em qualquer outro assistente junto com o seu pedido.
- **Sem nenhum código.** Para deixar um assistente executar o Nodaro por você, conecte-o por [MCP](https://nodaro.ai/docs/mcp).

## Referência
<Card title="Cliente" href="/docs/developers/sdk/client" description="createClient, todas as opções, os espaços de trabalho e a lista completa de recursos." />
<Card title="Autenticação" href="/docs/developers/sdk/auth" description="StaticTokenAuth, CallbackAuth, supabaseAuth e sessões compartilhadas do navegador." />
<Card title="Erros" href="/docs/developers/sdk/errors" description="Todas as classes de erro, o status e o código de cada uma, e como se recuperar." />
<Card title="Executar nós" href="/docs/developers/sdk/nodes" description="run, runAndWait e runMany, com parâmetros tipados." />
<Card title="Workflows e projetos" href="/docs/developers/sdk/workflows" description="Criar, atualizar, compartilhar, exportar e executar workflows." />
<Card title="Jobs e execuções" href="/docs/developers/sdk/jobs-and-executions" description="Consultar periodicamente, listar, cancelar e excluir execuções." />

O SDK encapsula os mesmos endpoints da [API REST](https://nodaro.ai/docs/developers/api). Para um endpoint que ainda não tem método no SDK, chame-o com `client.request()`, que mantém a mesma autenticação e os mesmos erros tipados.

## Frequently asked questions

### O que é o @nodaro/sdk?

É o cliente oficial em TypeScript da API REST do Nodaro. Ele executa nós e workflows, espera os resultados e gerencia personagens, vozes, mídias e muito mais, com um método tipado e um erro tipado para cada chamada.

### Como autenticar o SDK do Nodaro?

Crie um token no Nodaro em Configurações › Tokens de API, guarde-o em uma variável de ambiente e passe-o para createClient como new StaticTokenAuth(token). Apps de navegador e apps OAuth usam supabaseAuth ou CallbackAuth em vez disso.

### Quais runtimes o SDK suporta?

Node.js 20 ou mais recente e qualquer runtime com fetch e URL globais, como navegadores modernos, React Native, Cloudflare Workers, Deno e Bun.

### Preciso consultar os resultados periodicamente por conta própria?

Não. client.nodes.runAndWait inicia uma execução, consulta o job dela a cada 2 segundos e resolve com as URLs de saída. Escreva o seu próprio loop com client.jobs.getStatus apenas quando precisar de controle total.

### Posso usar o SDK com uma instalação self-hosted do Nodaro?

Sim. Defina baseUrl como o endereço da sua instância. Alguns recursos, como as produções do Studio, o Recast e as organizações, só existem no Nodaro Cloud e respondem 404 nas demais instalações.
