Working with APIs

APIs connect your Python scripts to external data: weather forecasts, stock prices, CRM systems, payment gateways. Business analysts use APIs to pull live data into reports, sync systems, and automate workflows. Master APIs and you unlock thousands of data sources.

Estimated reading time: 25–30 minutes

API Basics

  • GET → retrieve data from server
  • POST → send data to server
  • JSON → standard data format for APIs
  • Status codes → 200 OK, 404 Not Found, 500 Error

Great for: fetching live data, integrations

Best Practices

  • Authentication → API keys, tokens for security
  • Error handling → check status codes, handle timeouts
  • Rate limits → respect API usage limits
  • Caching → save responses to reduce API calls

Great for: production-ready integrations

Making GET Requests

GET requests retrieve data from an API endpoint.

python
import requests

# Simple GET request
response = requests.get('https://api.example.com/users')
print(response.status_code)  # 200 = success

# Parse JSON response
data = response.json()
print(data)

# GET with query parameters
params = {'page': 1, 'limit': 10}
response = requests.get('https://api.example.com/users', params=params)
print(response.url)  # shows full URL with params

Making POST Requests

POST requests send data to create or update resources.

python
import requests

# POST with JSON data
payload = {
    'name': 'Ana Garcia',
    'email': 'ana@company.com',
    'role': 'analyst'
}

response = requests.post(
    'https://api.example.com/users',
    json=payload
)

print(response.status_code)  # 201 = created
print(response.json())  # server response

Authentication with API Keys

Most APIs require authentication via API keys or tokens.

python
import requests

# API key in headers
headers = {
    'Authorization': 'Bearer YOUR_API_KEY',
    'Content-Type': 'application/json'
}

response = requests.get(
    'https://api.example.com/data',
    headers=headers
)

# API key in query params (less secure)
params = {'api_key': 'YOUR_API_KEY'}
response = requests.get('https://api.example.com/data', params=params)

Error Handling

Always handle errors: network issues, invalid responses, rate limits.

python
import requests

try:
    response = requests.get(
        'https://api.example.com/data',
        timeout=5  # 5 second timeout
    )
    response.raise_for_status()  # raises error for 4xx/5xx
    
    data = response.json()
    print("Success:", data)
    
except requests.exceptions.Timeout:
    print("Error: Request timed out")
except requests.exceptions.HTTPError as e:
    print("HTTP Error:", e)
except requests.exceptions.RequestException as e:
    print("Error:", e)

Pagination

APIs often return data in pages. Loop through all pages to get complete data.

python
import requests

def fetch_all_pages(base_url):
    all_data = []
    page = 1
    
    while True:
        response = requests.get(base_url, params={'page': page, 'limit': 100})
        response.raise_for_status()
        
        data = response.json()
        if not data:  # no more data
            break
        
        all_data.extend(data)
        page += 1
    
    return all_data

users = fetch_all_pages('https://api.example.com/users')
print("Total users:", len(users))

Cornerstone Project — Currency Exchange Rate Monitor (step-by-step)

Build a tool that fetches live currency exchange rates from an API, tracks changes over time, alerts on significant moves, and exports to CSV. This is useful for finance teams, international businesses, or personal investing.

Step 1 — Choose a free API

Use exchangerate-api.com (free tier available).

python
import requests

# Free API endpoint (replace with your API key)
API_KEY = "your_api_key_here"
BASE_URL = "https://v6.exchangerate-api.com/v6/" + API_KEY

def get_exchange_rates(base_currency="USD"):
    url = BASE_URL + "/latest/" + base_currency
    response = requests.get(url)
    response.raise_for_status()
    return response.json()

# Test it
data = get_exchange_rates("USD")
print("Base:", data['base_code'])
print("Rates:", data['conversion_rates'])

Step 2 — Fetch specific currency pairs

Get rates for currencies you care about.

python
def get_rate(from_currency, to_currency):
    data = get_exchange_rates(from_currency)
    rates = data['conversion_rates']
    return rates.get(to_currency)

# Example: USD to EUR
usd_to_eur = get_rate("USD", "EUR")
print("1 USD =", usd_to_eur, "EUR")

# Multiple pairs
pairs = [("USD", "EUR"), ("USD", "GBP"), ("USD", "JPY")]
for from_curr, to_curr in pairs:
    rate = get_rate(from_curr, to_curr)
    print(from_curr, "to", to_curr, ":", rate)

Step 3 — Track rates over time

Store historical data to detect trends.

python
from datetime import datetime
import json

