Lesson 15 of 20

Working with APIs

API Authentication

3 min read

APIs need to know who's making requests. Authentication verifies your identity and controls access to resources.

Common Authentication Methods

1. API Key in Header (Most Common for AI)

import requests
import os

headers = {
    "Authorization": f"Bearer {os.getenv('OPENAI_API_KEY')}",
    "Content-Type": "application/json"
}

response = requests.post(url, headers=headers, json=data)

Different providers use different header formats:

ProviderHeader Format
OpenAIAuthorization: Bearer sk-...
Anthropicx-api-key: sk-ant-...
GoogleAuthorization: Bearer ... (OAuth)
CustomOften X-API-Key: ...

2. API Key in Query Parameter

# Less secure - visible in logs!
response = requests.get(
    "https://api.example.com/data",
    params={"api_key": "your-key"}
)

3. Basic Authentication

from requests.auth import HTTPBasicAuth

response = requests.get(
    url,
    auth=HTTPBasicAuth("username", "password")
)

# Or shorthand:
response = requests.get(url, auth=("username", "password"))

Secure Key Management

import os
from dotenv import load_dotenv

# Load from .env file
load_dotenv()

# Get keys securely
OPENAI_KEY = os.getenv("OPENAI_API_KEY")
ANTHROPIC_KEY = os.getenv("ANTHROPIC_API_KEY")

# Validate at startup
if not OPENAI_KEY:
    raise ValueError("OPENAI_API_KEY not set!")

def get_headers(provider="openai"):
    """Get auth headers for different providers."""
    if provider == "openai":
        return {
            "Authorization": f"Bearer {OPENAI_KEY}",
            "Content-Type": "application/json"
        }
    elif provider == "anthropic":
        return {
            "x-api-key": ANTHROPIC_KEY,
            "Content-Type": "application/json",
            "anthropic-version": "2023-06-01"
        }

Creating a Reusable Client

import requests
import os

class AIClient:
    """A simple API client with built-in authentication."""

    def __init__(self, api_key=None):
        self.api_key = api_key or os.getenv("OPENAI_API_KEY")
        self.base_url = "https://api.openai.com/v1"
        self.session = requests.Session()
        self.session.headers.update({
            "Authorization": f"Bearer {self.api_key}",
            "Content-Type": "application/json"
        })

    def chat(self, messages, model="gpt-4"):
        response = self.session.post(
            f"{self.base_url}/chat/completions",
            json={"model": model, "messages": messages},
            timeout=60
        )
        response.raise_for_status()
        return response.json()

# Usage
client = AIClient()
result = client.chat([{"role": "user", "content": "Hello!"}])

Security Best Practices

DoDon't
Store keys in environment variablesHardcode keys in source code
Use .env files locallyCommit .env to git
Rotate keys periodicallyShare keys between projects
Use different keys per environmentUse production keys in development

Next, we'll learn async programming for concurrent API calls. :::

Quick check: how does this lesson land for you?

Quiz

Module 4: Working with APIs

Take Quiz
FREE WEEKLY NEWSLETTER

Stay on the Nerd Track

One email per week — courses, deep dives, tools, and AI experiments.

No spam. Unsubscribe anytime.