# API Design Walkthrough — Learn by Doing

## Before We Begin

REST APIs expose resources (nouns) via URLs and HTTP methods (verbs). Good design makes the API predictable and self-describing—clients can guess the shape of `GET /users/42` without reading docs.

**Diagnostic question:** When you've consumed or built an API, what made it easy or frustrating to use? Was it URLs, documentation, error messages, or something else?

**Checkpoint:** You can name at least one REST resource (e.g., users, orders) and one HTTP method beyond GET.

---

## Step 1: Model Resources

<!-- hint:diagram mermaid-type="flowchart" topic="REST resource and HTTP method mapping" -->
<!-- hint:code language="text" highlight="1,2" -->

**Task:** You're building an API for a task manager. List 3–4 main resources (nouns). For each, write the URL pattern and which HTTP methods apply (GET, POST, PUT, PATCH, DELETE).

**Question:** Why use `PATCH` instead of `PUT` for partial updates? When would you use `PUT`?

**Checkpoint:** You have a clear resource model and URL structure.

---

## Step 2: Design a REST Endpoint

<!-- hint:code language="json" highlight="1,5" -->

**Task:** Design `GET /tasks?status=open&assignee=42` for listing tasks. Define: (1) query parameters, (2) response shape (fields), (3) status codes (200, 400, 401). Write a sample JSON response.

**Question:** Should pagination be required or optional? What default `limit` would you use?

**Checkpoint:** You have a complete endpoint spec with params and response.

---

## Step 3: REST vs GraphQL

<!-- hint:buttons type="single" prompt="For a mobile app needing user + last 5 orders, which fits better?" options="REST (multiple requests),GraphQL (single query),Depends on use case" -->

**Task:** A mobile app needs: user profile (name, avatar) + last 5 orders (id, date). Compare: (a) REST: how many requests? (b) GraphQL: one query. Write the GraphQL query.

**Question:** When would REST with a compound endpoint (e.g., `GET /me?include=orders`) be simpler than GraphQL?

**Checkpoint:** You can articulate when each approach fits.

---

## Step 4: Contract-First with OpenAPI

<!-- hint:embed url="https://swagger.io/specification/" -->

**Embed:** https://editor.swagger.io/

**Task:** Add the `GET /tasks` endpoint to an OpenAPI spec. Include path, parameters, responses for 200 and 400. Use the standard OpenAPI 3.0 structure.

**Question:** What can you generate from an OpenAPI spec? (clients, mocks, docs, tests)

**Checkpoint:** You have a valid OpenAPI snippet for one endpoint.

---

## Step 5: Versioning Strategy

**Task:** Your API has `GET /users` returning `{ id, name, email }`. You need to add `avatar_url` without breaking old clients. Describe two versioning approaches: (1) URL versioning, (2) additive change (backward compatible). Which would you choose and why?

**Question:** When is additive change (adding optional fields) sufficient? When do you need a real new version?

**Checkpoint:** You understand when to add vs when to version.

---

## Step 6: Error Handling

**Task:** A client sends `POST /tasks` with `{ "title": "" }` — empty title is invalid. Design the error response: status code, body shape, and at least one header that would help a client.

**Question:** Should the body use a custom structure or follow a standard (e.g., RFC 7807 Problem Details)?

**Checkpoint:** You have a consistent error format with status and structured body.

---

## Step 7: Pagination and Rate Limiting

**Task:** Add cursor-based pagination to `GET /tasks`. Define: (1) request params (`cursor`, `limit`), (2) response shape (tasks array + `next_cursor`), (3) behavior when no more pages. Then add a rate limit header (e.g., 100 req/min). What would you return when the limit is exceeded?

**Checkpoint:** Pagination and rate limit are fully specified.
