docs
API

Gemini generateContent

Markdown

Formato nativo do Google Gemini: para Gemini CLI, Google GenAI SDK e clientes REST.

Guia completo
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": "Crie três nomes para um café."}]}
    ]
  }' 
200 OK
{
  "candidates": [
    {
      "content": {
        "role": "model",
        "parts": [{ "text": "1. «Grão e Vapor» 2. «Moagem Matinal» 3. «Café da Esquina»" }]
      },
      "finishReason": "STOP"
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 9,
    "candidatesTokenCount": 27,
    "totalTokenCount": 36
  },
  "modelVersion": "gemini-3.8-flash"
}

Autorização

  • x-goog-api-keyheaderobrigatório

    Chave sk-…. Também são aceites Authorization: Bearer ou x-api-key. Para compatibilidade com o Google, também é aceite ?key= no endereço — com a prioridade mais baixa; ?api_key= é rejeitado com 400. Recomendamos o cabeçalho: assim, a chave não fica nos registos.

Caminho

  • modelstringobrigatório

    ID de um modelo com o formato Gemini, por exemplo gemini-3.8-flash ou gemini-3.1-pro. No total, 27.

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

Corpo do pedido

  • contentsarrayobrigatório

    Mensagens com role (user/model) e parts: text, inlineData/fileData, functionCall/functionResponse. Os anexos têm de ser de tipos aceites pelo modelo como entrada.

  • systemInstructionobjectopcional

    Instrução de sistema em texto: {"parts": [{"text": "…"}]}.

  • generationConfigobjectopcional

    generationConfig aceita temperature, topP, topK, maxOutputTokens, thinkingConfig, responseMimeType (text/plain ou application/json), responseSchema ou responseJsonSchema (objeto JSON), stopSequences (array de cadeias de caracteres), candidateCount: 1, um inteiro seed, os valores numéricos presencePenalty e frequencyPenalty. Os intervalos e as capacidades permitidos dependem do modelo exato; para uma resposta JSON, escolha uma forma de esquema suportada e application/json. Nos modelos de texto, responseModalities — apenas ["TEXT"].

  • safetySettingsarrayopcional

    Objetos com os campos obrigatórios category e threshold, o campo opcional method. Os valores têm de ser suportados pelo modelo exato.

  • toolsarrayopcional

    As functionDeclarations do cliente são executadas pela sua aplicação. Os modelos de texto também aceitam {"googleSearch": {}} e {"urlContext": {}}: em separado ou em conjunto no array tools. Nem Google Search nem URL context podem ser combinados com functionDeclarations no mesmo pedido. Para imagens na saída, apenas estão disponíveis funções do cliente. As outras ferramentas incorporadas e a cache explícita não são suportadas. Search/URL context podem exigir uma reserva com base no limite total de entrada; os valores efetivos de toolUsePromptTokenCount são contabilizados como tokens de entrada.

  • toolConfigobjectopcional

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

Se o modelo não suportar um campo, um anexo ou uma combinação de ferramentas, o pedido é rejeitado antes da reserva — não há qualquer débito. Receberá HTTP 400 com status INVALID_ARGUMENT e a classe invalid_request (em ErrorInfo.reason — INVALID_REQUEST). JSON inválido, erros nos parâmetros do caminho e noutras validações também devolvem 400; leia o texto do erro e o Request ID. As capacidades dependem do modelo: consulte os seus formatos e entradas no catálogo.

PDF, áudio, vídeo e ligações

Nos modelos Gemini que suportam o tipo de entrada correspondente, parts[].inlineData contém mimeType e dados base64 não vazios; o PDF tem de ser um PDF válido. fileData contém um endereço público httpsno campo fileUri e o MIME do tipo de ficheiro. Para YouTube, pode omitir o MIME. http, endereços privados, gs:// e objetos Google Files API não são suportados, tal como o carregamento através da Google Files API. Para vídeo, pode acrescentar videoMetadata: startOffset/endOffset como cadeia de caracteres em segundos (por exemplo, 1.5s) e fps superior a 0 e não superior a 24. O tamanho do corpo, o contexto, a entrada permitida e o limite de resposta são validados de acordo com o modelo e o formato.

EntradaTipos MIME suportados
Imagens inlineimage/png, image/jpeg, image/webp
Documentosapplication/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
Áudioaudio/wav, audio/mp3, audio/mpeg, audio/aiff, audio/aac, audio/ogg, audio/flac
Vídeovideo/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"},
    )
    # Envie uma única vez. Em caso de timeout, consulte o ID do pedido no histórico de utilização antes de tentar novamente.
    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

