Sketching endpoints for a resource
On This Lesson 11 topics
Lesson Overview
Until now you have used other people's APIs. Now you become the person who writes the menu. Before a single line of server code exists, a backend developer sketches the endpoints: for each thing a client needs to do, which URL, which method, and which status codes. A sketch costs minutes, fits on a page, and catches design mistakes while they are still free to fix.
In the restaurant picture, this is the chef writing the menu before opening the kitchen. A good menu is short, consistent, and honest about what each dish is and what happens if it is sold out.
You will learn a repeatable four-step method and apply it to a members resource and to a harder case: "the loans of one member" and "overdue loans". This is also exactly the skill assessed at the end of the module and the one the Junior-level capstone relies on.
This lesson builds on Lessons 1 to 4. It uses plural-noun URLs, methods, and status codes from Lesson 2, and query parameters from Module BEG-052.
Learning Objectives
By the end of this lesson you will be able to:
- List what clients need to do with a resource, then map each need to a method and a URL.
- Choose success and failure status codes for each endpoint.
- Decide when a filter belongs in a query parameter.
- Express relationships ("loans of one member") with a nested URL.
- Express a derived list ("overdue loans") as a filter on the collection.
- Review a sketch against a short checklist (no verbs, plural nouns, consistent codes).
Written Explanation
The four-step method
- List the needs. What must clients be able to do? Usually: list, read one, create, replace or update, delete. Add special needs: filters, relationships.
- Name the resource. One plural noun:
members. - Map each need to a method and a URL (Lesson 2).
- Choose statuses: one for success, and the main failures.
Step 1 and 2: needs and noun
For a library, the client (a staff website) needs to: see all members, see one member, register a new member, change a member's data, and remove a member. The resource is members. The collection URL is /members and the item URL is /members/{id}. In sketches, curly braces mark a path variable: {id} stands for a real id such as 7.
Step 3: the map
| Need | Method and URL |
|---|---|
| See all members | GET /members |
| See one member | GET /members/{id} |
| Register a member | POST /members |
| Replace a member's data | PUT /members/{id} |
| Remove a member | DELETE /members/{id} |
POST goes to the collection because the client does not yet know the id; the server assigns it. PUT and DELETE go to the item because they act on a known member.
Step 4: statuses, including failures
Many beginners write only the happy path. A real sketch also says what happens when things go wrong. The MDN status pages give the meanings we need:
- 200 OK: success with a body (list, read, replace).
- 201 Created: a new resource exists. MDN says it should be reachable at the request URL or at the URL in a
Locationheader, so a goodPOSTanswer includes the new resource's URL and usually its representation. - 204 No Content: success, nothing to send back. Common for
DELETE. A 204 has no body. - 400 Bad Request: the client's request is malformed or invalid (for example, a required field is missing).
- 404 Not Found: the server cannot find the resource: the id does not exist or the path is wrong.
The completed sketch:
GET /members -> 200 (list)
GET /members/{id} -> 200, or 404
POST /members -> 201, or 400
PUT /members/{id} -> 200, or 400, or 404
DELETE /members/{id} -> 204, or 404Notice the pattern: anything with {id} can fail with 404, and anything that accepts a body can fail with 400. Spotting these patterns makes sketching fast.
Choices you must note down. Two decisions are the designer's, and the sketch should say which:
DELETEcould return 204 (no body) or 200 (with a body of what was deleted). We saw both in real APIs. Pick one and keep it.- A second
DELETEof the same id finds nothing. Returning 404 is honest. Returning 204 again is also seen. Either is fine if documented.
PUT and PATCH
PUT replaces the whole resource with the body (MDN's wording), so the client must send every field. PATCH changes only the fields it sends. For a first sketch, PUT is enough; add PATCH /members/{id} when partial changes are a real need.
Filters live in query parameters
Suppose staff want members of a certain city. Do not create /members/city/cairo or /getMembersByCity. Keep the collection and add a query parameter:
GET /members?city=cairo -> 200 (possibly an empty list)An important point: a filter that matches nothing is not a 404. The collection /members exists; it simply has no matching items, so the honest answer is 200 with an empty list. A 404 is for a resource that cannot be found, such as /members/99999.
Query parameters also carry paging (?limit=10&skip=20) and sorting. The parameter names are your choice, so write them down in the sketch, as providers do in their documentation. Real APIs differ: the practice API from earlier lessons uses limit, skip, sortBy, and order.
Relationships: "loans of one member"
A loan belongs to a member. The question "which loans does member 3 have?" is about the relationship, so a nested URL reads naturally:
GET /members/{id}/loans -> 200 (list, maybe empty), or 404 (no such member)Here the two outcomes differ from the filter case. If member 3 exists but has no loans, answer 200 with an empty list. If there is no member 3, answer 404, because the parent resource is missing.
Keep loans as their own resource as well (/loans, /loans/{id}), so that a loan can be read or removed directly without going through its member.
Derived lists: "overdue loans"
"Overdue" is not a new resource; it is a state of a loan. Treat it as a filter:
GET /loans?status=overdue -> 200Do not write /getOverdueLoans or /overdueLoans. A filter keeps the design small: later ?status=returned costs nothing new. If both filters are needed together, the query string handles it: /loans?status=overdue&memberId=3.
A sketch checklist
Before you show a sketch to anyone:
- [ ] No verb appears in any URL.
- [ ] Collections are plural nouns; items use
{id}. - [ ] Every endpoint has a success status and its likely failures.
- [ ]
POSTtargets the collection;PUTandDELETEtarget an item. - [ ] Filters are query parameters.
- [ ] Nesting is at most two levels.
- [ ] Choices (like 200 vs 204 on delete) are written down.
Examples
Example 1: Simple. Sketch for books
Needs: list, read one, create, delete.
GET /books -> 200
GET /books/{id} -> 200, or 404
POST /books -> 201, or 400
DELETE /books/{id} -> 204, or 404Four needs, four lines, one noun. Filters can come later: GET /books?author=herbert.
Example 2: Practical. A sketch with a request body
A sketch becomes more useful when it shows the JSON that goes in and comes out. For POST /members:
POST /members
Content-Type: application/json
{"name": "Salma", "email": "salma@example.com"}
-> 201 Created
Location: /members/12
{"id": 12, "name": "Salma", "email": "salma@example.com"}
-> 400 Bad Request (for example when "name" is missing)The example email uses the reserved example.com domain, which is meant for examples. Notice that the client does not send the id; the server creates it and returns it. The Location header gives the URL of the new member, as the MDN page on 201 describes.
Example 3: Realistic. The Library API, first sketch
Resources: books, members, loans.
GET /books -> 200 (?author=, ?limit=, ?skip=)
GET /books/{id} -> 200, 404
POST /books -> 201, 400
PUT /books/{id} -> 200, 400, 404
DELETE /books/{id} -> 204, 404
GET /members -> 200
GET /members/{id} -> 200, 404
POST /members -> 201, 400
PUT /members/{id} -> 200, 400, 404
DELETE /members/{id} -> 204, 404
GET /members/{id}/loans -> 200, 404
GET /loans -> 200 (?status=overdue)
GET /loans/{id} -> 200, 404
POST /loans -> 201, 400 (body: memberId, bookId)
DELETE /loans/{id} -> 204, 404Check it against the checklist: no verbs, plural nouns, statuses present, filters in query parameters, nesting one level. One open question remains that a reviewer should ask: what does the server do if the book in a new loan is already borrowed? That needs a decision, for instance 409 Conflict (the request conflicts with the current state). We have not discussed 409 in this course yet, so for now write it as an open question in your sketch.
Backend Insight
In a real team, the endpoint sketch is the first thing reviewed, often before any code. It is cheap to change a line in a document and expensive to change a published API, because clients depend on it. When you build the Junior capstone, each line of your sketch becomes one method in your server, and each status code in the sketch becomes a test case: "send a missing field, expect 400", "ask for id 99999, expect 404". A good sketch is therefore also your test plan.
Common Mistakes
- Verbs in URLs, like
/getBooksor/members/create. - Only the happy path. No 400 or 404 means the sketch is half done.
- 404 for an empty filter result. An empty list with
200is correct. - Sending the id in the body of a
POST. The server decides ids. - Putting
POSTon an item URL for creation (POST /books/{id}). - Creating a URL per filter (
/loans/overdue,/loans/returned) instead of?status=. - Deep nesting instead of giving the inner resource its own top-level URL.
- Silent choices. Not writing down 200 vs 204, or the name of a query parameter.
Exercises
Level A: Foundation
- Sketch
GET,POST, andDELETEendpoints with statuses for the resourcecourses. - Which two statuses can an endpoint with
{id}return besides its success status? (Think about what can go wrong with the id.) - Why does
POSTuse the collection URL?
Level B: Application
- Complete a full five-line sketch (list, read, create, replace, delete) with success and failure statuses for
animalsin a shelter. - Add the endpoint "all animals of one species" to your sketch, as a filter. Then add "all adoptions of adopter 9" as a relationship. Give statuses for both.
- A teammate proposes
GET /animals/search/dogsandGET /getCats. Rewrite them.
Level C: Challenge
- For
POST /adoptions(body:animalId,adopterId) list three failure cases and match each to a status: missing field, unknown animal, and animal already adopted. Mark any status we have not covered as an open question. - Review this sketch and list every problem:
POST /members/{id}-> 200;GET /members?city=cairo-> 404 when empty;GET /member/delete/3;DELETE /members-> 204.
Show solutions
- For example:
GET /courses200;GET /courses/{id}200 or 404;POST /courses201 or 400;DELETE /courses/{id}204 or 404. - 404 (id not found) and, if the endpoint takes a body, 400 (invalid request body).
- The client does not know the new id yet, and the server assigns it; creation adds an item to the collection.
GET /animals200;GET /animals/{id}200/404;POST /animals201/400;PUT /animals/{id}200/400/404;DELETE /animals/{id}204/404.GET /animals?species=dog200 (an empty list if none match, not 404).GET /adopters/9/adoptions200, or 404 if adopter 9 does not exist.GET /animals?species=dogandGET /animals?species=cat. Both use the collection with a filter. No verbs, no extra paths.- Missing field: 400. Unknown animal: 400 is common (the request refers to something that does not exist) or 404 may be argued; note your choice. Already adopted: a conflict with the current state, for example 409 (open question: not covered yet in this course).
- (a)
POSTon an item URL for creation is wrong: usePOST /memberswith 201. (b) An empty filter result should be200with an empty list. (c)/member/delete/3has a verb, is singular, and usesGETfor deletion: useDELETE /members/3. (d)DELETE /memberson the whole collection would remove everything; it is dangerous, usually not offered, and ambiguous. PreferDELETE /members/{id}only.
Mini Challenge
Choose a small app (a to-do list, a recipe book, a bike rental). Sketch one resource completely (five endpoints with statuses), one filter, one relationship, and one example request/response pair for the POST. Then run the seven-point checklist from this lesson and tick each box honestly, fixing anything that fails.
Summary & Next Lesson
Key takeaways
- Sketching is: list needs, name the resource, map to method plus URL, choose success and failure statuses.
POSTtargets the collection;PUTandDELETEtarget an item.- Anything with
{id}can return 404; anything with a body can return 400. - Filters and paging are query parameters; an empty result is
200with an empty list. - Relationships use a nested URL; derived lists like "overdue" are filters.
- Write down your choices (such as 200 or 204 on delete) and keep them consistent.
Next lesson
In "Demo: exploring a public API with Postman and curl" you will pull the whole module together: read documentation, call list, single, and filtered endpoints with both tools, hit a deliberate 404, and prepare the lab.
Self-check
- What are the four steps of sketching?
- Which method goes with the collection URL for creation?
- A filter matches nothing. Which status, and what body?
- How do you express "overdue loans" without a verb?
- Why is the sketch also a test plan?
Show answers
- List the needs, name the resource, map each need to method and URL, choose statuses.
POST.200with an empty list.GET /loans?status=overdue.- Each status code in the sketch can be checked by a request that should produce it.
References
- Mozilla Developer Network, 201 Created, 204 No Content, and 404 Not Found. Support the meaning of these statuses, the
Locationheader on creation, and that 204 has no body. - Mozilla Developer Network, HTTP request methods. Supports
PUTas a full replacement and the roles ofGET,POST, andDELETE. - DummyJSON, Products documentation. Used as an example of real parameter names (
limit,skip,sortBy,order). - Not verified against a page: the use of 400 for an unknown id inside a request body versus 404, and the use of 409 for an already-borrowed book, are design conventions that vary between teams. They are presented as choices to document, not as rules, and 409 is flagged as an open question.
Practice
Apply this lesson with the module's lab, exercises and quiz.
Marking a lesson complete is optional and you can undo it any time. Your progress stays in this browser.