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

# Nano Banana API: 이미지 생성, 참조 이미지, 연속 편집

> BetterToken에서 Nano Banana Pro, 2, 2.1을 연결하세요. 인증, 해상도, Python 예제, 참조 이미지 전송, 이미지 저장, 연속 편집과 매개변수 제한을 설명합니다.

같은 Gemini 기본 엔드포인트로 텍스트 생성, 참조 편집, 후속 편집을 수행합니다. 예제는 `nano-banana-2.1`을 사용합니다. 다른 두 모델은 URL이나 SDK의 모델 ID를 바꾸세요.

* [Gemini 텍스트 이미지 생성 API](/ko/api-reference/gemini-images-generations)
* [Gemini 이미지 편집 API](/ko/api-reference/gemini-images-edits)

<Warning>
  BetterToken API는 Google 웹 검색 및 이미지 검색 기반 이미지 생성을 지원하지 않습니다. 검색 도구를 추가하지 마세요.
</Warning>

## 연결 정보

| 항목 | 값 |
| - | - |
| Base URL | `https://bettertoken.ai` |
| 요청 | `POST /v1beta/models/{model}:generateContent` |
| 인증 | `x-goog-api-key: YOUR_API_KEY` 또는 `Authorization: Bearer YOUR_API_KEY` 중 하나를 사용하세요. |
| 본문 | `application/json` |
| Model ID | `nano-banana-pro`, `nano-banana-2`, `nano-banana-2.1` |

<a href={"https://bettertoken.ai/register"}>BetterToken API Key 만들기</a> · <a href={"https://bettertoken.ai/pricing"}>모델 카탈로그</a> · [Nano Banana 모델 소개](/ko/model-updates/nano-banana)

<Warning>
  세 모델은 `POST /v1/images/generations`와 `POST /v1/images/edits`를 지원하지 않으며 `400 unsupported_endpoint`를 반환합니다. GPT Image의 multipart, `image[]`, `data[].b64_json` 예제를 재사용하지 마세요.
</Warning>

## 첫 이미지 생성

터미널에서 `BETTERTOKEN_API_KEY`를 설정한 후 실행하세요. 생성이 완료될 때까지 기다려 전체 JSON을 `response.json`에 저장합니다.

