SDK quickstart
These examples use the official google-genai Python SDK and a Moonez.ai key
with permission for the selected model. See Authentication
and the Gemini-compatible API overview.
1. Install and configure
Section titled “1. Install and configure”pip install --upgrade google-genaiexport MOONEZ_API_KEY="YOUR_MOONEZ_API_KEY"import os
from google import genaifrom google.genai import types
client = genai.Client( api_key=os.environ["MOONEZ_API_KEY"], http_options=types.HttpOptions( base_url="https://api.moonez.ai/api/gemini/v1beta", base_url_resource_scope=types.ResourceScope.COLLECTION, ),)The base URL already includes /v1beta. ResourceScope.COLLECTION prevents the
SDK from adding the version again. This is the Google SDK’s supported
custom base URL configuration.
In Android apps and other clients with a custom Gemini provider, enter
https://api.moonez.ai/api/gemini/v1beta in the Base URL field and use your
Moonez.ai key. Requests should target /api/gemini/v1beta/models/...,
without a duplicate /v1beta.
2. Text-to-image: Nano Banana 2.1
Section titled “2. Text-to-image: Nano Banana 2.1”from pathlib import Path
response = client.models.generate_content( model="gemini-nano-banana-2.1", contents="Draw a red panda astronaut against a nebula.", config=types.GenerateContentConfig(response_modalities=["IMAGE"]),)
for part in response.candidates[0].content.parts: if part.inline_data: Path("out.png").write_bytes(part.inline_data.data) breakIn JSON, the image is base64-encoded in inlineData.data within one of the
response parts. The Python SDK already returns inline_data.data as bytes.
The image is not necessarily the first part; if generation is blocked, the
provider may not return an image at all.
This example omits aspectRatio; Moonez.ai does not add it automatically.
Nano Banana 2 Lite: 1K output
Section titled “Nano Banana 2 Lite: 1K output”Use gemini-3.1-flash-lite-image with a key that has its separate model permission.
It supports 1K output only and has its own tariff:
response = client.models.generate_content( model="gemini-3.1-flash-lite-image", contents="A ceramic cup in soft studio lighting.", config=types.GenerateContentConfig( response_modalities=["IMAGE"], image_config=types.ImageConfig(image_size="1K"), ),)Read image bytes from the response parts as in the example above. Do not use 2K or 4K for this model. For a native job, see the Lite reference.
3. Size and aspect ratio
Section titled “3. Size and aspect ratio”To set them explicitly, pass this config to generate_content:
config = types.GenerateContentConfig( response_modalities=["IMAGE"], image_config=types.ImageConfig( aspect_ratio="16:9", image_size="2K", ),)Nano Banana 2.1, gemini-3.1-flash-image, and gemini-3-pro-image support
1K, 2K, and 4K. gemini-3.1-flash-image also supports 512px;
gemini-2.5-flash-image outputs 1K. 512px is billed at the 1K rate.
gemini-3.1-flash-lite-image is also 1K only.
The provider validates the supplied parameters.
4. Image-to-image: editing
Section titled “4. Image-to-image: editing”Pass an image and an instruction in contents:
from pathlib import Path
response = client.models.generate_content( model="gemini-nano-banana-2.1", 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"]),)
for part in response.candidates[0].content.parts: if part.inline_data: Path("edited.png").write_bytes(part.inline_data.data) break5. Streaming: Gemini 3.8 Flash
Section titled “5. Streaming: Gemini 3.8 Flash”The SDK reads the SSE stream returned by streamGenerateContent:
for chunk in client.models.generate_content_stream( model="gemini-3.8-flash", contents="Write a haiku about servers.",): if chunk.text: print(chunk.text, end="")When the provider returns usageMetadata, those confirmed counters are used
to calculate the text generation cost.
6. Text generation: Gemini 4 Argon
Section titled “6. Text generation: Gemini 4 Argon”response = client.models.generate_content( model="gemini-4-argon", contents="Explain quantum computing in one sentence.",)print(response.text)7. Count tokens
Section titled “7. Count tokens”countTokens requests a token count from the provider and is free of charge
on Moonez.ai. Availability depends on the model and provider.
response = client.models.count_tokens( model="gemini-4-argon", contents="How many tokens is this?",)print(response.total_tokens)8. List models
Section titled “8. List models”for model in client.models.list(): print(model.name)GET /models returns the image, text, and Omni models permitted by your key,
without pagination. It excludes Veo, which uses the asynchronous
video API.
See the complete model catalog for all 18 IDs.
9. Handle errors
Section titled “9. Handle errors”Errors use the standard Gemini structure:
| HTTP status | Code | Meaning |
|---|---|---|
| 400 | INVALID_ARGUMENT | Invalid request parameters |
| 403 | PERMISSION_DENIED | The key lacks permission for the model |
| 404 | NOT_FOUND | Model or method not found |
| 429 | RESOURCE_EXHAUSTED | Request or quota limit reached |
| 503 | UNAVAILABLE | Service temporarily unavailable |
Use retries with increasing delays for transient errors. You can configure them using the SDK’s built-in retry options.