Nodaro ドキュメント
ドキュメントノードリファレンスモデルAI エージェント(MCP)開発者向けセルフホスティングリサーチ
REST API

キャラクター

REST API でキャラクターを作成、更新、アーカイブ、復元します。ポートレートの候補、表情、アングル、モーションクリップを生成し、基準となるポートレートを承認できます。

キャラクター API を使うと、キャラクタースタジオでできることを、すべてスクリプトから実行できます。キャラクターを作成し、ポートレートの候補を生成して、そのうち 1 つを基準となるポートレートとして承認し、表情、アングル、ポーズ、ライティングのバリエーション、モーションクリップを追加します。その後は画像ノードと動画ノードがそのキャラクターを再利用するので、同じ人物がどのショットでも同じ見た目になります。

これらのルートは、すべてのエディションで使えます。認証には Bearer トークンを使います。個人用 API トークン(ndr_…)、OAuth アプリのトークン(ndr_app_…)、Community エディションではセッショントークンのいずれかです。すべてのルートは呼び出し元に限定されており、表示や変更ができるのは自分のキャラクターだけです。認証を参照してください。

エンドポイント

メソッドパス説明
GET/v1/characters自分のキャラクターを、1 ページずつ一覧表示します。
GET/v1/characters/:id1 つのキャラクターを、進行中のジョブとともに取得します。
POST/v1/charactersキャラクターを作成します。ボディに id がある場合は、そのキャラクターを更新します。
POST/v1/characters/:id/duplicateキャラクターを、名前の末尾に (copy) が付いた新しいキャラクターとしてコピーします。
DELETE/v1/characters/:idキャラクターをアーカイブします。アーカイブしたキャラクターは復元できます。
POST/v1/characters/:id/restoreアーカイブしたキャラクターを復元します。
GET/v1/characters/:id/usageキャラクターを使っているワークフローの数と一覧を返します。
POST/v1/generate-characterポートレートの候補を 1〜10 個生成します。
POST/v1/generate-character-asset表情、ポーズ、アングル、ライティングのバリエーションを 1 つ生成します。
POST/v1/generate-character-motionキャラクターをアニメーション化して、モーションクリップを作ります。
POST/v1/characters/:id/approve-portrait候補をポートレートとして承認し、キャラクターの説明を作成します。
POST/v1/characters/:id/llm-caption現在のポートレートから、説明を作成し直します。

キャラクターで専用のモデルを学習させるのは Nodaro Cloud の機能で、専用のルートがあります。キャラクター学習を参照してください。

キャラクターが持つ情報

キャラクターは、保存された 1 つのアイデンティティです。次のフィールドは、GET /v1/characters/:id からキャメルケース(camelCase)で返されます。

フィールド説明
id, name識別子と表示名です。名前は、大文字と小文字を区別せずに、アカウント内で一意です。
description, gender, style, baseOutfit人物像についてのメモです。キャラクターの生成画像すべてに反映されます。
seedPromptポートレートの方向性を決める短いプロンプトで、最大 4,000 文字です。
sourceImageUrl基準となるポートレートです。候補を承認すると設定されます。
canonicalDescriptionポートレートの承認時に Nodaro が作成する、80〜120 語程度の見た目の説明です。キャラクターを参照するプロンプトには、この説明が含まれます。
expressions, poses, angles, bodyAngles, lightingVariations, motionsアセットバケットです。各エントリーは { name, url } です。
referencePhotos最大 20 枚の実際の写真です。それぞれにフレーミングのタグが付きます。
realLifeRefsByVariant, referenceVideosByVariant1 つのバリエーション(たとえば smile の表情)のための、追加のリファレンス写真やクリップです。
person, wardrobeキャラクタースタジオの「ピッカー」ページで設定する、外見と衣装の構造化された選択内容です。
voice, personalityキャラクターのボイスと性格です。
identityLock生成するアセットで、顔をどれだけ厳密に保つかです。off、soft、strict のいずれかで、デフォルトは off です。
deletedAtキャラクターをアーカイブすると設定されます。

