Gemini 4 Argon Beta supports text chat, streaming and Low / Medium / High thinking levels; Low is the default. Use the OpenAI SDK. Thinking tokens are billed as output.
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://kovapi.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-4-argon", "messages": [{"role": "user", "content": "Explain photosynthesis in one sentence"}]}'Response (HTTP 200)
{
"id": "chatcmpl-7f3c9a1e2b4d6f8a",
"object": "chat.completion",
"created": 1791281400,
"model": "gemini-4-argon",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Photosynthesis is how plants use sunlight to turn carbon dioxide and water into sugar, releasing oxygen.",
"reasoning_content": "..."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 18,
"completion_tokens": 186,
"total_tokens": 204,
"prompt_tokens_details": {"cached_tokens": 0},
"completion_tokens_details": {"reasoning_tokens": 144}
}
}message.content is the answer and message.reasoning_content the thinking. usage holds the tokens this request is billed for: thinking tokens are part of completion_tokens and bill at the output price.
Step 2 · Stream the answer (recommended)
curl -N https://kovapi.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-4-argon", "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://kovapi.com/v1", api_key="YOUR_API_KEY")
# 1. One request, one answer
resp = client.chat.completions.create(
model="gemini-4-argon",
messages=[{"role": "user", "content": "Explain photosynthesis in one sentence"}],
)
print(resp.choices[0].message.content)
# 2. Streaming
stream = client.chat.completions.create(
model="gemini-4-argon",
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 shared by input and output | About 1M tokens |
| Input | Text |
| Thinking | Choose low / medium / high; default: low. All levels use the same token rates. |
| 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-4-argon. |
| messages | array | Yes | The conversation: each message has a role (system, user, assistant or tool) and content. 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 | Requested output length, including thinking. This Beta does not guarantee a strict output cap. Constrain length in the prompt and split work to manage costs. |
| temperature / top_p | number | No | Sampling parameters may be supplied; their control effects have not been separately verified in this Beta. |
| reasoning_effort | string | No | Choose low / medium / high; default: low. All levels use the same token rates. |
| web_search | boolean | No | true runs a web search first and hands the results to the model as reference; see below. |
Start with the parameters listed here. Function calling, multimodal input and JSON mode are not currently promised; for web search, see the Web search section below.
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.50 | 100 |
| Output (thinking included) | $3.00 | 600 |
| Cache hit | $0.05 | 10 |
For example, a request with 2,000 input tokens and 1,000 output tokens (thinking included) costs about $0.004.
Thinking
Set reasoning_effort to low, medium or high; omitted values default to low.
Visible thinking is returned in reasoning_content. usage.completion_tokens includes thinking and answer tokens; do not add thinking tokens a second time.
All levels have the same rates. Higher thinking effort may consume more output tokens.
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).
{
"model": "gemini-4-argon",
"messages": [{"role": "user", "content": "Explain photosynthesis in one sentence"}],
"reasoning_effort": "medium"
}Prompt caching
Automatic implicit caching is supported. Repeated long inputs may hit the cache; actual hits cost one tenth of the normal input rate. Repetition does not guarantee a hit, and explicit cache creation is not provided.
usage.prompt_tokens is total input. usage.prompt_tokens_details.cached_tokens is the cached portion of that total. Only actual hits use the cached rate.
Web search
Web search on Gemini 4 Argon uses Google Search: add "web_search": true to the request, or pass {"type": "web_search"} in tools. Sources come back in message.annotations (when streaming, in delta.annotations of the last chunk) in OpenAI's url_citation format, and the number of searches actually run is in usage.server_tool_use.web_search_requests. Each search costs $0.0035 on top of the normal token charge; the model decides whether and how often to search.
curl https://kovapi.com/v1/chat/completions \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "gemini-4-argon", "web_search": true, "messages": [{"role": "user", "content": "What are the main tech news stories today"}]}'Beta limits
- Text chat, streaming, three thinking levels and Google Search have been verified. Function calling, multimodal input and JSON mode remain unverified.
- The official context is about 1M tokens shared by input and output. Long-input retrieval has passed testing; the full window and million-token output have not been tested.
- Split long tasks.
max_tokensis not a verified hard budget limit. Failed requests are not billed; interrupted requests that produced output settle at actual usage.
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. |
| 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 | The model is at capacity 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 | The upstream timed out, including taking too long to send the first token. | Retry; use stream: true for long answers. |
| 502 | upstream_unavailable | The upstream 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. |
| 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.