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