アセットバケット

各バケットには、基準となるポートレートのバリエーションが入ります。バリエーションには自由に名前を付けられます。次の表は、プリセットの名前です。

バケット内容プリセットのバリエーション
expressions頭と肩。別の感情の表情neutral, smile, angry, surprised, sad, talking, laughing, disgusted, fearful, smirk, crying
angles頭と肩を、別のカメラアングルからfront, 3/4 left, left profile, right profile, 3/4 right
bodyAngles全身を別のアングルから。腕は自然に下ろした状態front, 3/4 left, left profile, right profile, 3/4 right, back
poses別の姿勢の全身standing, walking, sitting, running, crouching, pointing, fighting stance, jumping, turning
lightingVariations同じポーズを、別の光のもとでdaylight, night, dramatic
motionsキャラクターが動く動画クリップ任意のラベル(たとえば walking や head turn)

キャラクターを一覧表示する

GET /v1/characters は、自分のキャラクターを新しい順に 1 ページ分返します。nextCursor が null になるまで、ページのリクエストを続けてください。キャラクターの数がページサイズを超えるアカウントでは、1 回のレスポンスが「すべてのキャラクター」になることはありません。

クエリパラメーター説明
limit1 ページあたりの行数です。デフォルトは 100、最大は 500 です。
cursor前のページの nextCursor です。
projectId1 つのプロジェクトのキャラクターだけを返します。
archivedtrue にすると、代わりにアーカイブしたキャラクターを一覧表示します。
CURSOR=""
while :; do
  PAGE=$(curl -s "https://app.nodaro.ai/v1/characters?limit=100${CURSOR:+&cursor=$CURSOR}" \
    -H "Authorization: Bearer $NODARO_API_KEY")
  echo "$PAGE" | jq -r '.characters[] | "\(.id) \(.name)"'
  CURSOR=$(echo "$PAGE" | jq -r '.nextCursor // empty')
  [ -z "$CURSOR" ] && break
done
import { createClient, StaticTokenAuth } from '@nodaro/sdk'

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

const all = []
let cursor: string | undefined
do {
  const page = await client.characters.list({ limit: 100, cursor })
  all.push(...page.characters)
  cursor = page.nextCursor ?? undefined
} while (cursor)
nodaro characters list --limit 100 --json
nodaro characters list --archived
{
  "characters": [
    {
      "id": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94",
      "name": "Kira",
      "description": "young protagonist with auburn hair",
      "sourceImageUrl": "https://cdn.nodaro.ai/characters/kira-portrait.png",
      "expressions": [{ "name": "smile", "url": "https://cdn.nodaro.ai/characters/kira-smile.png" }]
    }
  ],
  "nextCursor": "eyJjcmVhdGVkQXQiOiIyMDI2LTA5LTIwVDEwOjAwOjAxWiJ9"
}

カーソルは不透明な値です。サーバーから受け取った nextCursor だけを渡し、リリースをまたいで保存しないでください。形式が正しくないカーソルは、黙って最初のページに戻るのではなく、400 validation_error になります。ページをたどっている間に作成されたキャラクターは含まれません。それらを表示するには、カーソルなしで最初からやり直してください。

キャラクターを作成または更新する

POST /v1/characters は、ボディに id がない場合はキャラクターを作成し、id がある場合はそのキャラクターを更新します。作成には nodeId と name が必要です。nodeId は、キャラクターをキャンバスのノードに関連付けます。コードから作成する場合は、"scripted" のような任意のラベルを使います。

更新では、送信したフィールドだけが書き込まれます。省略したフィールドは値が保たれるので、保存によって、実行中のジョブが書き込んでいるアセットバケットが上書きされることはありません。アセットバケットは、置き換えるつもりのときだけ送信してください。

curl -X POST https://app.nodaro.ai/v1/characters \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "nodeId": "scripted",
    "name": "Kira",
    "description": "young protagonist with auburn hair",
    "style": "realistic",
    "seedPrompt": "kira portrait, warm natural lighting"
  }'
