Gemini 3.8 Flash chat API (Google), the 3.8-generation Flash, built for long-running coding, agent workflows and complex reasoning. Dynamic thinking (quick on easy questions, deeper on hard ones), a context window of about 1M tokens, up to 64K output, image input. OpenAI SDK compatible.
📥 Context window (max input):~1,000,000 tokens (million-token long context).
Try in Playground →Quick start
Two steps: send a request, then stream the answer. Replace YOUR_API_KEY with your key and the commands below run as they are. The endpoint matches OpenAI Chat Completions, so existing OpenAI code only needs a new base_url and model.
Step 1 · Send a request
curl https://nezhagate.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.8-flash", "messages": [{"role": "user", "content": "Explain photosynthesis in one sentence"}]}'Response (HTTP 200)
{
"id": "chatcmpl-7f3c9a1e2b4d6f8a",
"object": "chat.completion",
"created": 1791281400,
"model": "gemini-3.8-flash",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Photosynthesis is how plants use sunlight to turn carbon dioxide and water into sugar, releasing oxygen."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 18,
"completion_tokens": 42,
"total_tokens": 60,
"prompt_tokens_details": {"cached_tokens": 0}
}
}message.content is the answer. usage holds the tokens this request is billed for; prompt_tokens_details.cached_tokens is the part served from the cache and billed at the cache price.
Step 2 · Stream the answer (recommended)
curl -N https://nezhagate.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.8-flash", "stream": true, "messages": [{"role": "user", "content": "Explain photosynthesis in one sentence"}]}'The stream is standard SSE: each chunk carries text in choices[0].delta.content, the last chunk carries usage, and it ends with data: [DONE]. Stream long answers and thinking models: a non-streaming request is cut off after about 10 minutes.
Python (OpenAI SDK)
from openai import OpenAI
client = OpenAI(base_url="https://nezhagate.com/v1", api_key="YOUR_API_KEY")
# 1. One request, one answer
resp = client.chat.completions.create(
model="gemini-3.8-flash",
messages=[{"role": "user", "content": "Explain photosynthesis in one sentence"}],
)
print(resp.choices[0].message.content)
# 2. Streaming
stream = client.chat.completions.create(
model="gemini-3.8-flash",
messages=[{"role": "user", "content": "Explain photosynthesis in one sentence"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)Authentication
Authorization: Bearer YOUR_API_KEY Content-Type: application/json
Create an API Key in the console to start.
At a glance
| Context window | ~1,000,000 tokens |
| Max output per request | 64K tokens |
| Input | Text, images |
| Thinking | Dynamic: the model decides how much to think |
| Tool calling | Not guaranteed: tools may be ignored and the model answers directly |
| Web search | Yes (web_search: true; the search itself is free) |
| Endpoints | /v1/chat/completions |
| Streaming | Yes (stream: true, SSE) |
| Billing | Per token: input, output (thinking included) and cache hits each have a price; failures are free |
Request parameters
The JSON body of POST /v1/chat/completions, the same as OpenAI Chat Completions. The common parameters, and what each one does on this model:
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | Yes | The model id: gemini-3.8-flash. |
| messages | array | Yes | The conversation: each message has a role (system, user, assistant or tool) and content. content is a string, or an array of text and image_url parts (image input, see below). For multi-turn chat, send the whole history in order. |
| stream | boolean | No | true streams the answer as SSE, with usage in the last chunk. Defaults to false. |
| max_tokens | integer | No | The output cap, thinking tokens included. Set too low, the model can spend it all before writing the answer: the gateway then returns 400 max_tokens_too_small and bills nothing (512 or more is recommended). On some models a value that is too small is raised to a floor that leaves room for a full answer, still billed on actual usage only. |
| temperature / top_p | number | No | Sampling parameters, passed to the model as sent (temperature from 0 to 2). Thinking models may not follow them. |
| web_search | boolean | No | true runs a web search first and hands the results to the model as reference; see below. |
Other OpenAI parameters (such as stop, seed, user) are passed to the model as sent; whether they take effect is up to the model.
Price
Billed per token at the live rates below (per million tokens). Only successful requests are billed, on actual usage: failures, timeouts and refusals are free. 1 credit = $0.005.
| Type | USD / 1M tokens | Credits / 1M tokens |
|---|---|---|
| Input | $0.60 | 120 |
| Output (thinking included) | $3.60 | 720 |
| Cache hit | $0.06 | 12 |
For example, a request with 2,000 input tokens and 1,000 output tokens (thinking included) costs about $0.0048.
Thinking
Dynamic thinking: the model decides how much to think per question, quick on easy ones and deeper on hard ones, with no extra parameter. Thinking tokens count against the output budget, so do not set max_tokens too low.
Thinking tokens are part of usage.completion_tokens and bill at the output price (some models also break them out in completion_tokens_details.reasoning_tokens).
Prompt caching
No parameter needed: a repeated long prefix (the same system prompt, the earlier turns of a conversation) may be cached by the model provider automatically, and the cached part bills at the lower cache price. Whether and how much is cached is up to the provider; keep the parts that never change at the start of the messages for the best hit rate.
The cached token count comes back in usage.prompt_tokens_details.cached_tokens; that part bills at the cache-hit price and the rest of the input at the input price.
Image input
Put an image_url part in the content array. A base64 data URI (data:image/png;base64,...) is the recommended form and every line can read it; a public image link has to be downloaded by the line, and an occasional line cannot fetch it or times out. Images count as input tokens by the provider rules.
curl https://nezhagate.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.8-flash", "messages": [{"role": "user", "content": [{"type": "text", "text": "What is in this image"}, {"type": "image_url", "image_url": {"url": "data:image/png;base64,iVBORw0KGgo..."}}]}]}'Web search
Add "web_search": true to the request (or a {"type": "web_search"} entry in tools): the gateway first searches the live web based on the conversation, hands up to 5 results with their links to the model as reference, and the model answers and cites its sources. The search itself is free; the reference text bills as input tokens.
curl https://nezhagate.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-3.8-flash", "web_search": true, "messages": [{"role": "user", "content": "What are the main tech news stories today"}]}'Lines and reliability
- Every model runs on several lines. When one errors, times out or is full, the gateway moves to the next line before anything is returned, so you need not retry and are never billed twice.
- Once a stream starts sending, it stays on its line: if it breaks partway, you are billed for the usage produced up to that point (see Billing and refunds).
- When every line is full the gateway returns 429 with
Retry-After; wait that many seconds and retry. Failed requests are not billed. Each model status is on the status page.
Errors and refunds
Errors come back as an error object (message, type, code, param); decide by the HTTP status and code, never by matching the text of message. Failed requests are not billed; the full list is in Error codes.
| HTTP | code | Cause | What to do |
|---|---|---|---|
| 400 | invalid_messages / invalid_role / invalid_max_tokens | A chat request's messages is missing, empty or malformed, a role is not one of the allowed values, or max_tokens is not a positive integer. param names the field. | Fix the field named in param. |
| 400 | model_not_found | The model id is misspelled, model is missing, or the model cannot be used on this endpoint (a chat model on the image endpoint, for example). | Use a model id from GET /v1/models or the API reference. |
| 400 | max_tokens_too_small | A reasoning model spent all of max_tokens thinking and wrote no answer (non-streaming chat). | Raise max_tokens and retry. |
| 400 | content_filter | The model processed the request but returned nothing, usually because the content tripped the provider's safety policy. | Adjust the prompt and retry; the same prompt is usually refused again. |
| 4xx | invalid_request | The model provider rejected the request (an over-long context or an unsupported parameter, for example); the status and message are passed on as the provider sent them, and code is the provider's value. | Change the request as message says. |
| 401 | invalid_api_key | The key does not exist, was deleted or is disabled, or the account is disabled. | Check the key on the API Keys page of the console. |
| 402 | insufficient_quota | Not enough balance to hold this request. The gateway holds the highest possible cost of the request first, so a burst of concurrent calls can trigger it too. | After a burst, wait a few seconds and retry; otherwise top up. |
| 403 | permission_denied | The model is not on the key's model allowlist. | Use a model on the allowlist, or edit the allowlist in the console. |
| 429 | rate_limit_exceeded | Over the requests-per-minute limit set on this key (counted over the last 60 seconds). No Retry-After header. | Wait a few seconds and retry, or raise the key's limit in the console. |
| 429 | rate_limit_exceeded | Every line for this model is busy and the request was not sent. Chat endpoints only: image and video jobs are never refused but queue instead. The OpenAI-compatible endpoints add Retry-After. | Wait the seconds in Retry-After, then retry. |
| 502 | upstream_timeout | A line timed out, including taking too long to send the first token. | Retry; use stream: true for long answers. |
| 502 | upstream_unavailable | A line failed or is unavailable for the moment. | Retry shortly. |
| 502 | upstream_busy | The model provider is rate-limiting. A provider's 429 is never passed on as a 429; you get this 502 instead. | Retry shortly. |
| 502 | empty_completion | The model provider returned empty content. This is not a judgement of your content. | Retry. |
| 502 | upstream_prompt_filter | The provider's pre-check stopped the prompt. This is not a judgement by the model. | Retry shortly, or reword slightly. |
| 503 | model_maintenance | The model is under maintenance and takes no requests; no other model answers in its place meanwhile. | Retry when maintenance ends; see Status. |
If a stream fails after it started sending, the status code stays as it was: the error arrives as a data line carrying error, or the stream just ends (without data: [DONE]). Treat it as interrupted.