SPB Git

Repository Public

batch-api.md 80.7 KB 2,112 lines markdown

1> [!NOTE]2> **Note:** This feature is currently only available with the generateContent API. Please follow the content on this page for more information.34The Gemini Batch API is designed to process large volumes of requests5asynchronously at [50% of the standard cost](https://ai.google.dev/gemini-api/docs/pricing).6The target turnaround time is 24 hours, but in majority of cases, it is much7quicker.89Use Batch API for large-scale, non-urgent tasks such as data10pre-processing or running evaluations where an immediate response is not11required.1213## Creating a batch job1415You have two ways to submit your requests in Batch API:1617- **[Inline requests](https://ai.google.dev/gemini-api/docs/batch-api#inline-requests):** A list of [`GenerateContentRequest`](https://ai.google.dev/api/batch-mode#GenerateContentRequest) objects directly included in your batch creation request. This is suitable for smaller batches that keep the total request size under 20MB. The **output** returned from the model is a list of `inlineResponse` objects.18- **[Input file](https://ai.google.dev/gemini-api/docs/batch-api#input-file):** A [JSON Lines (JSONL)](https://jsonlines.org/) file where each line contains a complete [`GenerateContentRequest`](https://ai.google.dev/api/batch-mode#GenerateContentRequest) object. This method is recommended for larger requests. The **output** returned from the model is a JSONL file where each line is either a `GenerateContentResponse` or a status object.1920### Inline requests2122For a small number of requests, you can directly embed the23[`GenerateContentRequest`](https://ai.google.dev/api/batch-mode#GenerateContentRequest) objects24within your [`BatchGenerateContentRequest`](https://ai.google.dev/api/batch-mode#request-body). The25following example calls the26[`BatchGenerateContent`](https://ai.google.dev/api/batch-mode#google.ai.generativelanguage.v1beta.BatchService.BatchGenerateContent)27method with inline requests:2829### Python303132    from google import genai33    from google.genai import types3435    client = genai.Client()3637    # A list of dictionaries, where each is a GenerateContentRequest38    inline_requests = [39        {40            'contents': [{41                'parts': [{'text': 'Tell me a one-sentence joke.'}],42                'role': 'user'43            }]44        },45        {46            'contents': [{47                'parts': [{'text': 'Why is the sky blue?'}],48                'role': 'user'49            }]50        }51    ]5253    inline_batch_job = client.batches.create(54        model="gemini-3.8-flash",55        src=inline_requests,56        config={57            'display_name': "inlined-requests-job-1",58        },59    )6061    print(f"Created batch job: {inline_batch_job.name}")6263### JavaScript646566    import {GoogleGenAI} from '@google/genai';6768    const ai = new GoogleGenAI({});6970    const inlinedRequests = [71        {72            contents: [{73                parts: [{text: 'Tell me a one-sentence joke.'}],74                role: 'user'75            }]76        },77        {78            contents: [{79                parts: [{'text': 'Why is the sky blue?'}],80                role: 'user'81            }]82        }83    ]8485    const response = await ai.batches.create({86        model: 'gemini-3.8-flash',87        src: inlinedRequests,88        config: {89            displayName: 'inlined-requests-job-1',90        }91    });9293    console.log(response);9495### Java9697    import java.util.Arrays;98    import com.google.genai.Client;99    import com.google.genai.types.BatchJob;100    import com.google.genai.types.BatchJobSource;101    import com.google.genai.types.Content;102    import com.google.genai.types.CreateBatchJobConfig;103    import com.google.genai.types.InlinedRequest;104    import com.google.genai.types.Part;105    import java.util.List;106107    Client client = new Client();108109    // A list of InlinedRequest objects110    List<InlinedRequest> inlineRequests =111        Arrays.asList(112            InlinedRequest.builder()113                .contents(114                    Arrays.asList(115                        Content.builder()116                            .role("user")117                            .parts(Arrays.asList(Part.fromText("Tell me a one-sentence joke.")))118                            .build()))119                .build(),120            InlinedRequest.builder()121                .contents(122                    Arrays.asList(123                        Content.builder()124                            .role("user")125                            .parts(Arrays.asList(Part.fromText("Why is the sky blue?")))126                            .build()))127                .build());128129    BatchJobSource src = BatchJobSource.builder().inlinedRequests(inlineRequests).build();130    CreateBatchJobConfig config =131        CreateBatchJobConfig.builder().displayName("inlined-requests-job-1").build();132133    BatchJob inlineBatchJob = client.batches.create("gemini-3.8-flash", src, config);134135    System.out.println("Created batch job: " + inlineBatchJob.name().orElse(""));136137### REST138139    curl https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:batchGenerateContent \140    -H "x-goog-api-key: $GEMINI_API_KEY" \141    -X POST \142    -H "Content-Type:application/json" \143    -d '{144        "batch": {145            "display_name": "my-batch-requests",146            "input_config": {147                "requests": {148                    "requests": [149                        {150                            "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]},151                            "metadata": {152                                "key": "request-1"153                            }154                        },155                        {156                            "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]},157                            "metadata": {158                                "key": "request-2"159                            }160                        }161                    ]162                }163            }164        }165    }'166167### Input file168169For larger sets of requests, prepare a JSON Lines (JSONL) file. Each line in170this file must be a JSON object containing a user-defined key and a request171object, where the request is a valid172[`GenerateContentRequest`](https://ai.google.dev/api/batch-mode#GenerateContentRequest) object. The173user-defined key is used in the response to indicate which output is the result174of which request. For example, the request with the key defined as `request-1`175will have its response annotated with the same key name.176177This file is uploaded using the [File API](https://ai.google.dev/gemini-api/docs/files). The maximum178allowed file size for an input file is 2GB.179180The following is an example of a JSONL file. You can save it in a file named181`my-batch-requests.json`:182183    {"key": "request-1", "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}], "generation_config": {"temperature": 0.7}}}184    {"key": "request-2", "request": {"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}}185186Similarly to inline requests, you can specify other parameters like system187instructions, tools or other configurations in each request JSON.188189You can upload this file using the [File API](https://ai.google.dev/gemini-api/docs/files) as190shown in the following example. If191you are working with multimodal input, you can reference other uploaded files192within your JSONL file.193194### Python195196197    import json198    from google import genai199    from google.genai import types200201    client = genai.Client()202203    # Create a sample JSONL file204    with open("my-batch-requests.jsonl", "w") as f:205        requests = [206            {"key": "request-1", "request": {"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}]}},207            {"key": "request-2", "request": {"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}}208        ]209        for req in requests:210            f.write(json.dumps(req) + "\n")211212    # Upload the file to the File API213    uploaded_file = client.files.upload(214        file='my-batch-requests.jsonl',215        config=types.UploadFileConfig(display_name='my-batch-requests', mime_type='jsonl')216    )217218    print(f"Uploaded file: {uploaded_file.name}")219220### JavaScript221222223    import {GoogleGenAI} from '@google/genai';224    import * as fs from "fs";225    import * as path from "path";226    import { fileURLToPath } from 'url';227228    const ai = new GoogleGenAI({});229    const fileName = "my-batch-requests.jsonl";230231    // Define the requests232    const requests = [233        { "key": "request-1", "request": { "contents": [{ "parts": [{ "text": "Describe the process of photosynthesis." }] }] } },234        { "key": "request-2", "request": { "contents": [{ "parts": [{ "text": "What are the main ingredients in a Margherita pizza?" }] }] } }235    ];236237    // Construct the full path to file238    const __filename = fileURLToPath(import.meta.url);239    const __dirname = path.dirname(__filename);240    const filePath = path.join(__dirname, fileName); // __dirname is the directory of the current script241242    async function writeBatchRequestsToFile(requests, filePath) {243        try {244            // Use a writable stream for efficiency, especially with larger files.245            const writeStream = fs.createWriteStream(filePath, { flags: 'w' });246247            writeStream.on('error', (err) => {248                console.error(`Error writing to file ${filePath}:`, err);249            });250251            for (const req of requests) {252                writeStream.write(JSON.stringify(req) + '\n');253            }254255            writeStream.end();256257            console.log(`Successfully wrote batch requests to ${filePath}`);258259        } catch (error) {260            // This catch block is for errors that might occur before stream setup,261            // stream errors are handled by the 'error' event.262            console.error(`An unexpected error occurred:`, error);263        }264    }265266    // Write to a file.267    writeBatchRequestsToFile(requests, filePath);268269    // Upload the file to the File API.270    const uploadedFile = await ai.files.upload({file: 'my-batch-requests.jsonl', config: {271        mimeType: 'jsonl',272    }});273    console.log(uploadedFile.name);274275### Java276277    import java.util.Arrays;278    import com.google.genai.Client;279    import com.google.genai.types.File;280    import com.google.genai.types.UploadFileConfig;281    import java.nio.file.Files;282    import java.nio.file.Paths;283    import java.util.List;284285    Client client = new Client();286287    // Create a sample JSONL file288    List<String> requests =289        Arrays.asList(290            "{\"key\": \"request-1\", \"request\": {\"contents\": [{\"parts\": [{\"text\": \"Describe the process of photosynthesis.\"}]}]}}",291            "{\"key\": \"request-2\", \"request\": {\"contents\": [{\"parts\": [{\"text\": \"What are the main ingredients in a Margherita pizza?\"}]}]}}");292    Files.write(Paths.get("my-batch-requests.jsonl"), requests);293294    // Upload the file to the File API295    UploadFileConfig uploadConfig =296        UploadFileConfig.builder()297            .displayName("my-batch-requests")298            .mimeType("jsonl")299            .build();300    File uploadedFile = client.files.upload("my-batch-requests.jsonl", uploadConfig);301302    System.out.println("Uploaded file: " + uploadedFile.name().orElse(""));303304### REST305306    tmp_batch_input_file=batch_input.tmp307    echo -e '{"contents": [{"parts": [{"text": "Describe the process of photosynthesis."}]}], "generationConfig": {"temperature": 0.7}}\n{"contents": [{"parts": [{"text": "What are the main ingredients in a Margherita pizza?"}]}]}' > batch_input.tmp308    MIME_TYPE=$(file -b --mime-type "${tmp_batch_input_file}")309    NUM_BYTES=$(wc -c < "${tmp_batch_input_file}")310    DISPLAY_NAME=BatchInput311312    tmp_header_file=upload-header.tmp313314    # Initial resumable request defining metadata.315    # The upload url is in the response headers dump them to a file.316    curl "https://generativelanguage.googleapis.com/upload/v1beta/files" \317    -D "${tmp_header_file}" \318    -H "x-goog-api-key: $GEMINI_API_KEY" \319    -H "X-Goog-Upload-Protocol: resumable" \320    -H "X-Goog-Upload-Command: start" \321    -H "X-Goog-Upload-Header-Content-Length: ${NUM_BYTES}" \322    -H "X-Goog-Upload-Header-Content-Type: ${MIME_TYPE}" \323    -H "Content-Type: application/jsonl" \324    -d "{'file': {'display_name': '${DISPLAY_NAME}'}}" 2> /dev/null325326    upload_url=$(grep -i "x-goog-upload-url: " "${tmp_header_file}" | cut -d" " -f2 | tr -d "\r")327    rm "${tmp_header_file}"328329    # Upload the actual bytes.330    curl "${upload_url}" \331    -H "Content-Length: ${NUM_BYTES}" \332    -H "X-Goog-Upload-Offset: 0" \333    -H "X-Goog-Upload-Command: upload, finalize" \334    --data-binary "@${tmp_batch_input_file}" 2> /dev/null > file_info.json335336    file_uri=$(jq ".file.uri" file_info.json)337338The following example calls the339[`BatchGenerateContent`](https://ai.google.dev/api/batch-mode#google.ai.generativelanguage.v1beta.BatchService.BatchGenerateContent)340method with the input file uploaded using File API:341342### Python343344    from google import genai345346    # Assumes `uploaded_file` is the file object from the previous step347    client = genai.Client()348    file_batch_job = client.batches.create(349        model="gemini-3.8-flash",350        src=uploaded_file.name,351        config={352            'display_name': "file-upload-job-1",353        },354    )355356    print(f"Created batch job: {file_batch_job.name}")357358### JavaScript359360    // Assumes `uploadedFile` is the file object from the previous step361    const fileBatchJob = await ai.batches.create({362        model: 'gemini-3.8-flash',363        src: uploadedFile.name,364        config: {365            displayName: 'file-upload-job-1',366        }367    });368369    console.log(fileBatchJob);370371### Java372373    import com.google.genai.Client;374    import com.google.genai.types.BatchJob;375    import com.google.genai.types.BatchJobSource;376    import com.google.genai.types.CreateBatchJobConfig;377378    Client client = new Client();379380    // Assumes `uploadedFileName` is the file name from the previous step381    String uploadedFileName = "files/my-batch-requests-id";382383    BatchJobSource src = BatchJobSource.builder().fileName(uploadedFileName).build();384    CreateBatchJobConfig config =385        CreateBatchJobConfig.builder().displayName("file-upload-job-1").build();386387    BatchJob fileBatchJob = client.batches.create("gemini-3.8-flash", src, config);388389    System.out.println("Created batch job: " + fileBatchJob.name().orElse(""));390391### REST392393    # Set the File ID taken from the upload response.394    BATCH_INPUT_FILE='files/123456'395    curl https://generativelanguage.googleapis.com/v1beta/models/gemini-3.8-flash:batchGenerateContent \396    -X POST \397    -H "x-goog-api-key: $GEMINI_API_KEY" \398    -H "Content-Type:application/json" \399    -d "{400        'batch': {401            'display_name': 'my-batch-requests',402            'input_config': {403                'file_name': '${BATCH_INPUT_FILE}'404            }405        }406    }"407408When you create a batch job, you will get a job name returned. Use this name409for [monitoring](https://ai.google.dev/gemini-api/docs/batch-api#batch-job-status) the job status as well as410[retrieving the results](https://ai.google.dev/gemini-api/docs/batch-api#retrieve-batch-results) once the job completes.411412The following is an example output that contains a job name:413414415    Created batch job from file: batches/123456789416417### Batch embedding support418419You can use the Batch API to interact with the420[Embeddings model](https://ai.google.dev/gemini-api/docs/embeddings) for higher throughput.421To create an embeddings batch job with either [inline requests](https://ai.google.dev/gemini-api/docs/batch-api#inline-requests)422or [input files](https://ai.google.dev/gemini-api/docs/batch-api#input-file), use the `batches.create_embeddings` API and423specify the embeddings model.424425### Python426427    from google import genai428429    client = genai.Client()430431    # Creating an embeddings batch job with an input file request:432    file_job = client.batches.create_embeddings(433        model="gemini-embedding-2",434        src={'file_name': uploaded_batch_requests.name},435        config={'display_name': "Input embeddings batch"},436    )437438    # Creating an embeddings batch job with an inline request:439    batch_job = client.batches.create_embeddings(440        model="gemini-embedding-2",441        # For a predefined list of requests `inlined_requests`442        src={'inlined_requests': inlined_requests},443        config={'display_name': "Inlined embeddings batch"},444    )445446### JavaScript447448    // Creating an embeddings batch job with an input file request:449    let fileJob;450    fileJob = await client.batches.createEmbeddings({451        model: 'gemini-embedding-2',452        src: {fileName: uploadedBatchRequests.name},453        config: {displayName: 'Input embeddings batch'},454    });455    console.log(`Created batch job: ${fileJob.name}`);456457    // Creating an embeddings batch job with an inline request:458    let batchJob;459    batchJob = await client.batches.createEmbeddings({460        model: 'gemini-embedding-2',461        // For a predefined a list of requests `inlinedRequests`462        src: {inlinedRequests: inlinedRequests},463        config: {displayName: 'Inlined embeddings batch'},464    });465    console.log(`Created batch job: ${batchJob.name}`);466467### Java468469    import java.util.Arrays;470    import com.google.genai.Client;471    import com.google.genai.types.BatchJob;472    import com.google.genai.types.Content;473    import com.google.genai.types.CreateEmbeddingsBatchJobConfig;474    import com.google.genai.types.EmbedContentBatch;475    import com.google.genai.types.EmbeddingsBatchJobSource;476    import com.google.genai.types.Part;477    import java.util.List;478479    Client client = new Client();480481    String uploadedFileName = "files/my-embedding-requests-id";482483    // Creating an embeddings batch job with an input file request:484    BatchJob fileJob =485        client.batches.createEmbeddings(486            "gemini-embedding-2",487            EmbeddingsBatchJobSource.builder().fileName(uploadedFileName).build(),488            CreateEmbeddingsBatchJobConfig.builder().displayName("Input embeddings batch").build());489    System.out.println("Created batch job: " + fileJob.name().orElse(""));490491    // Creating an embeddings batch job with an inline request:492    EmbedContentBatch inlinedRequests =493        EmbedContentBatch.builder()494            .contents(Arrays.asList(Content.fromParts(Part.fromText("What is the meaning of life?"))))495            .build();496    BatchJob batchJob =497        client.batches.createEmbeddings(498            "gemini-embedding-2",499            EmbeddingsBatchJobSource.builder().inlinedRequests(inlinedRequests).build(),500            CreateEmbeddingsBatchJobConfig.builder().displayName("Inlined embeddings batch").build());501    System.out.println("Created batch job: " + batchJob.name().orElse(""));502503Read the Embeddings section in the [Batch API cookbook](https://github.com/google-gemini/cookbook/blob/main/quickstarts/Batch_mode.ipynb)504for more examples.505506### Request configuration507508You can include any request configurations you would use in a standard non-batch509request. For example, you could specify the temperature, system instructions or510even pass in other modalities. The following example shows an example inline511request that contains a system instruction for one of the requests:512513### Python514515    inline_requests_list = [516        {'contents': [{'parts': [{'text': 'Write a short poem about a cloud.'}]}]},517        {'contents': [{518            'parts': [{519                'text': 'Write a short poem about a cat.'520                }]521            }],522        'config': {523            'system_instruction': {'parts': [{'text': 'You are a cat. Your name is Neko.'}]}}524        }525    ]526527### JavaScript528529    inlineRequestsList = [530        {contents: [{parts: [{text: 'Write a short poem about a cloud.'}]}]},531        {contents: [{parts: [{text: 'Write a short poem about a cat.'}]}],532         config: {systemInstruction: {parts: [{text: 'You are a cat. Your name is Neko.'}]}}}533    ]534535### Java536537    import java.util.Arrays;538    import com.google.genai.types.Content;539    import com.google.genai.types.GenerateContentConfig;540    import com.google.genai.types.InlinedRequest;541    import com.google.genai.types.Part;542    import java.util.List;543544    List<InlinedRequest> inlineRequestsList =545        Arrays.asList(546            InlinedRequest.builder()547                .contents(Arrays.asList(Content.fromParts(Part.fromText("Write a short poem about a cloud."))))548                .build(),549            InlinedRequest.builder()550                .contents(Arrays.asList(Content.fromParts(Part.fromText("Write a short poem about a cat."))))551                .config(552                    GenerateContentConfig.builder()553                        .systemInstruction(554                            Content.fromParts(Part.fromText("You are a cat. Your name is Neko.")))555                        .build())556                .build());557558Similarly can specify tools to use for a request. The following example559shows a request that enables the [Google Search tool](https://ai.google.dev/gemini-api/docs/google-search):560561### Python562563    inlined_requests = [564    {'contents': [{'parts': [{'text': 'Who won the euro 1998?'}]}]},565    {'contents': [{'parts': [{'text': 'Who won the euro 2025?'}]}],566     'config':{'tools': [{'google_search': {}}]}}]567568### JavaScript569570    inlineRequestsList = [571        {contents: [{parts: [{text: 'Who won the euro 1998?'}]}]},572        {contents: [{parts: [{text: 'Who won the euro 2025?'}]}],573         config: {tools: [{googleSearch: {}}]}}574    ]575576### Java577578    import java.util.Arrays;579    import com.google.genai.types.Content;580    import com.google.genai.types.GenerateContentConfig;581    import com.google.genai.types.GoogleSearch;582    import com.google.genai.types.InlinedRequest;583    import com.google.genai.types.Part;584    import com.google.genai.types.Tool;585    import java.util.List;586587    List<InlinedRequest> inlinedRequests =588        Arrays.asList(589            InlinedRequest.builder()590                .contents(Arrays.asList(Content.fromParts(Part.fromText("Who won the euro 1998?"))))591                .build(),592            InlinedRequest.builder()593                .contents(Arrays.asList(Content.fromParts(Part.fromText("Who won the euro 2025?"))))594                .config(595                    GenerateContentConfig.builder()596                        .tools(Tool.builder().googleSearch(GoogleSearch.builder().build()).build())597                        .build())598                .build());599600You can specify [structured output](https://ai.google.dev/gemini-api/docs/structured-output) as well.601The following example shows how to specify for your batch requests.602603### Python604605    import time606    from google import genai607    from pydantic import BaseModel, TypeAdapter608609    class Recipe(BaseModel):610        recipe_name: str611        ingredients: list[str]612613    client = genai.Client()614615    # A list of dictionaries, where each is a GenerateContentRequest616    inline_requests = [617        {618            'contents': [{619                'parts': [{'text': 'List a few popular cookie recipes, and include the amounts of ingredients.'}],620                'role': 'user'621            }],622            'config': {623                'response_mime_type': 'application/json',624                'response_schema': list[Recipe]625            }626        },627        {628            'contents': [{629                'parts': [{'text': 'List a few popular gluten free cookie recipes, and include the amounts of ingredients.'}],630                'role': 'user'631            }],632            'config': {633                'response_mime_type': 'application/json',634                'response_schema': list[Recipe]635            }636        }637    ]638639    inline_batch_job = client.batches.create(640        model="gemini-3.8-flash",641        src=inline_requests,642        config={643            'display_name': "structured-output-job-1"644        },645    )646647    # wait for the job to finish648    job_name = inline_batch_job.name649    print(f"Polling status for job: {job_name}")650651    while True:652        batch_job_inline = client.batches.get(name=job_name)653        if batch_job_inline.state.name in ('JOB_STATE_SUCCEEDED', 'JOB_STATE_FAILED', 'JOB_STATE_CANCELLED', 'JOB_STATE_EXPIRED'):654            break655        print(f"Job not finished. Current state: {batch_job_inline.state.name}. Waiting 30 seconds...")656        time.sleep(30)657658    print(f"Job finished with state: {batch_job_inline.state.name}")659660    # print the response661    for i, inline_response in enumerate(batch_job_inline.dest.inlined_responses, start=1):662        print(f"\n--- Response {i} ---")663664        # Check for a successful response665        if inline_response.response:666            # The .text property is a shortcut to the generated text.667            print(inline_response.response.text)668669### JavaScript670671672    import {GoogleGenAI, Type} from '@google/genai';673674    const ai = new GoogleGenAI({});675676    const inlinedRequests = [677        {678            contents: [{679                parts: [{text: 'List a few popular cookie recipes, and include the amounts of ingredients.'}],680                role: 'user'681            }],682            config: {683                responseMimeType: 'application/json',684                responseSchema: {685                type: Type.ARRAY,686                items: {687                    type: Type.OBJECT,688                    properties: {689                    'recipeName': {690                        type: Type.STRING,691                        description: 'Name of the recipe',692                        nullable: false,693                    },694                    'ingredients': {695                        type: Type.ARRAY,696                        items: {697                        type: Type.STRING,698                        description: 'Ingredients of the recipe',699                        nullable: false,700                        },701                    },702                    },703                    required: ['recipeName'],704                },705                },706            }707        },708        {709            contents: [{710                parts: [{text: 'List a few popular gluten free cookie recipes, and include the amounts of ingredients.'}],711                role: 'user'712            }],713            config: {714                responseMimeType: 'application/json',715                responseSchema: {716                type: Type.ARRAY,717                items: {718                    type: Type.OBJECT,719                    properties: {720                    'recipeName': {721                        type: Type.STRING,722                        description: 'Name of the recipe',723                        nullable: false,724                    },725                    'ingredients': {726                        type: Type.ARRAY,727                        items: {728                        type: Type.STRING,729                        description: 'Ingredients of the recipe',730                        nullable: false,731                        },732                    },733                    },734                    required: ['recipeName'],735                },736                },737            }738        }739    ]740741    const inlinedBatchJob = await ai.batches.create({742        model: 'gemini-3.8-flash',743        src: inlinedRequests,744        config: {745            displayName: 'inlined-requests-job-1',746        }747    });748749### Java750751    import java.util.HashMap;752    import java.util.HashSet;753    import java.util.Arrays;754    import java.util.Collections;755    import com.google.genai.Client;756    import com.google.genai.types.BatchJob;757    import com.google.genai.types.BatchJobSource;758    import com.google.genai.types.Content;759    import com.google.genai.types.CreateBatchJobConfig;760    import com.google.genai.types.GenerateContentConfig;761    import com.google.genai.types.InlinedRequest;762    import com.google.genai.types.InlinedResponse;763    import com.google.genai.types.JobState;764    import com.google.genai.types.Part;765    import com.google.genai.types.Schema;766    import com.google.genai.types.Type;767    import java.util.List;768    import java.util.Map;769    import java.util.Set;770771    Client client = new Client();772773    Map<String, Schema> properties = new HashMap<>();774    properties.put("recipeName", Schema.builder().type(Type.Known.STRING).build());775    properties.put(776        "ingredients",777        Schema.builder()778            .type(Type.Known.ARRAY)779            .items(Schema.builder().type(Type.Known.STRING).build())780            .build());781782    Schema recipeSchema =783        Schema.builder()784            .type(Type.Known.ARRAY)785            .items(786                Schema.builder()787                    .type(Type.Known.OBJECT)788                    .properties(789    properties)790                    .required("recipeName")791                    .build())792            .build();793794    GenerateContentConfig jsonConfig =795        GenerateContentConfig.builder()796            .responseMimeType("application/json")797            .responseSchema(recipeSchema)798            .build();799800    List<InlinedRequest> inlineRequests =801        Arrays.asList(802            InlinedRequest.builder()803                .contents(804                    Arrays.asList(805                        Content.builder()806                            .role("user")807                            .parts(808                                Arrays.asList(809                                    Part.fromText(810                                        "List a few popular cookie recipes, and include the amounts of ingredients.")))811                            .build()))812                .config(jsonConfig)813                .build(),814            InlinedRequest.builder()815                .contents(816                    Arrays.asList(817                        Content.builder()818                            .role("user")819                            .parts(820                                Arrays.asList(821                                    Part.fromText(822                                        "List a few popular gluten free cookie recipes, and include the amounts of ingredients.")))823                            .build()))824                .config(jsonConfig)825                .build());826827    BatchJob inlineBatchJob =828        client.batches.create(829            "gemini-3.8-flash",830            BatchJobSource.builder().inlinedRequests(inlineRequests).build(),831            CreateBatchJobConfig.builder().displayName("structured-output-job-1").build());832833    // Wait for the job to finish834    String jobName = inlineBatchJob.name().get();835    System.out.println("Polling status for job: " + jobName);836837    Set<JobState.Known> completedStates =838        new HashSet<>(Arrays.asList(839            JobState.Known.JOB_STATE_SUCCEEDED,840            JobState.Known.JOB_STATE_FAILED,841            JobState.Known.JOB_STATE_CANCELLED,842            JobState.Known.JOB_STATE_EXPIRED));843844    BatchJob batchJobInline = client.batches.get(jobName, null);845    while (!completedStates.contains(batchJobInline.state().get().knownEnum())) {846      System.out.println(847          "Job not finished. Current state: " + batchJobInline.state().get() + ". Waiting 30 seconds...");848      Thread.sleep(30000);849      batchJobInline = client.batches.get(jobName, null);850    }851852    System.out.println("Job finished with state: " + batchJobInline.state().get());853854    // Print the response855    List<InlinedResponse> responses = batchJobInline.dest().get().inlinedResponses().orElse(Collections.emptyList());856    for (int i = 0; i < responses.size(); i++) {857      System.out.println("\n--- Response " + (i + 1) + " ---");858      InlinedResponse inlineResponse = responses.get(i);859      if (inlineResponse.response().isPresent()) {860        System.out.println(inlineResponse.response().get().text());861      }862    }863864The following shows an example output of this job:865866    --- Response 1 ---867    [868      {869        "recipe_name": "Chocolate Chip Cookies",870        "ingredients": [871          "1 cup (2 sticks) unsalted butter, softened",872          "3/4 cup granulated sugar",873          "3/4 cup packed light brown sugar",874          "1 large egg",875          "1 teaspoon vanilla extract",876          "2 1/4 cups all-purpose flour",877          "1 teaspoon baking soda",878          "1/2 teaspoon salt",879          "1 1/2 cups chocolate chips"880        ]881      },882      {883        "recipe_name": "Oatmeal Raisin Cookies",884        "ingredients": [885          "1 cup (2 sticks) unsalted butter, softened",886          "1 cup packed light brown sugar",887          "1/2 cup granulated sugar",888          "2 large eggs",889          "1 teaspoon vanilla extract",890          "1 1/2 cups all-purpose flour",891          "1 teaspoon baking soda",892          "1 teaspoon ground cinnamon",893          "1/2 teaspoon salt",894          "3 cups old-fashioned rolled oats",895          "1 cup raisins"896        ]897      },898      {899        "recipe_name": "Sugar Cookies",900        "ingredients": [901          "1 cup (2 sticks) unsalted butter, softened",902          "1 1/2 cups granulated sugar",903          "1 large egg",904          "1 teaspoon vanilla extract",905          "2 3/4 cups all-purpose flour",906          "1 teaspoon baking powder",907          "1/2 teaspoon salt"908        ]909      }910    ]911912    --- Response 2 ---913    [914      {915        "recipe_name": "Gluten-Free Chocolate Chip Cookies",916        "ingredients": [917          "1 cup (2 sticks) unsalted butter, softened",918          "3/4 cup granulated sugar",919          "3/4 cup packed light brown sugar",920          "2 large eggs",921          "1 teaspoon vanilla extract",922          "2 1/4 cups gluten-free all-purpose flour blend (with xanthan gum)",923          "1 teaspoon baking soda",924          "1/2 teaspoon salt",925          "1 1/2 cups chocolate chips"926        ]927      },928      {929        "recipe_name": "Gluten-Free Peanut Butter Cookies",930        "ingredients": [931          "1 cup (250g) creamy peanut butter",932          "1/2 cup (100g) granulated sugar",933          "1/2 cup (100g) packed light brown sugar",934          "1 large egg",935          "1 teaspoon vanilla extract",936          "1/2 teaspoon baking soda",937          "1/4 teaspoon salt"938        ]939      },940      {941        "recipe_name": "Gluten-Free Oatmeal Raisin Cookies",942        "ingredients": [943          "1/2 cup (1 stick) unsalted butter, softened",944          "1/2 cup granulated sugar",945          "1/2 cup packed light brown sugar",946          "1 large egg",947          "1 teaspoon vanilla extract",948          "1 cup gluten-free all-purpose flour blend",949          "1/2 teaspoon baking soda",950          "1/2 teaspoon ground cinnamon",951          "1/4 teaspoon salt",952          "1 1/2 cups gluten-free rolled oats",953          "1/2 cup raisins"954        ]955      }956    ]957958## Monitoring job status959960Use the operation name obtained when creating the batch job to poll its status.961The state field of the batch job will indicate its current status. A batch job962can be in one of the following states:963964- `JOB_STATE_PENDING`: The job has been created and is waiting to be processed by the service.965- `JOB_STATE_RUNNING`: The job is in progress.966- `JOB_STATE_SUCCEEDED`: The job completed successfully. You can now retrieve the results.967- `JOB_STATE_FAILED`: The job failed. Check the error details for more information.968- `JOB_STATE_CANCELLED`: The job was cancelled by the user.969- `JOB_STATE_EXPIRED`: The job has expired because it was running or pending for more than 48 hours. The job will not have any results to retrieve. You can try submitting the job again or splitting up the requests into smaller batches.970971You can poll the job status periodically to check for completion.972973### Python974975    import time976    from google import genai977978    client = genai.Client()979980    # Use the name of the job you want to check981    # e.g., inline_batch_job.name from the previous step982    job_name = "YOUR_BATCH_JOB_NAME"  # (e.g. 'batches/your-batch-id')983    batch_job = client.batches.get(name=job_name)984985    completed_states = set([986        'JOB_STATE_SUCCEEDED',987        'JOB_STATE_FAILED',988        'JOB_STATE_CANCELLED',989        'JOB_STATE_EXPIRED',990    ])991992    print(f"Polling status for job: {job_name}")993    batch_job = client.batches.get(name=job_name) # Initial get994    while batch_job.state.name not in completed_states:995      print(f"Current state: {batch_job.state.name}")996      time.sleep(30) # Wait for 30 seconds before polling again997      batch_job = client.batches.get(name=job_name)998999    print(f"Job finished with state: {batch_job.state.name}")1000    if batch_job.state.name == 'JOB_STATE_FAILED':1001        print(f"Error: {batch_job.error}")10021003### JavaScript10041005    // Use the name of the job you want to check1006    // e.g., inlinedBatchJob.name from the previous step1007    let batchJob;1008    const completedStates = new Set([1009        'JOB_STATE_SUCCEEDED',1010        'JOB_STATE_FAILED',1011        'JOB_STATE_CANCELLED',1012        'JOB_STATE_EXPIRED',1013    ]);10141015    try {1016        batchJob = await ai.batches.get({name: inlinedBatchJob.name});1017        while (!completedStates.has(batchJob.state)) {1018            console.log(`Current state: ${batchJob.state}`);1019            // Wait for 30 seconds before polling again1020            await new Promise(resolve => setTimeout(resolve, 30000));1021            batchJob = await client.batches.get({ name: batchJob.name });1022        }1023        console.log(`Job finished with state: ${batchJob.state}`);1024        if (batchJob.state === 'JOB_STATE_FAILED') {1025            // The exact structure of `error` might vary depending on the SDK1026            // This assumes `error` is an object with a `message` property.1027            console.error(`Error: ${batchJob.state}`);1028        }1029    } catch (error) {1030        console.error(`An error occurred while polling job ${batchJob.name}:`, error);1031    }10321033### Java10341035    import java.util.HashSet;1036    import java.util.Arrays;1037    import com.google.genai.Client;1038    import com.google.genai.types.BatchJob;1039    import com.google.genai.types.JobState;1040    import java.util.Set;10411042    Client client = new Client();10431044    // Use the name of the job you want to check1045    String jobName = "batches/your-batch-id";10461047    Set<JobState.Known> completedStates =1048        new HashSet<>(Arrays.asList(1049            JobState.Known.JOB_STATE_SUCCEEDED,1050            JobState.Known.JOB_STATE_FAILED,1051            JobState.Known.JOB_STATE_CANCELLED,1052            JobState.Known.JOB_STATE_EXPIRED));10531054    System.out.println("Polling status for job: " + jobName);1055    BatchJob batchJob = client.batches.get(jobName, null);1056    while (!completedStates.contains(batchJob.state().get().knownEnum())) {1057      System.out.println("Current state: " + batchJob.state().get());1058      Thread.sleep(30000); // Wait for 30 seconds before polling again1059      batchJob = client.batches.get(jobName, null);1060    }10611062    System.out.println("Job finished with state: " + batchJob.state().get());1063    if (batchJob.state().get().knownEnum() == JobState.Known.JOB_STATE_FAILED) {1064      System.out.println("Error: " + batchJob.error().orElse(null));1065    }10661067### Polling and webhooks10681069**Tired of polling?** Gemini now supports1070[Webhooks](https://ai.google.dev/gemini-api/docs/webhooks) for processing completions asynchronously.1071Instead of continuously calling `GET / operations`, subscribe to1072`batch.succeeded` directly to allow the Gemini API to push real-time1073notifications to your server when asynchronous or long-running operations1074complete.10751076### Python10771078    from google import genai10791080    client = genai.Client()10811082    webhook = client.webhooks.create(1083        name="MyBatchWebhook",1084        subscribed_events=["batch.succeeded", "batch.failed"],1085        uri="https://my-api.com/gemini-callback",1086    )10871088    print(f"Created webhook: {webhook.name}")10891090### JavaScript10911092    import { GoogleGenAI } from "@google/genai";10931094    const client = new GoogleGenAI();10951096    async function createWebhook() {1097      const webhook = await client.webhooks.create({1098        name: "MyBatchWebhook",1099        subscribed_events: ["batch.succeeded", "batch.failed"],1100        uri: "https://my-api.com/gemini-callback",1101      });11021103      console.log(`Created webhook: ${webhook.name}`);1104    }11051106    createWebhook();11071108### Java11091110    import java.util.Arrays;1111    import com.google.genai.Client;1112    import com.google.genai.gaos.models.webhooks.Webhook;1113    import com.google.genai.gaos.models.webhooks.WebhookInput;1114    import com.google.genai.gaos.models.webhooks.WebhookSubscribedEvent;1115    import java.util.List;11161117    Client client = new Client();11181119    WebhookInput input =1120        WebhookInput.builder()1121            .name("MyBatchWebhook")1122            .subscribedEvents(1123                Arrays.asList(1124                    WebhookSubscribedEvent.BATCH_SUCCEEDED,1125                    WebhookSubscribedEvent.BATCH_FAILED))1126            .uri("https://my-api.com/gemini-callback")1127            .build();11281129    Webhook webhook = client.webhooks.create(input).webhook().get();1130    System.out.println("Created webhook: " + webhook.name().orElse(""));11311132### REST11331134    curl -X POST \1135      "https://generativelanguage.googleapis.com/v1/webhooks?webhook_id=my-example-webhook-123" \1136      -H "Content-Type: application/json" \1137      -H "x-goog-api-key: $GOOGLE_API_KEY" \1138      -d '{1139        "name": "My Example Webhook",1140        "uri": "https://my-api.com/gemini-callback",1141        "subscribed_events": ["batch.succeeded", "batch.failed"]1142      }'11431144## Retrieving results11451146Once the job status indicates your batch job has succeeded, the results are1147available in the `response` field.1148By default, batch job results are stored and available for download for 6 weeks,1149before they are permanently deleted.11501151### Python11521153    import json1154    from google import genai11551156    client = genai.Client()11571158    # Use the name of the job you want to check1159    # e.g., inline_batch_job.name from the previous step1160    job_name = "YOUR_BATCH_JOB_NAME"1161    batch_job = client.batches.get(name=job_name)11621163    if batch_job.state.name == 'JOB_STATE_SUCCEEDED':11641165        # If batch job was created with a file1166        if batch_job.dest and batch_job.dest.file_name:1167            # Results are in a file1168            result_file_name = batch_job.dest.file_name1169            print(f"Results are in file: {result_file_name}")11701171            print("Downloading result file content...")1172            file_content = client.files.download(file=result_file_name)1173            # Process file_content (bytes) as needed1174            print(file_content.decode('utf-8'))11751176        # If batch job was created with inline request1177        # (for embeddings, use batch_job.dest.inlined_embed_content_responses)1178        elif batch_job.dest and batch_job.dest.inlined_responses:1179            # Results are inline1180            print("Results are inline:")1181            for i, inline_response in enumerate(batch_job.dest.inlined_responses):1182                print(f"Response {i+1}:")1183                if inline_response.response:1184                    # Accessing response, structure may vary.1185                    try:1186                        print(inline_response.response.text)1187                    except AttributeError:1188                        print(inline_response.response) # Fallback1189                elif inline_response.error:1190                    print(f"Error: {inline_response.error}")1191        else:1192            print("No results found (neither file nor inline).")1193    else:1194        print(f"Job did not succeed. Final state: {batch_job.state.name}")1195        if batch_job.error:1196            print(f"Error: {batch_job.error}")11971198### JavaScript11991200    // Use the name of the job you want to check1201    // e.g., inlinedBatchJob.name from the previous step1202    const jobName = "YOUR_BATCH_JOB_NAME";12031204    try {1205        const batchJob = await ai.batches.get({ name: jobName });12061207        if (batchJob.state === 'JOB_STATE_SUCCEEDED') {1208            console.log('Found completed batch:', batchJob.displayName);1209            console.log(batchJob);12101211            // If batch job was created with a file destination1212            if (batchJob.dest?.fileName) {1213                const resultFileName = batchJob.dest.fileName;1214                console.log(`Results are in file: ${resultFileName}`);12151216                console.log("Downloading result file content...");1217                const fileContentBuffer = await ai.files.download({ file: resultFileName });12181219                // Process fileContentBuffer (Buffer) as needed1220                console.log(fileContentBuffer.toString('utf-8'));1221            }12221223            // If batch job was created with inline responses1224            else if (batchJob.dest?.inlinedResponses) {1225                console.log("Results are inline:");1226                for (let i = 0; i < batchJob.dest.inlinedResponses.length; i++) {1227                    const inlineResponse = batchJob.dest.inlinedResponses[i];1228                    console.log(`Response ${i + 1}:`);1229                    if (inlineResponse.response) {1230                        // Accessing response, structure may vary.1231                        if (inlineResponse.response.text !== undefined) {1232                            console.log(inlineResponse.response.text);1233                        } else {1234                            console.log(inlineResponse.response); // Fallback1235                        }1236                    } else if (inlineResponse.error) {1237                        console.error(`Error: ${inlineResponse.error}`);1238                    }1239                }1240            }12411242            // If batch job was an embedding batch with inline responses1243            else if (batchJob.dest?.inlinedEmbedContentResponses) {1244                console.log("Embedding results found inline:");1245                for (let i = 0; i < batchJob.dest.inlinedEmbedContentResponses.length; i++) {1246                    const inlineResponse = batchJob.dest.inlinedEmbedContentResponses[i];1247                    console.log(`Response ${i + 1}:`);1248                    if (inlineResponse.response) {1249                        console.log(inlineResponse.response);1250                    } else if (inlineResponse.error) {1251                        console.error(`Error: ${inlineResponse.error}`);1252                    }1253                }1254            } else {1255                console.log("No results found (neither file nor inline).");1256            }1257        } else {1258            console.log(`Job did not succeed. Final state: ${batchJob.state}`);1259            if (batchJob.error) {1260                console.error(`Error: ${typeof batchJob.error === 'string' ? batchJob.error : batchJob.error.message || JSON.stringify(batchJob.error)}`);1261            }1262        }1263    } catch (error) {1264        console.error(`An error occurred while processing job ${jobName}:`, error);1265    }12661267### Java12681269    import com.google.genai.Client;1270    import com.google.genai.types.BatchJob;1271    import com.google.genai.types.BatchJobDestination;1272    import com.google.genai.types.InlinedEmbedContentResponse;1273    import com.google.genai.types.InlinedResponse;1274    import com.google.genai.types.JobState;1275    import java.nio.file.Files;1276    import java.nio.file.Paths;1277    import java.util.List;12781279    Client client = new Client();12801281    // Use the name of the job you want to check1282    String jobName = "batches/your-batch-id";1283    BatchJob batchJob = client.batches.get(jobName, null);12841285    if (batchJob.state().get().knownEnum() == JobState.Known.JOB_STATE_SUCCEEDED) {1286      BatchJobDestination dest = batchJob.dest().orElse(null);12871288      // If batch job was created with a file destination1289      if (dest != null && dest.fileName().isPresent()) {1290        String resultFileName = dest.fileName().get();1291        System.out.println("Results are in file: " + resultFileName);12921293        System.out.println("Downloading result file content...");1294        client.files.download(resultFileName, "batch_results.jsonl", null);1295        String fileContent = Files.readString(Paths.get("batch_results.jsonl"));1296        System.out.println(fileContent);1297      }1298      // If batch job was created with inline requests1299      else if (dest != null && dest.inlinedResponses().isPresent()) {1300        System.out.println("Results are inline:");1301        List<InlinedResponse> responses = dest.inlinedResponses().get();1302        for (int i = 0; i < responses.size(); i++) {1303          System.out.println("Response " + (i + 1) + ":");1304          InlinedResponse inlineResponse = responses.get(i);1305          if (inlineResponse.response().isPresent()) {1306            System.out.println(inlineResponse.response().get().text());1307          } else if (inlineResponse.error().isPresent()) {1308            System.out.println("Error: " + inlineResponse.error().get());1309          }1310        }1311      }1312      // If batch job was an embedding batch with inline responses1313      else if (dest != null && dest.inlinedEmbedContentResponses().isPresent()) {1314        System.out.println("Embedding results found inline:");1315        List<InlinedEmbedContentResponse> responses = dest.inlinedEmbedContentResponses().get();1316        for (int i = 0; i < responses.size(); i++) {1317          System.out.println("Response " + (i + 1) + ":");1318          InlinedEmbedContentResponse inlineResponse = responses.get(i);1319          if (inlineResponse.response().isPresent()) {1320            System.out.println(inlineResponse.response().get());1321          } else if (inlineResponse.error().isPresent()) {1322            System.out.println("Error: " + inlineResponse.error().get());1323          }1324        }1325      } else {1326        System.out.println("No results found (neither file nor inline).");1327      }1328    } else {1329      System.out.println("Job did not succeed. Final state: " + batchJob.state().get());1330      batchJob.error().ifPresent(err -> System.out.println("Error: " + err));1331    }13321333### REST13341335    BATCH_NAME="batches/123456" # Your batch job name13361337    curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \1338    -H "x-goog-api-key: $GEMINI_API_KEY" \1339    -H "Content-Type:application/json" 2> /dev/null > batch_status.json13401341    if jq -r '.done' batch_status.json | grep -q "false"; then1342        echo "Batch has not finished processing"1343    fi13441345    batch_state=$(jq -r '.metadata.state' batch_status.json)1346    if [[ $batch_state = "JOB_STATE_SUCCEEDED" ]]; then1347        if [[ $(jq '.response | has("inlinedResponses")' batch_status.json) = "true" ]]; then1348            jq -r '.response.inlinedResponses' batch_status.json1349            exit1350        fi1351        responses_file_name=$(jq -r '.response.responsesFile' batch_status.json)1352        curl https://generativelanguage.googleapis.com/download/v1beta/$responses_file_name:download?alt=media \1353        -H "x-goog-api-key: $GEMINI_API_KEY" 2> /dev/null1354    elif [[ $batch_state = "JOB_STATE_FAILED" ]]; then1355        jq '.error' batch_status.json1356    elif [[ $batch_state == "JOB_STATE_CANCELLED" ]]; then1357        echo "Batch was cancelled by the user"1358    elif [[ $batch_state == "JOB_STATE_EXPIRED" ]]; then1359        echo "Batch expired after 48 hours"1360    fi13611362## Listing batch jobs13631364You can list your recent batch jobs.13651366### Python13671368    batch_jobs = client.batches.list()13691370    # Optional query config:1371    # batch_jobs = client.batches.list(config={'page_size': 5})13721373    for batch_job in batch_jobs:1374        print(batch_job)13751376### JavaScript13771378    const batchJobs = await ai.batches.list();13791380    // Optional query config:1381    // const batchJobs = await ai.batches.list({config: {'pageSize': 5}});13821383    for await (const batchJob of batchJobs) {1384        console.log(batchJob);1385    }13861387### Java13881389    import com.google.genai.Client;1390    import com.google.genai.Pager;1391    import com.google.genai.types.BatchJob;1392    import com.google.genai.types.ListBatchJobsConfig;13931394    Client client = new Client();13951396    Pager<BatchJob> batchJobs = client.batches.list(null);13971398    // Optional query config:1399    // Pager<BatchJob> batchJobs = client.batches.list(ListBatchJobsConfig.builder().pageSize(5).build());14001401    for (BatchJob batchJob : batchJobs) {1402      System.out.println(batchJob);1403    }14041405### REST14061407    curl https://generativelanguage.googleapis.com/v1beta/batches \1408    -H "x-goog-api-key: $GEMINI_API_KEY"14091410## Cancelling a batch job14111412You can cancel an ongoing batch job using its name. When a job is1413canceled, it stops processing new requests.14141415### Python14161417    client.batches.cancel(name=batch_job_to_cancel.name)14181419### JavaScript14201421    await ai.batches.cancel({name: batchJobToCancel.name});14221423### Java14241425    import com.google.genai.Client;14261427    Client client = new Client();14281429    String batchJobToCancelName = "batches/your-batch-id";1430    client.batches.cancel(batchJobToCancelName, null);14311432### REST14331434    BATCH_NAME="batches/123456" # Your batch job name14351436    # Cancel the batch1437    curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME:cancel \1438    -H "x-goog-api-key: $GEMINI_API_KEY" \14391440    # Confirm that the status of the batch after cancellation is JOB_STATE_CANCELLED1441    curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \1442    -H "x-goog-api-key: $GEMINI_API_KEY" \1443    -H "Content-Type:application/json" 2> /dev/null | jq -r '.metadata.state'14441445## Deleting a batch job14461447You can delete an existing batch job using its name. When a job is1448deleted, it stops processing new requests and is removed from the list of1449batch jobs.14501451### Python14521453    client.batches.delete(name=batch_job_to_delete.name)14541455### JavaScript14561457    await ai.batches.delete({name: batchJobToDelete.name});14581459### Java14601461    import com.google.genai.Client;14621463    Client client = new Client();14641465    String batchJobToDeleteName = "batches/your-batch-id";1466    client.batches.delete(batchJobToDeleteName, null);14671468### REST14691470    BATCH_NAME="batches/123456" # Your batch job name14711472    # Delete the batch job1473    curl -X DELETE "https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME" \1474    -H "x-goog-api-key: $GEMINI_API_KEY"14751476## Generating images in batch14771478If you're using [Gemini Nano Banana](https://ai.google.dev/gemini-api/docs/image-generation) and need to generate a lot1479of images, you can use the Batch API to get higher1480[rate limits](https://ai.google.dev/gemini-api/docs/rate-limits) in exchange for a turnaround of up1481to 24 hours.14821483You can either use [inline requests](https://ai.google.dev/gemini-api/docs/batch-api#inline-requests-images) for small batches of requests (under 20MB) or1484a [JSONL input file](https://ai.google.dev/gemini-api/docs/batch-api#input-file-images) for large batches (recommended for image generation):14851486### Inline requests for images14871488### Python14891490    import time1491    import base641492    import json1493    from google import genai1494    from google.genai import types1495    from PIL import Image14961497    client = genai.Client()14981499    # 1. Create batch job with inline requests1500    inline_requests = [1501        {1502            'contents': [{'parts': [{'text': 'A big letter A surrounded by animals starting with the A letter'}]}],1503            'config': {'response_modalities': ['TEXT', 'IMAGE']}1504        },1505        {1506            'contents': [{'parts': [{'text': 'A big letter B surrounded by animals starting with the B letter'}]}],1507            'config': {'response_modalities': ['TEXT', 'IMAGE']}1508        }1509    ]15101511    inline_batch_job = client.batches.create(1512        model="gemini-3-pro-image-preview",1513        src=inline_requests,1514        config={1515            'display_name': "inlined-image-requests-job-1",1516        },1517    )15181519    print(f"Created batch job: {inline_batch_job.name}")15201521    # 2. Monitor job status1522    job_name = inline_batch_job.name1523    print(f"Polling status for job: {job_name}")15241525    completed_states = set([1526        'JOB_STATE_SUCCEEDED',1527        'JOB_STATE_FAILED',1528        'JOB_STATE_CANCELLED',1529        'JOB_STATE_EXPIRED',1530    ])15311532    batch_job = client.batches.get(name=job_name) # Initial get1533    while batch_job.state.name not in completed_states:1534      print(f"Current state: {batch_job.state.name}")1535      time.sleep(10) # Wait for 10 seconds before polling again1536      batch_job = client.batches.get(name=job_name)15371538    print(f"Job finished with state: {batch_job.state.name}")15391540    # 3. Retrieve results1541    if batch_job.state.name == 'JOB_STATE_SUCCEEDED':1542        print("Results are inline:")1543        for i, inline_response in enumerate(batch_job.dest.inlined_responses):1544            print(f"Response {i+1}:")1545            if inline_response.response:1546                for part in inline_response.response.candidates[0].content.parts:1547                    if part.text:1548                        print(part.text)1549                    elif part.inline_data:1550                        print(f"Image mime type: {part.inline_data.mime_type}")1551                        image = part.as_image()1552                        image.save(f"image_{i+1}.png")1553            elif inline_response.error:1554                print(f"Error: {inline_response.error}")1555    elif batch_job.state.name == 'JOB_STATE_FAILED':1556        print(f"Error: {batch_job.error}")15571558### JavaScript15591560    import {GoogleGenAI} from '@google/genai';15611562    const ai = new GoogleGenAI({});15631564    async function run() {1565        // 1. Create batch job with inline requests1566        const inlinedRequests = [1567            {1568                contents: [{parts: [{text: 'A big letter A surrounded by animals starting with the A letter'}]}],1569                config: {responseModalities: ['TEXT', 'IMAGE']}1570            },1571            {1572                contents: [{parts: [{text: 'A big letter B surrounded by animals starting with the B letter'}]}],1573                config: {responseModalities: ['TEXT', 'IMAGE']}1574            }1575        ]15761577        const inlineBatchJob = await ai.batches.create({1578            model: 'gemini-3-pro-image-preview',1579            src: inlinedRequests,1580            config: {1581                displayName: 'inlined-image-requests-job-1',1582            }1583        });15841585        console.log(inlineBatchJob);15861587        // 2. Monitor job status1588        let batchJob;1589        const completedStates = new Set([1590            'JOB_STATE_SUCCEEDED',1591            'JOB_STATE_FAILED',1592            'JOB_STATE_CANCELLED',1593            'JOB_STATE_EXPIRED',1594        ]);15951596        try {1597            batchJob = await ai.batches.get({name: inlineBatchJob.name});1598            while (!completedStates.has(batchJob.state)) {1599                console.log(`Current state: ${batchJob.state}`);1600                // Wait for 10 seconds before polling again1601                await new Promise(resolve => setTimeout(resolve, 10000));1602                batchJob = await ai.batches.get({ name: batchJob.name });1603            }1604            console.log(`Job finished with state: ${batchJob.state}`);1605        } catch (error) {1606            console.error(`An error occurred while polling job ${inlineBatchJob.name}:`, error);1607            return;1608        }16091610        // 3. Retrieve results1611        if (batchJob.state === 'JOB_STATE_SUCCEEDED') {1612            if (batchJob.dest?.inlinedResponses) {1613                console.log("Results are inline:");1614                for (let i = 0; i < batchJob.dest.inlinedResponses.length; i++) {1615                    const inlineResponse = batchJob.dest.inlinedResponses[i];1616                    console.log(`Response ${i + 1}:`);1617                    if (inlineResponse.response) {1618                        for (const part of inlineResponse.response.candidates[0].content.parts) {1619                            if (part.text) {1620                                console.log(part.text);1621                            } else if (part.inlineData) {1622                                console.log(`Image mime type: ${part.inlineData.mimeType}`);1623                            }1624                        }1625                    } else if (inlineResponse.error) {1626                        console.error(`Error: ${inlineResponse.error}`);1627                    }1628                }1629            } else {1630                console.log("No inline results found.");1631            }1632        } else if (batchJob.state === 'JOB_STATE_FAILED') {1633             console.error(`Error: ${typeof batchJob.error === 'string' ? batchJob.error : batchJob.error.message || JSON.stringify(batchJob.error)}`);1634        }1635    }1636    run();16371638### Java16391640    import java.util.HashSet;1641    import java.util.Arrays;1642    import java.util.Collections;1643    import com.google.genai.Client;1644    import com.google.genai.types.BatchJob;1645    import com.google.genai.types.BatchJobSource;1646    import com.google.genai.types.Content;1647    import com.google.genai.types.CreateBatchJobConfig;1648    import com.google.genai.types.GenerateContentConfig;1649    import com.google.genai.types.InlinedRequest;1650    import com.google.genai.types.InlinedResponse;1651    import com.google.genai.types.JobState;1652    import com.google.genai.types.Part;1653    import java.nio.file.Files;1654    import java.nio.file.Paths;1655    import java.util.List;1656    import java.util.Set;16571658    Client client = new Client();16591660    // 1. Create batch job with inline requests1661    GenerateContentConfig imageConfig =1662        GenerateContentConfig.builder().responseModalities("TEXT", "IMAGE").build();16631664    List<InlinedRequest> inlineRequests =1665        Arrays.asList(1666            InlinedRequest.builder()1667                .contents(1668                    Arrays.asList(1669                        Content.fromParts(1670                            Part.fromText(1671                                "A big letter A surrounded by animals starting with the A letter"))))1672                .config(imageConfig)1673                .build(),1674            InlinedRequest.builder()1675                .contents(1676                    Arrays.asList(1677                        Content.fromParts(1678                            Part.fromText(1679                                "A big letter B surrounded by animals starting with the B letter"))))1680                .config(imageConfig)1681                .build());16821683    BatchJob inlineBatchJob =1684        client.batches.create(1685            "gemini-3-pro-image-preview",1686            BatchJobSource.builder().inlinedRequests(inlineRequests).build(),1687            CreateBatchJobConfig.builder().displayName("inlined-image-requests-job-1").build());16881689    System.out.println("Created batch job: " + inlineBatchJob.name().orElse(""));16901691    // 2. Monitor job status1692    String jobName = inlineBatchJob.name().get();1693    System.out.println("Polling status for job: " + jobName);16941695    Set<JobState.Known> completedStates =1696        new HashSet<>(Arrays.asList(1697            JobState.Known.JOB_STATE_SUCCEEDED,1698            JobState.Known.JOB_STATE_FAILED,1699            JobState.Known.JOB_STATE_CANCELLED,1700            JobState.Known.JOB_STATE_EXPIRED));17011702    BatchJob batchJob = client.batches.get(jobName, null);1703    while (!completedStates.contains(batchJob.state().get().knownEnum())) {1704      System.out.println("Current state: " + batchJob.state().get());1705      Thread.sleep(10000); // Wait for 10 seconds before polling again1706      batchJob = client.batches.get(jobName, null);1707    }17081709    System.out.println("Job finished with state: " + batchJob.state().get());17101711    // 3. Retrieve results1712    if (batchJob.state().get().knownEnum() == JobState.Known.JOB_STATE_SUCCEEDED) {1713      System.out.println("Results are inline:");1714      List<InlinedResponse> responses = batchJob.dest().get().inlinedResponses().orElse(Collections.emptyList());1715      for (int i = 0; i < responses.size(); i++) {1716        System.out.println("Response " + (i + 1) + ":");1717        InlinedResponse inlineResponse = responses.get(i);1718        if (inlineResponse.response().isPresent()) {1719          for (Part part : inlineResponse.response().get().parts()) {1720            if (part.text().isPresent()) {1721              System.out.println(part.text().get());1722            } else if (part.inlineData().isPresent()) {1723              System.out.println("Image mime type: " + part.inlineData().get().mimeType().orElse(""));1724              Files.write(1725                  Paths.get("image_" + (i + 1) + ".png"),1726                  part.inlineData().get().data().get());1727            }1728          }1729        } else if (inlineResponse.error().isPresent()) {1730          System.out.println("Error: " + inlineResponse.error().get());1731        }1732      }1733    } else if (batchJob.state().get().knownEnum() == JobState.Known.JOB_STATE_FAILED) {1734      System.out.println("Error: " + batchJob.error().orElse(null));1735    }17361737### REST17381739    # 1. Create batch job1740    printf -v request_data '{1741        "batch": {1742            "display_name": "my-batch-image-requests",1743            "input_config": {1744                "requests": {1745                    "requests": [1746                        {1747                            "request": {1748                                "contents": [{"parts": [{"text": "A big letter A surrounded by animals starting with the A letter"}]}],1749                                "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}1750                            },1751                            "metadata": { "key": "request-1" }1752                        },1753                        {1754                            "request": {1755                                "contents": [{"parts": [{"text": "A big letter B surrounded by animals starting with the B letter"}]}],1756                                "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}1757                            },1758                            "metadata": { "key": "request-2" }1759                        }1760                    ]1761                }1762            }1763        }1764    }'1765    curl https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image-preview:batchGenerateContent \1766      -H "x-goog-api-key: $GEMINI_API_KEY" \1767      -X POST \1768      -H "Content-Type:application/json" \1769      -d "$request_data" > created_batch.json17701771    BATCH_NAME=$(jq -r '.name' created_batch.json)1772    echo "Created batch job: $BATCH_NAME"17731774    # 2. Poll job status until completion by repeating the following command1775    # Replace $BATCH_NAME with the name returned above.1776    curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \1777      -H "x-goog-api-key: $GEMINI_API_KEY" \1778      -H "Content-Type:application/json" > batch_status.json17791780    echo "Current status:"1781    jq '.' batch_status.json17821783    # 3. If state is JOB_STATE_SUCCEEDED, retrieve results from batch_status.json1784    batch_state=$(jq -r '.state' batch_status.json)1785    if [[ $batch_state = "JOB_STATE_SUCCEEDED" ]]; then1786        echo "Job succeeded. Results:"1787        jq -r '.dest.inlinedResponses' batch_status.json1788    fi17891790### Input file for images17911792### Python17931794    import json1795    import time1796    import base641797    from google import genai1798    from google.genai import types1799    from PIL import Image18001801    client = genai.Client()18021803    # 1. Create and upload file1804    file_name = "my-batch-image-requests.jsonl"1805    with open(file_name, "w") as f:1806        requests = [1807            {"key": "request-1", "request": {"contents": [{"parts": [{"text": "A big letter A surrounded by animals starting with the A letter"}]}], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}}},1808            {"key": "request-2", "request": {"contents": [{"parts": [{"text": "A big letter B surrounded by animals starting with the B letter"}]}], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}}}1809        ]1810        for req in requests:1811            f.write(json.dumps(req) + "\n")18121813    uploaded_file = client.files.upload(1814        file=file_name,1815        config=types.UploadFileConfig(display_name='my-batch-image-requests', mime_type='jsonl')1816    )1817    print(f"Uploaded file: {uploaded_file.name}")18181819    # 2. Create batch job1820    file_batch_job = client.batches.create(1821        model="gemini-3-pro-image-preview",1822        src=uploaded_file.name,1823        config={1824            'display_name': "file-image-upload-job-1",1825        },1826    )1827    print(f"Created batch job: {file_batch_job.name}")18281829    # 3. Monitor job status1830    job_name = file_batch_job.name1831    print(f"Polling status for job: {job_name}")18321833    completed_states = set([1834        'JOB_STATE_SUCCEEDED',1835        'JOB_STATE_FAILED',1836        'JOB_STATE_CANCELLED',1837        'JOB_STATE_EXPIRED',1838    ])18391840    batch_job = client.batches.get(name=job_name) # Initial get1841    while batch_job.state.name not in completed_states:1842      print(f"Current state: {batch_job.state.name}")1843      time.sleep(10) # Wait for 10 seconds before polling again1844      batch_job = client.batches.get(name=job_name)18451846    print(f"Job finished with state: {batch_job.state.name}")18471848    # 4. Retrieve results1849    if batch_job.state.name == 'JOB_STATE_SUCCEEDED':1850        result_file_name = batch_job.dest.file_name1851        print(f"Results are in file: {result_file_name}")1852        print("Downloading result file content...")1853        file_content_bytes = client.files.download(file=result_file_name)1854        file_content = file_content_bytes.decode('utf-8')1855        # The result file is also a JSONL file. Parse and print each line.1856        for line in file_content.splitlines():1857          if line:1858            parsed_response = json.loads(line)1859            if 'response' in parsed_response and parsed_response['response']:1860                for part in parsed_response['response']['candidates'][0]['content']['parts']:1861                  if part.get('text'):1862                    print(part['text'])1863                  elif part.get('inlineData'):1864                    print(f"Image mime type: {part['inlineData']['mimeType']}")1865                    data = base64.b64decode(part['inlineData']['data'])1866            elif 'error' in parsed_response:1867                print(f"Error: {parsed_response['error']}")1868    elif batch_job.state.name == 'JOB_STATE_FAILED':1869        print(f"Error: {batch_job.error}")18701871### JavaScript18721873    import {GoogleGenAI} from '@google/genai';1874    import * as fs from "fs";1875    import * as path from "path";1876    import { fileURLToPath } from 'url';18771878    const ai = new GoogleGenAI({});18791880    async function run() {1881        // 1. Create and upload file1882        const fileName = "my-batch-image-requests.jsonl";1883        const requests = [1884            { "key": "request-1", "request": { "contents": [{ "parts": [{ "text": "A big letter A surrounded by animals starting with the A letter" }] }], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]} } },1885            { "key": "request-2", "request": { "contents": [{ "parts": [{ "text": "A big letter B surrounded by animals starting with the B letter" }] }], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]} } }1886        ];1887        const __filename = fileURLToPath(import.meta.url);1888        const __dirname = path.dirname(__filename);1889        const filePath = path.join(__dirname, fileName);18901891        try {1892            const writeStream = fs.createWriteStream(filePath, { flags: 'w' });1893            for (const req of requests) {1894                writeStream.write(JSON.stringify(req) + '\n');1895            }1896            writeStream.end();1897            console.log(`Successfully wrote batch requests to ${filePath}`);1898        } catch (error) {1899            console.error(`An unexpected error occurred writing file:`, error);1900            return;1901        }19021903        const uploadedFile = await ai.files.upload({file: fileName, config: { mimeType: 'jsonl' }});1904        console.log(`Uploaded file: ${uploadedFile.name}`);19051906        // 2. Create batch job1907        const fileBatchJob = await ai.batches.create({1908            model: 'gemini-3-pro-image-preview',1909            src: uploadedFile.name,1910            config: {1911                displayName: 'file-image-upload-job-1',1912            }1913        });1914        console.log(fileBatchJob);19151916        // 3. Monitor job status1917        let batchJob;1918        const completedStates = new Set([1919            'JOB_STATE_SUCCEEDED',1920            'JOB_STATE_FAILED',1921            'JOB_STATE_CANCELLED',1922            'JOB_STATE_EXPIRED',1923        ]);19241925        try {1926            batchJob = await ai.batches.get({name: fileBatchJob.name});1927            while (!completedStates.has(batchJob.state)) {1928                console.log(`Current state: ${batchJob.state}`);1929                // Wait for 10 seconds before polling again1930                await new Promise(resolve => setTimeout(resolve, 10000));1931                batchJob = await ai.batches.get({ name: batchJob.name });1932            }1933            console.log(`Job finished with state: ${batchJob.state}`);1934        } catch (error) {1935            console.error(`An error occurred while polling job ${fileBatchJob.name}:`, error);1936            return;1937        }19381939        // 4. Retrieve results1940        if (batchJob.state === 'JOB_STATE_SUCCEEDED') {1941            if (batchJob.dest?.fileName) {1942                const resultFileName = batchJob.dest.fileName;1943                console.log(`Results are in file: ${resultFileName}`);1944                console.log("Downloading result file content...");1945                const fileContentBuffer = await ai.files.download({ file: resultFileName });1946                const fileContent = fileContentBuffer.toString('utf-8');1947                for (const line of fileContent.split('\n')) {1948                    if (line) {1949                        const parsedResponse = JSON.parse(line);1950                        if (parsedResponse.response) {1951                            for (const part of parsedResponse.response.candidates[0].content.parts) {1952                                if (part.text) {1953                                    console.log(part.text);1954                                } else if (part.inlineData) {1955                                    console.log(`Image mime type: ${part.inlineData.mimeType}`);1956                                }1957                            }1958                        } else if (parsedResponse.error) {1959                            console.error(`Error: ${parsedResponse.error}`);1960                        }1961                    }1962                }1963            } else {1964                console.log("No result file found.");1965            }1966        } else if (batchJob.state === 'JOB_STATE_FAILED') {1967             console.error(`Error: ${typeof batchJob.error === 'string' ? batchJob.error : batchJob.error.message || JSON.stringify(batchJob.error)}`);1968        }1969    }1970    run();19711972### Java19731974    import java.util.HashSet;1975    import java.util.Arrays;1976    import com.google.genai.Client;1977    import com.google.genai.types.BatchJob;1978    import com.google.genai.types.BatchJobSource;1979    import com.google.genai.types.CreateBatchJobConfig;1980    import com.google.genai.types.File;1981    import com.google.genai.types.JobState;1982    import com.google.genai.types.UploadFileConfig;1983    import java.nio.file.Files;1984    import java.nio.file.Paths;1985    import java.util.List;1986    import java.util.Set;19871988    Client client = new Client();19891990    // 1. Create and upload file1991    String fileName = "my-batch-image-requests.jsonl";1992    List<String> requests =1993        Arrays.asList(1994            "{\"key\": \"request-1\", \"request\": {\"contents\": [{\"parts\": [{\"text\": \"A big letter A surrounded by animals starting with the A letter\"}]}], \"generation_config\": {\"responseModalities\": [\"TEXT\", \"IMAGE\"]}}}",1995            "{\"key\": \"request-2\", \"request\": {\"contents\": [{\"parts\": [{\"text\": \"A big letter B surrounded by animals starting with the B letter\"}]}], \"generation_config\": {\"responseModalities\": [\"TEXT\", \"IMAGE\"]}}}");1996    Files.write(Paths.get(fileName), requests);19971998    File uploadedFile =1999        client.files.upload(2000            fileName,2001            UploadFileConfig.builder()2002                .displayName("my-batch-image-requests")2003                .mimeType("jsonl")2004                .build());2005    System.out.println("Uploaded file: " + uploadedFile.name().orElse(""));20062007    // 2. Create batch job2008    BatchJob fileBatchJob =2009        client.batches.create(2010            "gemini-3-pro-image-preview",2011            BatchJobSource.builder().fileName(uploadedFile.name().get()).build(),2012            CreateBatchJobConfig.builder().displayName("file-image-upload-job-1").build());2013    System.out.println("Created batch job: " + fileBatchJob.name().orElse(""));20142015    // 3. Monitor job status2016    String jobName = fileBatchJob.name().get();2017    System.out.println("Polling status for job: " + jobName);20182019    Set<JobState.Known> completedStates =2020        new HashSet<>(Arrays.asList(2021            JobState.Known.JOB_STATE_SUCCEEDED,2022            JobState.Known.JOB_STATE_FAILED,2023            JobState.Known.JOB_STATE_CANCELLED,2024            JobState.Known.JOB_STATE_EXPIRED));20252026    BatchJob batchJob = client.batches.get(jobName, null);2027    while (!completedStates.contains(batchJob.state().get().knownEnum())) {2028      System.out.println("Current state: " + batchJob.state().get());2029      Thread.sleep(10000); // Wait for 10 seconds before polling again2030      batchJob = client.batches.get(jobName, null);2031    }20322033    System.out.println("Job finished with state: " + batchJob.state().get());20342035    // 4. Retrieve results2036    if (batchJob.state().get().knownEnum() == JobState.Known.JOB_STATE_SUCCEEDED) {2037      String resultFileName = batchJob.dest().get().fileName().get();2038      System.out.println("Results are in file: " + resultFileName);2039      System.out.println("Downloading result file content...");2040      client.files.download(resultFileName, "batch_image_results.jsonl", null);2041      for (String line : Files.readAllLines(Paths.get("batch_image_results.jsonl"))) {2042        if (!line.isEmpty()) {2043          System.out.println(line);2044        }2045      }2046    } else if (batchJob.state().get().knownEnum() == JobState.Known.JOB_STATE_FAILED) {2047      System.out.println("Error: " + batchJob.error().orElse(null));2048    }20492050### REST20512052    # 1. Create and upload file2053    echo '{"key": "request-1", "request": {"contents": [{"parts": [{"text": "A big letter A surrounded by animals starting with the A letter"}]}], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}}}' > my-batch-image-requests.jsonl2054    echo '{"key": "request-2", "request": {"contents": [{"parts": [{"text": "A big letter B surrounded by animals starting with the B letter"}]}], "generation_config": {"responseModalities": ["TEXT", "IMAGE"]}}}' >> my-batch-image-requests.jsonl20552056    # Follow File API guide to upload: https://ai.google.dev/gemini-api/docs/files#upload_a_file2057    # This example assumes you have uploaded the file and set BATCH_INPUT_FILE to its name (e.g., files/abcdef123)2058    BATCH_INPUT_FILE="files/your-uploaded-file-name"20592060    # 2. Create batch job2061    printf -v request_data '{2062        "batch": {2063            "display_name": "my-batch-file-image-requests",2064            "input_config": { "file_name": "%s" }2065        }2066    }' "$BATCH_INPUT_FILE"2067    curl https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-image-preview:batchGenerateContent \2068      -X POST \2069      -H "x-goog-api-key: $GEMINI_API_KEY" \2070      -H "Content-Type:application/json" \2071      -d "$request_data" > created_batch.json20722073    BATCH_NAME=$(jq -r '.name' created_batch.json)2074    echo "Created batch job: $BATCH_NAME"20752076    # 3. Poll job status until completion by repeating the following command:2077    curl https://generativelanguage.googleapis.com/v1beta/$BATCH_NAME \2078      -H "x-goog-api-key: $GEMINI_API_KEY" \2079      -H "Content-Type:application/json" > batch_status.json20802081    echo "Current status:"2082    jq '.' batch_status.json20832084    # 4. If state is JOB_STATE_SUCCEEDED, download results file2085    batch_state=$(jq -r '.state' batch_status.json)2086    if [[ $batch_state = "JOB_STATE_SUCCEEDED" ]]; then2087        responses_file_name=$(jq -r '.dest.fileName' batch_status.json)2088        echo "Job succeeded. Downloading results from $responses_file_name..."2089        curl https://generativelanguage.googleapis.com/download/v1beta/$responses_file_name:download?alt=media \2090          -H "x-goog-api-key: $GEMINI_API_KEY" > batch_results.jsonl2091        echo "Results saved to batch_results.jsonl"2092    fi20932094## Technical details20952096- **Supported models:** Batch API supports a range of Gemini models. Refer to the [Models page](https://ai.google.dev/gemini-api/docs/models) for each model's support of Batch API. The supported modalities for Batch API are the same as what's supported on the interactive (or non-batch) API.2097- **Pricing:** Batch API usage is priced at 50% of the standard interactive API cost for the equivalent model. See the [pricing page](https://ai.google.dev/gemini-api/docs/pricing) for details. Refer to the [rate limits page](https://ai.google.dev/gemini-api/docs/rate-limits#batch-mode) for details on rate limits for this feature.2098- **Service level objective (SLO):** Batch jobs are designed to complete within a 24-hour turnaround time. Many jobs may complete much faster depending on their size and current system load.2099- **Caching:** [Context caching](https://ai.google.dev/gemini-api/docs/caching) is supported for batch requests. Reuse cached content by specifying the `cached_content` resource name in the configuration of individual requests within your batch. If a request in your batch results in a cache hit, you pay the [standard context caching rates](https://ai.google.dev/gemini-api/docs/pricing).21002101## Best practices21022103- **Use input files for large requests:** For a large number of requests, always use the file input method for better manageability and to avoid hitting request size limits for the [`BatchGenerateContent`](https://ai.google.dev/api/batch-mode#google.ai.generativelanguage.v1beta.BatchService.BatchGenerateContent) call itself. Note that there's a 2GB file size limit per input file.2104- **Error handling:** Check the `batchStats` for `failedRequestCount` after a job completes. If using file output, parse each line to check if it's a `GenerateContentResponse` or a status object indicating an error for that specific request. See the [troubleshooting2105  guide](https://ai.google.dev/gemini-api/docs/troubleshooting#error-codes) for a complete set of error codes.2106- **Submit jobs once:** The creation of a batch job is not idempotent. If you send the same creation request twice, two separate batch jobs will be created.2107- **Break up very large batches:** While the target turnaround time is 24 hours, actual processing time can vary based on system load and job size. For large jobs, consider breaking them into smaller batches if intermediate results are needed sooner.21082109## What's next21102111- Check out the [Batch API notebook](https://colab.research.google.com/github/google-gemini/cookbook/blob/main/quickstarts/Batch_mode.ipynb) for more examples.2112- The OpenAI compatibility layer supports Batch API. Read the examples on the [OpenAI Compatibility](https://ai.google.dev/gemini-api/docs/openai#batch) page.
Files main
Menu

Theme