const { id } = await client.characters.create({
  nodeId: 'scripted',
  name: 'Kira',
  description: 'young protagonist with auburn hair',
  style: 'realistic',
  seedPrompt: 'kira portrait, warm natural lighting',
})

await client.characters.update(id, { gender: 'female', identityLock: 'soft' })
nodaro characters create --name "Kira" \
  --description "young protagonist with auburn hair" \
  --style realistic --seed-prompt "kira portrait, warm natural lighting"

nodaro characters update <id> --gender female
{ "id": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94", "name": "Kira" }

Prop

Type

person と wardrobe が影響するのは、キャラクター自身のポートレートとアセットの生成だけです。これらは 人物(Person)ピッカーと同じカタログを使います。ピッカーカタログを参照してください。

ワークフローの実行時には、キャラクターの下流に接続された テキストから音声(Text to Speech)ノードに、キャラクターの voice から、ボイス、ボイスの種類、推奨モデルが設定されます。テキストから音声ノード自体で設定した値が優先されます。

ポートレートの候補を生成する

POST /v1/generate-character は、候補ごとに 1 つのジョブを開始し、それらの ID をすぐに返します。各ジョブが completed になるまで、ジョブ API でポーリングしてください。

attachToCharacterId を指定すると、最初に完了した候補がキャラクターのポートレートになります。候補が 1 つだけなら、これで完了です。候補が複数ある場合は、気に入ったものを承認してください。承認すると、ポートレートが置き換わります。

curl -X POST https://app.nodaro.ai/v1/generate-character \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Kira",
    "seedPrompt": "kira portrait, warm natural lighting",
    "count": 4,
    "attachToCharacterId": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94"
  }'
const { jobIds } = await client.characters.generate({
  name: 'Kira',
  seedPrompt: 'kira portrait, warm natural lighting',
  count: 4,
  attachToCharacterId: id,
})
nodaro characters generate <id> --count 4 \
  --seed-prompt "kira portrait, warm natural lighting" --watch
{
  "jobId": "a1c4e8f2-5b3d-4e6a-8f7c-2d9b1e0a3c5f",
  "jobIds": [
    "a1c4e8f2-5b3d-4e6a-8f7c-2d9b1e0a3c5f",
    "b7d2f9a1-6c4e-4a8b-9d3f-3e0c2f1b4d6a",
    "c3e5a7b9-8d1f-4c2e-a6b8-4f1d3a2c5e7b",
    "d9f1b3c5-2e4a-4d6f-b8c1-5a2e4b3d6f8c"
  ]
}

Prop

Type

quality と resolution による料金は、画像生成(Generate Image)とまったく同じです。4K や高品質での実行は、同じモデルの基本の段階よりも高くなります。モデルが対応していない値は、拒否されずに、対応している最も近い値に変更されます。クレジットも、変更後の値に従います。これらのルートは adjustments の一覧を返しません。実際に使われた値は、GET /v1/jobs/:id で取得したジョブの input_data で確認してください。

表情、アングル、ポーズ、ライティングのバリエーションを生成する

POST /v1/generate-character-asset は、基準となるポートレートのバリエーションを 1 つ生成し、{ jobId } を返します。結果をキャラクターに追加するには、attachToCharacterId、attachToColumn、attachName の 3 つの attach フィールドをすべて送信します。ジョブが完了すると、ワーカーがそのバケットに { name: attachName, url } を追加します。

curl -X POST https://app.nodaro.ai/v1/generate-character-asset \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Kira",
    "assetType": "expressions",
    "variant": "smile",
    "attachToCharacterId": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94",
    "attachToColumn": "expressions",
    "attachName": "smile"
  }'
