8. Web APIs
Design robust, observable HTTP services with predictable contracts and safe retries.
Q1 When designing a REST API endpoint, what are the key considerations?
Answer: Key considerations include using the correct HTTP methods, choosing appropriate status codes, implementing robust input validation, handling authentication/authorization, and ensuring security.
Explanation:
HTTP Methods: Use methods semantically (
POSTfor creation,GETfor retrieval,PUTfor replacement).GETandPUTshould be idempotent.Status Codes: Return standard codes like
200 OK,201 Created,400 Bad Request,404 Not Found.Validation: Use a library like Pydantic (as FastAPI does) to define data schemas and automatically validate incoming requests.
Security: Use HTTPS, handle authentication (e.g., with JWTs), and authorize that a user has permission to perform an action.
from fastapi import FastAPI, Depends, HTTPException
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
async def get_current_user():
# In a real app: validate token, return user or raise
return {"id": 1}
@app.post("/items", status_code=201)
async def create_item(item: Item, user = Depends(get_current_user)):
saved = await save_item(item, user)
if not saved:
raise HTTPException(400, "Cannot save item")
return saved
Q2 How do you implement basic rate limiting?
Answer: Use a token-bucket/leaky-bucket algorithm backed by Redis (or a gateway) to cap requests per key.
Q3 How do you expose OpenAPI docs and validate schemas?
Answer: Frameworks like FastAPI generate OpenAPI automatically; document response models and error formats.
Q4 Beyond the basics, what makes a REST API well-designed?
Answer: A well-designed REST API is consistent, well-documented, and predictable. Key features include clear versioning, support for idempotency, consistent error payloads, and hypermedia controls (HATEOAS).
Explanation:
Versioning: Expose the API version in the URL (e.g.,
/api/v1/...) or a header to manage changes without breaking clients.Idempotency: For non-
POSTrequests, ensure that making the same call multiple times has the same effect as making it once. Clients can safely retry failedPUTorDELETErequests.Consistent Error Payloads: Return errors in a standard format (e.g.,
{"error": {"code": "AUTH_ERROR", "message": "Invalid token"}}) across all endpoints.HATEOAS (Hypermedia as the Engine of Application State): Responses should include links to related actions or resources, making the API discoverable. For example, a response for a bank account might include links to "deposit," "withdraw," or "close" the account.
Q5 How do you implement pagination, filtering, and ETags for cache-friendly APIs?
Answer: Use cursor-based pagination for stability, accept filter/sort params, and include ETag/Last-Modified with conditional requests (If-None-Match).
Explanation: Cursors avoid page drift; ETags enable 304 Not Modified responses to save bandwidth.
GET /items?cursor=abc&limit=50&sort=created_at&filter=status%3Dactive
If-None-Match: "W/\"etag123\""
Q6 When should you use PATCH vs PUT?
Answer: PUT replaces the entire resource (idempotent); PATCH applies a partial update.
Explanation: Prefer PATCH for sparse updates; define a schema to avoid ambiguous merges.
Q7 How do you design for idempotency and safe retries in write APIs?
Answer: Make PUT/DELETE idempotent and use idempotency keys for POST. On duplicates, return the same response (200/201) or a clear conflict (409).
Explanation: Clients retry on network failures; servers should de-duplicate. Accept an Idempotency-Key header and cache the first result for that key for a TTL window.
POST /payments
Idempotency-Key: 3f2d-...-9a
Q8 What is the difference between JWT and OAuth2?
Answer: They are related but serve different purposes. JWT (JSON Web Token) is a token format for securely transmitting information. OAuth2 is an authorization framework that defines how a client can obtain access to resources on behalf of a user.
Explanation: OAuth2 is a protocol. It can use various token formats, and JWT is a popular choice. In a typical OAuth2 flow, a user authorizes a client application, which then receives an access token from an authorization server. This token (often a JWT) is then sent to the resource server (the API) with each request to prove the client is authorized. JWTs are self-contained; they carry user information and permissions as a JSON payload, which is digitally signed to prevent tampering.