# REST API 개요

> Nodaro REST API는 JSON과 Bearer 토큰으로 HTTPS를 통해 워크플로와 단일 노드를 실행하고, 작업을 폴링하고, 미디어를 업로드하고, 에셋을 관리합니다.

Source: https://nodaro.ai/ko/docs/developers/api

**Nodaro REST API**는 Nodaro의 HTTP 인터페이스입니다. 워크플로와 단일 노드를 실행하고, 작업 상태를 알려 주고, 내 미디어를 저장하고, 캐릭터, 프리셋, 워크스페이스를 관리합니다. 요청과 응답은 HTTPS를 통한 JSON이며, 모든 요청에 Bearer 토큰이 들어갑니다. 같은 API가 Nodaro Cloud와 셀프 호스팅 설치에서 작동하며, [TypeScript SDK](https://nodaro.ai/docs/developers/sdk)와 [CLI](https://nodaro.ai/docs/developers/cli)는 이 API의 얇은 클라이언트입니다.

## 기본 URL
| Nodaro 실행 위치 | 기본 URL |
| --- | --- |
| Nodaro Cloud | `https://app.nodaro.ai` |
| 셀프 호스팅 설치 | 설치의 자체 주소입니다. 예: 기본 Community Edition 설치는 `http://localhost:3000` |

모든 경로는 `/v1/`로 시작합니다. 예: `https://app.nodaro.ai/v1/nodes`. 크레딧과 조직처럼 Nodaro Cloud에만 있는 엔드포인트는 다른 에디션에서 `404`를 반환합니다. 엔드포인트가 제한되는 경우 각 페이지에 적혀 있습니다.

## 인증
모든 요청에 `Authorization: Bearer <token>`을 보내세요. 내 계정에는 **설정 › API 토큰**에서 만든 개인 API 토큰(`ndr_…`)을, 내 제품이 다른 Nodaro 사용자를 대신해 작동할 때는 OAuth 액세스 토큰(`ndr_app_…`)을, Community Edition 설치에서는 세션 JWT를 사용하세요. `GET /v1/nodes`, `GET /v1/models` 같은 일부 탐색 엔드포인트에는 토큰이 전혀 필요하지 않습니다. 토큰을 만들려면 [인증](https://nodaro.ai/docs/developers/api/authentication)을 읽어 보세요.

## 첫 번째 호출
이 예제는 노드 하나로 이미지를 생성하고 결과를 읽습니다. 생성은 비동기식입니다. 첫 호출은 작업 id를 반환하고, 작업이 완료될 때까지 폴링합니다.

**curl**

```bash
export NODARO_API_KEY="ndr_..."

# 1. Start the 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 snow leopard on a mountain ridge at dawn",
"provider": "nano-banana-pro",
"aspectRatio": "16:9"
}'
# {"jobId":"0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10"}

# 2. Poll the job until its status is "completed"
curl -s https://app.nodaro.ai/v1/jobs/0f1a9c2e-5b7d-4e8a-9c31-6d2f8b4a7e10/status \
  -H "Authorization: Bearer $NODARO_API_KEY"
```

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

**TypeScript SDK**

```ts

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

// Starts the job and polls it until it finishes.
const output = await client.nodes.runAndWait('generate-image', {
prompt: 'a snow leopard on a mountain ridge at dawn',
provider: 'nano-banana-pro',
aspectRatio: '16:9',
})
console.log(output.imageUrl)
```

**CLI**

```bash
nodaro nodes run generate-image \
  --param prompt="a snow leopard on a mountain ridge at dawn" \
  --param provider=nano-banana-pro \
  --param aspectRatio=16:9 \
  --watch --json | jq -r '.output_data.imageUrl'
```

모든 생성 노드가 같은 패턴으로 실행됩니다. 노드 설정을 담아 `POST /v1/<node-type>`을 보낸 다음 작업을 폴링하세요. [단일 노드 실행](https://nodaro.ai/docs/developers/api/nodes)을 참조하세요.

## 요청과 응답 규칙
- **JSON으로 보내고 JSON으로 받습니다.** 본문은 `Content-Type: application/json`과 함께 JSON으로 보내세요. 파일 업로드는 예외로 `multipart/form-data`를 사용합니다.
- **id는 UUID입니다.** 형식이 잘못된 id는 `400 validation_error`를 반환합니다.
- **대부분의 응답은 `data`로 감싸져 있습니다.** 읽기는 `{ "data": … }`를 반환하고, 삭제나 취소는 `{ "success": true }`를 반환합니다. `/v1/api/` 아래의 레거시 워크플로 엔드포인트는 페이로드를 그대로 반환합니다.
- **생성은 작업 id를 반환합니다.** `POST /v1/<node-type>`은 `{ "jobId": "…" }`로 응답하며, 그 옆에 `adjustments`나 `warnings`가 함께 올 때도 있습니다.
- **목록은 커서를 사용합니다.** 목록은 커서를 반환하며, 대개 `nextCursor`입니다(`GET /v1/jobs`에서는 `next`). 다음 페이지를 가져오려면 이 값을 `?cursor=`로 다시 보내세요. 커서가 `null`이면 더 이상 행이 없습니다. 커서는 불투명한 값이므로 파싱하거나 직접 만들지 마세요.
- **필드 형식은 두 가지입니다.** 작업 객체는 `output_data`, `created_at`처럼 snake_case를 사용합니다. 워크플로, 실행, 그 밖의 대부분의 리소스는 camelCase를 사용합니다.
- **응답은 늘어납니다.** 시간이 지나면서 새 필드가 추가됩니다. 모르는 필드 때문에 실패하지 말고 무시하세요.
- **오류의 형태는 하나입니다.** 실패한 호출은 HTTP 상태와 `{ "error": { "code": "…", "message": "…" } }`를 반환합니다. `code`로 분기하세요. [오류](https://nodaro.ai/docs/developers/api/errors)를 참조하세요.

선택 사항인 두 헤더로 요청 처리 방식을 바꿀 수 있습니다.

| 헤더 | 설명 |
| --- | --- |
| `X-Nodaro-Workspace` | 조직의 워크스페이스 하나에서 작동합니다. 목록이 어느 워크스페이스를 읽고, 새로 만든 항목이 어디에 들어갈지 정합니다. [워크스페이스](https://nodaro.ai/docs/developers/api/workspaces)를 참조하세요. |
| `X-Nodaro-Client` | 작업을 만든 클라이언트를 기록합니다. `sdk/<version>`, `cli/<version>`, `extension/<name>` 중 하나입니다. [내 클라이언트 식별](https://nodaro.ai/docs/developers/api/authentication#identify-your-client)을 참조하세요. |

## 동기와 비동기
Nodaro에서 하는 일은 대부분 몇 초에서 몇 분이 걸리므로 API는 비동기식입니다. 생성 라우트는 즉시 `jobId`로 응답하고, 워크플로 실행은 `executionId`와 함께 `202 Accepted`로 응답합니다. 그런 다음 최종 상태가 될 때까지 [작업](https://nodaro.ai/docs/developers/api/jobs)이나 [실행](https://nodaro.ai/docs/developers/api/executions)을 2~5초마다 폴링합니다. 1분 안에 끝날 것으로 예상되는 워크플로라면, `POST /v1/api/run?wait=true`가 최대 600초 동안 연결을 유지한 뒤 결과를 반환합니다. 인라인 텍스트 노드, 무료 미디어 처리, 구조화 LLM 호출처럼 동기식으로 응답하는 라우트도 일부 있습니다. 자세한 내용은 [동기 또는 비동기](https://nodaro.ai/docs/developers/api/workflows#sync-or-async)를 읽어 보세요. 작업을 폴링하지 않으려면 [Webhook 엔드포인트](https://nodaro.ai/docs/developers/api/webhooks#job-events)를 등록하세요. 그러면 내 작업 하나가 완료되거나 실패할 때마다 Nodaro가 서버로 서명된 이벤트를 보냅니다.

## 영역별 엔드포인트
### 실행하기
| 페이지 | 다루는 내용 | 주요 엔드포인트 |
| --- | --- | --- |
| [워크플로](https://nodaro.ai/docs/developers/api/workflows) | 저장된 워크플로를 입력값과 함께 또는 입력값 없이 실행, 워크플로 관리 | `POST /v1/workflows/:id/run`, `POST /v1/api/run`, `GET /v1/api/schema` |
| [노드](https://nodaro.ai/docs/developers/api/nodes) | 워크플로 없이 노드 하나 실행, 생성 세션, 팔레트와 무드보드, 노드, 모델, 피커 찾기 | `POST /v1/<node-type>`, `/v1/sessions`, `GET /v1/models` |
| [작업](https://nodaro.ai/docs/developers/api/jobs) | 작업 상태와 결과, 평가와 즐겨찾기, 일괄 폴링, 취소, **동영상 생성 Pro** 실행 제어 | `GET /v1/jobs/:id/status`, `POST /v1/jobs/batch-status` |
| [실행](https://nodaro.ai/docs/developers/api/executions) | 워크플로 실행의 상태와 기록 | `GET /v1/workflow-executions/:id`, `GET /v1/workflows/:id/executions` |
| [업로드](https://nodaro.ai/docs/developers/api/uploads) | 이미지, 동영상, 오디오 업로드, URL을 저장소로 복사, 내 미디어 라이브러리 검색 | `POST /v1/upload`, `GET /v1/library` |
| [Webhook](https://nodaro.ai/docs/developers/api/webhooks) | 서버에서 서명된 작업 이벤트 받기, HTTP 호출이나 일정으로 워크플로 시작, 결과를 외부로 보내기 | `/v1/webhook-endpoints`, `POST /v1/webhooks/:token` |

### 리소스
| 페이지 | 다루는 내용 | 주요 엔드포인트 |
| --- | --- | --- |
| [캐릭터](https://nodaro.ai/docs/developers/api/characters) | 캐릭터, 포트레이트 후보, 표정, 포즈, 모션 | `/v1/characters`, `POST /v1/generate-character` |
| [오브젝트](https://nodaro.ai/docs/developers/api/objects) | 대표 이미지와 변형이 있는 소품, 제품, 차량 | `/v1/objects`, `POST /v1/generate-object` |
| [장소](https://nodaro.ai/docs/developers/api/locations) | 대표 이미지와 변형이 있는 장소 | `/v1/locations`, `POST /v1/generate-location` |
| [크리처](https://nodaro.ai/docs/developers/api/creatures) | 대표 이미지와 변형이 있는 크리처 | `/v1/creatures` |
| [프리셋](https://nodaro.ai/docs/developers/api/presets) | 내 노드 프리셋 읽기와 쓰기, 공개된 기본 제공 카탈로그 읽기 | `/v1/node-presets`, `GET /v1/node-presets/factory` |
| [커뮤니티](https://nodaro.ai/docs/developers/api/community) | 공유된 캐릭터, 장소, 오브젝트 둘러보기와 복제 | `GET /v1/community/browse` |
| [파이프라인](https://nodaro.ai/docs/developers/api/pipelines) | **스토리 → 동영상** 파이프라인 | `POST /v1/pipelines/:id/branch` |
| [프롬프트 마법사](https://nodaro.ai/docs/developers/api/prompt-wizard) | 생성 노드용 프롬프트 개선 | `POST /v1/prompt-helper/wizard` |
| [Recast](https://nodaro.ai/docs/developers/api/recast) | 분석한 동영상을 내 캐스트로 다시 생성 | `POST /v1/recast` |
| [스튜디오 프로덕션](https://nodaro.ai/docs/developers/api/studio-productions) | 샷 단위 프로덕션 | `/v1/studio/productions` |
| [보이스와 미디어](https://nodaro.ai/docs/developers/api/voice-and-media) | 보이스, 보이스 변환, 더빙, 미디어 가져오기, 오디오 도구 | `/v1/voices`, `/v1/download-video`, `/v1/transcribe` |
| [캐릭터 학습](https://nodaro.ai/docs/developers/api/character-training) | 캐릭터 하나로 모델 학습 | `POST /v1/characters/:id/train` |
| [3D 장면](https://nodaro.ai/docs/developers/api/3d-scenes) | 편집 가능한 3D 장면과 **3D 렌더링 Pro** | `POST /v1/3d-scene/generate`, `POST /v1/pro-3d-render` |

### 계정
| 페이지 | 다루는 내용 | 주요 엔드포인트 |
| --- | --- | --- |
| [워크스페이스와 조직](https://nodaro.ai/docs/developers/api/workspaces) | 워크스페이스에서의 동작, 조직, 멤버, 초대, 사용량 | `/v1/orgs`, `/v1/workspaces` |
| [크레딧](https://nodaro.ai/docs/developers/api/credits) | 잔액, 요금제와 가격, 거래 내역, 가격 조회 | `GET /v1/credits/balance`, `GET /v1/credits/transactions` |

### 레퍼런스
| 페이지 | 다루는 내용 |
| --- | --- |
| [오류](https://nodaro.ai/docs/developers/api/errors) | 오류 응답 형식, 모든 오류 코드, 작업 실패 힌트 |
| [요청 한도](https://nodaro.ai/docs/developers/api/rate-limits) | 토큰별 한도, 라우트별 한도, `429` 처리 방법 |
| [OpenAPI 사양](https://nodaro.ai/docs/developers/api/openapi) | `GET /v1/openapi.json`에 있는 기계 판독용 사양과 다른 언어용 클라이언트 |

## 한도와 오류
개인 API 토큰은 워크플로 실행과 워크플로 목록 엔드포인트에서 기본적으로 분당 30회, 최대 120회까지 요청할 수 있으며, 일부 라우트에는 자체 한도가 있습니다. 상태 폴링은 토큰 한도에 포함되지 않습니다. `429`는 속도를 늦추고 백오프로 재시도하라는 뜻이고, `4xx`는 재시도하기 전에 요청을 고치라는 뜻이며, `5xx`는 대개 일시적입니다. [요청 한도](https://nodaro.ai/docs/developers/api/rate-limits)와 [오류](https://nodaro.ai/docs/developers/api/errors)를 읽어 보세요.

## 언어별 클라이언트
- **TypeScript와 JavaScript:** `npm install @nodaro/sdk`. [SDK](https://nodaro.ai/docs/developers/sdk)는 타입, 타입이 지정된 오류, 폴링 도우미로 이 엔드포인트를 감쌉니다.
- **터미널과 CI:** `npm install -g @nodaro/cli`. [CLI](https://nodaro.ai/docs/developers/cli)는 `--watch`, `--json`과 함께 워크플로, 앱, 단일 노드를 실행합니다.
- **그 밖의 언어:** [OpenAPI 사양](https://nodaro.ai/docs/developers/api/openapi)으로 클라이언트를 생성하거나, 일반 HTTPS 요청을 보내세요.
- **AI 어시스턴트:** 코드를 작성하는 대신 [MCP 서버](https://nodaro.ai/docs/mcp)를 연결하세요.

## 자주 묻는 질문

### Nodaro API의 기본 URL은 무엇인가요?

Nodaro Cloud에서는 https://app.nodaro.ai이며, 모든 경로는 /v1/로 시작합니다. 예: https://app.nodaro.ai/v1/nodes. 셀프 호스팅 설치에서는 설치의 자체 주소를 사용하세요.

### Nodaro API는 동기식인가요, 비동기식인가요?

대부분 비동기식입니다. 생성은 작업 id를, 워크플로 실행은 실행 id를 반환하며, 끝날 때까지 폴링합니다. 1분 안에 끝나는 워크플로라면 POST /v1/api/run?wait=true로 연결을 유지할 수도 있습니다.

### Nodaro API는 어떤 프로그래밍 언어로 사용할 수 있나요?

JSON으로 HTTPS 요청을 보낼 수 있는 모든 언어에서 사용할 수 있습니다. TypeScript와 JavaScript에는 @nodaro/sdk 패키지가 있으며, OpenAPI 3.1 사양으로 Go, Rust, Python 등의 타입 클라이언트를 생성할 수 있습니다.

### Nodaro API를 쓰면 크레딧이 드나요?

생성에는 크레딧이 듭니다. Nodaro Cloud에서는 각 생성이 에디터와 마찬가지로 모델 가격만큼 크레딧을 사용합니다. 셀프 호스팅 Community Edition 설치에는 크레딧 시스템이 없으며, 모델 공급자에게 직접 비용을 지불합니다.

### API를 사용하려면 구독이 필요한가요?

아니요. Nodaro Cloud에서는 크레딧 팩을 하나라도 구매하면 종량제가 활성화되며, 종량제 크레딧은 API, SDK, CLI, MCP에서 사용할 수 있습니다. 웹 에디터를 사용하려면 구독이 필요합니다.