await client.characters.generateAsset({
  name: 'Kira',
  assetType: 'bodyAngles',
  variant: 'front',
  attachToCharacterId: id,
  attachToColumn: 'body_angles',
  attachName: 'front',
})
nodaro characters generate-asset <id> --asset-type expressions --variant smile --watch
フィールド説明
name必須。キャラクターの名前です。
assetType必須。expressions、poses、lighting、headAngles、angles(headAngles と同じ)、bodyAngles、custom のいずれかです。
variant必須。生成するバリエーションで、1〜100 文字です。たとえば smile や 3/4 left です。
descriptionこのバリエーションを 1 文で説明したもので、最大 1,000 文字です。キャラクターに関連付けてこれを省略すると、キャラクターの基準となる説明をもとに、Nodaro が自動で作成します。
sourceImageUrlバリエーションの元にする画像です。通常は、承認済みのポートレートです。
provider, quality, resolution画像モデルと、その出力の段階です。料金は画像生成と同じです。
aspectRatio1:1、3:4、16:9、9:16 のいずれかです。デフォルトは種類によって異なり、表情は 1:1、ポーズと全身のアングルは 9:16、それ以外は 3:4 です。
attachToCharacterId, attachToColumn, attachName結果の保存先です。attachToColumn は expressions、poses、angles、body_angles、lighting_variations のいずれかです。custom のバリエーションでは、列を必ず指定します。

バリエーションをキャラクターに関連付けると、realLifeRefsByVariant でそのバリエーションのキーに保存されている実際の写真が、リクエストと一緒に自動で送信されます。

キャラクターをアニメーション化する

POST /v1/generate-character-motion は、キャラクターの静止画を動画クリップにして、{ jobId } を返します。attachToCharacterId と attachName を指定すると、完成したクリップが motions バケットに追加されます。

キャラクターに関連付けて sourceImageUrl を省略した場合、Nodaro は次の順で開始フレームを選びます。

  1. 送信した sourceImageUrl。常にこれが優先されます。
  2. bodyAngles の front のエントリー。全身のフレームは、頭と肩のポートレートよりもはるかにうまくアニメーション化できます。
  3. bodyAngles のほかのエントリー。新しいものから順に使います。
  4. 基準となるポートレート。

最良のクリップを得るには、最初のモーションの前に、front の全身のアングルを生成してください。

curl -X POST https://app.nodaro.ai/v1/generate-character-motion \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Kira",
    "motionPrompt": "slow head turn left, soft smile",
    "provider": "kling",
    "attachToCharacterId": "3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94",
    "attachName": "head turn"
  }'
await client.characters.generateMotion({
  name: 'Kira',
  motionPrompt: 'slow head turn left, soft smile',
  provider: 'kling',
  attachToCharacterId: id,
  attachName: 'head turn',
})
nodaro characters generate-motion <id> \
  --motion-prompt "slow head turn left, soft smile" --attach-name "head turn" --watch
フィールド説明
name必須。キャラクターの名前です。
motionPrompt必須。何がどのように動くかで、1〜2,000 文字です。
provider動画モデルです。kling(デフォルト)、kling-turbo、kling-3.0、wan-i2v、wan-2.7-i2v のいずれかです。
sourceImageUrl開始フレームです。キャラクターに関連付けない場合は必須です。
description, motionDescription見た目の説明(最大 1,000 文字)と、動きの説明(最大 500 文字)です。キャラクターに関連付けてこれらを省略すると、Nodaro が両方を自動で作成します。
aspectRatio1:1、3:4、16:9、9:16 のいずれかです。デフォルトは 9:16 で、全身が入る縦長のクリップになります。
attachToCharacterId, attachNameキャラクターと、motions でのクリップの名前です。

キャラクターをアニメーション化できるモデルは、次のとおりです。料金は、そのモデルで画像から動画を生成する料金です。