<Tabs>
  <Tab title="macOS / Linux">
    ```bash theme={null}
    export BETTERTOKEN_API_KEY="YOUR_API_KEY"

    curl --fail-with-body --max-time 650 \
      "https://bettertoken.ai/v1beta/models/nano-banana-2.1:generateContent" \
      -H "x-goog-api-key: $BETTERTOKEN_API_KEY" \
      -H "Content-Type: application/json" \
      -H "X-BetterToken-Max-Images: 1" \
      -d '{
        "contents": [{
          "role": "user",
          "parts": [{"text": "흰색 테이블 위 파란색 세라믹 머그컵의 스튜디오 제품 사진."}]
        }],
        "generationConfig": {
          "responseModalities": ["IMAGE"],
          "candidateCount": 1,
          "imageConfig": {"imageSize": "1K", "aspectRatio": "1:1"}
        }
      }' -o response.json
    ```
  </Tab>

  <Tab title="Windows PowerShell">
    ```powershell theme={null}
    $env:BETTERTOKEN_API_KEY = "YOUR_API_KEY"
    $headers = @{
        "x-goog-api-key" = $env:BETTERTOKEN_API_KEY
        "X-BetterToken-Max-Images" = "1"
    }
    $body = @{
        contents = @(@{
            role = "user"
            parts = @(@{ text = "흰색 테이블 위 파란색 세라믹 머그컵의 스튜디오 제품 사진." })
        })
        generationConfig = @{
            responseModalities = @("IMAGE")
            candidateCount = 1
            imageConfig = @{ imageSize = "1K"; aspectRatio = "1:1" }
        }
    } | ConvertTo-Json -Depth 10
    Invoke-WebRequest `
        -Uri "https://bettertoken.ai/v1beta/models/nano-banana-2.1:generateContent" `
        -Method Post `
        -Headers $headers `
        -ContentType "application/json" `
        -Body ([System.Text.Encoding]::UTF8.GetBytes($body)) `
        -TimeoutSec 650 `
        -OutFile "response.json"
    ```
  </Tab>
</Tabs>

고해상도는 `imageSize`를 `2K` 또는 `4K`로 바꾸세요. 처음에는 `1K`, `1:1`, 한 장으로 시작하고 `--retry` 자동 재전송을 추가하지 마세요.

## 주요 매개변수

제품 사진에는 대상, 재질, 조명, 배경을 설명하세요. 포스터에는 정확한 문구와 배치를 지정하세요. 편집할 때는 바꿀 부분과 유지할 부분을 알려주세요.

기본 HTTP는 아래 필드, Python SDK는 snake\_case를 사용합니다. 이미지 설정은 `generationConfig.imageConfig` 안에 넣으세요.

| 항목 | 값 |
| - | - |
| `contents[].parts[].text` | 대상, 배경, 스타일, 변경 사항을 설명합니다. |
| `contents[].parts[].inlineData` | 원본 참조 파일의 `mimeType`과 base64이며 이미지 URL이 아닙니다. |
| `generationConfig.responseModalities` | `["IMAGE"]`를 명시합니다. |
| `generationConfig.imageConfig.imageSize` | 대문자 `1K`, `2K`, `4K`; 기본값 `1K`. |
| `generationConfig.imageConfig.aspectRatio` | 아래 표에서 모델에 맞는 비율을 선택하세요. 예제는 `1:1`입니다. |
| `generationConfig.candidateCount` | 생략하거나 정수 `1`. 기본 요청 루트에 `n`을 넣지 않습니다. |
| `X-BetterToken-Max-Images` | 선택 헤더. 정수 `1`\~`4`, 기본값 `1`. 수신 및 과금을 허용하는 최대 이미지 수. |

<span id="aspect-ratios" />

### Google 공식 지원 비율

Nano Banana 2와 2.1은 14개, Pro는 10개 비율을 지원합니다. 첫 요청은 `1:1`부터 시작하세요.

| 모델 | 해상도 | 비율 |
| - | - | - |
| `nano-banana-pro` | `1K`, `2K`, `4K` | `1:1`, `2:3`, `3:2`, `3:4`, `4:3`, `4:5`, `5:4`, `9:16`, `16:9`, `21:9` |
| `nano-banana-2` | `1K`, `2K`, `4K` | `1:1`, `1:4`, `1:8`, `2:3`, `3:2`, `3:4`, `4:1`, `4:3`, `4:5`, `5:4`, `8:1`, `9:16`, `16:9`, `21:9` |
| `nano-banana-2.1` | `1K`, `2K`, `4K` | `1:1`, `1:4`, `1:8`, `2:3`, `3:2`, `3:4`, `4:1`, `4:3`, `4:5`, `5:4`, `8:1`, `9:16`, `16:9`, `21:9` |

[Google 비율 및 이미지 크기 안내](https://ai.google.dev/gemini-api/docs/image-generation#aspect-ratios-and-image-size)

상한은 생성 수 보장이 아닙니다. 여러 장을 요청해도 한 장만 반환할 수 있습니다. 고정 수량은 개별 요청으로 보내세요.

## 응답에서 이미지 저장

이미지는 `candidates[].content.parts[].inlineData`에 있습니다. 아래는 구조 예시이며 `BASE64_IMAGE_DATA`는 자리표시자입니다. 모든 최종 이미지 part를 읽고 `thought: true`는 제외하세요.

```json theme={null}
{
  "candidates": [{
    "content": {
      "role": "model",
      "parts": [{
        "inlineData": {
          "mimeType": "image/jpeg",
          "data": "BASE64_IMAGE_DATA"
        }
      }]
    },
    "finishReason": "STOP"
  }]
}
```

다음 Python으로 curl 결과를 저장합니다. `mimeType`에 맞는 확장자를 쓰세요. JPEG일 수 있으므로 항상 `.png`로 저장하지 마세요.

```python theme={null}
import base64
import json
from pathlib import Path

suffixes = {"image/png": ".png", "image/jpeg": ".jpg"}
result = json.loads(Path("response.json").read_text())
saved = 0
for candidate in result.get("candidates", []):
    for part in candidate.get("content", {}).get("parts", []):
        if part.get("thought"):
            continue
        blob = part.get("inlineData")
        if not blob:
            continue
        suffix = suffixes.get(blob["mimeType"])
        if suffix is None:
            raise ValueError("Unexpected image MIME type: " + blob["mimeType"])
        saved += 1
        Path(f"generated-{saved}{suffix}").write_bytes(
            base64.b64decode(blob["data"], validate=True)
        )
if saved == 0:
    raise RuntimeError("No final image returned; inspect response.json.")
