Gemini API — Build AI Apps with Google AI 2026

Sanjeev SharmaSanjeev Sharma
5 min read

Advertisement

Introduction

Why This Matters

The Gemini API provides programmatic access to Google's most capable models, with a free tier through Google AI Studio and competitive pricing for production. Its combination of real-time search access, a 1M-token context window, and the lowest per-token cost among major providers makes it an important option for developers building high-volume or research-heavy AI features. This guide covers everything from first call to production deployment.

Authentication and Setup

Option 1: Google AI Studio (Recommended for development)

  1. Go to aistudio.google.com
  2. Click "Get API key"
  3. Create a new project or use an existing one
  4. Copy the key — it starts with AIza

Option 2: Google Cloud Vertex AI (For enterprise/production)

Uses Google Cloud authentication and supports VPC networking, IAM, and audit logging.

pip install google-generativeai              # Python SDK
npm install @google/generative-ai            # Node.js SDK
# Set your API key
export GOOGLE_API_KEY="AIza..."

Basic Text Generation

import google.generativeai as genai
import os
 
genai.configure(api_key=os.environ["GOOGLE_API_KEY"])
 
model = genai.GenerativeModel(
    model_name="gemini-2.0-flash",
    generation_config={
        "temperature": 0.2,
        "top_p": 0.95,
        "max_output_tokens": 2048,
    },
    system_instruction="You are a senior software architect. Be specific and practical.",
)
 
response = model.generate_content(
    "What are the trade-offs between event sourcing and CRUD for a financial ledger system?"
)
 
print(response.text)
print(f"\nFinish reason: {response.candidates[0].finish_reason}")
print(f"Input tokens: {response.usage_metadata.prompt_token_count}")
print(f"Output tokens: {response.usage_metadata.candidates_token_count}")

Streaming Responses

import google.generativeai as genai
 
genai.configure(api_key="AIza...")
 
model = genai.GenerativeModel("gemini-2.0-flash")
 
def stream_explanation(topic: str) -> str:
    full_text = ""
 
    for chunk in model.generate_content(
        f"Explain {topic} with a practical Python example.",
        stream=True,
    ):
        print(chunk.text, end="", flush=True)
        full_text += chunk.text
 
    print()  # New line after stream ends
    return full_text
 
stream_explanation("Python asyncio event loop internals")

Function Calling

import google.generativeai as genai
import json
 
genai.configure(api_key="AIza...")
 
# Define tools
get_repo_stats = genai.protos.FunctionDeclaration(
    name="get_repo_stats",
    description="Get GitHub repository statistics including stars, forks, and open issues",
    parameters=genai.protos.Schema(
        type=genai.protos.Type.OBJECT,
        properties={
            "owner": genai.protos.Schema(
                type=genai.protos.Type.STRING,
                description="Repository owner or organization",
            ),
            "repo": genai.protos.Schema(
                type=genai.protos.Type.STRING,
                description="Repository name",
            ),
        },
        required=["owner", "repo"],
    ),
)
 
tool = genai.protos.Tool(function_declarations=[get_repo_stats])
 
model = genai.GenerativeModel("gemini-2.0-flash", tools=[tool])
 
def fetch_repo_stats(owner: str, repo: str) -> dict:
    # In production, call GitHub API here
    return {"stars": 12500, "forks": 890, "open_issues": 45, "language": "Python"}
 
def run_agent(question: str) -> str:
    chat = model.start_chat()
    response = chat.send_message(question)
 
    while response.candidates[0].content.parts[0].function_call.name:
        fn_call = response.candidates[0].content.parts[0].function_call
        fn_name = fn_call.name
        fn_args = dict(fn_call.args)
 
        if fn_name == "get_repo_stats":
            result = fetch_repo_stats(**fn_args)
        else:
            result = {"error": f"Unknown function: {fn_name}"}
 
        response = chat.send_message(
            genai.protos.Content(
                parts=[
                    genai.protos.Part(
                        function_response=genai.protos.FunctionResponse(
                            name=fn_name,
                            response=result,
                        )
                    )
                ]
            )
        )
 
    return response.text
 
