Gemini-compatible
generateContent
Call models on NoviaHub in the native Gemini format — generateContent and streamGenerateContent URLs, authentication, parameters, response and sample code.
Compatible with the Gemini API’s generateContent; you can use the Google Gen AI SDKs directly.
POST https://noviahub.com/v1beta/models/{model}:generateContentPOST https://noviahub.com/v1beta/models/{model}:streamGenerateContent?alt=sseReplace {model} with a model ID, such as gemini-3-flash. For models whose endpoint labels include Gemini (check on Models & Pricing).
Authentication
Section titled “Authentication”Use any one of these:
| Form | Example |
|---|---|
Header x-goog-api-key |
x-goog-api-key: <your API key> |
Query parameter key |
...:generateContent?key=<your API key> |
Header Authorization |
Authorization: Bearer <your API key> |
Also send Content-Type: application/json.
Request parameters
Section titled “Request parameters”Write the body as defined by Gemini. The table lists the fields NoviaHub recognises and forwards; whether a parameter takes effect depends on the model.
| Parameter | Type | Required | Description |
|---|---|---|---|
contents |
array | Yes | The conversation. Each item has a role (user or model) and parts. |
systemInstruction |
object | No | System instruction, shaped like one item of contents. The snake_case system_instruction is also accepted. |
generationConfig |
object | No | Generation settings; fields below. |
tools |
array | No | Tools (function declarations, search and so on), forwarded as is. |
toolConfig |
object | No | Tool calling settings. |
safetySettings |
array | No | Safety settings. |
cachedContent |
string | No | Use a context cache you created earlier. |
Each item in parts can be text, inlineData (mimeType plus Base64 data, for images and other files), fileData, functionCall, functionResponse and so on.
Fields accepted in generationConfig: temperature, topP, topK, maxOutputTokens, candidateCount, stopSequences, responseMimeType, responseSchema, responseJsonSchema, presencePenalty, frequencyPenalty, seed, responseLogprobs, logprobs, responseModalities, mediaResolution, thinkingConfig (includeThoughts, thinkingBudget, thinkingLevel), speechConfig, imageConfig. The snake_case forms (such as max_output_tokens) are also accepted.
Sample code
Section titled “Sample code”curl "https://noviahub.com/v1beta/models/gemini-3-flash:generateContent" \ -H "x-goog-api-key: $NOVIAHUB_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "contents": [{"parts": [{"text": "Explain what an API is in one sentence."}]}] }'import os
from google import genaifrom google.genai import types
client = genai.Client( api_key=os.environ["NOVIAHUB_API_KEY"], http_options=types.HttpOptions(base_url="https://noviahub.com"),)
response = client.models.generate_content( model="gemini-3-flash", contents="Explain what an API is in one sentence.",)
print(response.text)import { GoogleGenAI } from '@google/genai'
const ai = new GoogleGenAI({ apiKey: process.env.NOVIAHUB_API_KEY, httpOptions: { baseUrl: 'https://noviahub.com' },})
const response = await ai.models.generateContent({ model: 'gemini-3-flash', contents: 'Explain what an API is in one sentence.',})
console.log(response.text)The Google Gen AI SDK’s base URL is just https://noviahub.com; don’t include /v1beta.
Response
Section titled “Response”| Field | Description |
|---|---|
candidates[].content.parts[] |
The reply. Text is in text; images from image models are in inlineData (mimeType plus Base64 data). |
candidates[].finishReason |
Why generation stopped, such as STOP (finished) or MAX_TOKENS (hit the limit). |
usageMetadata.promptTokenCount |
Input tokens. |
usageMetadata.candidatesTokenCount |
Output tokens. |
usageMetadata.totalTokenCount |
Total. |
usageMetadata.thoughtsTokenCount |
Tokens spent on thinking (when the model reports it). |
usageMetadata.cachedContentTokenCount |
Tokens served from cache (when the model reports it). |
modelVersion |
Model version. |
responseId |
ID of this reply. |
{ "candidates": [ { "content": { "role": "model", "parts": [{ "text": "Hello from the mock upstream." }] }, "finishReason": "STOP", "index": 0 } ], "usageMetadata": { "promptTokenCount": 12, "candidatesTokenCount": 7, "totalTokenCount": 19 }, "modelVersion": "gemini-3-flash", "responseId": "mock-resp-123"}When you call a non-Gemini model here (through protocol conversion), the response also contains safetyRatings (an empty array) and some internal fields in usageMetadata; you can ignore them.
Streaming
Section titled “Streaming”Use streamGenerateContent and add ?alt=sse to the URL. The response arrives as SSE; each data: piece has the same structure as above, with text arriving piece by piece in candidates[0].content.parts[0].text. The last piece carries finishReason and the full usageMetadata.
In our tests NoviaHub answered with SSE even without ?alt=sse. Add it anyway so every client behaves the same.
data: {"candidates":[{"content":{"role":"model","parts":[{"text":"Hello"}]},"index":0}],"usageMetadata":{"promptTokenCount":12,"totalTokenCount":12},"modelVersion":"gemini-3-flash","responseId":"mock-resp-123"}
data: {"candidates":[{"content":{"role":"model","parts":[{"text":" from the mock upstream."}]},"finishReason":"STOP","index":0}],"usageMetadata":{"promptTokenCount":12,"candidatesTokenCount":7,"totalTokenCount":19},"modelVersion":"gemini-3-flash","responseId":"mock-resp-123"}curl "https://noviahub.com/v1beta/models/gemini-3-flash:streamGenerateContent?alt=sse" \ -H "x-goog-api-key: $NOVIAHUB_API_KEY" \ -H "Content-Type: application/json" \ -N \ -d '{"contents": [{"parts": [{"text": "Write a four-line poem."}]}]}'import os
from google import genaifrom google.genai import types
client = genai.Client( api_key=os.environ["NOVIAHUB_API_KEY"], http_options=types.HttpOptions(base_url="https://noviahub.com"),)
for chunk in client.models.generate_content_stream( model="gemini-3-flash", contents="Write a four-line poem.",): print(chunk.text or "", end="", flush=True)import { GoogleGenAI } from '@google/genai'
const ai = new GoogleGenAI({ apiKey: process.env.NOVIAHUB_API_KEY, httpOptions: { baseUrl: 'https://noviahub.com' },})
const stream = await ai.models.generateContentStream({ model: 'gemini-3-flash', contents: 'Write a four-line poem.',})
for await (const chunk of stream) { process.stdout.write(chunk.text ?? '')}Generating images
Section titled “Generating images”Gemini image models (such as gemini-3.1-flash-image) use this endpoint too. Put the image model’s ID in {model}; the generated image is in inlineData in the response. Decode data from Base64 and save it as a file of the given mimeType. These models can’t be called through /v1/images/generations; see Image generation.
Not supported
Section titled “Not supported”:countTokens(token counting) is not available and returns 404.
Common errors
Section titled “Common errors”| HTTP status | Cause |
|---|---|
| 400 | The body isn’t valid JSON. |
| 401 | The key is invalid, disabled, expired or out of quota, or it was sent in the wrong place. |
| 403 | The key isn’t allowed to use this model, the IP isn’t on the allow list, or the account balance is too low. |
| 503 | Wrong model ID, or no channel is currently available for the model. |
Errors use the OpenAI shape ({"error": {...}}); see API overview · Error format. See Errors and troubleshooting for details.