Chapter 5 · Python for AI Work
Web APIs with requests
- Page 16 of 20
- 3 min read
An API (Application Programming Interface) is a way for one program to ask another for something. A web API does it over the internet with HTTP — the same protocol your browser uses. Every hosted AI model — OpenAI, Anthropic, Google, Hugging Face — is used through a web API. Before using an AI SDK on the next page, it is worth seeing what it does underneath, with the popular requests library (python -m pip install requests).
A request and a response
Your program sends a request: a method, a URL, some headers and sometimes a body. The server sends back a response: a status code, headers and a body, usually JSON.
| Method | Meaning | Example |
|---|---|---|
GET | Read something | Fetch a list of available models |
POST | Send something to be processed or created | Send a prompt and get an answer |
PUT / PATCH / DELETE | Replace / change / remove | Update or delete a stored file |
GET: reading data
The examples use httpbin.org, a free service that echoes back what you send — perfect for learning:
import requests
response = requests.get(
"https://httpbin.org/get",
params={"q": "python for ai", "page": 1}, # becomes ?q=python+for+ai&page=1
timeout=10, # seconds — always set one
)
print(response.status_code)
print(response.headers["Content-Type"])
data = response.json() # JSON text → Python dict
print(data["args"])
print(data["url"])200
application/json
{'page': '1', 'q': 'python for ai'}
https://httpbin.org/get?q=python+for+ai&page=1POST: sending data
This is the shape of every call to an AI model: a POST with a JSON body and an Authorization header carrying your API key:
import requests
payload = {"model": "demo-model", "input": "Translate 'good morning' into Bangla."}
response = requests.post(
"https://httpbin.org/post",
json=payload, # sends JSON and sets Content-Type
headers={"Authorization": "Bearer my-secret-key"},
timeout=10,
)
echo = response.json() # httpbin sends back what it received
print(response.status_code)
print(echo["json"])
print(echo["headers"]["Content-Type"])
print(echo["headers"]["Authorization"])200
{'input': "Translate 'good morning' into Bangla.", 'model': 'demo-model'}
application/json
Bearer my-secret-keyjson=payload converts the dictionary to JSON for you and sets the Content-Type: application/json header.
Status codes
| Code | Meaning | What to do |
|---|---|---|
| 200–299 | Success | Read the body |
| 400 | Bad request — something in what you sent is wrong | Fix your code; retrying will not help |
| 401 / 403 | Not authenticated / not allowed | Check your API key and permissions |
| 404 | Not found | Check the URL or the resource name |
| 429 | Too many requests (rate limit) | Wait, then retry with backoff (page 11) |
| 500–599 | The server had a problem | Retry later with backoff |
Handling failures properly
The network fails in three different ways, and robust code handles each one:
import requests
def fetch_json(url):
try:
response = requests.get(url, timeout=2)
response.raise_for_status() # turns 4xx/5xx into an exception
return response.json()
except requests.Timeout:
print("Timed out:", url)
except requests.HTTPError as error:
print("HTTP error:", error.response.status_code, url)
except requests.ConnectionError:
print("Could not connect:", url)
return None
print(fetch_json("https://httpbin.org/json") is not None)
fetch_json("https://httpbin.org/status/404")
fetch_json("https://httpbin.org/status/503")
fetch_json("https://httpbin.org/delay/5")True
HTTP error: 404 https://httpbin.org/status/404
HTTP error: 503 https://httpbin.org/status/503
Timed out: https://httpbin.org/delay/5- Always pass
timeout. Without one,requestscan wait forever for a server that never answers, and your program hangs. raise_for_status()turns an error status into an exception. Without it, a 404 is a "successful" call whose body is an error page.- Catch the specific exceptions: a timeout and a 503 are worth retrying; a 404 is not.
Never put a real API key in your code. The next page shows the right way to keep it secret.
Try it yourself
- Send a GET to
https://httpbin.org/getwith your name as a parameter and print it from the response. - Write
get_with_retries(url, attempts=3)that retries only on timeouts and 5xx errors, waiting longer each time. - Use
https://httpbin.org/headersto see which headersrequestssends by default.