モデル開発元モードクレジット詳細
Kling 2.6Kuaishou画像から動画、テキストから動画138 から画像から動画を生成する Kling 2.6 で、動きのリアルさに優れています。長さは 5 秒または 10 秒で、ネイティブオーディオを任意で付けられます。
Kling 2.5 Turbo ProKuaishou画像から動画、テキストから動画110 からより高速な Kling で、低コストで良好な品質が得られます。終了フレームに対応しています。
Kling 3.0Kuaishou画像から動画、テキストから動画270 からプレミアムな Kling 3.0 で、長さは 3〜15 秒の間で変えられ、ネイティブオーディオに対応し、720P/1080P で出力します。
Wan 2.6 I2VAlibaba画像から動画175 から画像から動画を生成する Wan 2.6 で、720p/1080p で 5/10/15 秒の動画を作ります。
Wan 2.7 I2VAlibaba画像から動画188画像から動画を生成する Wan 2.7 で、720p/1080p で 2〜15 秒の動画を作り、開始フレームと終了フレームに対応しています。

ポートレートを承認する

POST /v1/characters/:id/approve-portrait は、完了した候補を基準となるポートレートに設定します。同じ呼び出しの中で、Nodaro はポートレートを見て canonicalDescription を作成します。これは、以降のプロンプトがキャラクターを説明するために使うテキストです。この説明がないと、シーンごとにキャラクターの見た目がずっと大きく変わってしまいます。

候補は、自分の completed のジョブである必要があります。説明の作成に失敗した場合でもポートレートは設定され、canonicalDescription は null になります。その場合は、POST /v1/characters/:id/llm-caption を呼び出して、もう一度試してください。どちらのルートも、繰り返し呼び出して問題ありません。承認は無料です。llm-caption は呼び出し 1 回につき 7 クレジットかかり、失敗した呼び出し(502)の分は返還されます。

curl -X POST https://app.nodaro.ai/v1/characters/3f6c2a9e-8d41-4b7a-9c35-1e2f7a6b0d94/approve-portrait \
  -H "Authorization: Bearer $NODARO_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "candidateJobId": "b7d2f9a1-6c4e-4a8b-9d3f-3e0c2f1b4d6a" }'
const { portraitUrl, canonicalDescription } =
  await client.characters.approvePortrait(id, jobIds[1])

if (canonicalDescription === null) {
  await client.characters.recaption(id)
}
nodaro characters approve-portrait <id> --job <jobId>
nodaro characters recaption <id>
{
  "portraitUrl": "https://cdn.nodaro.ai/characters/kira-portrait-2.png",
  "canonicalDescription": "Kira is a woman in her mid-twenties with shoulder-length auburn hair, green eyes and light freckles..."
}

llm-caption は { canonicalDescription } を返します。キャラクターにまだポートレートがない場合は 400 no_portrait を、説明を作成できなかった場合は 502 を返します。

キャラクターのアーカイブ、復元、コピー

  • アーカイブ:DELETE /v1/characters/:id はキャラクターをアーカイブし、{ success: true, archived: true } を返します。キャラクターはデフォルトの一覧から外れますが、GET /v1/characters/:id では引き続き返されるので、そのキャラクターを使うワークフローはそのまま動作します。Nodaro Cloud では、アーカイブすると、進行中の学習もキャンセルされてそのクレジットが返還され、学習済みモデルが削除されます。
  • 復元:POST /v1/characters/:id/restore は { id, name } を返します。同じ名前の有効なキャラクターがその時点で存在する場合、Nodaro は名前の末尾に (restored) を付け、新しい名前を返します。
  • 完全な削除:キャラクターを完全に削除する API ルートはありません。エディターのライブラリにある、アーカイブの表示を使ってください。
  • コピー:POST /v1/characters/:id/duplicate は、名前の末尾に (copy) が付いた新しいキャラクターの { id, name } を返します。コピーは、アセットを再生成するまで、元のキャラクターのアセットの URL を共有します。
  • 使用状況:GET /v1/characters/:id/usage は { workflowCount, workflows: [{ id, name }] } を返します。キャラクターをアーカイブする前に確認してください。