print(run_agent("How popular is the FastAPI repository on GitHub?"))

Embeddings

Gemini provides text embeddings for semantic search, clustering, and similarity tasks:

import google.generativeai as genai
import numpy as np
 
genai.configure(api_key="AIza...")
 
def get_embedding(text: str) -> list[float]:
    result = genai.embed_content(
        model="models/text-embedding-004",
        content=text,
        task_type="retrieval_document",
    )
    return result["embedding"]
 
def cosine_similarity(a: list[float], b: list[float]) -> float:
    a_arr = np.array(a)
    b_arr = np.array(b)
    return float(np.dot(a_arr, b_arr) / (np.linalg.norm(a_arr) * np.linalg.norm(b_arr)))
 
# Build a simple semantic search
documents = [
    "FastAPI is a modern Python web framework for building APIs",
    "PostgreSQL is an open-source relational database",
    "Docker enables containerized application deployment",
    "Redis is an in-memory data structure store used as a cache",
]
 
doc_embeddings = [get_embedding(doc) for doc in documents]
 
def semantic_search(query: str, top_k: int = 2) -> list[str]:
    query_embedding = get_embedding(query)
    similarities = [cosine_similarity(query_embedding, de) for de in doc_embeddings]
    top_indices = sorted(range(len(similarities)), key=lambda i: similarities[i], reverse=True)[:top_k]
    return [documents[i] for i in top_indices]
 
results = semantic_search("How do I cache database results?")
print(results)  # Returns Redis and PostgreSQL documents as most relevant

JavaScript / TypeScript Integration

import { GoogleGenerativeAI } from '@google/generative-ai';
 
const genAI = new GoogleGenerativeAI(process.env.GOOGLE_API_KEY!);
 
const model = genAI.getGenerativeModel({
  model: 'gemini-2.0-flash',
  systemInstruction: 'You are a TypeScript expert. Provide concise, typed examples.',
});
 
async function generateCode(prompt: string): Promise<string> {
  const result = await model.generateContent(prompt);
  return result.response.text();
}
 
// Streaming in TypeScript
async function streamCode(prompt: string): Promise<void> {
  const result = await model.generateContentStream(prompt);
 
  for await (const chunk of result.stream) {
    const text = chunk.text();
    process.stdout.write(text);
  }
  console.log();
}
 
await streamCode(
  'Write a TypeScript utility type that makes all properties of T optional recursively.'
);

Common Mistakes

  • Using AIza API keys in Vertex AI calls — these are different authentication systems
  • Not checking finish_reasonSAFETY means content was blocked, not a successful response
  • Forgetting genai.configure(api_key=...) before creating a model — results in authentication errors
  • Using embedding models for generation tasks — text-embedding-004 only returns vectors, not text
  • Not handling rate limits — free tier has significant rate limits; production requires billing

Best Practices

  • Set generation_config with explicit max_output_tokens to control cost on every model call
  • Use task_type parameter on embeddings — "retrieval_document" for indexed documents, "retrieval_query" for queries
  • Enable request caching (context caching) for repeated use of the same large document context
  • Monitor usage_metadata on every response for cost tracking and quota management
  • Use Vertex AI for production workloads requiring SLA guarantees, VPC networking, and IAM controls

Key Takeaways

  • The Gemini API is accessed via google-generativeai (Python) or @google/generative-ai (Node.js)
  • API keys from Google AI Studio (AIza...) are separate from Google Cloud service account authentication
  • Function calling in Gemini uses genai.protos.FunctionDeclaration with typed parameter schemas
  • text-embedding-004 provides 768-dimensional embeddings for semantic search and clustering
  • The finish_reason field distinguishes normal completion from safety blocks — always check it in production
  • Free tier at Google AI Studio is generous for development; Vertex AI is the production path for enterprise
  • gemini-2.0-flash is the default choice: fastest, cheapest, 1M context window with real-time search
  • Streaming uses generate_content(..., stream=True) in Python and generateContentStream() in JavaScript

Advertisement

Sanjeev Sharma

Written by

Sanjeev Sharma

Full Stack Engineer · E-mopro

Related reading