docs
API

Gemini generateContent

Markdown

Format natif de Google Gemini : pour Gemini CLI, le SDK Google GenAI et les clients REST.

Guide complet
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": "Propose trois noms pour un café."}]}
    ]
  }' 
200 OK
{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [{ "text": "1. « Grain et vapeur » 2. « La mouture du matin » 3. « Le café du coin »" }]
      },
      "finishReason": "STOP"
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 9,
    "candidatesTokenCount": 27,
    "totalTokenCount": 36
  },
  "modelVersion": "gemini-3.8-flash"
}

Authentification

  • x-goog-api-keyheaderobligatoire

    Clé sk-…. Conviennent également Authorization: Bearer ou x-api-key. Pour assurer la compatibilité avec Google, le paramètre ?key= est aussi accepté dans l’URL, avec la priorité la plus faible ; ?api_key= est rejeté avec le statut 400. Nous recommandons de transmettre la clé dans un en-tête pour qu’elle n’apparaisse pas dans les journaux.

Chemin

  • modelstringobligatoire

    ID d’un modèle prenant en charge le format Gemini, par exemple gemini-3.8-flash ou gemini-3.1-pro. Il y en a 27 au total.

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

Corps de la requête

  • contentsarrayobligatoire

    Messages avec role (user/model) et parts : text, inlineData/fileData, functionCall/functionResponse. Les pièces jointes doivent correspondre aux entrées acceptées par le modèle.

  • systemInstructionobjectfacultatif

    Instruction système textuelle : {"parts": [{"text": "…"}]}.

  • generationConfigobjectfacultatif

    generationConfig accepte temperature, topP, topK, maxOutputTokens, thinkingConfig, responseMimeType (text/plain ou application/json), responseSchema ou responseJsonSchema (objet JSON), stopSequences (tableau de chaînes), candidateCount: 1, le paramètre entier seed, les paramètres numériques presencePenalty et frequencyPenalty. Les plages autorisées et les capacités dépendent du modèle exact ; pour une réponse JSON, choisissez une seule représentation de schéma prise en charge et application/json. Pour les modèles textuels, responseModalities — uniquement ["TEXT"].

  • safetySettingsarrayfacultatif

    Objets avec les champs obligatoires category et threshold, le champ facultatif method. Les valeurs doivent être prises en charge par le modèle exact.

  • toolsarrayfacultatif

    Les fonctions déclarées côté client dans functionDeclarations sont exécutées par votre application. Les modèles textuels acceptent aussi {"googleSearch": {}} et {"urlContext": {}} : séparément ou ensemble dans le tableau tools. Ni Google Search ni URL context ne peuvent être combinés avec functionDeclarations dans une même requête. Pour les images en sortie, seules les fonctions clientes sont disponibles. Les autres outils intégrés et le cache explicite (explicit cache) ne sont pas pris en charge. Search/URL context peuvent exiger une réservation correspondant à la limite maximale d’entrée ; les valeurs réelles toolUsePromptTokenCount sont comptées comme tokens d’entrée.

  • toolConfigobjectfacultatif

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

Si le modèle ne prend pas en charge un champ, une pièce jointe ou une combinaison d’outils, la requête est rejetée avant la réservation, sans débit. Vous recevrez un statut HTTP 400 avec status INVALID_ARGUMENT et la classe invalid_request (dans ErrorInfo.reason — INVALID_REQUEST). Un JSON incorrect, des erreurs de paramètres de chemin ou d’autres validations renvoient aussi 400; lisez le message d’erreur et le Request ID. Les capacités dépendent du modèle : vérifiez ses formats et les entrées acceptées dans le catalogue.

PDF, audio, vidéo et liens

Pour les modèles Gemini prenant en charge l’entrée concernée, parts[].inlineData contient mimeType et des données base64 non vides ; le PDF doit être un véritable fichier PDF. fileData contient une URL publique https dans fileUri et le type MIME du fichier. Pour YouTube, le MIME peut être omis. http, les adresses privées, gs:// et les objets Google Files API ne sont pas pris en charge, pas plus que l’envoi de fichiers via Google Files API. Pour une vidéo, vous pouvez ajouter videoMetadata : startOffset/endOffset sous forme de chaîne exprimée en secondes (par exemple, 1.5s) et fps supérieur à 0 et inférieur ou égal à 24. La taille du corps, le contexte, l’entrée autorisée et la limite de réponse sont vérifiés selon le modèle et le format.

