> ## Documentation Index
> Fetch the complete documentation index at: https://docs.comfy.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Comfy Router로 Nano Banana Pro 사용하기

> Comfy Router를 통해 HTTP로 Nano Banana Pro(Gemini 3 Pro Image)로 이미지를 생성하는 Python, TypeScript, cURL 스니펫과 요청 필드 및 결과 형태

Nano Banana Pro API 레퍼런스입니다. Nano Banana Pro(Gemini 3 Pro Image)는 Google의 Nano Banana 이미지 생성 제품군 가운데 Pro 티어로, 복잡한 장면과 읽기 쉬운 텍스트를 겨냥합니다.

<h2 id="quick-start">
  빠른 시작
</h2>

[내 Comfy 워크스페이스](https://platform.comfy.org/profile/api-keys)에서 키를 생성하고 `COMFY_API_KEY`로 내보내세요. Python 및 TypeScript 스니펫은 Comfy SDK(`pip install comfy-sdk`, `npm install @comfyorg/sdk`)를 사용하며, cURL 스니펫은 동일한 호출을 raw HTTP로 수행합니다.

**모델 ID:** `vertexai/gemini-3-pro-image`

**엔드포인트:** `POST https://api.comfy.org/v2/models/vertexai/gemini-3-pro-image`

<Tabs>
  <Tab title="Wait for the result">
    <CodeGroup>
      ```python Python theme={null}
      from comfy_sdk import Comfy

      # Reads COMFY_API_KEY from the environment.
      # The SDK automatically creates an idempotency key and reuses it for automatic retries.
      with Comfy() as client:
          result = client.models.run(
              "vertexai/gemini-3-pro-image",
              {
                  "contents": [
                      {
                          "role": "user",
                          "parts": [
                              {
                                  "text": "a single red maple leaf on a plain white background, studio lighting",
                              },
                          ],
                      },
                  ],
                  "generationConfig": {
                      "responseModalities": ["IMAGE"],
                      "imageConfig": {
                          "aspectRatio": "1:1",
                      },
                  },
              },
          )

      print("image (base64):", result["candidates"][0]["content"]["parts"][0]["inlineData"]["data"])
      ```

      ```typescript TypeScript theme={null}
      import { comfy } from "@comfyorg/sdk";

      // Reads COMFY_API_KEY from the environment.
      // The SDK automatically creates an idempotency key and reuses it for automatic retries.
      type Result = { candidates: { content: { parts: { inlineData: { data: string } }[] } }[] };
      const { data } = await comfy.models.run<Result>("vertexai/gemini-3-pro-image", {
        contents: [
          {
            role: "user",
            parts: [
              {
                text: "a single red maple leaf on a plain white background, studio lighting",
              },
            ],
          },
        ],
        generationConfig: {
          responseModalities: ["IMAGE"],
          imageConfig: {
            aspectRatio: "1:1",
          },
        },
      });

      console.log("image (base64):", data.candidates[0].content.parts[0].inlineData.data);
      ```

      ```bash cURL theme={null}
      curl https://api.comfy.org/v2/models/vertexai/gemini-3-pro-image \
        -H "X-API-Key: $COMFY_API_KEY" \
        -H "Idempotency-Key: $(uuidgen)" \
        -H "Content-Type: application/json" \
        -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"a single red maple leaf on a plain white background, studio lighting\"}]}], \"generationConfig\": {\"responseModalities\":[\"IMAGE\"],\"imageConfig\":{\"aspectRatio\":\"1:1\"}}}"
      ```
    </CodeGroup>
  </Tab>

  <Tab title="Queue and collect later">
    <CodeGroup>
      ```python Python theme={null}
      from comfy_sdk import Comfy

      # Reads COMFY_API_KEY from the environment.
      # Each submit() call mints its own Idempotency-Key and reuses it for automatic retries.
      with Comfy() as client:
          handle = client.models.submit(
              "vertexai/gemini-3-pro-image",
              {
                  "contents": [
                      {
                          "role": "user",
                          "parts": [
                              {
                                  "text": "a single red maple leaf on a plain white background, studio lighting",
                              },
                          ],
                      },
                  ],
                  "generationConfig": {
                      "responseModalities": ["IMAGE"],
                      "imageConfig": {
                          "aspectRatio": "1:1",
                      },
                  },
              },
          )
          print("request_id:", handle.request_id)  # with the model ID, all another process needs

          # Poll until the request completes, waiting the Retry-After the server names.
          for update in handle.iter_events():
              print(update.status, update.queue_position)

          # The provider's own payload, the same value models.run() returns.
          # A request that failed or was cancelled raises the typed Router error here.
          result = handle.get()

      print("image (base64):", result["candidates"][0]["content"]["parts"][0]["inlineData"]["data"])
      ```

      ```typescript TypeScript theme={null}
      import { comfy } from "@comfyorg/sdk";

      // Reads COMFY_API_KEY from the environment.
      // Each submit() call mints its own Idempotency-Key and reuses it for automatic retries.
      type Result = { candidates: { content: { parts: { inlineData: { data: string } }[] } }[] };
      const handle = await comfy.models.submit<Result>("vertexai/gemini-3-pro-image", {
        contents: [
          {
            role: "user",
            parts: [
              {
                text: "a single red maple leaf on a plain white background, studio lighting",
              },
            ],
          },
        ],
        generationConfig: {
          responseModalities: ["IMAGE"],
          imageConfig: {
            aspectRatio: "1:1",
          },
        },
      });
      console.log("requestId:", handle.requestId); // with the model ID, all another process needs

      // Poll until the request completes, waiting the Retry-After the server names.
      for await (const update of handle.events()) {
        console.log(update.status, update.queuePosition);
      }

      // The same result models.run() returns. A request that failed or was cancelled rejects here.
      const result = await handle.get();
      if (result.kind !== "json") throw new Error("expected a JSON result");

      console.log("image (base64):", result.data.candidates[0].content.parts[0].inlineData.data);
      ```

      ```bash cURL theme={null}
      # 1. Submit. Router answers 201 with request_id, status_url, response_url and cancel_url.
      curl https://api.comfy.org/v2/models/vertexai/gemini-3-pro-image/requests \
        -H "X-API-Key: $COMFY_API_KEY" \
        -H "Idempotency-Key: $(uuidgen)" \
        -H "Content-Type: application/json" \
        -d "{\"contents\": [{\"role\":\"user\",\"parts\":[{\"text\":\"a single red maple leaf on a plain white background, studio lighting\"}]}], \"generationConfig\": {\"responseModalities\":[\"IMAGE\"],\"imageConfig\":{\"aspectRatio\":\"1:1\"}}}"

      # 2. Poll until status is COMPLETED, waiting the Retry-After seconds each response names.
      REQUEST_ID="<request_id from the 201 body>"
      curl -i https://api.comfy.org/v2/models/vertexai/gemini-3-pro-image/requests/$REQUEST_ID/status \
        -H "X-API-Key: $COMFY_API_KEY"

      # 3. Collect. 200 with the model's native output, 202 with the status body while it is still running.
      curl https://api.comfy.org/v2/models/vertexai/gemini-3-pro-image/requests/$REQUEST_ID \
        -H "X-API-Key: $COMFY_API_KEY"
      ```
    </CodeGroup>
  </Tab>
</Tabs>

## 스키마

### 입력

<ParamField body="contents" type="object[]" required>
  모델과의 현재 대화 콘텐츠입니다. 단일 턴 쿼리의 경우 단일 인스턴스입니다. 멀티 턴 쿼리의 경우 대화 기록과 최신 요청을 포함하는 반복 필드입니다.
</ParamField>

<ParamField body="contents[].parts" type="object[]" required />

<ParamField body="contents[].parts[].fileData" type="object">
  URI 기반 데이터입니다.
</ParamField>

<ParamField body="contents[].parts[].fileData.fileUri" type="string">
  URI
</ParamField>

<ParamField body="contents[].parts[].fileData.mimeType" type="string">
  data 또는 fileUri 필드에 지정된 파일의 미디어 타입입니다. 허용되는 값은 다음과 같습니다. gemini-2.0-flash-lite 및 gemini-2.0-flash의 경우 오디오 파일의 최대 길이는 8.4시간이고 비디오 파일(오디오 제외)의 최대 길이는 1시간입니다. 자세한 내용은 Gemini 오디오 및 비디오 요구 사항을 참조하세요. 텍스트 파일은 UTF-8로 인코딩되어야 합니다. 텍스트 파일의 내용은 토큰 한도에 포함됩니다. 이미지 해상도에는 제한이 없습니다.

  가능한 값: `application/pdf`, `audio/mpeg`, `audio/mp3`, `audio/wav`, `image/png`, `image/jpeg`, `image/webp`, `text/plain`, `video/mov`, `video/mpeg`, `video/mp4`, `video/mpg`, `video/avi`, `video/wmv`, `video/mpegps`, `video/flv`, `image/heic`, `image/heif`, `audio/flac`, `video/webm`
</ParamField>

<ParamField body="contents[].parts[].inlineData" type="object">
  원시 바이트의 인라인 데이터입니다. gemini-2.0-flash-lite 및 gemini-2.0-flash의 경우 inlineData를 사용하여 최대 3000개의 이미지를 지정할 수 있습니다.
</ParamField>

<ParamField body="contents[].parts[].inlineData.data" type="string (byte)">
  프롬프트에 인라인으로 포함할 이미지, PDF 또는 비디오의 base64 인코딩입니다. 미디어를 인라인으로 포함할 때는 데이터의 미디어 타입(mimeType)도 지정해야 합니다. 크기 제한: 20MB

  형식: `byte`
</ParamField>

<ParamField body="contents[].parts[].inlineData.mimeType" type="string">
  data 또는 fileUri 필드에 지정된 파일의 미디어 타입입니다. 허용되는 값은 다음과 같습니다. gemini-2.0-flash-lite 및 gemini-2.0-flash의 경우 오디오 파일의 최대 길이는 8.4시간이고 비디오 파일(오디오 제외)의 최대 길이는 1시간입니다. 자세한 내용은 Gemini 오디오 및 비디오 요구 사항을 참조하세요. 텍스트 파일은 UTF-8로 인코딩되어야 합니다. 텍스트 파일의 내용은 토큰 한도에 포함됩니다. 이미지 해상도에는 제한이 없습니다.

  가능한 값: `application/pdf`, `audio/mpeg`, `audio/mp3`, `audio/wav`, `image/png`, `image/jpeg`, `image/webp`, `text/plain`, `video/mov`, `video/mpeg`, `video/mp4`, `video/mpg`, `video/avi`, `video/wmv`, `video/mpegps`, `video/flv`, `image/heic`, `image/heif`, `audio/flac`, `video/webm`
</ParamField>

<ParamField body="contents[].parts[].mediaProcessing" type="string">
  모델이 이 파트의 동영상을 읽는 방식입니다. "AGENTIC"으로 설정하면 고정 비율 프레임 샘플링 대신 모델이 검사할 세그먼트를 결정합니다. 기본 고정 비율 샘플링을 사용하려면 생략합니다. gemini-3.7-flash 이상의 Flash 모델에서 지원됩니다.
</ParamField>

<ParamField body="contents[].parts[].text" type="string">
  텍스트 프롬프트 또는 코드 스니펫입니다.
</ParamField>

<ParamField body="contents[].parts[].thought" type="boolean">
  이 부분이 모델의 사고/추론 단계임을 나타냅니다.
</ParamField>

<ParamField body="contents[].role" type="string">
  가능한 값: `user`, `model`
</ParamField>

<ParamField body="generationConfig" type="object">
  생성을 위한 샘플링, 길이 및 출력 설정입니다. 모든 필드는 선택 사항입니다. 아래에서 `default`를 선언한 필드는 생략 시 해당 값을 적용하고, 나머지는 모델 자체 동작으로 대체됩니다.
</ParamField>

<ParamField body="generationConfig.imageConfig" type="object">
  이미지 생성을 위한 구성
</ParamField>

<ParamField body="generationConfig.imageConfig.aspectRatio" type="string">
  생성된 이미지의 가로세로 비율
</ParamField>

<ParamField body="generationConfig.imageConfig.imageOutputOptions" type="object">
  선택 사항입니다. 생성된 이미지의 이미지 출력 형식입니다.
</ParamField>

<ParamField body="generationConfig.imageConfig.imageOutputOptions.compressionQuality" type="integer">
  선택 사항입니다. 출력 이미지의 압축 품질입니다.
</ParamField>

<ParamField body="generationConfig.imageConfig.imageOutputOptions.mimeType" type="string">
  선택 사항입니다. 출력을 저장할 이미지 형식입니다.
</ParamField>

<ParamField body="generationConfig.imageConfig.imageSize" type="string">
  선택 사항입니다. 생성된 이미지의 크기를 지정합니다. 지원되는 값은 1K, 2K, 4K입니다. 지정하지 않으면 모델은 기본값 1K를 사용합니다.
</ParamField>

<ParamField body="generationConfig.maxOutputTokens" type="integer">
  응답에서 생성할 수 있는 최대 토큰 수입니다. 토큰은 대략 4자입니다. 100 토큰은 대략 60-80 단어에 해당합니다.

  범위: `16` \~ `65536`
</ParamField>

<ParamField body="generationConfig.responseModalities" type="`TEXT`, `IMAGE`[]" />

<ParamField body="generationConfig.seed" type="integer">
  시드가 특정 값으로 고정되면 모델은 반복 요청에 대해 동일한 응답을 제공하기 위해 최선을 다합니다. 결정론적 출력은 보장되지 않습니다. 또한 temperature와 같은 모델 또는 매개변수 설정을 변경하면 동일한 시드 값을 사용하더라도 응답에 변동이 생길 수 있습니다. 기본적으로 임의의 시드 값이 사용됩니다. 다음 모델에서 사용할 수 있습니다: gemini-2.5-flash, gemini-2.5-pro, gemini-2.5-flash-preview-04-1, gemini-2.5-pro-preview-05-0, gemini-2.0-flash-lite-00, gemini-2.0-flash-001
</ParamField>

<ParamField body="generationConfig.stopSequences" type="string[]" />

<ParamField body="generationConfig.temperature" type="number" default="1">
  Temperature는 응답 생성 중 샘플링에 사용되며, 이는 topP와 topK가 적용될 때 발생합니다. Temperature는 token 선택의 무작위성 정도를 제어합니다. 낮은 temperature는 덜 개방적이거나 창의적인 응답이 필요한 프롬프트에 적합하고, 높은 temperature는 더 다양하거나 창의적인 결과를 낼 수 있습니다. Temperature가 0이면 항상 확률이 가장 높은 token이 선택됩니다. 이 경우 주어진 프롬프트에 대한 응답은 대부분 결정적이지만, 약간의 변동은 여전히 가능합니다. 모델이 너무 일반적이거나 너무 짧은 응답을 반환하거나 대체 응답(fallback)을 제공하는 경우 temperature를 높여 보세요.

  범위: `0` \~ `2`

  형식: `float`
</ParamField>

<ParamField body="generationConfig.thinkingConfig" type="object">
  선택 사항. 사고(thinking) 기능에 대한 설정입니다. 사고는 모델이 복잡한 작업을 더 작은 단계로 나누어 더 높은 품질의 응답을 생성하는 과정입니다.
</ParamField>

<ParamField body="generationConfig.thinkingConfig.includeThoughts" type="boolean">
  선택 사항. 참이면 모델이 응답에 자신의 사고 내용을 포함합니다.
</ParamField>

<ParamField body="generationConfig.thinkingConfig.thinkingBudget" type="integer">
  선택 사항. 모델의 사고 과정에 대한 token 예산입니다. 모델은 이 예산을 지키기 위해 최선을 다합니다.
</ParamField>

<ParamField body="generationConfig.thinkingConfig.thinkingLevel" type="string">
  선택 사항. 모델의 사고 수준입니다.

  가능한 값: `THINKING_LEVEL_UNSPECIFIED`, `LOW`, `MEDIUM`, `HIGH`, `MINIMAL`
</ParamField>

<ParamField body="generationConfig.topK" type="integer" default="40">
  Top-K는 모델이 출력할 token을 선택하는 방식을 변경합니다. Top-K가 1이면 다음에 선택되는 token은 모델 어휘 전체에서 가장 확률이 높은 token입니다. Top-K가 3이면 다음 token은 확률이 가장 높은 3개의 token 중에서 temperature를 사용해 선택됩니다.

  범위: `1` \~ `…`
</ParamField>

<ParamField body="generationConfig.topP" type="number" default="0.95">
  지정된 경우 nucleus sampling이 사용됩니다.
  Top-P는 모델이 출력할 token을 선택하는 방식을 변경합니다. 확률의 합이 top-P 값과 같아질 때까지 확률이 가장 높은(see top-K) token부터 가장 낮은 token까지 선택됩니다. 예를 들어 token A, B, C의 확률이 각각 0.3, 0.2, 0.1이고 top-P 값이 0.5라면, 모델은 temperature를 사용해 A 또는 B를 다음 token으로 선택하고 C는 후보에서 제외합니다.
  무작위성이 적은 응답을 원하면 더 낮은 값을, 무작위성이 큰 응답을 원하면 더 높은 값을 지정하세요.

  범위: `0` \~ `1`

  형식: `float`
</ParamField>

<ParamField body="safetySettings" type="object[]">
  안전하지 않은 콘텐츠를 차단하기 위한 요청별 설정입니다. GenerateContentResponse.candidates에 적용됩니다.
</ParamField>

<ParamField body="safetySettings[].category" type="string" required>
  가능한 값: `HARM_CATEGORY_SEXUALLY_EXPLICIT`, `HARM_CATEGORY_HATE_SPEECH`, `HARM_CATEGORY_HARASSMENT`, `HARM_CATEGORY_DANGEROUS_CONTENT`
</ParamField>

<ParamField body="safetySettings[].threshold" type="string" required>
  가능한 값: `OFF`, `BLOCK_NONE`, `BLOCK_LOW_AND_ABOVE`, `BLOCK_MEDIUM_AND_ABOVE`, `BLOCK_ONLY_HIGH`
</ParamField>

<ParamField body="systemInstruction" type="object">
  모델을 더 나은 성능으로 이끌기 위한 지침입니다. 예를 들어 "가능한 한 간결하게 답하세요" 또는 "응답에 전문 용어를 사용하지 마세요"와 같습니다. 텍스트 문자열은 token 한도에 포함됩니다. systemInstruction의 역할(role) 필드는 무시되며 모델의 성능에 영향을 주지 않습니다. 참고: parts에는 텍스트만 사용해야 하며, 각 part의 콘텐츠는 별도의 단락에 있어야 합니다.
</ParamField>

<ParamField body="systemInstruction.parts" type="object[]" required>
  하나의 메시지를 구성하는 순서가 지정된 part 목록입니다. part마다 서로 다른 IANA MIME 유형을 가질 수 있습니다. 최대 token 수나 이미지 수와 같은 입력 제한은 Google 모델 페이지의 모델 사양을 참고하세요.
</ParamField>

<ParamField body="systemInstruction.parts[].text" type="string">
  텍스트 프롬프트 또는 코드 조각입니다.
</ParamField>

<ParamField body="systemInstruction.role" type="string">
  메시지를 생성하는 주체의 identity입니다. 다음 값이 지원됩니다: user: 메시지가 실제 사람에 의해 전송되었음을 나타내며, 일반적으로 사용자가 생성한 메시지입니다. model: 메시지가 모델에 의해 생성되었음을 나타냅니다. model 값은 다중 턴 대화 중에 모델의 메시지를 대화에 삽입하는 데 사용됩니다. 다중 턴 대화가 아닌 경우 이 필드는 비워 두거나 설정하지 않아도 됩니다.

  가능한 값: `user`, `model`
</ParamField>

<ParamField body="tools" type="object[]">
  시스템이 외부 시스템과 상호작용하여 모델의 지식과 범위를 벗어난 작업 또는 작업 집합을 수행할 수 있게 하는 코드 조각입니다. 함수 호출(Function calling)을 참고하세요.
</ParamField>

<ParamField body="tools[].functionDeclarations" type="object[]" />

<ParamField body="tools[].functionDeclarations[].description" type="string" />

<ParamField body="tools[].functionDeclarations[].name" type="string" required />

<ParamField body="tools[].functionDeclarations[].parameters" type="object">
  함수 parameters에 대한 JSON schema입니다
</ParamField>

<ParamField body="uploadImagesToStorage" type="boolean">
  참이면 생성된 이미지가 클라우드 스토리지에 업로드되고 인라인 base64 데이터 대신 서명된 URL로 반환됩니다. URL은 24시간 후에 만료됩니다.
</ParamField>

<ParamField body="videoMetadata" type="object">
  비디오 입력의 경우, Duration 형식으로 된 비디오의 시작 및 종료 오프셋입니다. 예를 들어 1:00에서 시작하는 10초 클립을 지정하려면 "startOffset": \{ "seconds": 60 } 및 "endOffset": \{ "seconds": 70 }으로 설정합니다. 메타데이터는 비디오 데이터가 inlineData 또는 fileData로 제공될 때만 지정해야 합니다.
</ParamField>

<ParamField body="videoMetadata.endOffset" type="object">
  비디오 타임라인 위치에 대한 재생 시간 오프셋을 나타냅니다.
</ParamField>

<ParamField body="videoMetadata.endOffset.nanos" type="integer">
  나노초 해상도의 부호 있는 초 단위 소수입니다. 소수를 포함한 음수 초 값이라도 nanos 값은 음수가 아니어야 합니다.

  범위: `0`부터 `999999999`까지
</ParamField>

<ParamField body="videoMetadata.endOffset.seconds" type="integer">
  시간 범위의 부호 있는 초입니다. -315,576,000,000부터 +315,576,000,000까지(양끝 포함)여야 합니다.

  범위: `-315576000000`부터 `315576000000`까지
</ParamField>

<ParamField body="videoMetadata.startOffset" type="object">
  비디오 타임라인 위치에 대한 재생 시간 오프셋을 나타냅니다.
</ParamField>

<ParamField body="videoMetadata.startOffset.nanos" type="integer">
  나노초 해상도의 부호 있는 초 단위 소수입니다. 소수를 포함한 음수 초 값이라도 nanos 값은 음수가 아니어야 합니다.

  범위: `0`부터 `999999999`까지
</ParamField>

<ParamField body="videoMetadata.startOffset.seconds" type="integer">
  시간 범위의 부호 있는 초입니다. -315,576,000,000부터 +315,576,000,000까지(양끝 포함)여야 합니다.

  범위: `-315576000000`부터 `315576000000`까지
</ParamField>

Router가 `GET /v2/models/vertexai/gemini-3-pro-image/openapi.json`에서 제공하는 스키마에서 생성되었으며, 이는 요청이 공급자에 도달하기 이전에 호출을 검증하는 데 사용하는 것과 동일한 문서입니다.

### 출력

<ResponseField name="candidates" type="object[]" />

<ResponseField name="candidates[].citationMetadata" type="object" />

<ResponseField name="candidates[].citationMetadata.citations" type="object[]" />

<ResponseField name="candidates[].citationMetadata.citations[].authors" type="string[]" />

<ResponseField name="candidates[].citationMetadata.citations[].endIndex" type="integer" />

<ResponseField name="candidates[].citationMetadata.citations[].license" type="string" />

<ResponseField name="candidates[].citationMetadata.citations[].publicationDate" type="string (date)">
  형식: `date`
</ResponseField>

<ResponseField name="candidates[].citationMetadata.citations[].startIndex" type="integer" />

<ResponseField name="candidates[].citationMetadata.citations[].title" type="string" />

<ResponseField name="candidates[].citationMetadata.citations[].uri" type="string" />

<ResponseField name="candidates[].content" type="object">
  모델과의 현재 대화 콘텐츠입니다. 단일 턴 쿼리의 경우 단일 인스턴스입니다. 멀티 턴 쿼리의 경우 대화 기록과 최신 요청을 포함하는 반복 필드입니다.
</ResponseField>

<ResponseField name="candidates[].content.parts" type="object[]" required />

<ResponseField name="candidates[].content.parts[].fileData" type="object">
  URI 기반 데이터입니다.
</ResponseField>

<ResponseField name="candidates[].content.parts[].fileData.fileUri" type="string">
  URI
</ResponseField>

<ResponseField name="candidates[].content.parts[].fileData.mimeType" type="string">
  data 또는 fileUri 필드에 지정된 파일의 미디어 유형입니다. 허용되는 값은 다음과 같습니다. gemini-2.0-flash-lite 및 gemini-2.0-flash의 경우 오디오 파일의 최대 길이는 8.4시간이고 비디오 파일(오디오 제외)의 최대 길이는 1시간입니다. 자세한 내용은 Gemini 오디오 및 비디오 요구 사항을 참조하세요. 텍스트 파일은 UTF-8로 인코딩되어야 합니다. 텍스트 파일의 내용은 토큰 한도에 포함됩니다. 이미지 해상도에는 제한이 없습니다.

  가능한 값: `application/pdf`, `audio/mpeg`, `audio/mp3`, `audio/wav`, `image/png`, `image/jpeg`, `image/webp`, `text/plain`, `video/mov`, `video/mpeg`, `video/mp4`, `video/mpg`, `video/avi`, `video/wmv`, `video/mpegps`, `video/flv`, `image/heic`, `image/heif`, `audio/flac`, `video/webm`
</ResponseField>

<ResponseField name="candidates[].content.parts[].inlineData" type="object">
  원시 바이트 형식의 인라인 데이터입니다. gemini-2.0-flash-lite 및 gemini-2.0-flash의 경우 inlineData를 사용하여 최대 3000개의 이미지를 지정할 수 있습니다.
</ResponseField>

<ResponseField name="candidates[].content.parts[].inlineData.data" type="string (byte)">
  프롬프트에 인라인으로 포함할 이미지, PDF 또는 비디오의 base64 인코딩입니다. 미디어를 인라인으로 포함할 때는 데이터의 미디어 유형(mimeType)도 지정해야 합니다. 크기 제한: 20MB

  형식: `byte`
</ResponseField>

<ResponseField name="candidates[].content.parts[].inlineData.mimeType" type="string">
  data 또는 fileUri 필드에 지정된 파일의 미디어 유형입니다. 허용되는 값은 다음과 같습니다. gemini-2.0-flash-lite 및 gemini-2.0-flash의 경우 오디오 파일의 최대 길이는 8.4시간이고 비디오 파일(오디오 제외)의 최대 길이는 1시간입니다. 자세한 내용은 Gemini 오디오 및 비디오 요구 사항을 참조하세요. 텍스트 파일은 UTF-8로 인코딩되어야 합니다. 텍스트 파일의 내용은 토큰 한도에 포함됩니다. 이미지 해상도에는 제한이 없습니다.

  가능한 값: `application/pdf`, `audio/mpeg`, `audio/mp3`, `audio/wav`, `image/png`, `image/jpeg`, `image/webp`, `text/plain`, `video/mov`, `video/mpeg`, `video/mp4`, `video/mpg`, `video/avi`, `video/wmv`, `video/mpegps`, `video/flv`, `image/heic`, `image/heif`, `audio/flac`, `video/webm`
</ResponseField>

<ResponseField name="candidates[].content.parts[].mediaProcessing" type="string">
  모델이 이 파트의 동영상을 읽는 방식입니다. "AGENTIC"으로 설정하면 고정 비율 프레임 샘플링 대신 모델이 검사할 세그먼트를 결정합니다. 기본 고정 비율 샘플링을 사용하려면 생략합니다. gemini-3.7-flash 이상의 Flash 모델에서 지원됩니다.
</ResponseField>

<ResponseField name="candidates[].content.parts[].text" type="string">
  텍스트 프롬프트 또는 코드 스니펫입니다.
</ResponseField>

<ResponseField name="candidates[].content.parts[].thought" type="boolean">
  이 부분이 모델의 사고/추론 단계임을 나타냅니다.
</ResponseField>

<ResponseField name="candidates[].content.role" type="string">
  가능한 값: `user`, `model`
</ResponseField>

<ResponseField name="candidates[].finishReason" type="string" />

<ResponseField name="candidates[].safetyRatings" type="object[]" />

<ResponseField name="candidates[].safetyRatings[].category" type="string">
  가능한 값: `HARM_CATEGORY_SEXUALLY_EXPLICIT`, `HARM_CATEGORY_HATE_SPEECH`, `HARM_CATEGORY_HARASSMENT`, `HARM_CATEGORY_DANGEROUS_CONTENT`
</ResponseField>

<ResponseField name="candidates[].safetyRatings[].probability" type="string">
  콘텐츠가 지정된 안전 카테고리를 위반할 확률입니다.

  가능한 값: `NEGLIGIBLE`, `LOW`, `MEDIUM`, `HIGH`, `UNKNOWN`
</ResponseField>

<ResponseField name="createTime" type="string">
  응답이 생성된 타임스탬프입니다.
</ResponseField>

<ResponseField name="modelVersion" type="string">
  응답을 생성하는 데 사용된 모델 버전입니다.
</ResponseField>

<ResponseField name="promptFeedback" type="object" />

<ResponseField name="promptFeedback.blockReason" type="string" />

<ResponseField name="promptFeedback.blockReasonMessage" type="string" />

<ResponseField name="promptFeedback.safetyRatings" type="object[]" />

<ResponseField name="promptFeedback.safetyRatings[].category" type="string">
  가능한 값: `HARM_CATEGORY_SEXUALLY_EXPLICIT`, `HARM_CATEGORY_HATE_SPEECH`, `HARM_CATEGORY_HARASSMENT`, `HARM_CATEGORY_DANGEROUS_CONTENT`
</ResponseField>

<ResponseField name="promptFeedback.safetyRatings[].probability" type="string">
  콘텐츠가 지정된 안전 카테고리를 위반할 확률입니다.

  가능한 값: `NEGLIGIBLE`, `LOW`, `MEDIUM`, `HIGH`, `UNKNOWN`
</ResponseField>

<ResponseField name="responseId" type="string">
  응답의 고유 식별자입니다.
</ResponseField>

<ResponseField name="usageMetadata" type="object" />

<ResponseField name="usageMetadata.cachedContentTokenCount" type="integer">
  출력 전용입니다. 입력에서 캐시된 부분(캐시된 콘텐츠)의 토큰 수입니다.
</ResponseField>

<ResponseField name="usageMetadata.candidatesTokenCount" type="integer">
  응답에 포함된 토큰 수입니다.
</ResponseField>

<ResponseField name="usageMetadata.candidatesTokensDetails" type="object[]">
  모달리티별 후보 토큰의 세부 내역입니다.
</ResponseField>

<ResponseField name="usageMetadata.candidatesTokensDetails[].modality" type="string">
  입력 또는 출력 콘텐츠 모달리티의 유형입니다.

  가능한 값: `MODALITY_UNSPECIFIED`, `TEXT`, `IMAGE`, `VIDEO`, `AUDIO`, `DOCUMENT`
</ResponseField>

<ResponseField name="usageMetadata.candidatesTokensDetails[].tokenCount" type="integer">
  해당 모달리티의 토큰 수입니다.
</ResponseField>

<ResponseField name="usageMetadata.promptTokenCount" type="integer">
  요청에 포함된 토큰 수입니다. cachedContent가 설정된 경우에도 이는 총 유효 프롬프트 크기이며, 캐시된 콘텐츠의 토큰 수를 포함합니다.
</ResponseField>

<ResponseField name="usageMetadata.promptTokensDetails" type="object[]">
  모달리티별 프롬프트 토큰의 세부 내역입니다.
</ResponseField>

<ResponseField name="usageMetadata.promptTokensDetails[].modality" type="string">
  입력 또는 출력 콘텐츠 모달리티의 유형입니다.

  가능한 값: `MODALITY_UNSPECIFIED`, `TEXT`, `IMAGE`, `VIDEO`, `AUDIO`, `DOCUMENT`
</ResponseField>

<ResponseField name="usageMetadata.promptTokensDetails[].tokenCount" type="integer">
  해당 모달리티의 토큰 수입니다.
</ResponseField>

<ResponseField name="usageMetadata.thoughtsTokenCount" type="integer">
  thoughts 출력에 포함된 토큰 수입니다.
</ResponseField>

<ResponseField name="usageMetadata.toolUsePromptTokenCount" type="integer">
  도구 사용 프롬프트에 포함된 토큰 수입니다.
</ResponseField>

<ResponseField name="usageMetadata.toolUsePromptTokensDetails" type="object[]">
  모달리티별 도구 사용 프롬프트 토큰의 내역입니다.
</ResponseField>

<ResponseField name="usageMetadata.toolUsePromptTokensDetails[].modality" type="string">
  입력 또는 출력 콘텐츠 모달리티의 유형입니다.

  가능한 값: `MODALITY_UNSPECIFIED`, `TEXT`, `IMAGE`, `VIDEO`, `AUDIO`, `DOCUMENT`
</ResponseField>

<ResponseField name="usageMetadata.toolUsePromptTokensDetails[].tokenCount" type="integer">
  해당 모달리티의 토큰 수입니다.
</ResponseField>

<ResponseField name="usageMetadata.totalTokenCount" type="integer">
  총 토큰 수입니다(프롬프트 + 후보).
</ResponseField>

<ResponseField name="usageMetadata.trafficType" type="string">
  요청에 사용된 트래픽 유형입니다(예: PROVISIONED\_THROUGHPUT).
</ResponseField>

## 예시

### 입력

```json theme={null}
{
  "contents": [
    {
      "role": "user",
      "parts": [
        {
          "text": "a single red maple leaf on a plain white background, studio lighting"
        }
      ]
    }
  ],
  "generationConfig": {
    "responseModalities": [
      "IMAGE"
    ],
    "imageConfig": {
      "aspectRatio": "1:1"
    }
  }
}
```

### 출력

```json theme={null}
{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [
          {
            "inlineData": {
              "mimeType": "image/png",
              "data": "PGJhc2U2ND4="
            }
          }
        ]
      },
      "finishReason": "STOP"
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 12,
    "candidatesTokenCount": 1290
  }
}
```

기본적으로 생성된 이미지 part에는 `inlineData.data`에 base64 바이트가, `inlineData.mimeType`에 미디어 타입이 포함됩니다. 바이트를 디코딩하여 파일로 저장하세요. `uploadImagesToStorage: true`인 경우, 업로드된 이미지는 대신 서명된 URL에 `fileData.fileUri`를, 미디어 타입에 `fileData.mimeType`을 사용합니다. URL이 만료되기 전에 이 이미지들을 다운로드하세요. URL은 생성된 후 24시간이 지나면 만료됩니다. 업로드가 실패하면 해당 이미지는 인라인으로 남으므로, 각 part에서 `inlineData` 또는 `fileData`를 확인하세요. 텍스트 part도 나타날 수 있으며, 이미지가 첫 번째 part라는 보장은 없습니다.

## 배포 전 확인

SDK는 `Idempotency-Key`를 생성하고 자동 재시도에서 재사용합니다. 수동 재시도 시에는 원래 키를 재사용하세요. Router는 연결을 최대 10분간 유지할 수 있습니다.

요청이 실패하면 Router는 이유를 설명하는 `X-Comfy-Error-Type` 응답 헤더를 보냅니다. `422`는 Router가 프로바이더를 호출하기 전에 입력을 거부했음을 의미합니다. 생성된 에셋은 [결과 URL이 만료](/ko/development/comfy-router/reference#결과-에셋)될 수 있으므로 즉시 다운로드하세요.

<CardGroup cols={3}>
  <Card title="헤더" icon="list" href="/ko/development/comfy-router/quickstart">
    인증, 멱등성, 요청 ID, 오류 분류, 재시도 간격, 지출 한도.
  </Card>

  <Card title="Router API 사용" icon="code" href="/ko/development/comfy-router/quickstart">
    모델 검색, 유효성 검사 오류, 재시도, 과금.
  </Card>

  <Card title="제한 사항" icon="triangle-exclamation" href="/ko/development/comfy-router/limitations">
    Router가 현재 지원하지 않는 기능과 대체 방법.
  </Card>
</CardGroup>