```

## Python SDK 전체 예제

Python 3.10 이상과 `google-genai==2.30.1`을 사용합니다. 프로젝트 가상 환경에 설치하세요. 이전 SDK는 `image_size`를 전송하지 않을 수 있습니다.

```bash theme={null}
python -m pip install "google-genai==2.30.1"
```

SDK Base URL은 `/v1`, `/v1beta`가 없는 도메인 루트입니다. `timeout`은 밀리초이며 `attempts=1`은 자동 재시도를 끕니다. `save_images`는 모든 최종 이미지를 저장합니다.

```python theme={null}
import os
from pathlib import Path
from google import genai
from google.genai import types

MODEL = "nano-banana-2.1"
client = genai.Client(
    vertexai=False,
    api_key=os.environ["BETTERTOKEN_API_KEY"],
    http_options=types.HttpOptions(
        base_url="https://bettertoken.ai",
        api_version="v1beta",
        timeout=650_000,
        retry_options=types.HttpRetryOptions(attempts=1),
        headers={"X-BetterToken-Max-Images": "1"},
    ),
)
config = types.GenerateContentConfig(
    response_modalities=["IMAGE"],
    candidate_count=1,
    image_config=types.ImageConfig(image_size="1K", aspect_ratio="1:1"),
)

def save_images(response, prefix):
    if len(response.candidates or []) != 1 or not response.candidates[0].content:
        raise RuntimeError("No single image candidate returned.")
    saved = 0
    suffixes = {"image/png": ".png", "image/jpeg": ".jpg"}
    for part in response.candidates[0].content.parts or []:
        if part.thought or not part.inline_data:
            continue
        blob = part.inline_data
        suffix = suffixes.get(blob.mime_type)
        if suffix is None:
            raise ValueError("Unexpected image MIME type: " + str(blob.mime_type))
        saved += 1
        Path(f"{prefix}-{saved}{suffix}").write_bytes(blob.data)
    if saved == 0:
        raise RuntimeError("No final image returned; inspect the response.")

first_turn = types.Content(
    role="user",
    parts=[types.Part(text="흰색 테이블 위 파란색 세라믹 머그컵의 스튜디오 제품 사진.")],
)
response = client.models.generate_content(
    model=MODEL, contents=[first_turn], config=config,
)
save_images(response, "generated")
```

## 참조 이미지 전송

Python 예제 뒤에 실행하면 새 편집 요청을 보냅니다. `reference.jpg`를 로컬 파일로 바꾸세요. PNG는 `mime_type="image/png"`를 사용합니다. 추가 참조는 같은 사용자 메시지의 `parts`에 넣으세요.

```python theme={null}
first_turn = types.Content(
    role="user",
    parts=[
        types.Part(text="머그컵을 빨간색으로 바꾸고 모양과 배경은 유지하세요."),
        types.Part.from_bytes(
            data=Path("reference.jpg").read_bytes(),
            mime_type="image/jpeg",
        ),
    ],
)
response = client.models.generate_content(
    model=MODEL, contents=[first_turn], config=config,
)
save_images(response, "reference-edit")
```

기본 JSON은 `inlineData: {"mimeType": "image/jpeg", "data": "BASE64_IMAGE_DATA"}`입니다. 원본 바이트를 base64로 인코딩하며 `data:image/...;base64,` 접두사를 넣지 않습니다. multipart, Files 업로드, `fileData`를 사용하지 않습니다.

## 계속 편집

생성이나 참조 편집 성공 후 실행하세요. 모델 응답의 전체 `content`, part 순서, `thoughtSignature`를 유지합니다. 이미지 하나로 이력을 재구성하거나 서명을 만들거나 수정하지 마세요.

```python theme={null}
history = [first_turn, response.candidates[0].content]
edit_turn = types.Content(
    role="user",
    parts=[types.Part(text="작은 금색 손잡이를 추가하고 나머지는 그대로 유지하세요.")],
)
edited = client.models.generate_content(
    model=MODEL, contents=[*history, edit_turn], config=config,
)
save_images(edited, "follow-up")
history.extend([edit_turn, edited.candidates[0].content])
```

각 단계는 새 생성 요청입니다. 전체 `history`에 사용자 지시와 반환된 모델 `content`를 순서대로 추가하세요. Interactions의 `previous_interaction_id`는 사용하지 않습니다.

## API 지원 범위

* 비스트리밍 `generateContent`를 사용하세요. 이 연결은 Files / `fileData`, Batch, Interactions 및 스트리밍을 지원하지 않습니다.
* `responseMimeType`, `responseSchema` 및 사용자 지정 이미지 압축 형식은 지원하지 않습니다. `imageConfig`에는 위의 두 필드만 사용하세요.
* `cachedContent`, 함수 호출, 코드 실행, 파일 검색, Maps, URL context, 오디오 입력 및 생성 설정을 추가하지 마세요.

## 기존 OpenAI Chat 클라이언트 사용

`POST /v1/chat/completions`와 Base URL `https://bettertoken.ai/v1`을 사용할 수 있습니다. 새 연결, 참조 이미지 및 연속 편집에는 위의 Gemini 기본 API를 권장합니다. Chat의 `n`은 생략하거나 정수 `1`로 설정하세요.

