Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions .vitepress/theme/OfficialNativeApiSidebar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ const googleModels = [
text: 'Gemini Omni 1.1 Flash Preview',
link: '/model-api-reference/official-native-api/google/gemini-omni-1.1-flash-preview',
},
{
text: 'Nano Banana Pro',
link: '/model-api-reference/official-native-api/google/gemini-3-pro-image',
},
{
text: 'Nano Banana 2',
link: '/model-api-reference/official-native-api/google/gemini-3.1-flash-image',
},
]

function normalize(path: string) {
Expand Down
22 changes: 20 additions & 2 deletions api-reference/gemini-generate-content.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,24 @@ curl -N -X POST \
-d '{"contents":[{"role":"user","parts":[{"text":"Write a short greeting."}]}]}'
```

## Translation boundaries
## Native image generation

SandBase accepts text, function calls and responses, inline `image/*` data, and public HTTP(S) image references. Unsupported inline MIME types, private Google Files or `gs://` references, multiple candidates, and non-text response modalities are rejected with a Google-style `400 INVALID_ARGUMENT` response instead of being silently discarded.
These image models have dedicated native GenerateContent mappings:

- [Nano Banana Pro (Gemini 3 Pro Image)](/model-api-reference/official-native-api/google/gemini-3-pro-image)
- [Nano Banana 2 (Gemini 3.1 Flash Image)](/model-api-reference/official-native-api/google/gemini-3.1-flash-image)

For these mappings, SandBase forwards the request and response payloads without converting them through Chat
Completions. This preserves image parts, response modalities, and provider-defined fields. Use the bare model name in
the URL; for example, `google/gemini-3.1-flash-image` becomes `gemini-3.1-flash-image` in the path.

## Routing and translation boundaries

SandBase selects only providers that support the requested native Gemini protocol. If the selected model has no
compatible native mapping, the request fails instead of falling back to a provider with a different protocol.

Models that use the translated GenerateContent path support text, function calls and responses, inline `image/*` data,
and public HTTP(S) image references. That translated path rejects unsupported inline MIME types, private Google Files or
`gs://` references, multiple candidates, and unsupported response modalities with a Google-style `400 INVALID_ARGUMENT`
response. The image-generation mappings listed above use raw passthrough and are not subject to those translation-only
limits; validate the returned media fields according to the selected provider's response.
12 changes: 12 additions & 0 deletions api-reference/gemini-interactions.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ apiReference:

Use `x-goog-api-key`, `Authorization: Bearer …`, or the `key` query parameter, in that priority order. Prefer a header because query-string credentials can be logged.

## Supported models

The Interactions endpoint is not a generic route for every model whose catalog name starts with `google/`. The model
must have an Interactions-compatible provider mapping. SandBase currently documents these compatible models:

- [Gemini Omni Flash Preview](/model-api-reference/official-native-api/google/gemini-omni-flash-preview)
- [Gemini Omni 1.1 Flash Preview](/model-api-reference/official-native-api/google/gemini-omni-1.1-flash-preview)

Use the endpoint documented on each model page. For example, Nano Banana Pro and Nano Banana 2 use
`/v1beta/models/{model}:generateContent`, not `/v1beta/interactions`. An unsupported model fails instead of being routed
through a different Google protocol.

## Success and polling

Successful submissions return HTTP `200`, including background work and synchronous requests whose bounded wait expires. Always inspect `status`:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
---
title: "Nano Banana Pro Native API Reference"
description: "Native Gemini GenerateContent API reference for google/gemini-3-pro-image (Nano Banana Pro) on SandBase."
aside: false
outline: false
apiReference:
title: Nano Banana Pro (Gemini 3 Pro Image)
operation: Gemini GenerateContent
method: POST
path: /v1beta/models/gemini-3-pro-image:generateContent
description: Generate or edit images with Nano Banana Pro through the native Google Gemini protocol. SandBase preserves the provider request and response payload instead of converting it to Chat Completions.
groups:
- title: Request body
description: Send a native Gemini GenerateContent body. Provider-defined fields are passed through for this model.
fields:
- { name: contents, type: array, required: true, description: Gemini Content objects containing the prompt and optional input images. }
- { name: generationConfig.responseModalities, type: "array<string>", required: true, description: "Requested output modalities. Include IMAGE; include TEXT when you also want a text part." }
- { name: generationConfig.imageConfig, type: object, required: false, description: "Image options such as aspectRatio, when supported by the provider." }
examples:
- label: cURL
language: bash
code: |-
curl -X POST \
"https://api.sandbase.ai/v1beta/models/gemini-3-pro-image:generateContent" \
-H "x-goog-api-key: $SANDBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{
"role": "user",
"parts": [{"text": "Create a studio product photo of a translucent blue perfume bottle on white marble."}]
}],
"generationConfig": {
"responseModalities": ["TEXT", "IMAGE"],
"imageConfig": {"aspectRatio": "1:1"}
}
}'
response:
status: 200 OK
code: |-
{
"candidates": [{
"content": {
"role": "model",
"parts": [
{"text": "Here is the generated image."},
{"inlineData": {"mimeType": "image/png", "data": "<base64-image>"}}
]
},
"finishReason": "STOP",
"index": 0
}],
"usageMetadata": {"totalTokenCount": 1290}
}
seo:
modelName: "Nano Banana Pro (Gemini 3 Pro Image)"
modelId: "google/gemini-3-pro-image"
vendor: "Google"
vendorSlug: "google"
modelSlug: "gemini-3-pro-image"
protocol: "Gemini GenerateContent API"
endpoint: "/v1beta/models/gemini-3-pro-image:generateContent"
publishedAt: "2026-08-31T00:00:00Z"
capabilities: ["image_generation", "image_editing"]
category: "Official Native API"
---

<ApiReferencePage />

## Edit an image

Add the source image as an `inlineData` part next to the text instruction. Use the MIME type of the bytes you send:

```json
{
"contents": [{
"role": "user",
"parts": [
{"text": "Replace the background with a warm sunset gradient."},
{"inlineData": {"mimeType": "image/jpeg", "data": "<base64-input-image>"}}
]
}],
"generationConfig": {"responseModalities": ["IMAGE"]}
}
```

## Response handling

Read generated media from the returned candidate parts. Because this model uses native passthrough, provider-defined
field casing and MIME metadata are returned as received. Decode the base64 payload and verify the actual media bytes
before choosing a file extension.

## Official Google resources

- [Gemini API documentation](https://ai.google.dev/gemini-api/docs)
- [Image generation documentation](https://ai.google.dev/gemini-api/docs/image-generation)
- [GenerateContent API reference](https://ai.google.dev/api/generate-content)
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
---
title: "Nano Banana 2 Native API Reference"
description: "Native Gemini GenerateContent API reference for google/gemini-3.1-flash-image (Nano Banana 2) on SandBase."
aside: false
outline: false
apiReference:
title: Nano Banana 2 (Gemini 3.1 Flash Image)
operation: Gemini GenerateContent
method: POST
path: /v1beta/models/gemini-3.1-flash-image:generateContent
description: Generate or edit images with Nano Banana 2 through the native Google Gemini protocol. SandBase preserves the provider request and response payload instead of converting it to Chat Completions.
groups:
- title: Request body
description: Send a native Gemini GenerateContent body. Provider-defined fields are passed through for this model.
fields:
- { name: contents, type: array, required: true, description: Gemini Content objects containing the prompt and optional input images. }
- { name: generationConfig.responseModalities, type: "array<string>", required: true, description: "Requested output modalities. Include IMAGE; include TEXT when you also want a text part." }
- { name: generationConfig.imageConfig, type: object, required: false, description: "Image options such as aspectRatio, when supported by the provider." }
examples:
- label: cURL
language: bash
code: |-
curl -X POST \
"https://api.sandbase.ai/v1beta/models/gemini-3.1-flash-image:generateContent" \
-H "x-goog-api-key: $SANDBASE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{
"role": "user",
"parts": [{"text": "Create a wide editorial illustration of a solar-powered city at sunrise."}]
}],
"generationConfig": {
"responseModalities": ["IMAGE"],
"imageConfig": {"aspectRatio": "16:9"}
}
}'
response:
status: 200 OK
code: |-
{
"candidates": [{
"content": {
"role": "model",
"parts": [
{"inline_data": {"mime_type": "image/png", "data": "<base64-image>"}}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Use camelCase for Gemini response media fields

Clients following this response example will look for inline_data.mime_type, but GenerateContent JSON uses inlineData.mimeType, as shown by the request on this page, the companion Gemini 3 Pro Image response, and the shared OpenAPI schema. Since this page documents native Gemini passthrough, use the actual camelCase response keys so copied parsing code can find and decode the returned image.

Useful? React with 👍 / 👎.

]
},
"finishReason": "STOP",
"index": 0
}],
"usageMetadata": {"totalTokenCount": 980}
}
seo:
modelName: "Nano Banana 2 (Gemini 3.1 Flash Image)"
modelId: "google/gemini-3.1-flash-image"
vendor: "Google"
vendorSlug: "google"
modelSlug: "gemini-3.1-flash-image"
protocol: "Gemini GenerateContent API"
endpoint: "/v1beta/models/gemini-3.1-flash-image:generateContent"
publishedAt: "2026-08-31T00:00:00Z"
capabilities: ["image_generation", "image_editing"]
category: "Official Native API"
---

<ApiReferencePage />

## Edit an image

Add the source image as an `inlineData` part next to the text instruction. Use the MIME type of the bytes you send:

```json
{
"contents": [{
"role": "user",
"parts": [
{"text": "Keep the subject unchanged and turn the background into a paper-cut landscape."},
{"inlineData": {"mimeType": "image/png", "data": "<base64-input-image>"}}
]
}],
"generationConfig": {"responseModalities": ["IMAGE"]}
}
```

## Response handling

Read generated media from the returned candidate parts. Because this model uses native passthrough, provider-defined
field casing and MIME metadata are returned as received. Decode the base64 payload and verify the actual media bytes
before choosing a file extension.

## Official Google resources

- [Gemini API documentation](https://ai.google.dev/gemini-api/docs)
- [Image generation documentation](https://ai.google.dev/gemini-api/docs/image-generation)
- [GenerateContent API reference](https://ai.google.dev/api/generate-content)
11 changes: 9 additions & 2 deletions model-api-reference/official-native-api/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@ description: Use official provider-native protocols through SandBase, organized
# Official Native API

Official Native APIs preserve a provider's request and response protocol for easier migration of existing integrations.
Browse by provider, then choose the exact model. SandBase currently documents native protocols for ByteDance, Google Gemini Omni, and OpenAI; other LLMs are documented in the LLM Models section because their provider-native protocol is the default model interface.
Browse by provider, then choose the exact model. SandBase currently documents native protocols for ByteDance, Google,
and OpenAI. Models listed here have a dedicated provider-native request path; other LLMs remain in the LLM Models
section.

## OpenAI

Expand All @@ -23,8 +25,13 @@ GPT Image 2 uses the native OpenAI Images API at `/v1/images/generations`. Pass

- [Gemini Omni Flash Preview](/model-api-reference/official-native-api/google/gemini-omni-flash-preview)
- [Gemini Omni 1.1 Flash Preview](/model-api-reference/official-native-api/google/gemini-omni-1.1-flash-preview)
- [Nano Banana Pro (Gemini 3 Pro Image)](/model-api-reference/official-native-api/google/gemini-3-pro-image)
- [Nano Banana 2 (Gemini 3.1 Flash Image)](/model-api-reference/official-native-api/google/gemini-3.1-flash-image)

Gemini Omni models use the native Google Gemini Interactions protocol at `/v1beta/interactions`.
Gemini Omni models use the native Google Gemini Interactions protocol at `/v1beta/interactions`. The two image models
use Google GenerateContent at `/v1beta/models/{model}:generateContent`; their native request and response payloads are
passed through without conversion. See the [GenerateContent protocol reference](/api-reference/gemini-generate-content)
for authentication and shared request fields.

## Seedance protocol

Expand Down
12 changes: 7 additions & 5 deletions public/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,8 @@ paths:
Accepts a Google Gemini GenerateContent request and returns a Gemini-compatible response. A bare model name,
such as gemini-3.5-flash, is normalized to the SandBase catalog name google/gemini-3.5-flash. This endpoint
also accepts x-goog-api-key and the key query parameter for Google SDK compatibility, although headers are safer.
Models with a native passthrough mapping preserve provider-defined request and response fields, including image
response modalities. Other mappings may use the translated capability subset documented in the schema below.
security:
- GoogleApiKey: []
- BearerAuth: []
Expand All @@ -464,14 +466,14 @@ paths:
schema: { $ref: '#/components/schemas/GeminiGenerateContentRequest' }
responses:
'200': { description: Gemini GenerateContent response, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiGenerateContentResponse' } } } }
'400': { description: Invalid JSON or an input field that SandBase cannot safely translate, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'400': { description: Invalid JSON or a request rejected by the selected native or translated mapping, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'401': { description: 'Missing, invalid, revoked, or expired API key', content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'402': { description: Organization balance and credit are exhausted, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'403': { description: 'API Key spending limit reached, organization disabled, or upstream permission rejected', content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'404': { description: 'Model, method, or upstream resource not found', content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'429': { description: Provider rate limit exceeded, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'500': { description: Prediction lifecycle or provider error, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'502': { description: Upstream response could not be translated, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'502': { description: Upstream response failed or could not be processed, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'503': { description: Routing failed or all provider candidates were unavailable, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }
'504': { description: Upstream request timed out, content: { application/json: { schema: { $ref: '#/components/schemas/GeminiError' } } } }

Expand Down Expand Up @@ -3976,7 +3978,7 @@ components:
GeminiGenerateContentRequest:
type: object
additionalProperties: true
description: Google Gemini GenerateContent request. Unknown top-level fields are ignored by the current translator.
description: Google Gemini GenerateContent request. Native passthrough mappings preserve provider-defined fields; translated mappings use the documented capability subset.
properties:
contents:
type: array
Expand All @@ -3992,7 +3994,7 @@ components:
topK: { type: integer }
maxOutputTokens: { type: integer }
stopSequences: { type: array, items: { type: string } }
candidateCount: { type: integer, description: The current translator accepts only 1 when supplied. }
candidateCount: { type: integer, description: Translated mappings accept only 1 when supplied; native passthrough mappings preserve the provider request. }
seed: { type: integer }
presencePenalty: { type: number }
frequencyPenalty: { type: number }
Expand All @@ -4001,7 +4003,7 @@ components:
responseModalities:
type: array
items: { type: string }
description: The current translator supports TEXT only.
description: Native image mappings support provider image modalities. Other translated mappings may support TEXT only.
thinkingConfig: { type: object, additionalProperties: true }
tools:
type: array
Expand Down
11 changes: 11 additions & 0 deletions scripts/validate-doc-content.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,17 @@ const geminiOmniReference = readFileSync('model-api-reference/official-native-ap
assert.match(geminiOmniReference, /path\\?\":\\?\"\/v1beta\/interactions/, 'Gemini Omni must use the native Interactions endpoint')
assert.doesNotMatch(geminiOmniReference, /path\\?\":\\?\"\/v1\/chat\/completions/, 'Gemini Omni must not advertise Chat Completions')

const geminiInteractionsReference = readFileSync('api-reference/gemini-interactions.md', 'utf8')
assert.match(geminiInteractionsReference, /not a generic route for every model/, 'Gemini Interactions must not imply support for every Google model')
assert.match(geminiInteractionsReference, /Nano Banana Pro and Nano Banana 2 use\s+`\/v1beta\/models\/\{model\}:generateContent`/, 'Gemini Interactions must direct image models to GenerateContent')

for (const filename of ['gemini-3-pro-image.md', 'gemini-3.1-flash-image.md']) {
const geminiImageReference = readFileSync(`model-api-reference/official-native-api/google/${filename}`, 'utf8')
assert.match(geminiImageReference, /path:\s*\/v1beta\/models\//, `${filename} must use the native GenerateContent endpoint`)
assert.match(geminiImageReference, /:generateContent/, `${filename} must document the GenerateContent action`)
assert.doesNotMatch(geminiImageReference, /path:\s*\/v1\/chat\/completions/, `${filename} must not advertise Chat Completions`)
}

const runReference = readFileSync('api-reference/models/run.md', 'utf8')
assert.doesNotMatch(runReference, /webhook_url[^\n]*API tasks/i, 'Run reference must not promise callbacks for API capabilities')
assert.match(runReference, /webhook_url[^\n]*image, video, or audio tasks/i, 'Run reference must match webhook capability scope')
Expand Down
Loading