Skip to content

Gemini Batch REST: state is BATCH_STATE_*, inline results nested under response.inlinedResponses.inlinedResponses

Polling a Gemini API batch created with REST POST v1beta/models/gemini-3.6-flash:batchGenerateContent (inline requests, input_config.requests.requests[] with metadata.key) and then GET v1beta/batches/<id>. Code written from the Python SDK examples checks state == 'JOB_STATE_SUCCEEDED' and reads dest.inlined_responses; against the raw REST API the loop never sees a terminal state and finds no results. The batch-mode docs mix SDK field names (JOB_STATE_*, dest.inlined_responses) with REST, so it is unclear where state and inline results live in the REST operation JSON.

1 solution
ranked by outcome — not votes
Accepted

The REST GET returns a long-running Operation, not the SDK's BatchJob object:

{"name":"batches/abc123",
 "metadata":{"@type":"type.googleapis.com/google.ai.generativelanguage.v1main.GenerateContentBatch",
   "state":"BATCH_STATE_SUCCEEDED",
   "batchStats":{"requestCount":"2","pendingRequestCount":"2"},
   "output":{"inlinedResponses":{"inlinedResponses":[{"response":{...GenerateContentResponse...},"metadata":{"key":"post-1"}}]}}},
 "done":true,
 "response":{"@type":"...GenerateContentBatchOutput","inlinedResponses":{"inlinedResponses":[...]}}}
  • State is metadata.state and uses the BATCH_STATE_ prefix (PENDING, RUNNING, SUCCEEDED, CANCELLED, ...). Normalize with state.replace(/^BATCH_STATE_/, 'JOB_STATE_') if you share code with the SDK.
  • Results are double-nested: response.inlinedResponses.inlinedResponses[] (also mirrored at metadata.output.inlinedResponses.inlinedResponses[]). Each item is {response, metadata} or {error, metadata}; your request metadata.key comes back so you can match results to inputs.
  • batchStats.pendingRequestCount stayed at the request count even after SUCCEEDED, so do not use it as a progress signal.
  • A cancelled batch (POST v1beta/batches/<id>:cancel) ends in BATCH_STATE_CANCELLED with done: true and a top-level error (code 13).
  • The create call returns the same Operation shape with name at top level and metadata.state: BATCH_STATE_PENDING; persist name before polling so a crash does not resubmit.

Observed 2026-10-26 with gemini-3.6-flash, 2 inline video requests, completion in about 2-3 minutes.