This guide gets you started with the Gemini API using the Interactions API. You'll make your first API call in under a minute and explore text generation, multimodal understanding, image generation, structured output, tools, function calling, agents, and background execution.
The Interactions API is available through the Python and JavaScript SDKs, as well as through REST.
1. Get an API key
To use the Gemini API, you need to have an API key to authenticate your requests, enforce security limits, and track usage to your account.
- Google AI Studio automatically creates a project and API key for new users. You can copy it from the API keys page.
- If you need a new key, click Create API key in AI Studio and follow the dialog to add a new key-project pair.
Set your key as an environment variable:
export GEMINI_API_KEY="YOUR_API_KEY"
Upgrade to the paid tier
Upgrading to the paid tier increases your rate limits and requires setting up Cloud Billing.
- Click Set up billing on the AI Studio API keys or Projects pages.
- Follow the Cloud Billing dialog to create or link a billing account, add a payment method, and prepay a minimum of $5 (or currency equivalent) in paid credits.
- View your API usage in Google AI Studio under Dashboard > Usage.
See the Billing page for more information.
2. Install the SDK and make your first call
Install the SDK and generate text with a single API call.
Python
Install the SDK:
pip install -U google-genai
Initialize the client and make a request:
from google import genai
client = genai.Client()
interaction = client.interactions.create(
model="gemini-3.8-flash",
input="Explain how AI works in a few words"
)
print(interaction.output_text)
JavaScript
Install the SDK:
npm install @google/genai
Initialize the client and make a request:
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({});
const interaction = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "Explain how AI works in a few words",
});
console.log(interaction.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
Client client = new Client();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Explain how AI works in a few words"))
.build();
Interaction interaction =
client.interactions.create(CreateInteractionRequestBody.of(params)).interaction().get();
System.out.println(interaction.outputText().orElse(""));
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "gemini-3.8-flash",
"input": "Explain how AI works in a few words"
}'
Response:
{
"id": "v1_ChdpQUFvYXI...",
"status": "completed",
"usage": {
"total_tokens": 197,
"total_input_tokens": 8,
"total_output_tokens": 12
},
"created": "2026-06-09T12:01:25Z",
"steps": [
{
"type": "thought",
"signature": "EvEFCu4FAQw..."
},
{
"type": "model_output",
"content": [
{
"type": "text",
"text": "AI learns patterns from data, then uses those patterns to make predictions or decisions on new data."
}
]
}
],
"object": "interaction",
"model": "gemini-3.8-flash",
}
When using REST, the API returns the full Interaction resource containing metadata, usage statistics, and the step-by-step history of the turn.
While the SDKs expose the full response, they also provide convenience properties like interaction.output_text and interaction.output_image to access final outputs directly. Learn more about the response structure in the Interactions overview or read the text generation guide for details on system instructions and generation config.
3. Stream the response
For more fluid interactions, stream the response as it's generated. Each step.delta event delivers a chunk of text you can display immediately.
Python
from google import genai
client = genai.Client()
stream = client.interactions.create(
model="gemini-3.8-flash",
input="Explain how AI works",
stream=True
)
for event in stream:
print(event)
JavaScript
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({});
const stream = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "Explain how AI works",
stream: true,
});
for await (const event of stream) {
console.log(event);
}
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.InteractionSSEStreamEvent;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import com.google.genai.gaos.models.operations.CreateInteractionResponse;
import com.google.genai.gaos.utils.EventStream;
Client client = new Client();
CreateModelInteraction params =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("Explain how AI works"))
.stream(true)
.build();
CreateInteractionResponse response =
client.interactions.create(CreateInteractionRequestBody.of(params));
try (EventStream<InteractionSSEStreamEvent> stream = response.events()) {
for (InteractionSSEStreamEvent event : stream) {
System.out.println(event);
}
}
REST
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions?alt=sse" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
--no-buffer \
-d '{
"model": "gemini-3.8-flash",
"input": "Explain how AI works",
"stream": true
}'
When streaming, the server responds with a stream of server-sent events (SSE). Each event includes a type and JSON data.
Response:
event: interaction.created
data: {"interaction":{"id":"v1_Chd...","status":"in_progress","model":"gemini-3.8-flash"},"event_type":"interaction.created"}
event: step.start
data: {"index":0,"step":{"type":"thought"},"event_type":"step.start"}
event: step.delta
data: {"index":0,"delta":{"signature":"EvEFCu4F...","type":"thought_signature"},"event_type":"step.delta"}
event: step.stop
data: {"index":0,"event_type":"step.stop"}
event: step.start
data: {"index":1,"step":{"type":"model_output"},"event_type":"step.start"}
event: step.delta
data: {"index":1,"delta":{"text":"AI ","type":"text"},"event_type":"step.delta"}
event: step.delta
data: {"index":1,"delta":{"text":"works ","type":"text"},"event_type":"step.delta"}
event: step.stop
data: {"index":1,"event_type":"step.stop"}
event: interaction.completed
data: {"interaction":{"id":"v1_Chd...","status":"completed","usage":{"total_tokens":197}},"event_type":"interaction.completed"}
For a detailed look at handling streaming events and delta types, see the streaming interactions guide.
4. Multi-turn conversations
The Interactions API supports multi-turn conversations with two approaches:
- Stateful (recommended): Continue a conversation on the server using
previous_interaction_id. Ideal for most chat and agentic workflows where you want the server to manage history and optimize caching. Stateless: Manage the conversation history on the client by passing all previous turns (including intermediate model thought and tool steps) in each request.
Stateful (recommended)
Chain interactions by passing previous_interaction_id. The server manages the full conversation history for you.
Python
from google import genai
client = genai.Client()
# Server-side state (recommended)
interaction1 = client.interactions.create(
model="gemini-3.8-flash",
input="I have 2 dogs in my house.",
)
print("Response 1:", interaction1.output_text)
interaction2 = client.interactions.create(
model="gemini-3.8-flash",
input="How many paws are in my house?",
previous_interaction_id=interaction1.id,
)
print("Response 2:", interaction2.output_text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({});
// Server-side state (recommended)
const interaction1 = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "I have 2 dogs in my house.",
});
console.log("Response 1:", interaction1.output_text);
const interaction2 = await ai.interactions.create({
model: "gemini-3.8-flash",
input: "How many paws are in my house?",
previous_interaction_id: interaction1.id,
});
console.log("Response 2:", interaction2.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
Client client = new Client();
// Server-side state (recommended)
CreateModelInteraction params1 =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("I have 2 dogs in my house."))
.build();
Interaction interaction1 =
client.interactions.create(CreateInteractionRequestBody.of(params1)).interaction().get();
System.out.println("Response 1: " + interaction1.outputText().orElse(""));
CreateModelInteraction params2 =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.input(InteractionsInput.of("How many paws are in my house?"))
.previousInteractionId(interaction1.id().orElse(""))
.build();
Interaction interaction2 =
client.interactions.create(CreateInteractionRequestBody.of(params2)).interaction().get();
System.out.println("Response 2: " + interaction2.outputText().orElse(""));
REST
RESPONSE1=$(curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "gemini-3.8-flash",
"input": "I have 2 dogs in my house."
}')
INTERACTION_ID=$(echo "$RESPONSE1" | jq -r '.id')
echo "Interaction 1 ID: $INTERACTION_ID"
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "gemini-3.8-flash",
"input": "How many paws are in my house?",
"previous_interaction_id": "'$INTERACTION_ID'"
}'
Stateless
Set store=false and manage conversation history on the client side. You must preserve and resend all model-generated steps (including thought and function_call steps) exactly as received.
Python
from google import genai
client = genai.Client()
history = [
{
"type": "user_input",
"content": [{"type": "text", "text": "I have 2 dogs in my house."}]
}
]
interaction1 = client.interactions.create(
model="gemini-3.8-flash",
store=False,
input=history
)
print("Response 1:", interaction1.steps[-1].content[0].text)
for step in interaction1.steps:
history.append(step.model_dump())
history.append({
"type": "user_input",
"content": [{"type": "text", "text": "How many paws are in my house?"}]
})
interaction2 = client.interactions.create(
model="gemini-3.8-flash",
store=False,
input=history
)
print("Response 2:", interaction2.steps[-1].content[0].text)
JavaScript
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({});
const history = [
{
type: "user_input",
content: [{ type: "text", text: "I have 2 dogs in my house." }]
}
];
const interaction1 = await ai.interactions.create({
model: "gemini-3.8-flash",
store: false,
input: history
});
console.log("Response 1:", interaction1.steps.at(-1).content[0].text);
history.push(...interaction1.steps);
history.push({
type: "user_input",
content: [{ type: "text", text: "How many paws are in my house?" }]
});
const interaction2 = await ai.interactions.create({
model: "gemini-3.8-flash",
store: false,
input: history
});
console.log("Response 2:", interaction2.steps.at(-1).content[0].text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.Step;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.interactions.UserInputStep;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
Client client = new Client();
List<Step> history = new ArrayList<>();
history.add(
UserInputStep.builder()
.content(Arrays.asList(TextContent.builder().text("I have 2 dogs in my house.").build()))
.build());
CreateModelInteraction params1 =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.store(false)
.input(InteractionsInput.ofStep(history))
.build();
Interaction interaction1 =
client.interactions.create(CreateInteractionRequestBody.of(params1)).interaction().get();
System.out.println("Response 1: " + interaction1.outputText().orElse(""));
interaction1.steps().ifPresent(history::addAll);
history.add(
UserInputStep.builder()
.content(Arrays.asList(TextContent.builder().text("How many paws are in my house?").build()))
.build());
CreateModelInteraction params2 =
CreateModelInteraction.builder()
.model(Model.of("gemini-3.8-flash"))
.store(false)
.input(InteractionsInput.ofStep(history))
.build();
Interaction interaction2 =
client.interactions.create(CreateInteractionRequestBody.of(params2)).interaction().get();
System.out.println("Response 2: " + interaction2.outputText().orElse(""));
REST
# Turn 1: Send with store: false
RESPONSE1=$(curl -s -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"model": "gemini-3.8-flash",
"store": false,
"input": [
{
"type": "user_input",
"content": "I have 2 dogs in my house."
}
]
}')
MODEL_STEPS=$(echo "$RESPONSE1" | jq '.steps')
# Turn 2: Build full history
HISTORY=$(jq -n \
--argjson first_input '[{"type": "user_input", "content": "I have 2 dogs in my house."}]' \
--argjson model_steps "$MODEL_STEPS" \
--argjson second_input '[{"type": "user_input", "content": "How many paws are in my house?"}]' \
'$first_input + $model_steps + $second_input')
curl -X POST "https://generativelanguage.googleapis.com/v1beta/interactions" \
-H "x-goog-api-key: $GEMINI_API_KEY" \
-H 'Content-Type: application/json' \
-d "{
\"model\": \"gemini-3.8-flash\",
\"store\": false,
\"input\": $HISTORY
}"
Response:
{
"id": "v2_Chd...",
"status": "completed",
"usage": {
"total_tokens": 240,
"total_input_tokens": 60,
"total_output_tokens": 20
},
"steps": [
{
"type": "model_output",
"content": [
{
"type": "text",
"text": "There are 8 paws in your house. 2 dogs \u00d7 4 paws = 8 paws."
}
]
}
],
"object": "interaction",
"model": "gemini-3.8-flash"
}
The second interaction returns a complete response object that includes only the new steps, but is grounded in the previous turn's context. Learn more about maintaining state in the multi-turn conversations guide, or explore stateless mode for client-side history management.
5. Multimodal understanding
Gemini models understand images, audio, video, and documents natively. Pass media alongside text in a single request.
Python
import base64
from google import genai
client = genai.Client()
# Load a local image
with open("sample.jpg", "rb") as f:
image_bytes = f.read()
image_b64 = base64.b64encode(image_bytes).decode("utf-8")
interaction = client.interactions.create(
model="gemini-3.8-flash",
input=[
{"type": "text", "text": "Compare this local image and this remote audio file."},
{
"type": "image",
"data": image_b64,
"mime_type": "image/jpeg"
},
{
"type": "audio",
"uri": "https://storage.googleapis.com/generativeai-downloads/data/sample.mp3",
"mime_type": "audio/mp3"
}
]
)
print(interaction.output_text)
JavaScript
import fs from "fs";
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({});
// Load a local image
const imageBytes = fs.readFileSync("sample.jpg");
const imageB64 = imageBytes.toString("base64");
const interaction = await ai.interactions.create({
model: "gemini-3.8-flash",
input: [
{ type: "text", text: "Compare this local image and this remote audio file." },
{
type: "image",
data: imageB64,
mime_type: "image/jpeg"
},
{
type: "audio",
uri: "https://storage.googleapis.com/generativeai-downloads/data/sample.mp3",
mime_type: "audio/mp3"
}
],
});
console.log(interaction.output_text);
Java
import com.google.genai.Client;
import com.google.genai.gaos.models.interactions.AudioContent;
import com.google.genai.gaos.models.interactions.AudioContentMimeType;
import com.google.genai.gaos.models.interactions.CreateModelInteraction;
import com.google.genai.gaos.models.interactions.ImageContent;
import com.google.genai.gaos.models.interactions.ImageContentMimeType;
import com.google.genai.gaos.models.interactions.Interaction;
import com.google.genai.gaos.models.interactions.InteractionsInput;
import com.google.genai.gaos.models.interactions.Model;
import com.google.genai.gaos.models.interactions.TextContent;
import com.google.genai.gaos.models.operations.CreateInteractionRequestBody;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Base64;
Client client = new Client();
// Load a local image
byte[] imageBytes = Files.readAllBytes(Path.of("sample.jpg"