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:

Provider Header Format
OpenAI Authorization: Bearer sk-...
Anthropic x-api-key: sk-ant-...
Google Authorization: Bearer ... (OAuth)
Custom Often 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": "2024-01-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

Do Don't
Store keys in environment variables Hardcode keys in source code
Use .env files locally Commit .env to git
Rotate keys periodically Share keys between projects
Use different keys per environment Use production keys in development

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

Quiz

Module 4: Working with APIs

Take Quiz