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 $10 (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.7-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.7-flash",
input: "Explain how AI works in a few words",
});
console.log(interaction.output_text);
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.7-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.7-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.7-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.7-flash",
input: "Explain how AI works",
stream: true,
});
for await (const event of stream) {
console.log(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.7-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.7-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.7-flash",
input="I have 2 dogs in my house.",
)
print("Response 1:", interaction1.output_text)
interaction2 = client.interactions.create(
model="gemini-3.7-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.7-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.7-flash",
input: "How many paws are in my house?",
previous_interaction_id: interaction1.id,
});
console.log("Response 2:", interaction2.output_text);
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.7-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.7-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.7-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.7-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.7-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.7-flash",
store: false,
input: history
});
console.log("Response 2:", interaction2.steps.at(-1).content[0].text);
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.7-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.7-flash\",
\"store\": false,
\"input\": $HISTORY
}"
Response:
{
"id": "v2_Chd...",
"status": "completed",
"usage": {
"total_tokens": 240,
"total_input_tokens": 60,
"total_output_tokens": 20