操作curlTypeScript SDKCLI
アーカイブDELETE /v1/characters/:idclient.characters.delete(id)nodaro characters delete <id>
復元POST /v1/characters/:id/restoreclient.characters.restore(id)nodaro characters restore <id>
コピーPOST /v1/characters/:id/duplicateclient.characters.duplicate(id)nodaro characters duplicate <id>
使用状況GET /v1/characters/:id/usageclient.characters.usage(id)nodaro characters usage <id>

一連の流れ:作成、生成、承認、バリエーションの追加

キャラクターを作成する

nodeId、name、seedPrompt を指定して、POST /v1/characters を呼び出します。返された id を控えておきます。

ポートレートの候補を生成する

count: 4 と attachToCharacterId を指定して、POST /v1/generate-character を呼び出します。各ジョブ ID を、completed か failed になるまでポーリングします。

気に入った候補を承認する

その候補のジョブ ID を指定して、POST /v1/characters/:id/approve-portrait を呼び出します。ポートレートと基準となる説明が設定されます。

バリエーションとモーションを追加する

POST /v1/generate-character-asset で、まず front の全身のアングルを生成し、続けて表情とポーズを生成します。クリップは、POST /v1/generate-character-motion で生成します。

ほかの生成でキャラクターを使う

アセットができたら、その URL をリファレンス画像として、画像生成や 動画生成(Generate Video)に渡します。たとえば、expressions の smile のエントリーを読み取り、その URL をプロンプトと一緒にリファレンスとして送信します。コードでは、URL を明示的に指定するのが最も簡単です。ワークフローの接続のしかたに左右されないためです。リクエストのフィールドについては、単体のノードを実行するを参照してください。

ワークフローでは、キャラクターアセット(Character Asset)ノードを画像ノードや動画ノードに接続するか、プロンプトで @ を使ってキャラクターをメンションします(たとえば @kira:1:smile)。メンションの記法はリファレンスの役割で、全体の手法はキャラクターの一貫性で説明しています。

MCP から使う

AI アシスタントは、次のツールを通じて同じルートを使います。アーカイブと復元は、意図的に MCP では使えないようにしています。

ツール説明
list_characters, get_characterキャラクターを探し、そのアセットの URL を読み取ります。
create_character, update_characterキャラクターを作成するか、その基本情報のフィールドを変更します。
generate_characterポートレート(kind: "main")またはバリエーション(kind: "asset")を生成します。
generate_character_motionキャラクターをアニメーション化して、クリップを作ります。
approve_portrait, recaption_characterポートレートを承認するか、その説明を作成し直します。

MCP ツールリファレンスを参照してください。

クレジット

Nodaro Cloud では、キャラクターの生成に、対応するノードと同じクレジット料金がかかります。

ルート料金
POST /v1/generate-character画像モデルの料金 × count です。最初のジョブが始まる前に、すべての候補の分が確保されます。
POST /v1/generate-character-assetバリエーション 1 つにつき、画像モデルの料金です。
POST /v1/generate-character-motionクリップ 1 本につき、動画モデルで画像から動画を生成する料金です。
approve-portrait無料です。
llm-caption呼び出し 1 回につき 7 クレジットです。

各モデルの正確な料金は、それぞれのモデルのページに記載されています。クレジットを参照してください。

エラー

エラーは、標準のエンベロープ { "error": { "code", "message" } } で返されます。エラーを参照してください。

ステータスコード説明
400validation_errorフィールドが不足しているか、無効です。または、カーソルの形式が正しくないか、生成リクエストに seedPrompt、description、referencePhotos のいずれもありません。
400no_portraitキャラクターにポートレートがない状態で、llm-caption が呼び出されました。
401unauthorizedトークンがないか、無効か、取り消されています。
402insufficient_creditsNodaro Cloud のみ。アカウントの残高では、確保に必要なクレジットが足りません。
404not_foundその ID を持つ自分のキャラクターまたはジョブがありません。
409name_takenほかの有効なキャラクターが、すでにその名前を使っています。
502—基準となる説明を作成できませんでした。ポートレートは変更されていません。もう一度試してください。

よくある質問

最終更新

目次