generateContent requests work by changing only the base URL and the key:
POST https://api.omnirelay.ai/v1beta/models/{model}:generateContentreturns the whole answer as JSON.POST https://api.omnirelay.ai/v1beta/models/{model}:streamGenerateContent?alt=ssestreams it as server-sent events.
x-goog-api-key header, as the Gemini SDKs do, or as a Bearer token. The same key rules apply as for every other model: key expiry, IP allowlist, model limits, budgets and rate and concurrency limits. A key in a ?key= query parameter is not read.
Models
Other models answer this route with
unsupported_parameter and nothing is charged. Text-only Gemini calls also work through Chat Completions.
Analyse a video
Put the video in afileData part with a public https URL, followed by your question:
candidates[0].content.parts, and usageMetadata reports the tokens, including promptTokensDetails with the video’s share.
Video input
- By URL:
fileData.fileUrimust be a publichttpsURL the model can download. - Inline: a small clip can go in an
inlineDatapart as base64. The whole request body is limited to 4 MB, so use a URL for anything larger. - Gemini Files API URIs (
generativelanguage.googleapis.com/.../files/...) andcachedContentare not supported.
generateContent request are passed to the model as you send them: systemInstruction, generationConfig (including responseSchema and thinkingConfig), safetySettings, and tools with functionDeclarations plus toolConfig.functionCallingConfig. Use camelCase field names. candidateCount must be 1, a thinkingBudget must fit within maxOutputTokens, and the built-in search, URL context, code execution and file search tools are not available on this route. Do not put model or stream in the body; the path sets both. If you leave out generationConfig.maxOutputTokens, OmniRelay sets the model’s default of 32,000.
Streaming
Use:streamGenerateContent?alt=sse. Each event is a JSON chunk in Gemini’s shape, and every chunk carries the usage so far. The call is charged from the last chunk, after the model reports a finish reason. Streaming is the better choice for long videos: a non-streamed call must answer within 90 seconds, while a stream only needs its first chunk in that time.
Pricing
Video understanding is billed by tokens at the model’s text prices. The video’s frames and audio count as input tokens; the model’s thinking counts as output tokens, as in Google’s own billing. Forgemini-3.1-pro-preview:
A short clip with a detailed JSON answer is typically about USD 0.01–0.02. Your discount applies as for text models.
When the call starts, OmniRelay holds its maximum cost: the text of your request, 131,072 input tokens for each video by URL, and the full
maxOutputTokens plus 1,024 tokens, because a model may finish a few tokens past its limit. You pay only for the tokens reported; the rest of the hold returns to your balance when the call ends. Keep maxOutputTokens near what you need, so the hold stays small. A call whose usage goes well beyond its hold, such as a very long video, is held for review instead of being charged automatically.
The charge for each call is in the X-OmniRelay-Cost-Microusd response header of a non-streamed call, and on the usage page for both.
Errors
Errors come back in Gemini’s shape, so the Gemini SDKs raise them as API errors:code is the HTTP status, status is the OmniRelay error code. If the model cannot fetch or read the video, the call fails with invalid_parameter and nothing is charged. In a stream, a failure arrives as a final event with the same error object.