Nodaro 문서
문서노드 레퍼런스모델템플릿AI 에이전트(MCP)개발자셀프 호스팅리서치비교
TypeScript SDK

앱과 템플릿

TypeScript로 게시된 Nodaro 앱을 둘러보고 실행하고, 실행 기록을 읽고, 워크플로 템플릿을 프로젝트에 복제하고, 튜토리얼을 나열하세요.

client.apps는 게시된 앱, 즉 입력과 출력으로 된 간단한 양식으로 감싼 워크플로를 둘러보고 실행합니다. client.templates는 템플릿 마켓플레이스를 둘러보고 템플릿을 내 프로젝트 중 하나에 복제하며, client.tutorials는 튜토리얼 동영상과 튜토리얼 워크플로를 나열합니다. 개념은 앱과 튜토리얼과 템플릿을 참조하세요.

메서드

메서드하는 일
apps.list(params?)게시된 앱 둘러보기
apps.get(slug)앱과 그 입력, 출력 읽기
apps.run(slug, inputs?, opts?)앱 실행
apps.listRuns(slug, params?)앱의 내 실행 나열
apps.getRun(slug, runId)실행 하나 읽기
apps.deleteRun(slug, runId)실행 보관
templates.browse(params?)템플릿 마켓플레이스 둘러보기
templates.get(slug)템플릿과 그 워크플로 읽기
templates.clone(slug, params)템플릿을 프로젝트에 복사
tutorials.list()카테고리별 튜토리얼 나열

client.apps

list()와 get()은 공개되어 있습니다. run()과 실행 기록은 로그인한 호출자로서 작동합니다.

apps.list(params?)

게시된 앱을 한 페이지씩 둘러봅니다.

list(params?: { search?: string; category?: string; limit?: number; cursor?: string }): Promise<{
  data: PublishedApp[]
  nextCursor?: string | null
}>

속성

타입

const { data: apps, nextCursor } = await client.apps.list({ search: "headshot", limit: 20 })

PublishedApp에는 id, slug, name, description, creatorId, creatorName, thumbnailUrl, category, isFeatured, runCount, estimatedCredits, perMinuteCredits, perItemCredits, createdAt, updatedAt이 있습니다.

estimatedCredits는 앱의 실행당 표시 가격입니다. 어떤 앱은 입력받는 녹음의 길이에 따라 가격이 정해집니다. 예를 들어 편집 계획 단계나 에피소드 전체의 렌더링입니다. 이런 앱은 perMinuteCredits가 0보다 크며, 가격은 estimatedCredits에 녹음 1분마다 perMinuteCredits를 더한 값입니다. 앱에 사용자가 채우는 목록 입력이 있으면 perItemCredits가 0보다 큽니다. 제작자가 저장한 항목을 넘는 항목마다 그만큼의 크레딧이 더해집니다.

앱 사용자가 고를 수 있는 선택지가 더 비싸면 표시 가격은 범위가 됩니다. maxEstimatedCredits는 maxPerMinuteCredits, maxPerItemCredits와 함께, 제작자가 정한 제한 안에서 앱이 노출한 필드로 실행 한 번에 들 수 있는 최대 가격입니다. estimatedCredits와 그 구성 요소는 저장된 설정의 가격, 즉 "부터" 가격입니다. max* 필드는 값이 다를 때만 있습니다. 범위가 생기기 전에 게시된 앱에는 다음에 게시할 때까지 이 필드가 없습니다.

apps.get(slug)

앱 하나를 읽습니다. 최종 사용자가 채우는 필드인 inputSchema와 앱이 반환하는 것인 outputs가 함께 들어 있습니다.

get(slug: string): Promise<{ data: PublishedAppDetail }>

속성

타입

const { data: app } = await client.apps.get("pro-headshot")
console.log(app.inputSchema, app.outputs) // outputs: [{ nodeId, label, type }]

