SDK quickstart
Generate, edit, stream images, and call text models with the google-genai SDK.
This guide uses Google’s official Python SDK. The only Moonez.ai-specific step is
overriding base_url. See Gemini-compatible API for the concept.
You’ll need an active API key with permission for the model you call. See Authentication.
1. Install and configure
Section titled “1. Install and configure”pip install google-genaiPoint the client at Moonez.ai and pass your API key:
from google import genaifrom google.genai import types
client = genai.Client( api_key="YOUR_MOONEZ_API_KEY", http_options=types.HttpOptions( base_url="https://api.moonez.ai/api/gemini", ),)Any Gemini client works the same way — set the base URL to
https://api.moonez.ai/api/gemini and send your key as x-goog-api-key.
2. Text-to-image
Section titled “2. Text-to-image”Request the IMAGE modality and read the base64 image from the first candidate.
resp = client.models.generate_content( model="gemini-2.5-flash-image", contents="a red panda astronaut floating in a nebula", config=types.GenerateContentConfig( response_modalities=["IMAGE"], image_config=types.ImageConfig( aspect_ratio="16:9", ), ),)
image = resp.candidates[0].content.parts[0].inline_data.data # raw PNG bytesopen("out.png", "wb").write(image)The response is standard Gemini JSON. The image is base64 in
candidates[0].content.parts[0].inlineData.data.
3. Resolution
Section titled “3. Resolution”For gemini-3.1-flash-image and gemini-3-pro-image, select the output size with imageSize — 1K, 2K, 4K,
plus 512px on gemini-3.1-flash-image:
config = types.GenerateContentConfig( response_modalities=["IMAGE"], image_config=types.ImageConfig( aspect_ratio="1:1", image_size="2K", ),)imageSize is validated by the model — supported values are 1K, 2K, 4K (plus
512px on gemini-3.1-flash-image); anything else returns 400 INVALID_ARGUMENT. gemini-2.5-flash-image
(gemini-2.5-flash-image) outputs 1K only. Sizes below 1K (e.g. 512px) are
billed at the 1K rate.
4. Image-to-image (edit)
Section titled “4. Image-to-image (edit)”Pass one or more input images plus an instruction in contents:
from pathlib import Path
resp = client.models.generate_content( model="gemini-3-pro-image", contents=[ types.Part.from_bytes( data=Path("input.png").read_bytes(), mime_type="image/png", ), "add a tiny astronaut helmet", ], config=types.GenerateContentConfig(response_modalities=["IMAGE"]),)
open("edited.png", "wb").write(resp.candidates[0].content.parts[0].inline_data.data)5. Streaming
Section titled “5. Streaming”streamGenerateContent returns real SSE frames — the same format the SDK consumes:
for chunk in client.models.generate_content_stream( model="gemini-3.6-flash", contents="Write a haiku about servers.",): if chunk.text: print(chunk.text, end="")The final chunk carries usageMetadata with the exact token counts your balance is
charged against.
6. Text generation
Section titled “6. Text generation”Text models are billed per token and called exactly like Google’s own API:
resp = client.models.generate_content( model="gemini-3.5-flash", contents="Explain quantum computing in one sentence.",)print(resp.text)7. Count tokens
Section titled “7. Count tokens”countTokens is proxied to Google for a real token count — no charge:
resp = client.models.count_tokens( model="gemini-3.5-flash", contents="How many tokens is this?",)print(resp.total_tokens)8. Handle errors
Section titled “8. Handle errors”Gemini-compatible errors use Google’s standard status envelope. The most common ones:
| Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_ARGUMENT |
Unsupported imageSize, malformed request, etc. |
| 403 | PERMISSION_DENIED |
Key lacks permission for the requested model |
| 404 | NOT_FOUND |
Unknown model ID |
| 429 | RESOURCE_EXHAUSTED |
Rate limit reached |
Retry with backoff on transient failures; use the SDK’s built-in retry configuration for resilience.