AI Engineering: Build AI-Powered Apps
Hands-onIntermediate 35 min· Working with LLM APIs · 1 of 19

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 requestWhat it isExample
ModelWhich LLM answersA Gemini Flash model
ContentsThe prompt, or the whole conversation so far"Explain DNS in 3 lines"
System instructionStanding rules for the model"You are a friendly tutor"
ConfigSettings such as temperature and max output tokenstemperature 0.2
API keyProves 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

  1. 1Open Google AI Studio (aistudio.google.com) and sign in with a Google account.
  2. 2Choose the option to get an API key and create a key. Copy it.
  3. 3Treat the key like a password. Anyone who has it can use your quota.
  4. 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

Terminal
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-dotenv

google-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.

.env
GEMINI_API_KEY=paste-your-key-here

Put this file next to your script.

.gitignore
.env
.venv/
__pycache__/

Stops you committing your key by accident.

Step 3: Make the call

first_call.py
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.

Terminal
python first_call.py
Example output (your wording will differ)
DNS 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

SettingWhat it doesWhen to change it
system_instructionStanding rules and persona that apply to the whole requestAlmost always: set tone, audience, format
temperatureRandomness. Lower is steadier, higher is more variedLow (0 to 0.3) for facts and extraction, higher for brainstorming
max_output_tokensHard cap on the length of the answerTo protect cost and keep answers short
first_call_config.py
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.

chat_cli.py
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.

Example session
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

Terminal
mkdir gemini-js && cd gemini-js
npm init -y
npm install @google/genai

Also set "type": "module" in package.json so import works.

first_call.mjs
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.

retry.py
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
            raise

Exponential backoff: wait longer after each failure. Other errors, such as 400 or 403, are your fault and should not be retried.

Prompt · Explain an API error
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

  1. API key is in .env and .env is in .gitignore
  2. Model name lives in one constant
  3. Short max_output_tokens is not choking the answer
  4. Errors 429 and 503 are retried, other errors are not
  5. The key is only used on a server, never in browser code

Key takeaways

  1. An LLM API call sends a model name, your prompt and settings, and returns text plus usage metadata.
  2. Get a free key from Google AI Studio, keep it in an environment variable and never commit it.
  3. generate_content is one-shot; the API is stateless, so a chat re-sends the history each turn.
  4. System instruction sets the rules, temperature sets randomness, max output tokens caps length.
  5. Retry 429 and 5xx errors with growing waits; fix 4xx errors instead.
  6. 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.

Start free