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.

text
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:

ActionBehaviour
generateContentbuffered JSON response
streamGenerateContentSSE by default; ?alt=json returns Google's JSON array of frames
countTokensbuffered, 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.

bash
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:

bash
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:

bash
-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 spelling

Whichever 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

python
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)
js
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:

text
/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:

bash
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:

json
{
  "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.

StatuscodeMeaning
404unknown_routethe path is not /v1beta/models/{model}:{action}
404unsupported_actionnot one of the three actions above
400bad_request_bodya body was sent that is not a JSON object
413request_too_largeover 32 MiB
502empty_streamthe 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.