docs
API

Gemini generateContent

Markdown

Het native Google Gemini-formaat: voor Gemini CLI, Google GenAI SDK en REST-clients.

Volledige gids
POSThttps://api.ailoot.ai/v1beta/models/{model}:generateContent
Gemini generateContent
curl "https://api.ailoot.ai/v1beta/models/gemini-3.8-flash:generateContent" \
  -H "x-goog-api-key: $AILOOT_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "contents": [
      {"role": "user", "parts": [{"text": "Bedenk drie namen voor een koffiebar."}]}
    ]
  }' 
200 OK
{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [{ "text": "1. «Boon en stoom» 2. «De ochtendmaling» 3. «Koffiehuis op de hoek»" }]
      },
      "finishReason": "STOP"
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 9,
    "candidatesTokenCount": 27,
    "totalTokenCount": 36
  },
  "modelVersion": "gemini-3.8-flash"
}

Authenticatie

  • x-goog-api-keyheaderverplicht

    Sleutel sk-…. Ook deze headers werken: Authorization: Bearer of x-api-key. Voor compatibiliteit met Google wordt ook ?key= in het adres geaccepteerd — met de laagste prioriteit; ?api_key= wordt afgewezen met 400. We raden een header aan: zo komt de sleutel niet in de logs terecht.

Pad

  • modelstringverplicht

    Model-ID met het Gemini-formaat, bijvoorbeeld gemini-3.8-flash of gemini-3.1-pro. In totaal 27.

POSThttps://api.ailoot.ai/v1beta/models/{model}:streamGenerateContent?alt=sse
GEThttps://api.ailoot.ai/v1beta/models

Verzoekbody

  • contentsarrayverplicht

    Berichten met role (user/model) en parts: text, inlineData/fileData, functionCall/functionResponse. Alleen bijlagen die het model als invoer ondersteunt.

  • systemInstructionobjectoptioneel

    Systeeminstructie in tekstvorm: {"parts": [{"text": "…"}]}.

  • generationConfigobjectoptioneel

    generationConfig accepteert temperature, topP, topK, maxOutputTokens, thinkingConfig, responseMimeType (text/plain of application/json), responseSchema of responseJsonSchema (JSON-object), stopSequences (array van strings), candidateCount: 1, een geheel getal voor seed, numerieke waarden voor presencePenalty en frequencyPenalty. Toegestane bereiken en mogelijkheden hangen af van het specifieke model; kies voor een JSON-antwoord één ondersteunde schemavorm en application/json. Bij tekstmodellen is responseModalities uitsluitend ["TEXT"].

  • safetySettingsarrayoptioneel

    Objecten met verplichte category en threshold, optionele method. Het specifieke model moet deze waarden ondersteunen.

  • toolsarrayoptioneel

    Clientfuncties in functionDeclarations worden uitgevoerd door je applicatie. Bij tekstmodellen worden ook {"googleSearch": {}} en {"urlContext": {}} geaccepteerd: afzonderlijk of samen in de array tools. Noch Google Search noch URL context kan worden gecombineerd met functionDeclarations in hetzelfde verzoek. Voor afbeeldingen als output zijn alleen clientfuncties beschikbaar. Andere ingebouwde tools en explicit cache worden niet ondersteund. Search/URL context kunnen een reservering vereisen op basis van de volledige invoerlimiet; de daadwerkelijke toolUsePromptTokenCount worden als invoertokens geteld.

  • toolConfigobjectoptioneel

    functionCallingConfig: mode (AUTO/ANY/NONE/VALIDATED/MODE_UNSPECIFIED), allowedFunctionNames.

Als het model een veld, bijlage of combinatie van tools niet ondersteunt, wordt het verzoek vóór de reservering afgewezen — er wordt niets afgeschreven. Je ontvangt HTTP 400 met status INVALID_ARGUMENT en de klasse invalid_request (in ErrorInfo.reason — INVALID_REQUEST). Ongeldige JSON, fouten in padparameters en andere controles geven ook 400 terug; lees de foutmelding en de Request ID. De mogelijkheden hangen af van het model: controleer de formaten en invoertypen in de catalogus.

PDF, audio, video en links