EntréeTypes MIME pris en charge
Images intégrées (inline)image/png, image/jpeg, image/webp
Documentsapplication/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
Vidéovideo/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"},
    )
    # Un seul envoi. En cas de dépassement du délai, vérifiez le Request ID dans votre historique d’utilisation avant de réessayer.
    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

# Fournissez un fichier PDF, audio ou vidéo local réel, avec son type MIME pris en charge.
path, mime = pathlib.Path(sys.argv[1]), sys.argv[2]
payload = {"contents": [{"role": "user", "parts": [
    {"text": "Décris brièvement le contenu du fichier."},
    {"inlineData": {"mimeType": mime,
                    "data": base64.b64encode(path.read_bytes()).decode()}},
]}]}
print(generate("gemini-3.8-flash", payload))
# Autre pièce jointe : {"fileData": {"mimeType": mime, "fileUri": public_https_url}}
# Pour une URL YouTube réelle : {"fileData": {"fileUri": youtube_url}}

Search et URL context

Les fonctions déclarées côté client dans functionDeclarations sont exécutées par votre application. Les modèles textuels acceptent aussi {"googleSearch": {}} et {"urlContext": {}} : séparément ou ensemble dans le tableau tools. Ni Google Search ni URL context ne peuvent être combinés avec functionDeclarations dans une même requête. Pour les images en sortie, seules les fonctions clientes sont disponibles. Les autres outils intégrés et le cache explicite (explicit cache) ne sont pas pris en charge. Search/URL context peuvent exiger une réservation correspondant à la limite maximale d’entrée ; les valeurs réelles toolUsePromptTokenCount sont comptées comme tokens d’entrée.

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

Images en sortie

Seul le modèle suivant peut produire des images dans une réponse au format Gemini : gemini-3.1-flash-image. Cette capacité est distincte de /v1/images/generations : les autres modèles d’image ne fonctionnent pas ici. Ce modèle accepte jusqu’à 131072 tokens en entrée et 32768 en réponse ; le coût total de la réponse la plus longue est réservé à l’avance.

responseModalities — ensemble non vide de TEXT/IMAGE, sans doublons. 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. Ce modèle accepte du texte et des images inline PNG/JPEG/WebP. PDF/audio/video/fileData et les outils intégrés Search/URL context ne sont pas acceptés ici. La disponibilité et les prix pour votre clé figurent dans le catalogue et dans 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"},
    )
    # Un seul envoi. En cas de dépassement du délai, vérifiez le Request ID dans votre historique d’utilisation avant de réessayer.
    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": "Aquarelle : un phare à l’aube"}]}],
    "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)

Cycle complet d’appel de fonctions (function calling)

Les fonctions sont exécutées par le client. Renvoyez l’intégralité du content d’origine du modèle, y compris thoughtSignature, sans modification, puis functionResponse avec les mêmes name et id, si cet id figurait dans functionCall.

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"},
    )
    # Un seul envoi. En cas de dépassement du délai, vérifiez le Request ID dans votre historique d’utilisation avant de réessayer.
    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": "Multiplier deux nombres",
    "parameters": {"type": "object", "properties": {
        "a": {"type": "number"}, "b": {"type": "number"}},
        "required": ["a", "b"]},
}]}]
contents = [{"role": "user", "parts": [{"text": "Multiplie 7 par 8 à l’aide de la fonction"}]}]
for turn in range(4):  # Limitez la boucle d’outils ; ne renvoyez pas une requête dont le résultat est incertain.
    reply = generate("gemini-3.8-flash", {"contents": contents, "tools": tools})
    content = reply["candidates"][0]["content"]
    contents.append(content)  # Conservez TOUTES (ALL) les parties (parts) d’origine et thoughtSignature sans les modifier.
    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")

Réponse

  • candidates[].content.partsarray

    Réponse du modèle.

  • usageMetadataobject

    promptTokenCount, candidatesTokenCount, totalTokenCount.

Encore des questions ? Envoyez le Request ID et une description : nous vous aiderons à l’analyser.Contacter l’assistance