runEstimatedCredits, runPerMinuteCredits, runPerItemCredits는 앱 실행만의 가격입니다. 표시 가격에서 최종 렌더링 부분을 뺀 값이며, 최종 렌더링은 따로 실행되고 따로 청구됩니다. editPlanPerMinute는 편집 계획 노드가 녹음의 시작된 1분마다 청구되면 true이고, 15, 30, 60, 90, 120, 180분 단위로 청구되면 false입니다.

apps.run(slug, inputs?, opts?)

앱을 실행하고 { executionId, status, runId? }를 즉시 반환합니다. 결과는 client.executions.get(executionId)를 폴링해 받으세요.

run(slug: string, inputs?: Record<string, unknown>, opts?: {
  inputOverrides?: Record<string, Record<string, unknown>>
}): Promise<{ executionId: string; status: "pending" | "running"; runId?: string }>

속성

타입

const { executionId } = await client.apps.run("pro-headshot", { photo: photoUrl })

// Add hidden text before the app's prompt, for this run only
await client.apps.run(
  "pro-headshot",
  { photo: photoUrl },
  { inputOverrides: { n1: { promptPrefix: "Studio portrait of" } } },
)

노출된 동영상 URL 노드로 동영상 링크를 받는 앱은 링크를 입력값으로 넣어 실행합니다. 예: client.apps.run("clip-pack", { episode: "https://www.youtube.com/watch?v=..." }). 서버는 첫 노드가 실행되기 전에 게시물 링크를 다운로드합니다. 4분 이상인 YouTube 동영상은 inputOverrides로 지정한 구간만 다운로드됩니다. 그 밖의 웹 링크는 그대로 사용됩니다.

inputOverrides는 고급 옵션입니다. 예를 들어 노드의 앞뒤 텍스트(promptPrefix와 promptSuffix)를 설정할 수 있습니다. 하지만 Webhook 출력 URL, 게시 계정, 스크레이퍼의 대상 같은 출력 노드의 대상은 설정할 수 없습니다. 그런 재정의는 400 locked_field로 거부됩니다.

apps.listRuns(slug, params?)

앱의 내 실행을 한 페이지씩 나열합니다.

listRuns(slug: string, params?: { limit?: number; cursor?: string }): Promise<{ data: AppRun[]; nextCursor?: string | null }>

속성

타입

const { data: runs } = await client.apps.listRuns("pro-headshot", { limit: 10 })
for (const run of runs) console.log(run.status, run.outputs)

AppRun에는 id, appSlug, executionId, status(pending, running, completed, failed 또는 cancelled), inputs, outputs(각각 { nodeId, type, url?, text? }), startedAt, finishedAt이 있습니다.

apps.getRun(slug, runId)

앱의 실행 하나를 읽습니다.

getRun(slug: string, runId: string): Promise<{ data: AppRun }>

속성

타입

const { data: run } = await client.apps.getRun("pro-headshot", runId)

apps.deleteRun(slug, runId)

실행을 보관합니다. 실행을 복원하거나 영구 삭제하는 기능은 Nodaro 앱에서만 사용할 수 있으므로, 스크립트가 데이터를 없앨 수는 없습니다.

deleteRun(slug: string, runId: string): Promise<{ success: true; archived: true }>

속성

타입

await client.apps.deleteRun("pro-headshot", runId)

client.templates

설계상 공개된 템플릿 마켓플레이스입니다. 둘러보고, 템플릿을 전체 워크플로와 함께 읽고, 내 프로젝트에 무료로 복제하세요.

templates.browse(params?)

마켓플레이스를 한 페이지씩 둘러봅니다(GET /v1/templates/browse). 로그인이 필요 없습니다.

browse(params?: BrowseTemplatesParams): Promise<{ data: TemplateBrowseCard[]; nextCursor: string | null }>

속성

타입

const page = await client.templates.browse({ sort: "popular", search: "trailer" })

