REST API Consuming APIs with Code
Testing tools help you explore an API. Real apps call APIs from code. A weather widget fetches forecasts, a shop page loads products, and a script saves reports. Writing these calls well means handling success, failure, and slow networks.
The Phone Call Picture
Calling a friend involves dialing, waiting for an answer, speaking, listening, and hanging up. Sometimes the line is busy or nobody picks up. Code that calls an API follows the same steps. It builds the request, sends it, waits, reads the reply, and plans for the busy signal.
The Life of a Call
Build request ──→ Send ──→ Wait ──→ Receive response
│ │
timeout? status code?
│ │
retry or fail 2xx: read JSON
4xx: fix the request
5xx: retry later
GET Request in JavaScript
The fetch function ships with modern browsers and Node.js.
async function loadBook(id) {
const response = await fetch("https://api.example.com/books/" + id);
if (!response.ok) {
throw new Error("Request failed with status " + response.status);
}
const book = await response.json();
return book;
}
Fetch only rejects its promise on network failure. A 404 or 500 status still counts as a completed call, so the code must check response.ok.
POST Request in JavaScript
const response = await fetch("https://api.example.com/books", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": "Bearer " + token
},
body: JSON.stringify({ title: "Atlas", price: 450 })
});
const created = await response.json();
GET and POST in Python
The requests library keeps Python code short.
import requests
reply = requests.get("https://api.example.com/books/5", timeout=10)
reply.raise_for_status()
book = reply.json()
reply = requests.post(
"https://api.example.com/books",
json={"title": "Atlas", "price": 450},
headers={"Authorization": "Bearer " + token},
timeout=10,
)
The json argument converts the dictionary and sets the Content-Type header. The raise_for_status call turns 4xx and 5xx replies into exceptions.
Always Set a Timeout
Many libraries wait forever by default. A stuck call can freeze a page or hold a server thread. Pick a limit, such as 10 seconds, and handle the timeout error with a friendly message.
Reacting to Status Codes
| Status | Action in Code |
|---|---|
| 200, 201 | Read the body and continue |
| 400, 422 | Show the validation messages to the user |
| 401 | Refresh the token or ask the user to sign in |
| 404 | Show a not found message |
| 429 | Wait for the time in Retry-After and try again |
| 500, 503 | Retry a few times with growing delays |
Retry with Backoff
Attempt 1 fails ── wait 1 second Attempt 2 fails ── wait 2 seconds Attempt 3 fails ── wait 4 seconds Attempt 4 fails ── stop and report the error
Retry only safe or idempotent requests. A repeated POST without an idempotency key can create duplicates.
Keep Secrets Out of Client Code
Code that runs in a browser is visible to every visitor. Store API keys and secrets on a server, and let the browser call your own backend. The backend adds the secret and forwards the request.
Browser ──→ Your Backend (holds the key) ──→ Third-Party API
Organize Your Code
- Place every API call in one module, so URLs and headers live in one place.
- Read the base URL from configuration.
- Convert API responses into your own simple data objects.
- Log failed calls with the status code and the request id.
Common Mistakes
Ignoring Failed Statuses
Code that parses the body of every response crashes on error replies. Check the status first.
Calling Inside Loops
Fetching one record per loop turn creates hundreds of calls. Use list endpoints, filters, or bulk operations.
Hard-Coded URLs
A URL repeated in twenty places turns a server move into a long search. Keep one constant.