# Indique um ficheiro local real em formato PDF, áudio ou vídeo e o respetivo tipo MIME suportado.
path, mime = pathlib.Path(sys.argv[1]), sys.argv[2]
payload = {"contents": [{"role": "user", "parts": [
    {"text": "Descreva brevemente o conteúdo do ficheiro."},
    {"inlineData": {"mimeType": mime,
                    "data": base64.b64encode(path.read_bytes()).decode()}},
]}]}
print(generate("gemini-3.8-flash", payload))
# Anexo alternativo: {"fileData": {"mimeType": mime, "fileUri": public_https_url}}
# Para um URL real do YouTube: {"fileData": {"fileUri": youtube_url}}

Search e URL context

As functionDeclarations do cliente são executadas pela sua aplicação. Os modelos de texto também aceitam {"googleSearch": {}} e {"urlContext": {}}: em separado ou em conjunto no array tools. Nem Google Search nem URL context podem ser combinados com functionDeclarations no mesmo pedido. Para imagens na saída, apenas estão disponíveis funções do cliente. As outras ferramentas incorporadas e a cache explícita não são suportadas. Search/URL context podem exigir uma reserva com base no limite total de entrada; os valores efetivos de toolUsePromptTokenCount são contabilizados como tokens de entrada.

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

Imagens na saída

Apenas o modelo seguinte suporta imagens nas respostas em formato Gemini: gemini-3.1-flash-image. Esta capacidade é distinta de /v1/images/generations: os outros modelos de imagem não funcionam aqui. Este modelo aceita até 131072 tokens de entrada e até 32768 de resposta; o custo total da resposta mais longa é reservado antecipadamente.

responseModalities — conjunto não vazio de TEXT/IMAGE sem repetições. 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. A entrada deste modelo é texto e PNG/JPEG/WebP inline; PDF/audio/video/fileData e Search/URL context incorporados não são aceites aqui. A disponibilidade e os preços para a sua chave estão no catálogo e em 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"},
    )
    # Envie uma única vez. Em caso de timeout, consulte o ID do pedido no histórico de utilização antes de tentar novamente.
    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": "Aguarela: um farol ao amanhecer"}]}],
    "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)

Ciclo completo de function calling

As funções são executadas pelo cliente. Devolva todo o content original do modelo com thoughtSignature sem alterações, seguido de functionResponse com o mesmo name e id, caso este exista em 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"},
    )
    # Envie uma única vez. Em caso de timeout, consulte o ID do pedido no histórico de utilização antes de tentar novamente.
    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": "Multiplicar dois números",
    "parameters": {"type": "object", "properties": {
        "a": {"type": "number"}, "b": {"type": "number"}},
        "required": ["a", "b"]},
}]}]
contents = [{"role": "user", "parts": [{"text": "Multiplique 7 por 8 com a função"}]}]
for turn in range(4):  # Limite o ciclo de ferramentas; não volte a enviar um pedido cujo resultado não esteja claro.
    reply = generate("gemini-3.8-flash", {"contents": contents, "tools": tools})
    content = reply["candidates"][0]["content"]
    contents.append(content)  # Mantenha todas (ALL) as partes originais e thoughtSignature sem alterações.
    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")

Resposta

  • candidates[].content.partsarray

    Resposta do modelo.

  • usageMetadataobject

    promptTokenCount, candidatesTokenCount, totalTokenCount.

Ainda tem dúvidas? Envie o Request ID e uma descrição — ajudamos a esclarecer.Contactar o suporte