Beyond `requests.get`: Why a Simple API Call Reveals Your Engineering Depth
Q: Show how you would use Python to send a GET request to an API and print the response status code.
Why this matters: This is the "hello, world" of microservices and automation. But its simplicity is a deception. They aren't testing your ability to type `requests.get()`. They're testing your awareness of the most common failure point in any distributed system: the network.
Interview frequency: Guaranteed. A building block for countless engineering tasks.
❌ The Death Trap
The trap is assuming the network is reliable and the API is perfect. The candidate writes a single, optimistic line of code that will crash their application the moment reality intervenes.
"The most common—and most dangerous—answer is:"
import requests
response = requests.get('https://api.example.com/data')
print(response.status_code)
This code is a landmine. It will raise an unhandled exception and crash if there's a DNS failure, a network timeout, a connection error, or if the server hangs. This isn't just bad code; it's a denial of how distributed systems actually work.
🔄 The Reframe
What they're really asking: "How do you build a reliable bridge between your system and another? Show me you can handle the inevitable failures of that bridge with grace and intelligence."
This reveals if you practice defensive programming. Modern software is a mesh of conversations between services. Your answer demonstrates whether you can build a polite, resilient conversationalist, or one that hangs up and crashes at the first sign of a bad connection.
🧠 The Mental Model
I use the **"Polite Phone Call"** model for any network request.
📖 The War Story
Situation: "We built a nightly cron job to sync user data from a third-party marketing API. The script was simple: fetch the data, do some processing, and save it to our database."
Challenge: "The engineer wrote the brittle, one-line version of the API call. It worked for months. Then, one Tuesday, the marketing API had a 30-minute outage right when our job was scheduled to run. Their server stopped accepting connections."
Stakes: "Our script, instead of handling the connection error, crashed with an unhandled `requests.exceptions.ConnectionError`. Because it crashed, the rest of the sync job—including critical cleanup and state-updating steps—never ran. This left our database in an inconsistent state, which took a senior engineer half a day to manually reconcile. A 30-minute external outage became a 4-hour internal incident because of one unprotected line of code."
✅ The Answer
"My approach is to treat any network call as an operation that can, and will, eventually fail. The code must be prepared for this reality from the start. I'd use the excellent `requests` library and wrap the call in robust error handling."
The Robust Solution
import requests
import sys
def get_api_status(url: str, timeout_seconds: int = 5):
"""
Makes a GET request to a URL and prints its status code.
Includes robust error handling for network issues and bad responses.
"""
print(f"Attempting to reach {url}...")
# The "Polite Phone Call" model in action
try:
# 1. Make the call, but don't wait forever (timeout)
response = requests.get(url, timeout=timeout_seconds)
# 2. Check for obvious client/server errors (4xx/5xx)
response.raise_for_status()
# 3. Handle bad connections (DNS failure, connection refused, etc.)
except requests.exceptions.RequestException as e:
print(f"Error: Could not connect to the API. {e}", file=sys.stderr)
return None
# 4. If the call was successful, print the good news
print(f"Success! Response Status Code: {response.status_code}")
return response.status_code
if __name__ == "__main__":
get_api_status('https://api.github.com') # A reliable API
get_api_status('https://api.github.com/this-does-not-exist') # Will trigger a 404
get_api_status('http://localhost:9999') # Will trigger a connection error
Key Improvements:
- Timeout: The `timeout=5` is the most critical addition. It prevents the script from hanging indefinitely and tying up resources.
- Exception Handling: Wrapping the call in `try...except requests.exceptions.RequestException` catches a whole family of network-related problems gracefully.
- Status Code Check: `response.raise_for_status()` is a convenient way to automatically raise an exception if the status code is a 4xx (client error) or 5xx (server error), turning bad responses into explicit failures that can be caught.
- Clarity: The function returns the status code on success and `None` on failure, providing a clean interface for other parts of a program to use.
🎯 The Memorable Hook
"A network call is an expression of trust in another system. Defensive code is the prenuptial agreement."
This reframes the problem as one of risk management. It shows you think about contracts and failure modes, not just code execution. It's a statement of engineering maturity.
💭 Inevitable Follow-ups
Q: "How would you pass an API key for authentication?"
Be ready: "The standard way is to use the `headers` parameter. I'd add `headers={'Authorization': f'Bearer {api_key}'}` to the `requests.get()` call. The key itself should be loaded securely from an environment variable or secrets manager, never hardcoded."
Q: "What if the API you're calling is occasionally flaky? How would you make your script more resilient?"
Be ready: "For transient errors like a `503 Service Unavailable`, I'd implement a retry mechanism with exponential backoff. Instead of failing immediately, the script would wait 1 second, then 2, then 4, and try again a few times before giving up. A great library for this is `tenacity`."
🔄 Adapt This Framework
If you're junior: The robust solution with `try/except` and a `timeout` is a perfect answer. It demonstrates a huge leap in maturity over the naive approach.
If you're senior: You should present the robust solution as your baseline, and then proactively discuss the follow-up topics. "Here's the basic safe way to do it. In a real production system, I'd immediately add retry logic with exponential backoff for 5xx errors and structured logging to capture the context of any failures."
