Permalink to Gemini nativeGemini native
Some projects are written against Google's native API rather than the OpenAI shape: contents
instead of messages, parts instead of content, usageMetadata instead of usage. Rewriting
that to fit an OpenAI client is work you should not have to do, so hypit.ai serves the native format
directly.
POST https://hypit.ai/v1beta/models/{model}:{action}Note this is /v1beta, not /v1. The body is forwarded to Google byte for byte and the
response comes back untouched.
Permalink to actionsActions
Exactly three are supported:
| Action | Behaviour |
|---|---|
generateContent | buffered JSON response |
streamGenerateContent | SSE by default; ?alt=json returns Google's JSON array of frames |
countTokens | buffered, and not billed |
Anything else — embedContent, batchEmbedContents, predict, file uploads — is
404 unsupported_action. Only POST is routed; a GET to this path is a plain 404.
curl "https://hypit.ai/v1beta/models/gemini-3.1-pro:generateContent" \
-H "x-goog-api-key: $HYPIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"contents": [{"parts": [{"text": "What is Hypit? One sentence."}]}]
}'Streaming:
curl -N "https://hypit.ai/v1beta/models/gemini-3.1-pro:streamGenerateContent?alt=sse" \
-H "x-goog-api-key: $HYPIT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contents": [{"parts": [{"text": "Write a haiku about a paper boat."}]}]}'streamGenerateContent with no alt parameter defaults to alt=sse, matching Google. There is
no [DONE] sentinel on this surface — Google does not send one, and adding it would make the
official SDK try to decode it as a GenerateContentResponse.
Permalink to authenticationAuthentication
The same hypit.ai sk-hh- key as everywhere else, in any of the places a Google client puts it:
-H "x-goog-api-key: $HYPIT_API_KEY" # what the GenAI SDKs send
-H "Authorization: Bearer $HYPIT_API_KEY"
"…:generateContent?key=$HYPIT_API_KEY" # the REST spellingWhichever you use, the credential is stripped from the query string before we forward the request —
key, api_key, apikey and access_token are removed. Every other query parameter is passed
through.
Permalink to pointing-the-google-sdks-herePointing the Google SDKs here
import os
from google import genai
client = genai.Client(
api_key=os.environ["HYPIT_API_KEY"],
http_options={"base_url": "https://hypit.ai"},
)
response = client.models.generate_content(
model="gemini-3.1-pro",
contents="What is Hypit? One sentence.",
)
print(response.text)import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({
apiKey: process.env.HYPIT_API_KEY,
httpOptions: { baseUrl: "https://hypit.ai" },
});
const response = await ai.models.generateContent({
model: "gemini-3.1-pro",
contents: "What is Hypit? One sentence.",
});
console.log(response.text);The base URL here is the origin, without /v1beta — the SDK appends the version segment itself.
Permalink to model-names-with-a-colonModel names with a colon
Google's URLs put the action after a literal colon inside the last path segment. We split on the last colon, so a model name that itself contains one still resolves:
/v1beta/models/tunedModels/my-tune:generateContent → model "tunedModels/my-tune"A percent-encoded %3A is decoded when no literal colon is present.
Permalink to which-modelsWhich models
A model is reachable here when its card lists gemini in endpoints:
curl -s https://hypit.ai/v1/models \
-H "Authorization: Bearer $HYPIT_API_KEY" |
jq -r '.data[] | select(.endpoints[] == "gemini") | .id'Many of these models are reachable on /v1/chat/completions too — the same model card usually lists
both chat and gemini. Pick whichever wire format your code already speaks; billing is identical.
Permalink to errorsErrors
Errors come back in the OpenAI envelope, not Google's
Google returns {"error": {"code": 400, "message": "…", "status": "INVALID_ARGUMENT"}}. hypit.ai
returns its own shape on every surface, including this one:
{
"error": {
"message": "action \"embedContent\" is not supported; use generateContent, streamGenerateContent or countTokens",
"type": "not_found_error",
"code": "unsupported_action",
"param": null
}
}A Google SDK will see an unfamiliar error body. Handle non-2xx responses yourself rather than relying on the SDK's error parsing.
| Status | code | Meaning |
|---|---|---|
404 | unknown_route | the path is not /v1beta/models/{model}:{action} |
404 | unsupported_action | not one of the three actions above |
400 | bad_request_body | a body was sent that is not a JSON object |
413 | request_too_large | over 32 MiB |
502 | empty_stream | the upstream produced no frames |
Everything in Errors and limits applies here too — this route sits behind
the same authentication, rate limiting and credit gate as /v1.