From key to code
In Level 1 you got an API key from Google AI Studio. Now you'll use it from your own code. Google ships one Gen AI SDK per language. For Python it's the google-genai package and for JavaScript/TypeScript it's @google/genai. Both talk to the same Gemini API. Think of the SDK as a well-typed HTTP client: it builds the request, sends it, and gives you back a response object you can look inside.
In this level you will:
- install the SDK and set your key,
- make one
generate_contentcall, - look inside the response,
- break things on purpose so you can see what the errors look like.
Two API styles, one honest note. Google's newest docs lead with the Interactions API (
client.interactions.create(...), read withinteraction.output_text). Google calls it generally available, recommends it for new projects, and says new features will launch there first. The oldergenerateContentmethod is still fully supported, and the SDK documents it in detail. We start withgenerate_contentbecause its response shows the basics clearly: candidates, finish reasons and token counts. Everything you learn here carries over.
Step 1: Install and set the key
# Python (use a virtual environment)
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -U google-genai
# Node (the SDK needs Node 20+, and its 3.x releases need Node 22+)
npm init -y
npm install @google/genai
Put the key in an environment variable, never in your source code:
export GEMINI_API_KEY="paste-your-key" # macOS/Linux
$env:GEMINI_API_KEY = "paste-your-key" # Windows PowerShell
Gotcha: the Python SDK reads
GEMINI_API_KEYorGOOGLE_API_KEY. If both are set,GOOGLE_API_KEYwins. If you set a new key and still get "invalid key", look for an oldGOOGLE_API_KEYleft in your shell profile.
Step 2: Your first call
Python (hello.py):
from google import genai
client = genai.Client() # reads the key from the environment
response = client.models.generate_content(
model="gemini-3.8-flash", # a current stable Flash model; check the models page
contents="Explain what an HTTP 429 status means in one sentence.",
)
print(response.text) # shortcut: the text of the first candidate
Node (hello.mjs):
import { GoogleGenAI } from "@google/genai";
const ai = new GoogleGenAI({ apiKey: process.env.GEMINI_API_KEY });
const response = await ai.models.generateContent({
model: "gemini-3.8-flash",
contents: "Explain what an HTTP 429 status means in one sentence.",
});
console.log(response.text);
Run python hello.py or node hello.mjs. You should see one sentence about rate limiting. If you do, you've proved three things at once: the key works, the network path is open, and the model name is valid.
Model names change often. Google retires and renames models every few months. The SDK's own README uses the alias
gemini-flash-latest, which moves when Google promotes a new model. Aliases are handy for experiments. In production, pin an exact name so the model doesn't change under you. Level 3 covers how to choose one.
Step 3: Look inside the response
response.text is a shortcut. Here is what sits underneath it:
cand = response.candidates[0] # usually exactly one candidate
print("finish:", cand.finish_reason) # e.g. FinishReason.STOP
u = response.usage_metadata
print("prompt tokens:", u.prompt_token_count)
print("output tokens:", u.candidates_token_count)
print("thinking tokens:", u.thoughts_token_count) # may be None
print("total tokens:", u.total_token_count)
print("model:", response.model_version)
In Node the same fields use camelCase: response.candidates[0].finishReason, response.usageMetadata.totalTokenCount.
Typical output:
finish: FinishReason.STOP
prompt tokens: 14
output tokens: 27
thinking tokens: 180
total tokens: 221
Why each field matters:
finish_reasontells you why the model stopped.STOPmeans it finished normally.MAX_TOKENSmeans it hit the output cap, so the answer is cut off.SAFETYmeans the content was blocked. Check this before you trust the text. A truncated JSON answer will break your parser later.usage_metadatais what you pay for. Thinking tokens are real tokens too, which is why the total can be much bigger than the visible answer. Log these numbers from day one.candidatesis a list because the API can return more than one alternative. Most apps read index 0.
Step 4: Break it on purpose
Good engineers learn the failure modes before production shows them. The Python SDK raises errors.APIError, which carries an HTTP code and a message:
import time
from google import genai
from google.genai import errors
client = genai.Client()
def ask(prompt, model="gemini-3.8-flash", retries=4):
for attempt in range(retries):
try:
return client.models.generate_content(model=model, contents=prompt).text
except errors.APIError as e:
if e.code in (429, 500, 503): # temporary: back off and retry
wait = 2 ** attempt # 1s, 2s, 4s, 8s
print(f"{e.code}, retrying in {wait}s")
time.sleep(wait)
else: # 400/403/404: fix the request
raise
raise RuntimeError("gave up after retries")
print(ask("Say hi", model="gemini-9-ultra")) # try a made-up model name
The three errors to recognise:
| Symptom | Typical code | What to do |
|---|---|---|
| Missing, wrong or revoked key | 403 (or a client error before the request is even sent if no key is found) | Fix the environment variable. Don't retry. |
| Unknown or retired model name | 404 NOT_FOUND |
Check the model list. Don't retry. |
| Too many requests or tokens | 429 RESOURCE_EXHAUSTED |
Back off exponentially, then retry. |
In Node, catch the error and read e.status and e.message. The SDK's ApiError class exposes both.
Best practice: retry only temporary errors (429, 500, 503). Retrying a 403 or 404 just burns time and quota. A 429 that says your daily quota is used up won't clear in eight seconds, so read the message before you assume it's a per-minute limit.
Check your work
hello.py(or.mjs) prints a sentence, andfinish_reasonisSTOP.total_token_countis roughly the sum of the prompt, output and thinking counts.- The made-up model name raises a 404 right away, with no retries.
- With
GEMINI_API_KEYunset, the script fails with a clear key error.
Key takeaways
- Install
google-genai(Python) or@google/genai(Node). Keep the key inGEMINI_API_KEY, and rememberGOOGLE_API_KEYtakes precedence in Python. generate_contentis still fully supported. Google now recommends the Interactions API for new projects.- Check
finish_reasonbefore you trustresponse.text, and logusage_metadatato track cost. - 403 and 404 mean fix your request. 429 and 5xx mean back off and retry.
- Model names change, so check them against Google's current models page.