Chapter 20: Exercises
Working with External APIs and Integrations
These exercises progress from foundational knowledge through advanced application. Complete them in order, as later exercises build on skills developed in earlier ones.
Tier 1: Remember and Understand (Exercises 1-6)
Exercise 1: API Authentication Methods
List the four most common API authentication methods discussed in this chapter. For each, provide a one-sentence description and an example of when you would use it.
Exercise 2: OAuth 2.0 Flow Identification
For each of the following scenarios, identify the appropriate OAuth 2.0 grant type and explain your reasoning: - A web application that needs to access a user's Google Calendar - A backend service that processes nightly analytics from a third-party API - A command-line tool that needs to authenticate a developer with GitHub - A single-page React application that needs to access a user's Dropbox files
Exercise 3: Circuit Breaker States
Draw a state diagram showing the three states of a circuit breaker (Closed, Open, Half-Open). Label each transition with the condition that triggers it. Then explain in your own words why the Half-Open state is necessary.
Exercise 4: Rate Limit Headers
Given the following HTTP response headers, answer the questions below:
HTTP/1.1 200 OK
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 15
X-RateLimit-Reset: 1700000000
Retry-After: 45
- What is the maximum number of requests allowed in the current window?
- How many requests can the client still make?
- What should the client do if it receives a 429 response with these headers?
Exercise 5: Webhook vs. Polling
Compare webhooks and polling for receiving updates from an external service. Create a table with at least five criteria (e.g., latency, complexity, resource usage) and evaluate each approach against those criteria.
Exercise 6: Idempotency in Payments
Explain why idempotency keys are critical for payment processing. Describe a specific scenario where the lack of an idempotency key could lead to a customer being charged twice. Then explain how an idempotency key prevents this.
Tier 2: Apply (Exercises 7-12)
Exercise 7: Basic API Client
Write a Python class GitHubAPIClient that:
- Uses httpx to make requests to the GitHub REST API
- Accepts a personal access token for authentication
- Implements methods: get_user(username), list_repos(username), and get_repo(owner, repo)
- Sets appropriate timeouts and headers
- Raises meaningful exceptions on errors
Exercise 8: Token Refresh Implementation
Implement a TokenManager class that:
- Stores an access token and its expiration time
- Provides a method get_token() that returns a valid token
- Automatically refreshes the token when it is within 60 seconds of expiring
- Uses a mock token endpoint (you can simulate the HTTP call)
- Includes proper error handling for failed refresh attempts
Exercise 9: Retry with Exponential Backoff
Write a function retry_request() that:
- Accepts an async function and its arguments
- Retries on 5xx errors and connection timeouts
- Uses exponential backoff with jitter
- Has a configurable maximum number of retries (default 3)
- Has a configurable maximum delay (default 60 seconds)
- Does NOT retry on 4xx errors (except 429)
- For 429 errors, respects the Retry-After header
Exercise 10: Webhook Signature Verification
Implement a FastAPI endpoint that:
- Receives webhook payloads at POST /webhooks/github
- Verifies the X-Hub-Signature-256 header using HMAC-SHA256
- Parses the event type from the X-GitHub-Event header
- Routes events to appropriate handler functions (at least: push, pull_request, issues)
- Returns 401 for invalid signatures and 200 for successfully processed events
Exercise 11: Simple Rate Limiter
Implement a SlidingWindowRateLimiter class that:
- Tracks request timestamps in a sliding window
- Accepts max_requests and window_seconds parameters
- Provides an async acquire() method that blocks until a request can be made
- Provides a can_proceed() method that returns True/False without blocking
- Cleans up old timestamps to prevent memory leaks
Exercise 12: Email Service Abstraction
Create an EmailService abstract base class and two concrete implementations:
- SendGridEmailService that formats requests for the SendGrid API
- MailgunEmailService that formats requests for the Mailgun API
- Both should implement send(to, subject, html_body, text_body) and send_template(to, template_id, variables)
- Write a factory function that returns the appropriate implementation based on a configuration string
Tier 3: Analyze (Exercises 13-18)
Exercise 13: API Client Code Review
Review the following API client code and identify at least five problems. For each problem, explain the issue and provide the corrected code:
import requests
def get_weather(city):
url = f"http://api.weather.com/v1/weather?city={city}&key=abc123hardcoded"
response = requests.get(url)
return response.json()
def get_forecast(city, days):
url = f"http://api.weather.com/v1/forecast?city={city}&days={days}&key=abc123hardcoded"
response = requests.get(url)
data = response.json()
return data["forecast"]["daily"]
Exercise 14: Rate Limit Strategy Analysis
A service you depend on has the following rate limits: - 100 requests per minute for the standard tier - Burst allowance of 10 requests per second - Daily limit of 10,000 requests - Each request can return up to 100 items
Your application needs to sync 50,000 items per day. Analyze the rate limits and design a strategy that: 1. Stays within all rate limit tiers 2. Maximizes throughput 3. Handles the case where rate limits are temporarily exceeded 4. Includes a fallback plan if the daily limit is reached before all items are synced
Exercise 15: OAuth Security Analysis
Analyze the following OAuth implementation and identify security vulnerabilities:
@app.get("/auth/callback")
async def oauth_callback(code: str, state: str):
# Exchange code for token
token_response = await httpx.AsyncClient().post(
"https://auth.example.com/token",
data={
"grant_type": "authorization_code",
"code": code,
"client_id": "my_client_id",
"client_secret": "my_secret_embedded_here",
"redirect_uri": "http://localhost:8000/auth/callback",
},
)
token_data = token_response.json()
# Store token in cookie
response = RedirectResponse("/dashboard")
response.set_cookie("access_token", token_data["access_token"])
return response
List every security issue you can find, explain why each is problematic, and provide the corrected implementation.
Exercise 16: Webhook Reliability Analysis
Your application receives webhooks from a payment processor. Analyze the following scenario and answer the questions:
- A webhook is sent but your server is temporarily down. The payment processor retries 3 times over 24 hours. What mechanisms should you have in place to handle this?
- Your server receives the same webhook event 4 times (initial + 3 retries) because your 200 responses were not received by the payment processor due to network issues. How do you ensure the order is only fulfilled once?
- A webhook arrives for a payment success, but the corresponding order does not exist in your database yet (race condition). How do you handle this?
Exercise 17: Integration Architecture Comparison
Compare two architectures for an e-commerce checkout system:
Architecture A: Synchronous - Client submits order - Server creates payment, sends email, generates invoice, updates inventory -- all in the request handler - Returns result to client
Architecture B: Event-Driven - Client submits order - Server creates payment and publishes an "order.created" event - Background workers handle email, invoice, inventory updates - Client polls for status or receives WebSocket updates
For each architecture, analyze: reliability, latency, complexity, error handling, and scalability. Which would you recommend for a startup vs. a large-scale operation? Explain your reasoning.
Exercise 18: API Dependency Mapping
You are building a travel booking application that depends on these external services: - Flight search API (3 providers for redundancy) - Hotel search API (2 providers) - Payment processor - Email service - SMS notification service - Currency exchange rate API - Weather API for destination forecasts
Create a dependency map showing: 1. Which services are critical (booking fails without them) vs. optional (booking succeeds but with degraded experience) 2. Which services can be cached and for how long 3. Which services need real-time data 4. Your fallback strategy for each service category
Tier 4: Evaluate (Exercises 19-24)
Exercise 19: SDK vs. Direct API Calls
Evaluate the trade-offs between using an official SDK (e.g., stripe Python package) versus making direct HTTP calls (e.g., httpx) for the following criteria:
- Maintenance burden
- Flexibility
- Testing
- Dependency management
- Documentation
- Error handling
- Performance
For a new project, write a recommendation with justification for when to use each approach.
Exercise 20: Circuit Breaker Tuning
You have a circuit breaker protecting calls to an email service. Evaluate the following configurations and recommend the best one for a production e-commerce application. Justify your choice.
Config A: failure_threshold=3, recovery_timeout=10s, success_threshold=1 Config B: failure_threshold=5, recovery_timeout=30s, success_threshold=2 Config C: failure_threshold=10, recovery_timeout=120s, success_threshold=5
Consider: What happens during brief network blips? What about sustained outages? What about slow recovery scenarios?
Exercise 21: Payment Integration Comparison
Compare two approaches to payment integration:
Approach A: Client-Side Tokenization - Client-side JavaScript widget collects card details - Card details sent directly to payment processor - Token returned to client, then sent to your server - Server creates payment using token
Approach B: Server-Side Redirect - Server creates a checkout session with the payment processor - Client is redirected to the payment processor's hosted page - Payment processor redirects back to your server after payment - Server receives payment confirmation via redirect and webhook
Evaluate each approach for: PCI compliance burden, user experience, customization ability, mobile support, and error handling complexity.
Exercise 22: Retry Strategy Evaluation
Evaluate the following retry strategies for a critical API call that sends appointment reminders via SMS:
- Immediate retry: Retry up to 3 times with no delay
- Fixed delay: Retry up to 3 times with 5-second delay
- Exponential backoff: Retry up to 5 times with 1s, 2s, 4s, 8s, 16s delays
- Exponential backoff with jitter: Same as above but with random 0-1s added to each delay
- Exponential backoff with dead letter queue: Retry 3 times, then send to a queue for manual review
Which strategy would you recommend and why? What factors influenced your decision?
Exercise 23: API Versioning Impact Assessment
An external API you depend on announces they are deprecating v2 and migrating to v3. The changes include: - Different authentication method (API key in header instead of query parameter) - Changed response format (nested objects instead of flat) - New required fields on several endpoints - Removed two endpoints you use (replaced by one combined endpoint) - Rate limits changed from 100/min to 60/min
Evaluate the impact on your application and create a migration plan. Consider: How do you run both versions simultaneously during migration? How do you test the migration? What is your rollback plan?
Exercise 24: Multi-Provider Fallback Evaluation
Design and evaluate a fallback system for an email sending service that uses three providers (SendGrid, Mailgun, Amazon SES). Consider: 1. How do you detect that a provider is failing? 2. In what order do you try providers? 3. How do you prevent duplicate sends when failing over? 4. How do you handle the case where all providers are down? 5. How do you automatically recover when a failed provider comes back online?
Write the evaluation as a design document with trade-offs clearly stated.
Tier 5: Create (Exercises 25-30)
Exercise 25: Universal API Client Library
Build a reusable Python library called api_toolkit that provides:
- A base APIClient class with configurable retry logic, rate limiting, and circuit breaker
- Automatic request/response logging
- Token management with automatic refresh
- Response caching with configurable TTL
- A clean interface for subclassing to create service-specific clients
Write at least three service-specific clients using your library (e.g., GitHub, weather, currency exchange).
Exercise 26: Webhook Testing Framework
Create a webhook testing tool that:
- Runs a local HTTP server to receive webhooks
- Generates properly signed test payloads for common services (Stripe, GitHub)
- Records all received webhooks with full headers and body
- Provides assertion helpers (e.g., assert_received(event_type="payment.succeeded"))
- Supports replaying recorded webhooks
- Can be used as a pytest fixture
Exercise 27: Integration Health Dashboard
Build a FastAPI application that: - Monitors the health of 5+ external service integrations - Periodically checks each service's availability and response time - Displays a dashboard showing current status, uptime percentage, and response time graphs - Sends alerts (via one of the monitored services, with fallback) when a service goes down - Provides a REST API for programmatic health checks - Stores historical health data
Exercise 28: Multi-Service Data Aggregator
Build a data aggregation service that: - Accepts a city name and returns a comprehensive profile including: - Current weather (from a weather API) - Geographic coordinates (from a geocoding API) - Current time and timezone - Currency information for the country - A relevant news headline - Fetches all data concurrently - Caches results appropriately (different TTLs for different data types) - Handles partial failures gracefully (returns available data with indicators for failed services) - Includes comprehensive error handling and logging
Exercise 29: Payment Integration Test Suite
Create a comprehensive test suite for a payment integration that: - Tests the complete payment lifecycle: create intent, confirm, capture, refund - Tests error scenarios: declined cards, expired cards, insufficient funds, network timeouts - Tests webhook handling: signature verification, event routing, idempotent processing - Tests concurrent payment processing - Uses mocks for unit tests and a sandbox environment for integration tests - Generates a coverage report showing which payment scenarios are tested
Exercise 30: Integration Orchestration System
Build a complete integration orchestration system for an e-commerce platform that: - Receives order events and coordinates multiple external service calls - Implements the Saga pattern for distributed transactions (e.g., if email fails after payment succeeds, the system tracks the failure and retries) - Provides a retry queue with configurable retry policies per service - Implements circuit breakers for each external service - Logs all integration events in a structured format for debugging - Provides an admin API to view integration status, retry failed operations, and manually trigger integrations - Includes comprehensive tests with mocked external services
Submission Guidelines
- All Python code must include type hints, docstrings, and follow PEP 8 conventions.
- Include a
requirements.txtlisting all dependencies. - Write at least 3 unit tests for each coding exercise.
- For Tier 4-5 exercises, include a brief write-up (200-500 words) explaining your design decisions.
- Use environment variables for all secrets and API keys -- never hardcode them.