카드의 estimatedCredits는 템플릿의 표시 가격입니다. 가격이 템플릿에 입력되는 녹음의 길이를 따르면 estimatedPerMinuteCredits가 0보다 큽니다. 그러면 가격은 estimatedCredits에 녹음 1분마다 그만큼의 크레딧을 더한 값입니다. 그렇지 않으면 estimatedPerMinuteCredits는 없거나 0입니다. 템플릿의 선택지가 더 비쌀 수 있으면 카드에는 가격 범위의 상한인 maxEstimatedCredits와 maxEstimatedPerMinuteCredits도 있습니다.

경로는 템플릿 페이지의 크레딧 적은 순 정렬인 sort=cheapest도 받습니다. 60분 녹음의 가격이 낮은 순서로 정렬하며, 그 가격은 estimatedCredits에 estimatedPerMinuteCredits의 60배를 더한 값입니다. SDK의 TemplateSort 타입에는 cheapest가 없으므로 client.request()로 보내세요.

templates.get(slug)

공개 템플릿 하나를 전체 워크플로 스냅샷인 snapshotNodes, snapshotEdges, snapshotSettings와 함께 읽습니다(GET /v1/templates/:slug).

get(slug: string): Promise<Template>

속성

타입

const template = await client.templates.get("noir-trailer")
console.log(template.snapshotNodes.length)

슬러그를 알 수 없거나, 목록에서 제외되었거나, 비활성 상태이면 NotFoundError를 발생시킵니다.

templates.clone(slug, params)

템플릿을 내 프로젝트 중 하나에 새 워크플로로 복사합니다(POST /v1/templates/:slug/clone). 크레딧이 들지 않습니다.

clone(slug: string, params: { projectId: string; name?: string }): Promise<{ workflowId: string; projectId: string }>

속성

타입

const { workflowId } = await client.templates.clone("noir-trailer", { projectId })
await client.workflows.run(workflowId)

client.tutorials

tutorials.list()

모든 튜토리얼 카테고리를 그 튜토리얼 동영상, 튜토리얼 워크플로와 함께 나열합니다(GET /v1/tutorials). 공개되어 있으며 읽기 전용입니다.

list(): Promise<{ categories: TutorialCategory[] }>
const { categories } = await client.tutorials.list()
for (const category of categories) {
  console.log(category.name, category.videos.length, category.flows.length)
}

각 카테고리에는 id, name, slug, sortOrder, videos, flows가 있습니다. 동영상에는 title, videoUrl, thumbnailUrl이 있습니다. 플로는 튜토리얼로 표시된 템플릿으로, title, complexity, estimatedCredits, 사용하는 노드 유형과 모델, 그리고 templates.get()과 templates.clone()에 전달할 수 있는 slug가 있습니다.

자주 묻는 질문

코드에서 Nodaro 앱을 실행하려면 어떻게 하나요?

앱의 슬러그와, 키가 앱의 입력 필드와 일치하는 inputs 객체를 담아 client.apps.run을 호출하세요. executionId가 반환되므로, 결과는 client.executions.get(executionId)를 폴링해 받으세요.

앱이 기대하는 입력은 어떻게 알 수 있나요?

client.apps.get(slug)을 호출하세요. inputSchema에는 최종 사용자가 채우는 필드가, outputs에는 앱이 반환하는 것이 나열됩니다.

템플릿을 복제하면 크레딧이 드나요?

아니요. client.templates.clone은 템플릿을 내 프로젝트 중 하나에 무료로 복사합니다. 비용은 새 워크플로를 실행할 때만 듭니다.

inputOverrides로 앱이 결과를 보내는 곳을 바꿀 수 있나요?

아니요. 재정의로는 Webhook 출력 URL이나 게시 계정 같은 대상을 설정할 수 없습니다. 이런 실행은 400 locked_field로 거부됩니다.

최종 업데이트

목차