Voor Gemini-modellen die dit invoertype ondersteunen, geldt: parts[].inlineData bevat mimeType en niet-lege base64-data; een PDF moet een echt PDF-bestand zijn. fileData bevat een openbaar https-adres in fileUri en het MIME-type van het bestand. Voor YouTube mag je het MIME-type weglaten. http, niet-openbare adressen, gs:// en Google Files API-objecten worden niet ondersteund; uploaden via Google Files API ook niet. Bij video kun je videoMetadata: startOffset/endOffset toevoegen als string in seconden (bijvoorbeeld 1.5s) en fps moet groter dan 0 en maximaal 24 zijn. De bodygrootte, context, toegestane invoer en antwoordlimiet worden per model en formaat gecontroleerd.

InvoerOndersteunde MIME-typen
Inline-afbeeldingenimage/png, image/jpeg, image/webp
Documentenapplication/pdf; text/plain, text/html, text/css, text/csv, text/xml, text/rtf, text/markdown, text/javascript, application/x-javascript, text/x-python, application/x-python
Audioaudio/wav, audio/mp3, audio/mpeg, audio/aiff, audio/aac, audio/ogg, audio/flac
Videovideo/mp4, video/mpeg, video/mov, video/quicktime, video/avi, video/x-flv, video/mpg, video/webm, video/wmv, video/3gpp
import json, os, urllib.request

def generate(model, payload):
    req = urllib.request.Request(
        "https://api.ailoot.ai/v1beta/models/" + model + ":generateContent",
        data=json.dumps(payload).encode(),
        headers={"x-goog-api-key": os.environ["AILOOT_API_KEY"],
                 "Content-Type": "application/json"},
    )
    # Eén keer versturen. Controleer na een time-out de Request ID in je gebruiksgeschiedenis voordat je opnieuw probeert.
    with urllib.request.urlopen(req, timeout=300) as response:
        print("Request ID:", response.headers.get("X-Request-ID"))
        return json.load(response)

import base64, pathlib, sys

# Geef een echt lokaal PDF-, audio- of videobestand op, met het ondersteunde MIME-type.
path, mime = pathlib.Path(sys.argv[1]), sys.argv[2]
payload = {"contents": [{"role": "user", "parts": [
    {"text": "Beschrijf kort de inhoud van het bestand."},
    {"inlineData": {"mimeType": mime,
                    "data": base64.b64encode(path.read_bytes()).decode()}},
]}]}
print(generate("gemini-3.8-flash", payload))
# Alternatieve bijlage: {"fileData": {"mimeType": mime, "fileUri": public_https_url}}
# Voor een echte YouTube-URL: {"fileData": {"fileUri": youtube_url}}

Search en URL context

Clientfuncties in functionDeclarations worden uitgevoerd door je applicatie. Bij tekstmodellen worden ook {"googleSearch": {}} en {"urlContext": {}} geaccepteerd: afzonderlijk of samen in de array tools. Noch Google Search noch URL context kan worden gecombineerd met functionDeclarations in hetzelfde verzoek. Voor afbeeldingen als output zijn alleen clientfuncties beschikbaar. Andere ingebouwde tools en explicit cache worden niet ondersteund. Search/URL context kunnen een reservering vereisen op basis van de volledige invoerlimiet; de daadwerkelijke toolUsePromptTokenCount worden als invoertokens geteld.

{"tools": [{"googleSearch": {}}, {"urlContext": {}}]}

Afbeeldingen als output

Afbeeldingen in antwoorden in het Gemini-formaat worden alleen ondersteund door gemini-3.1-flash-image. Dit staat los van /v1/images/generations: andere afbeeldingsmodellen werken hier niet. Dit model accepteert maximaal 131072 invoertokens en 32768 antwoordtokens; de volledige kosten van het langst mogelijke antwoord worden vooraf gereserveerd.

responseModalities — een niet-lege verzameling TEXT/IMAGE zonder duplicaten. imageConfig.imageSize: 1K/2K/4K; aspectRatio: 1:1, 2:3, 3:2, 3:4, 4:3, 4:5, 5:4, 9:16, 16:9, 21:9, 1:4, 4:1, 1:8, 8:1. Dit model accepteert tekst en inline PNG/JPEG/WebP als invoer; PDF/audio/video/fileData en ingebouwde Search/URL context worden hier niet geaccepteerd. Beschikbaarheid en prijzen voor jouw sleutel vind je in de catalogus en in GET /v1/models.