HTTP는 `google.image_config`를 JSON 루트에 넣습니다. Python OpenAI SDK는 `extra_body`를 루트에 병합합니다. 여기서는 `generationConfig`를 사용하지 마세요.

```bash theme={null}
curl --fail-with-body --max-time 650 \
  "https://bettertoken.ai/v1/chat/completions" \
  -H "Authorization: Bearer $BETTERTOKEN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "X-BetterToken-Max-Images: 1" \
  -d '{
    "model": "nano-banana-2.1",
    "messages": [{"role": "user", "content": "흰색 테이블 위의 파란색 세라믹 머그컵."}],
    "n": 1,
    "stream": false,
    "google": {"image_config": {"image_size": "1K", "aspect_ratio": "1:1"}}
  }'
```

Python OpenAI SDK 예제는 같은 가상 환경에 `openai==1.66.2`를 설치하고 실행하세요:

```python theme={null}
import base64
import os
import re
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key=os.environ["BETTERTOKEN_API_KEY"],
    base_url="https://bettertoken.ai/v1",
    max_retries=0,
    timeout=650,
)
response = client.chat.completions.create(
    model="nano-banana-2.1",
    messages=[{"role": "user", "content": "흰색 테이블 위의 파란색 세라믹 머그컵."}],
    n=1,
    stream=False,
    extra_headers={"X-BetterToken-Max-Images": "1"},
    extra_body={
        "google": {"image_config": {"image_size": "1K", "aspect_ratio": "1:1"}}
    },
)
content = response.choices[0].message.content or ""
images = re.findall(r"data:(image/(?:png|jpeg));base64,([A-Za-z0-9+/=]+)", content)
if not images:
    raise RuntimeError("No inline image in Chat response.")
for index, (mime, data) in enumerate(images, 1):
    suffix = ".png" if mime == "image/png" else ".jpg"
    Path(f"chat-{index}{suffix}").write_bytes(base64.b64decode(data, validate=True))
```

Chat 이미지는 `choices[0].message.content`의 Markdown Data URL이며 Images API의 `data[]`가 아닙니다. 이 텍스트에서 서명 이력을 만들지 말고 기본 편집 예제를 쓰세요.

## 일반적인 오류

| 문제 | 조치 |
| - | - |
| `401` / 잘못된 Key | Google이 아닌 BetterToken API Key를 사용하고 변수와 헤더 확인. |
| `404` / URL | 루트 Base URL, `api_version="v1beta"`, 세 공개 Model ID 중 하나 사용. |
| `400 unsupported_endpoint` | `/v1/images/*`를 `:generateContent`로 변경. |
| `400` / 매개변수 | 필드 계층, `1K/2K/4K` 대문자 및 선택한 모델의 비율을 확인하세요. `candidateCount`는 생략하거나 정수 `1`로 설정하고 검색 도구는 추가하지 마세요. |
| 최종 이미지 없음 | 전체 응답의 오류·안전 정보·텍스트·`finishReason` 확인. thought 이미지는 최종 결과가 아님. |
| 저장 파일이 열리지 않음 | base64 디코딩과 MIME 확장자 사용. JSON·Markdown 전체를 이미지로 저장하지 않음. |
| 시간 초과·연결 끊김 | 사용 내역과 응답 요청 ID를 확인. 재시도 전 지원팀에 결과를 확인해 중복 생성·과금 방지. |

이미지는 현재 응답으로 반환됩니다. 이 흐름에는 백그라운드 이미지 재조회나 작업 폴링이 없습니다. 결과를 바로 저장하고 SDK와 프록시에 충분한 대기 시간을 설정하며 자동 재시도를 끄세요.

## 공식 자료

* [Nano Banana Pro 모델](https://ai.google.dev/gemini-api/docs/models/gemini-3-pro-image)
* [Nano Banana 2 모델](https://ai.google.dev/gemini-api/docs/models/gemini-3.1-flash-image)
* [Nano Banana 2.1 모델](https://ai.google.dev/gemini-api/docs/models/gemini-nano-banana-2.1)
* [Google 이미지 생성 가이드](https://ai.google.dev/gemini-api/docs/generate-content/image-generation)
* [Google 출시 기록](https://ai.google.dev/gemini-api/docs/changelog)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.