# 오브젝트

> REST로 소품과 제품을 다룹니다. 오브젝트를 만들고 보관하며, 대표 이미지와 재질·앵글 베리언트, 모션 클립을 생성하고 대표 이미지를 승인합니다.

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

**오브젝트 API**는 오브젝트/소품 스튜디오가 소품과 제품에 대해 하는 모든 작업을 스크립트로 실행합니다. 오브젝트를 만들고, 대표 이미지 후보를 생성하고, 그중 하나를 승인한 다음, 앵글, 재질, 변형 베리언트와 모션 클립을 추가합니다. 그러면 이미지 노드와 동영상 노드가 오브젝트를 재사용하므로, 같은 랜턴, 자동차, 의자가 모든 샷에서 똑같이 보입니다.

이 라우트는 모든 에디션에서 작동하며 Bearer 토큰을 받습니다. 개인 API 토큰(`ndr_…`), OAuth 앱 토큰(`ndr_app_…`), 또는 Community Edition에서는 세션 토큰을 사용합니다. 모든 라우트는 호출자 범위로 제한됩니다. [인증](https://nodaro.ai/docs/developers/api/authentication)을 참조하세요.

## 엔드포인트
| 메서드 | 경로 | 하는 일 |
| --- | --- | --- |
| `GET` | `/v1/objects` | 내 오브젝트 목록을 가져옵니다. |
| `GET` | `/v1/objects/:id` | 진행 중인 작업과 함께 오브젝트 하나를 가져옵니다. |
| `POST` | `/v1/objects` | 오브젝트를 만들거나, 본문에 `id`가 있으면 업데이트합니다. |
| `DELETE` | `/v1/objects/:id` | 오브젝트를 보관합니다. 복원할 수 있습니다. |
| `DELETE` | `/v1/objects/:id?permanent=true` | 보관된 오브젝트와 그 파일을 영구 삭제합니다. |
| `POST` | `/v1/objects/:id/restore` | 보관된 오브젝트를 복원합니다. |
| `POST` | `/v1/generate-object` | 대표 이미지 후보를 생성합니다. |
| `POST` | `/v1/generate-object-asset` | 앵글, 재질, 변형 또는 사용자 지정 베리언트 하나를 생성합니다. |
| `POST` | `/v1/generate-object-motion` | 대표 이미지에 움직임을 주어 모션 클립으로 만듭니다. |
| `POST` | `/v1/objects/:id/approve-main-image` | 후보를 대표 이미지로 승인하고 오브젝트의 설명을 작성합니다. |
| `POST` | `/v1/objects/:id/llm-caption` | 현재 대표 이미지로 설명을 다시 작성합니다. |

## 오브젝트의 구성
| 필드 | 담는 내용 |
| --- | --- |
| `id`, `name`, `description` | 식별자, 표시 이름, 정체성 메모입니다. |
| `category` | `furniture`, `vehicle`, `weapon`, `food`, `clothing`, `electronics`, `nature`, `tool`, `animal` 또는 `other`입니다. |
| `style` | `realistic`, `anime`, `3d-pixar` 또는 `illustration`입니다. |
| `sourceImageUrl` | 기준이 되는 대표 이미지로, 후보를 승인하면 설정됩니다. |
| `canonicalDescription` | 약 80~120단어의 시각적 설명으로, 대표 이미지가 승인될 때 Nodaro가 작성합니다. 그 전까지는 빈 문자열입니다. |
| `styleLock` | 베리언트를 대표 이미지에서 생성할지 여부입니다. 기본값은 `true`입니다. |
| `angles`, `materials`, `variations`, `motionClips` | 에셋 버킷입니다. 각 항목은 `{ name, url }`이며, `motionClips`에는 동영상이 들어갑니다. |
| `referencePhotos` | 최대 20장의 무드 보드 사진으로, 각각 `{ kind, url }`입니다. |
| `pendingJobs` | `GET /v1/objects/:id`에서만 제공됩니다. 이 오브젝트에 대해 아직 실행 중인 베리언트 작업입니다. |

### 에셋 버킷
| 버킷 | 보여 주는 것 | 프리셋 베리언트 |
| --- | --- | --- |
| `angles` | 다른 시점에서 본 오브젝트 | front, side, top, back, three-quarter, detail, in-context, exploded, perspective |
| `materials` | 다른 재질로 된 오브젝트 | wood, metal, glass, plastic, fabric, stone, ceramic, leather, paper, gold, silver, copper, marble |
| `variations` | 다른 상태나 스타일 | clean, weathered, damaged, ornate, minimal, broken, antique, futuristic, holographic, dirty, polished |
| `motionClips` | 반복 재생되는 카메라 무브 클립 | rotate-360, hover, spin-slow, parallax, pulse, drift, dolly-around, push-in, drone-orbit |

### 레퍼런스 사진
무드 보드는 오브젝트와 함께 전달됩니다. 오브젝트를 사용하는 모든 노드는 이미지를 연결하지 않아도 이 사진들을 추가 레퍼런스로 받으며, 각 사진의 `kind`는 그 사진이 무엇을 위한 것인지 모델에게 알려 줍니다.

| `kind` | 용도 |
| --- | --- |
| `front` | 깔끔한 정면 모습입니다. |
| `side` | 측면 프로필로, 탈것, 가구, 무기에 유용합니다. |
| `detail` | 각인이나 경첩처럼 특징적인 부분의 클로즈업입니다. |
| `context` | 크기를 가늠할 수 있도록 놓이거나, 손에 들리거나, 장착된 상태의 오브젝트입니다. |
| `moodBoard` | 색상 팔레트나 분위기입니다. |
| `other` | 그 밖의 모든 것입니다. |

사진은 최대 20장까지 추가할 수 있으며, 종류별 개수에는 제한이 없습니다. 주인공 소품이나 대표 제품이라면 첫 생성 전에 사진을 3~6장 추가하세요. 그러면 첫 결과가 훨씬 더 충실해집니다.

## 오브젝트 목록
`GET /v1/objects`는 활성 오브젝트를 최신순으로 반환합니다. 보관함을 보려면 `archived=true`를, 프로젝트 하나로 좁히려면 `projectId`를 추가하세요. 이름이나 설명에 그 단어가 모두 들어 있는 오브젝트만 남기려면 `q`를 추가하세요. 대소문자는 구분하지 않으며, [캐릭터](https://nodaro.ai/docs/developers/api/characters#search)와 같은 검색입니다. MCP `list_objects` 도구는 같은 검색을 `search`로 받습니다. `limit`이 없으면 라우트는 전체 목록을 반환합니다. `limit`(최대 500)을 지정하면 한 페이지와 `nextCursor`를 반환합니다. 이 값이 `null`이 될 때까지 `cursor`로 다시 전달하세요.

**curl**

```bash
curl "https://app.nodaro.ai/v1/objects?limit=100" \
  -H "Authorization: Bearer $NODARO_API_KEY"
```

**TypeScript SDK**

```ts

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

const page = await client.objects.list({ limit: 100 })
const next = await client.objects.list({ limit: 100, cursor: page.nextCursor! })
const { objects: archived } = await client.objects.listArchived()
```

**CLI**

```bash
nodaro objects list --json
nodaro objects list --archived
```

`GET /v1/objects/:id`는 `pendingJobs`와 함께 오브젝트 하나를 반환합니다. 보관된 오브젝트는 존재하지 않는 오브젝트와 똑같이 `404 not_found`를 반환합니다.

## 오브젝트 만들기 또는 업데이트
`POST /v1/objects`는 본문에 `id`가 없으면 오브젝트를 만들고, 있으면 업데이트합니다. 만들 때는 `nodeId`와 `name`이 필요합니다. 캔버스 노드가 없으면 `nodeId`에 `"scripted"` 같은 아무 레이블이나 사용하세요.

업데이트에서는 보낸 필드만 기록됩니다. 에셋 버킷은 업데이트로 기록되지 않으므로, 저장이 작업에서 추가 중인 베리언트를 덮어쓸 수 없습니다. `expectedUpdatedAt`에 오브젝트의 현재 `updatedAt` 값을 넣어 보내면, 읽은 뒤에 누군가 오브젝트를 변경한 경우 업데이트가 거부됩니다. 이때 라우트는 `409 concurrent_modification`으로 응답합니다.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/objects \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
"nodeId": "scripted",
"name": "Antique Lantern",
"description": "Weathered brass lantern with hand-engraved filigree",
"category": "tool",
"style": "realistic"
}'
```

**TypeScript SDK**

```ts
const { id } = await client.objects.create({
nodeId: 'scripted',
name: 'Antique Lantern',
description: 'Weathered brass lantern with hand-engraved filigree',
category: 'tool',
style: 'realistic',
})

const object = await client.objects.get(id)
await client.objects.update(id, { styleLock: false, expectedUpdatedAt: object.updatedAt })
```

**CLI**

```bash
nodaro objects create "Antique Lantern" --node-id scripted \
  --description "Weathered brass lantern with hand-engraved filigree" \
  --category tool --style realistic

nodaro objects update <id> --style-lock false
```

만들기는 `{ id }`를 반환합니다. 업데이트는 `{ id, updatedAt }`을 반환합니다.

<TypeTable
type={{
id: { type: 'string (uuid)', description: '업데이트할 오브젝트입니다. 오브젝트를 만들려면 생략하세요.' },
nodeId: { type: 'string', description: '만들 때 필수입니다. 오브젝트가 속한 캔버스 노드이며, 노드가 없으면 아무 레이블이나 사용합니다.' },
name: { type: 'string', description: '만들 때 필수입니다.' },
description: { type: 'string', description: '오브젝트를 특징짓는 점을 1~3문장으로 씁니다.' },
category: { type: 'string', description: 'furniture, vehicle, weapon, food, clothing, electronics, nature, tool, animal 또는 other입니다.' },
style: { type: 'string', description: 'realistic, anime, 3d-pixar 또는 illustration입니다.' },
styleLock: { type: 'boolean', description: '승인된 대표 이미지에서 베리언트를 생성합니다.', default: 'true' },
referencePhotos: { type: 'array', description: '최대 20장의 { kind, url } 무드 보드 사진입니다.' },
canonicalDescription: { type: 'string', description: '작성된 설명을 바꿉니다.' },
sourceImageUrl: { type: 'string', description: '대표 이미지를 직접 설정합니다.' },
projectId: { type: 'string (uuid)', description: '오브젝트를 넣을 프로젝트입니다.' },
expectedUpdatedAt: { type: 'string (ISO 8601)', description: '업데이트 시: 이 타임스탬프 이후 오브젝트가 변경되었으면 409로 쓰기를 거부합니다.' },
}}
/>

### 스타일 고정의 효과
- **켜짐(기본값).** 모든 앵글, 재질, 변형이 승인된 대표 이미지에서 생성됩니다. 베리언트는 비율, 실루엣, 특징적인 디테일을 유지합니다. 오브젝트를 사용하는 노드는 기준 설명도 받습니다. 모든 샷에서 같은 물건으로 보여야 하는 경우에 사용하세요.
- **꺼짐.** 베리언트가 텍스트만으로 생성됩니다. 노드는 여전히 기준 설명을 받지만 참고용일 뿐이므로, 모델이 디자인을 새롭게 해석할 수 있습니다. 다른 안을 탐색하거나 룩을 비교할 때 사용하세요.

## 대표 이미지 후보 생성
`POST /v1/generate-object`는 후보마다 작업을 하나씩 시작하고, 후보당 ID가 하나씩 든 `jobIds`를 즉시 반환합니다. 후보가 하나인 요청은 `jobId`도 반환합니다. [작업 API](https://nodaro.ai/docs/developers/api/jobs)로 작업을 폴링하세요.

`attachToObjectId`와 `count` 1을 함께 보내면 작업이 완료될 때 결과가 오브젝트의 대표 이미지가 됩니다. 후보가 여러 개이면 아무것도 연결되지 않습니다. 마음에 드는 후보를 승인하세요.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/generate-object \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "Antique Lantern", "count": 4 }'
```

**TypeScript SDK**

```ts
const { jobIds } = await client.objects.generate({
name: 'Antique Lantern',
description: 'Weathered brass lantern with hand-engraved filigree',
count: 4,
})
```

**CLI**

```bash
nodaro objects generate --name "Antique Lantern" --count 1 \
  --attach-to-object-id <id> --watch
```

```json
{
"jobIds": [
"5e2a8c1f-3b7d-4f9a-a6c2-8d1e4b7f0a3c",
"6f3b9d2a-4c8e-4a1b-b7d3-9e2f5c8a1b4d",
"7a4c1e3b-5d9f-4b2c-c8e4-1f3a6d9b2c5e",
"8b5d2f4c-6e1a-4c3d-d9f5-2a4b7e1c3d6f"
]
}
```

| 필드 | 하는 일 |
| --- | --- |
| `name` | 필수입니다. 오브젝트 이름으로, 1~200자입니다. |
| `description` | 정체성 메모로, 최대 2,000자입니다. |
| `category`, `style` | 오브젝트의 카테고리와 시각 스타일입니다. |
| `count` | 생성할 후보 수로, 1~10입니다. 기본값은 1입니다. |
| `provider` | 이미지 모델 ID입니다. 기본 모델을 쓰려면 생략하세요. |
| `seedPromptHint` | 프롬프트에 녹여 넣을 프롬프트 조각으로, 최대 2,000자입니다. 예를 들어 [재질](https://nodaro.ai/docs/nodes/creative-controls/material) 피커의 `antique brass`입니다. |
| `sourceImageUrl` | 시작할 이미지입니다. |
| `aspectRatio` | 대표 이미지의 프레임입니다. |
| `attachToObjectId`, `expectedUpdatedAt` | 후보 하나를 이 오브젝트에 연결합니다. 필요하면 오브젝트가 변경되지 않은 경우에만 연결합니다. |

`seedPromptHint`는 `generate-object-asset`과 `generate-object-motion`에서도 받습니다. 피커 노드를 연결하지 않고도 탈것이나 재질 같은 카탈로그 선택을 프롬프트에 조합할 수 있습니다.

## 베리언트 생성
`POST /v1/generate-object-asset`은 베리언트 하나를 생성하고 `{ jobId }`를 반환합니다. 작업이 완료될 때 버킷에 `{ name: attachName, url }`을 추가하려면 `attachToObjectId`, `attachToColumn`, `attachName`을 보내세요.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/generate-object-asset \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
"name": "Antique Lantern",
"assetType": "materials",
"variant": "gold",
"attachToObjectId": "2c7e9a4b-1d3f-4e8a-9b6c-5f0d2a7e3b1c",
"attachToColumn": "materials",
"attachName": "gold"
}'
```

**TypeScript SDK**

```ts
await client.objects.generateAsset({
name: 'Antique Lantern',
assetType: 'variations',
variant: 'weathered',
attachToObjectId: id,
attachToColumn: 'variations',
attachName: 'weathered',
})
```

**CLI**

```bash
nodaro objects generate-asset --asset-type materials --variant gold \
  --attach-to-object-id <id> --attach-to-column materials --watch
```

| 필드 | 하는 일 |
| --- | --- |
| `name` | 필수입니다. 오브젝트 이름입니다. |
| `assetType` | 필수입니다. `angles`, `materials`, `variations` 또는 `custom`입니다. |
| `variant` | 필수입니다. 생성할 베리언트로, 1~100자입니다. |
| `description` | 이 베리언트의 설명으로, 최대 1,000자입니다. 오브젝트에 연결하면서 생략하면 Nodaro가 오브젝트의 기준 설명과 베리언트 이름으로 초안을 작성합니다. 초안을 건너뛰려면 직접 쓴 설명을 보내세요. |
| `provider`, `sourceImageUrl`, `aspectRatio` | 이미지 모델, 변형할 이미지, 프레임입니다. |
| `attachToObjectId`, `attachToColumn`, `attachName` | 결과가 들어갈 위치입니다. `attachToColumn`은 `angles`, `materials` 또는 `variations`이며, `custom` 베리언트에는 반드시 지정해야 합니다. |

## 대표 이미지 애니메이션
`POST /v1/generate-object-motion`은 오브젝트 이미지를 느린 회전, 호버, 드론 오빗 같은 짧은 카메라 무브 클립으로 만듭니다. 클립은 B롤이나 더 긴 동영상의 시작으로 사용하세요. 이 라우트는 `{ jobId }`를 반환합니다.

`sourceImageUrl`은 필수이며 대체값이 없으므로, 승인된 대표 이미지를 전달하세요. `attachToObjectId`와 `attachName`을 보내면 클립이 완료될 때 `motionClips`에 추가됩니다. 컬럼은 보내지 않습니다.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/generate-object-motion \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
"name": "Antique Lantern",
"motionPrompt": "slow 360 rotation, soft golden rim light",
"sourceImageUrl": "https://cdn.nodaro.ai/objects/lantern-main.png",
"provider": "kling-turbo",
"attachToObjectId": "2c7e9a4b-1d3f-4e8a-9b6c-5f0d2a7e3b1c",
"attachName": "rotate-360"
}'
```

**TypeScript SDK**

```ts
const lantern = await client.objects.get(id)

await client.objects.generateMotion({
name: 'Antique Lantern',
motionPrompt: 'slow 360 rotation, soft golden rim light',
sourceImageUrl: lantern.sourceImageUrl!,
provider: 'kling-turbo',
attachToObjectId: id,
attachName: 'rotate-360',
})
```

**CLI**

```bash
nodaro objects generate-motion --name "Antique Lantern" \
  --motion-prompt "slow 360 rotation, soft golden rim light" \
  --source-image-url "https://cdn.nodaro.ai/objects/lantern-main.png" \
  --provider kling-turbo --attach-to-object-id <id> --attach-name "rotate-360" --watch
```

| 필드 | 하는 일 |
| --- | --- |
| `name`, `motionPrompt` | 필수입니다. 오브젝트 이름과 만들 움직임입니다. |
| `sourceImageUrl` | 필수입니다. 시작 프레임입니다. |
| `provider` | `kling-turbo`(기본값), `kling`, `kling-3.0`, `minimax`, `hailuo-2.3`, `wan-i2v`, `seedance` 또는 `bytedance-lite`입니다. |
| `aspectRatio` | `1:1`(기본값, 제품을 가운데에 둔 프레임), `3:4`, `16:9`, `9:16` 또는 `4:3`입니다. |
| `refineFromVideoUrl` | 이미지에서 다시 시작하는 대신 새 프롬프트로 다듬을 기존 클립입니다. 구도는 유지됩니다. `wan-i2v`처럼 동영상-동영상 변환을 지원하는 모델을 사용하세요. |
| `attachToObjectId`, `attachName` | 오브젝트와, `motionClips` 안에서 쓸 클립 이름입니다. |

클립 가격은 모델의 이미지-동영상 변환 가격입니다.

| Model | Maker | Modes | Credits | Details |
| --- | --- | --- | --- | --- |
| [Kling 2.5 Turbo Pro](https://nodaro.ai/docs/models/video/kling-2-5-turbo-pro) | Kuaishou | Image to video, Text to video | 121부터 | Faster Kling — good quality at lower cost. Supports end frame. |
| [Kling 2.6](https://nodaro.ai/docs/models/video/kling-2-6) | Kuaishou | Image to video, Text to video | 152부터 | Kling 2.6 I2V — strong motion realism. 5s/10s, optional native audio. |
| [Kling 3.0](https://nodaro.ai/docs/models/video/kling-3-0) | Kuaishou | Image to video, Text to video | 297부터 | Premium Kling 3.0 — variable 3-15s duration, native audio, 720P/1080P. |
| [Hailuo 02 I2V Pro](https://nodaro.ai/docs/models/video/hailuo-02-i2v-pro) | MiniMax | Image to video, Text to video | 158 | Hailuo 02 Pro — strong photoreal motion, fixed 5-second clips. Supports end frame. |
| [Hailuo 2.3 Standard](https://nodaro.ai/docs/models/video/hailuo-2-3-standard) | MiniMax | Image to video | 83부터 | Cheaper Hailuo 2.3 tier — good baseline quality. |
| [Wan 2.6 I2V](https://nodaro.ai/docs/models/video/wan-2-6-i2v) | Alibaba | Image to video | 193부터 | Wan 2.6 image-to-video — 5/10/15s at 720p/1080p. |
| [Bytedance Lite I2V](https://nodaro.ai/docs/models/video/bytedance-lite-i2v) | Bytedance | Image to video, Text to video | 63 | Cheapest Bytedance video tier with end-frame support. |

`seedance`(Seedance 1.5 Pro)는 이전 모델입니다. 라우트는 여전히 이 모델을 받지만, 모델 카탈로그(`GET /v1/models`)에 더 이상 나오지 않으므로 표에 행이 없습니다.

## 대표 이미지 승인
`POST /v1/objects/:id/approve-main-image`는 완료된 후보를 대표 이미지로 설정하고, 같은 호출에서 `canonicalDescription`을 작성합니다. 이후 프롬프트가 오브젝트를 설명할 때 쓰는 텍스트입니다. 본문은 `{ candidateJobId, expectedUpdatedAt? }`이며, 후보는 내 소유의 `completed` 작업이어야 합니다.

이 라우트는 `{ sourceImageUrl, canonicalDescription }`을 반환합니다. 설명 작성에 실패해도 대표 이미지는 설정되며, `canonicalDescription`은 빈 문자열이 됩니다. SDK는 대신 `null`을 반환합니다. 다시 시도하려면 `POST /v1/objects/:id/llm-caption`을 호출하세요. 이 라우트는 `{ canonicalDescription }`을 반환하고, 설명을 작성할 수 없으면 `502`로, 아직 대표 이미지가 없으면 `400 main_image_required`로 응답합니다. `expectedUpdatedAt`은 받지 않으므로 언제든 안전하게 반복할 수 있습니다.

**curl**

```bash
curl -X POST https://app.nodaro.ai/v1/objects/2c7e9a4b-1d3f-4e8a-9b6c-5f0d2a7e3b1c/approve-main-image \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "candidateJobId": "6f3b9d2a-4c8e-4a1b-b7d3-9e2f5c8a1b4d" }'
```

**TypeScript SDK**

```ts
const approved = await client.objects.approveMainImage(id, jobIds[1])
if (approved.canonicalDescription === null) {
await client.objects.recaption(id)
}
```

**CLI**

```bash
nodaro objects approve-main-image <id> --candidate-job-id <jobId>
nodaro objects recaption <id>
```

## 오브젝트 보관, 복원, 삭제
| 작업 | curl | TypeScript SDK | CLI |
| --- | --- | --- | --- |
| 보관 | `DELETE /v1/objects/:id` | `client.objects.delete(id)` | `nodaro objects delete <id>` |
| 복원 | `POST /v1/objects/:id/restore` | `client.objects.restore(id)` | `nodaro objects restore <id>` |
| 영구 삭제 | `DELETE /v1/objects/:id?permanent=true` | `client.objects.permanentDelete(id)` | `nodaro objects delete <id> --permanent` |

- **보관**은 `{ success: true, archived: true }`를 반환합니다. 이미 보관된 오브젝트를 보관하면 아무것도 바뀌지 않습니다.
- **복원**은 `{ id, name }`을 반환합니다. 대소문자를 무시하고 같은 이름의 활성 오브젝트가 있으면 Nodaro가 `(restored)` 접미사를 붙이고 새 이름을 반환합니다.
- **영구 삭제**는 `{ success: true, permanent: true }`를 반환하고, 오브젝트와 오브젝트가 참조하는 파일 중 내 파일을 모두 제거합니다. 대표 이미지, 베리언트, 클립, 레퍼런스 사진이 모두 포함됩니다. 다른 사용자의 생성 작업이 만든 파일이나, 다른 사용자의 업로드 폴더 또는 라이브러리에 있는 파일은 저장소에 남습니다. 그런 파일은 내 저장 용량에 포함된 적이 없으므로 돌려받는 용량도 없습니다. 영구 삭제는 보관된 오브젝트에서만 작동하며, 활성 오브젝트는 `400 not_archived`를 반환합니다. 먼저 보관한 다음 삭제하세요.

## 앱 실행 시 베리언트 선택
[오브젝트/소품 에셋](https://nodaro.ai/docs/nodes/assets/object) 노드가 있는 워크플로를 앱으로 게시하면 오브젝트가 앱의 입력 중 하나가 됩니다. 해당 실행에서 베리언트를 오브젝트의 대표 이미지로 쓰려면 `"materials/gold"`처럼 `"<bucket>/<variant>"`를 전달하세요. 베리언트 이름은 소문자로 쓰고 공백은 하이픈으로 바꾸세요. `polished-brass`는 Polished Brass라는 베리언트와 일치합니다. 알 수 없는 버킷이나 베리언트는 대표 이미지로 대체됩니다. 앱 실행은 [워크플로](https://nodaro.ai/docs/developers/api/workflows)를 참조하세요.

## 다른 생성에서 오브젝트 사용
오브젝트의 에셋 URL을 [이미지 생성](https://nodaro.ai/docs/nodes/image/generate-image) 또는 [동영상 생성](https://nodaro.ai/docs/nodes/video/generate-video)에 레퍼런스 이미지로 전달하세요. 코드에서는 명시적인 URL이 가장 간단합니다. 워크플로에서는 오브젝트 노드를 이미지 노드에 연결하거나, 프롬프트에서 베리언트를 멘션하세요. 예를 들어 Lantern이라는 오브젝트라면 `@lantern:1:materials/gold`입니다. 멘션 없이 오브젝트를 연결하면 Nodaro는 프롬프트에서 베리언트 이름도 찾습니다. 프롬프트에 “gold finish”(금색 마감)가 있으면 `materials/gold`가 선택됩니다. [오브젝트](https://nodaro.ai/docs/guides/objects)를 참조하세요.

## MCP에서 사용
| 도구 | 하는 일 |
| --- | --- |
| `list_objects`, `get_object` | 오브젝트를 찾고 베리언트 URL을 읽습니다. |
| `generate_object` | 대표 이미지나 베리언트를 생성합니다. |
| `approve_object_main_image`, `recaption_object` | 대표 이미지를 승인하거나 설명을 다시 작성합니다. |
| `generate_object_motion` | 대표 이미지에 움직임을 줍니다. |

오브젝트를 만들고, 업데이트하고, 보관하고, 복원하고, 삭제하는 MCP 도구는 없습니다. `generate_object`가 오브젝트를 만들며, 나머지 변경은 REST, SDK 또는 CLI로 합니다. [MCP 도구 레퍼런스](https://nodaro.ai/docs/mcp/tools)를 참조하세요.

## 크레딧
| 라우트 | Nodaro Cloud 가격 |
| --- | --- |
| `POST /v1/generate-object` | 이미지 모델 가격에 `count`를 곱한 값입니다. 첫 작업이 시작되기 전에 모든 후보분이 예약됩니다. |
| `POST /v1/generate-object-asset` | 베리언트당 이미지 모델 가격입니다. |
| `POST /v1/generate-object-motion` | 클립당 동영상 모델의 이미지-동영상 변환 가격입니다. |
| `approve-main-image` | 무료입니다. |
| `llm-caption` | 호출당 8크레딧입니다. |

## 오류
| 상태 | 코드 | 의미 |
| --- | --- | --- |
| `400` | `validation_error` | 필드가 누락되었거나 잘못되었습니다. |
| `400` | `not_archived` | 보관되지 않은 오브젝트에 영구 삭제를 보냈습니다. |
| `400` | `main_image_required` | 오브젝트에 대표 이미지가 생기기 전에 `llm-caption`을 호출했습니다. |
| `401` | `unauthorized` | 토큰이 없거나, 잘못되었거나, 폐기되었습니다. |
| `402` | `insufficient_credits` | Nodaro Cloud 전용입니다. 계정의 크레딧이 예약에 부족합니다. |
| `404` | `not_found` | 해당 ID를 가진 내 활성 오브젝트가 없습니다. |
| `409` | `concurrent_modification` | `expectedUpdatedAt`이 더 이상 일치하지 않습니다. 오브젝트를 다시 읽고 병합한 다음 다시 시도하세요. |
| `502` | — | 기준 설명을 작성하지 못했습니다. 다시 시도하세요. |

## 자주 묻는 질문

### Nodaro API에서 오브젝트란 무엇인가요?

오브젝트는 승인된 대표 이미지, 글로 쓴 설명, 베리언트 이미지를 갖춘 저장된 소품, 제품, 탈것 또는 가구입니다. 이미지 노드와 동영상 노드가 오브젝트를 재사용하므로 모든 샷에서 같은 물건으로 보입니다.

### 스타일 고정은 무엇을 하나요?

기본값대로 스타일 고정을 켜면 모든 베리언트가 승인된 대표 이미지에서 생성되므로 비율과 디테일이 그대로 유지됩니다. 끄면 베리언트가 디자인을 새롭게 해석할 수 있으며, 예를 들어 다른 안을 탐색할 때 유용합니다.

### API로 오브젝트를 영구 삭제할 수 있나요?

네. 먼저 DELETE /v1/objects/:id로 보관한 다음 DELETE /v1/objects/:id?permanent=true를 호출하세요. 영구 삭제는 오브젝트와 그 파일을 제거하며, 보관되지 않은 오브젝트는 거부합니다.

### 오브젝트에 애니메이션을 적용할 수 있는 모델은 무엇인가요?

공급자 ID 기준으로 8개의 동영상 모델입니다. kling-turbo(기본값, Kling 2.5 Turbo Pro), kling, kling-3.0, minimax, hailuo-2.3, wan-i2v, seedance, bytedance-lite입니다. 클립 하나의 가격은 해당 모델의 이미지-동영상 변환 가격입니다.

### 보관한 오브젝트에 대해 GET /v1/objects/:id가 404를 반환하는 이유는 무엇인가요?

보관된 오브젝트는 ID로 읽을 때 숨겨집니다. GET /v1/objects?archived=true로 목록을 보고, POST /v1/objects/:id/restore로 복원하세요.