def save_rate_snapshot(base_currency, currencies):
    data = get_exchange_rates(base_currency)
    
    snapshot = {
        'timestamp': datetime.now().isoformat(),
        'base': base_currency,
        'rates': {curr: data['conversion_rates'][curr] for curr in currencies}
    }
    
    # Append to file
    with open('rate_history.json', 'a') as f:
        f.write(json.dumps(snapshot) + '\n')
    
    return snapshot

# Save snapshot
currencies = ['EUR', 'GBP', 'JPY']
snapshot = save_rate_snapshot('USD', currencies)
print("Saved:", snapshot)

Step 4 — Calculate rate changes

Compare current rate to previous snapshot.

python
def load_rate_history():
    history = []
    try:
        with open('rate_history.json', 'r') as f:
            for line in f:
                history.append(json.loads(line))
    except FileNotFoundError:
        pass
    return history

def calculate_changes(current_snapshot):
    history = load_rate_history()
    if len(history) < 2:
        return {}
    
    previous = history[-2]
    changes = {}
    
    for currency, rate in current_snapshot['rates'].items():
        prev_rate = previous['rates'].get(currency)
        if prev_rate:
            change_pct = ((rate - prev_rate) / prev_rate) * 100
            changes[currency] = round(change_pct, 2)
    
    return changes

# Get changes
snapshot = save_rate_snapshot('USD', ['EUR', 'GBP', 'JPY'])
changes = calculate_changes(snapshot)
print("Changes:", changes)

Step 5 — Alert on significant moves

Flag currencies that moved more than threshold.

python
def check_alerts(changes, threshold=1.0):
    alerts = []
    for currency, change_pct in changes.items():
        if abs(change_pct) >= threshold:
            direction = "up" if change_pct > 0 else "down"
            alerts.append({
                'currency': currency,
                'change': change_pct,
                'direction': direction
            })
    return alerts

# Check for alerts
alerts = check_alerts(changes, threshold=0.5)
if alerts:
    print("ALERTS:")
    for alert in alerts:
        print(" •", alert['currency'], "moved", alert['change'], "%", alert['direction'])
else:
    print("No significant moves")

Step 6 — Export to CSV

Create report for stakeholders.

python
import csv

def export_to_csv(filename='exchange_rates.csv'):
    history = load_rate_history()
    if not history:
        return
    
    # Get all currencies
    currencies = set()
    for snapshot in history:
        currencies.update(snapshot['rates'].keys())
    
    # Write CSV
    with open(filename, 'w', newline='') as f:
        fieldnames = ['timestamp', 'base'] + sorted(currencies)
        writer = csv.DictWriter(f, fieldnames=fieldnames)
        writer.writeheader()
        
        for snapshot in history:
            row = {
                'timestamp': snapshot['timestamp'],
                'base': snapshot['base']
            }
            row.update(snapshot['rates'])
            writer.writerow(row)
    
    print("Exported to", filename)

export_to_csv()

Step 7 — Put it all together

Create monitoring script that runs periodically.

python
def monitor_exchange_rates():
    base = 'USD'
    currencies = ['EUR', 'GBP', 'JPY', 'CAD', 'AUD']
    
    # Fetch current rates
    snapshot = save_rate_snapshot(base, currencies)
    print("Fetched rates for", base)
    
    # Calculate changes
    changes = calculate_changes(snapshot)
    if changes:
        print("Changes since last check:")
        for curr, change in changes.items():
            print(" •", curr, ":", change, "%")
    
    # Check alerts
    alerts = check_alerts(changes, threshold=0.5)
    if alerts:
        print("\nALERTS:")
        for alert in alerts:
            print(" • WARNING:", alert['currency'], "moved", alert['change'], "%")
    
    # Export
    export_to_csv()
    print("\nMonitoring complete!")

# Run it (schedule with cron or Task Scheduler)
monitor_exchange_rates()

How this helps at work

  • Live data → always current, no manual updates
  • Automated alerts → catch significant moves immediately
  • Historical tracking → analyze trends over time
  • Reusable pattern → adapt for stock prices, weather, any API

Key Takeaways

  • GET requests → retrieve data from APIs
  • POST requests → send data to APIs
  • Authentication → API keys in headers or params
  • Error handling → timeouts, HTTP errors, network issues
  • Pagination → loop through pages for complete data
  • Cornerstone → currency monitor tracks live exchange rates

Next Steps

You have mastered API basics. Next, explore authentication methods (OAuth, JWT), or dive intobuilding your own API with Flask or FastAPI.