import json, os, urllib.request

def generate(model, payload):
    req = urllib.request.Request(
        "https://api.ailoot.ai/v1beta/models/" + model + ":generateContent",
        data=json.dumps(payload).encode(),
        headers={"x-goog-api-key": os.environ["AILOOT_API_KEY"],
                 "Content-Type": "application/json"},
    )
    # Eén keer versturen. Controleer na een time-out de Request ID in je gebruiksgeschiedenis voordat je opnieuw probeert.
    with urllib.request.urlopen(req, timeout=300) as response:
        print("Request ID:", response.headers.get("X-Request-ID"))
        return json.load(response)

import base64, pathlib

reply = generate("gemini-3.1-flash-image", {
    "contents": [{"role": "user", "parts": [{"text": "Aquarel: een vuurtoren bij zonsopgang"}]}],
    "generationConfig": {
        "responseModalities": ["TEXT", "IMAGE"],
        "imageConfig": {"aspectRatio": "1:1", "imageSize": "1K"},
    },
})
index = 0
for candidate in reply.get("candidates", []):
    for part in candidate.get("content", {}).get("parts", []):
        if "text" in part:
            print(part["text"])
        blob = part.get("inlineData", {})
        if blob.get("mimeType", "").startswith("image/") and blob.get("data"):
            index += 1
            extension = {"image/png": "png", "image/jpeg": "jpg",
                         "image/webp": "webp"}.get(blob["mimeType"], "bin")
            pathlib.Path(f"gemini-image-v{index}.{extension}").write_bytes(
                base64.b64decode(blob["data"]))
print("All returned images:", index)

De volledige function calling-cyclus

De client voert de functies uit. Geef de volledige oorspronkelijke content van het model met thoughtSignature ongewijzigd terug, daarna functionResponse met dezelfde name en dezelfde id, als die id in functionCall aanwezig was.

import json, os, urllib.request

def generate(model, payload):
    req = urllib.request.Request(
        "https://api.ailoot.ai/v1beta/models/" + model + ":generateContent",
        data=json.dumps(payload).encode(),
        headers={"x-goog-api-key": os.environ["AILOOT_API_KEY"],
                 "Content-Type": "application/json"},
    )
    # Eén keer versturen. Controleer na een time-out de Request ID in je gebruiksgeschiedenis voordat je opnieuw probeert.
    with urllib.request.urlopen(req, timeout=300) as response:
        print("Request ID:", response.headers.get("X-Request-ID"))
        return json.load(response)

tools = [{"functionDeclarations": [{
    "name": "multiply", "description": "Twee getallen vermenigvuldigen",
    "parameters": {"type": "object", "properties": {
        "a": {"type": "number"}, "b": {"type": "number"}},
        "required": ["a", "b"]},
}]}]
contents = [{"role": "user", "parts": [{"text": "Vermenigvuldig 7 met 8 met behulp van de functie"}]}]
for turn in range(4):  # Beperk de toollus; verstuur een verzoek met een onduidelijk resultaat niet opnieuw.
    reply = generate("gemini-3.8-flash", {"contents": contents, "tools": tools})
    content = reply["candidates"][0]["content"]
    contents.append(content)  # Bewaar ALLE (ALL) oorspronkelijke onderdelen (parts) en thoughtSignature ongewijzigd.
    results = []
    for part in content.get("parts", []):
        call = part.get("functionCall")
        if not call:
            continue
        if call["name"] != "multiply":
            raise ValueError("Unexpected function")
        args = call["args"]
        result = {"name": call["name"], "response": {"value": args["a"] * args["b"]}}
        if "id" in call:
            result["id"] = call["id"]
        results.append({"functionResponse": result})
    if not results:
        print(content)
        break
    contents.append({"role": "user", "parts": results})
else:
    raise RuntimeError("Tool loop limit reached")

Antwoord

  • candidates[].content.partsarray

    Antwoord van het model.

  • usageMetadataobject

    promptTokenCount, candidatesTokenCount, totalTokenCount.

Nog vragen? Stuur de Request ID en een beschrijving — we helpen je verder.Contact opnemen met support