Your first LLM API call (free Gemini API)
Get a free Gemini API key, make your first call from Python, control the answer with a config, build a small memory-enabled chatbot and handle rate-limit errors. This one call is the base of every AI feature you will build.
What you will build: a small Python script that sends a question to a Gemini model through the API, prints the answer, reads the token usage, and then becomes a tiny command-line chatbot that remembers the conversation. You will also see the same call in JavaScript.
Prerequisites: Python 3.10 or newer (or Node.js 18+ for the JavaScript version), a Google account, and basic comfort with the terminal. The Gemini API has a free tier with rate limits, so you do not need a credit card to follow this lesson.
What an LLM API call really is
When you chat in an app like Gemini or ChatGPT, a program sends your text to a server and shows what comes back. An LLM API lets your own code do the same. You send a request (a model name, your prompt and some settings) over HTTPS, and you get a response with the generated text and some metadata.
That is all there is to it. Every AI feature in a product, from a support bot to a resume reviewer, starts with this one call. The skill is in what you build around it, which the rest of this track covers.
Anatomy of a request
| Part of the request | What it is | Example |
|---|---|---|
| Model | Which LLM answers | A Gemini Flash model |
| Contents | The prompt, or the whole conversation so far | "Explain DNS in 3 lines" |
| System instruction | Standing rules for the model | "You are a friendly tutor" |
| Config | Settings such as temperature and max output tokens | temperature 0.2 |
| API key | Proves who is calling (and who is billed or rate-limited) | Stored in an environment variable |
Step 1: Get a free API key
Create the key
- 1Open Google AI Studio (aistudio.google.com) and sign in with a Google account.
- 2Choose the option to get an API key and create a key. Copy it.
- 3Treat the key like a password. Anyone who has it can use your quota.
- 4Free-tier limits (requests per minute and per day, and which models are included) change over time. Check the rate-limits page in the Gemini API docs instead of trusting a blog post.
Keep the key secret
Never paste the key into your source code, a GitHub repository, a screenshot or a chat. Bots scan public repositories for keys within minutes. Keep it in an environment variable or a .env file that is listed in .gitignore.
Step 2: Set up the project
mkdir gemini-first-call
cd gemini-first-call
python -m venv .venv
# macOS / Linux
source .venv/bin/activate
# Windows PowerShell
# .venv\Scripts\Activate.ps1
pip install -U google-genai python-dotenvgoogle-genai is Google's official Python SDK. python-dotenv loads variables from a .env file.
Now create two files. The first holds your key. The SDK looks for an environment variable called GEMINI_API_KEY automatically, so you never pass the key in code.
GEMINI_API_KEY=paste-your-key-herePut this file next to your script.
.env
.venv/
__pycache__/Stops you committing your key by accident.
Step 3: Make the call
from dotenv import load_dotenv
from google import genai
load_dotenv() # reads .env so GEMINI_API_KEY is available
# Model names change as new versions ship. Pick a current Flash model
# from the models page in the Gemini API docs and put it here.
MODEL = "gemini-flash-latest"
client = genai.Client() # picks up GEMINI_API_KEY from the environment
response = client.models.generate_content(
model=MODEL,
contents="Explain what DNS is in three short lines for a first-year student.",
)
print(response.text)Sends one prompt and prints the text of the answer.
python first_call.pyDNS is the internet's phone book. It turns a name like example.com into an IP address.
Your browser asks a DNS server first, then connects to the address it gets back.
Without DNS you would have to remember numbers instead of names.Your answer will not match this word for word. LLMs are not deterministic by default, so the same prompt can produce different text each time.
Model not found?
If you get an error about the model not being found, the name in MODEL is probably out of date. Model IDs are retired and new ones appear regularly. Open the models page in the Gemini API docs, copy a current Flash model ID and paste it in. Keep the model name in one constant so changing it is a one-line edit.
A note on APIs. Google also offers a newer "Interactions API" in the same SDK, and its docs now recommend it for new projects, especially for agents. The generate_content call used here remains supported and is the simplest way to learn the ideas. The concepts in this track (prompts, tokens, streaming, schemas, tools) carry over to either.
Step 4: Control the answer with a config
The config argument changes how the model behaves. Three settings matter most at the start.
Common config settings
| Setting | What it does | When to change it |
|---|---|---|
| system_instruction | Standing rules and persona that apply to the whole request | Almost always: set tone, audience, format |
| temperature | Randomness. Lower is steadier, higher is more varied | Low (0 to 0.3) for facts and extraction, higher for brainstorming |
| max_output_tokens | Hard cap on the length of the answer | To protect cost and keep answers short |
from dotenv import load_dotenv
from google import genai
from google.genai import types
load_dotenv()
MODEL = "gemini-flash-latest"
client = genai.Client()
response = client.models.generate_content(
model=MODEL,
contents="What should I order at a coffee shop if I want something strong but not bitter?",
config=types.GenerateContentConfig(
system_instruction=(
"You are a barista at Brew & Bean in Indiranagar, Bengaluru. "
"Answer in at most two sentences. Be friendly and plain."
),
temperature=0.4,
max_output_tokens=300,
),
)
print(response.text)
print("Why it stopped:", response.candidates[0].finish_reason)
print("Prompt tokens:", response.usage_metadata.prompt_token_count)
print("Total tokens:", response.usage_metadata.total_token_count)Adds a system instruction, temperature and a length cap, then prints usage numbers.
A tiny token cap can give an empty answer
Some current Gemini models "think" before answering, and those thinking tokens can count against max_output_tokens. If you set a very small cap, you may get an empty or cut-off answer. Start with a generous cap (a few hundred tokens or more) and check finish_reason. The next lesson explains tokens and cost in detail.
Step 5: Add memory with a chat
The API is stateless: each call knows nothing about the previous one. A chatbot feels like it remembers because the program sends the earlier messages again each time. The SDK's chat helper does this bookkeeping for you.
from dotenv import load_dotenv
from google import genai
from google.genai import types
load_dotenv()
MODEL = "gemini-flash-latest"
client = genai.Client()
chat = client.chats.create(
model=MODEL,
config=types.GenerateContentConfig(
system_instruction="You are a patient tutor. Keep answers under 80 words."
),
)
print("Type 'quit' to stop.")
while True:
user = input("You: ").strip()
if user.lower() in {"quit", "exit"}:
break
if not user:
continue
reply = chat.send_message(user)
print("AI:", reply.text, "\n")A loop that keeps the conversation history inside chat.
You: What is a primary key?
AI: A primary key is a column (or set of columns) that uniquely identifies each row in a table...
You: Give me an example with students.
AI: In a students table, `student_id` can be the primary key...Notice that the second question says "an example" without repeating the topic. It works because the history was sent again. This also means long chats cost more: every turn re-sends everything before it. The next lesson shows how to measure that.
The same call in JavaScript
mkdir gemini-js && cd gemini-js
npm init -y
npm install @google/genaiAlso set "type": "module" in package.json so import works.
import { GoogleGenAI } from "@google/genai";
// Node 20.6+: run with node --env-file=.env first_call.mjs
const ai = new GoogleGenAI({}); // reads GEMINI_API_KEY from the environment
const response = await ai.models.generateContent({
model: "gemini-flash-latest", // use a current model ID
contents: "Explain what DNS is in three short lines.",
});
console.log(response.text);Same request as the Python version.
Keep keys on the server
Never call the Gemini API directly from browser JavaScript with your key. Anyone can open DevTools and copy it. Call the API from a backend you control and let your frontend call your backend.
Handling errors
Real calls fail: the network drops, you hit a rate limit (HTTP 429), or the service is briefly overloaded (HTTP 503). Free tiers hit rate limits quickly during testing. A small retry with waiting makes scripts far more reliable.
import time
from google.genai import errors
def ask(client, model, prompt, retries=3):
for attempt in range(retries):
try:
return client.models.generate_content(model=model, contents=prompt).text
except errors.APIError as e:
# 429 = rate limited, 5xx = server trouble: wait and retry
if e.code in (429, 500, 503) and attempt < retries - 1:
time.sleep(2 ** attempt) # 1s, 2s, 4s...
continue
raiseExponential backoff: wait longer after each failure. Other errors, such as 400 or 403, are your fault and should not be retried.
I called the Gemini API with the Python google-genai SDK and got this error:
[paste the full error]
Here is my code:
[paste the code, with the API key removed]
Explain what the error means in plain English, list the 3 most likely causes in order, and tell me how to check each one.What to expect: A good answer separates auth errors (key missing or wrong), quota errors (429) and request errors (bad model name or parameters). Remove your key before pasting.
Try it: Build a one-shot summariser
Write summarise.py that reads a text file named on the command line (python summarise.py notes.txt), sends it to the model with a system instruction that asks for exactly five bullet points in simple English, and prints the bullets and the token count.
Before you move on
- API key is in
.envand.envis in.gitignore - Model name lives in one constant
- Short
max_output_tokensis not choking the answer - Errors 429 and 503 are retried, other errors are not
- The key is only used on a server, never in browser code
Key takeaways
- An LLM API call sends a model name, your prompt and settings, and returns text plus usage metadata.
- Get a free key from Google AI Studio, keep it in an environment variable and never commit it.
generate_contentis one-shot; the API is stateless, so a chat re-sends the history each turn.- System instruction sets the rules, temperature sets randomness, max output tokens caps length.
- Retry 429 and 5xx errors with growing waits; fix 4xx errors instead.
- Model IDs change often: keep one constant and check the models page in the docs.
Check yourself
Finishing the quiz marks the lesson as done.
1. Why does a chatbot built on an LLM API "remember" earlier messages?
2. Where should the Gemini API key be stored in a web app?
3. You set max_output_tokens=20 and get a cut-off or empty reply. What is the best first fix?
4. Which errors are worth retrying with a delay?
5. When is a low temperature (about 0 to 0.3) the better choice?
Saved on this device. Create a free account to keep it on every device.
Practise this with Sam
A real mock interview, out loud, with an honest scorecard. Free to start.