REST and Resource-Oriented APIs

Day 049: REST and Resource-Oriented APIs

REST becomes useful when an API stops looking like a remote control for backend functions and starts looking like a stable interface over resources and their state.


Today's "Aha!" Moment

Many awkward APIs are really RPC systems wearing HTTP clothing. They expose endpoints like /createEnrollment, /completeLesson, or /getCourseDetails, which mirror backend actions closely but give clients very little stable structure to reason about. The interface feels easy to build at first because it follows the server’s internal functions. Over time, it becomes harder to document, harder to cache, and harder to evolve because every new action becomes another special case.

REST is useful because it pushes you to ask a different question first: what are the stable things in this domain that clients actually care about? For a learning platform, that might be courses, lessons, enrollments, progress records, certificates, and drafts. Once those resources are clear, HTTP methods and status codes can express how clients read or change them. The API stops being a bag of commands and becomes a more predictable model of the domain.

That predictability matters because HTTP already carries semantics around safety, idempotency, caching, and status interpretation. If you use those semantics honestly, clients and infrastructure can reason better about repeated requests, retries, cacheability, and failures. If you ignore them and use POST for everything, you throw away much of what makes HTTP helpful as an application protocol.

The key shift is this: REST is not mainly about pretty URLs. It is about choosing a stable resource model and then using HTTP as a language for interacting with that model. Once you see that, the style becomes much less dogmatic and much more practical.


Why This Matters

The problem: Teams often design HTTP APIs by exposing server-side methods directly, which makes the interface drift with backend implementation details instead of with stable domain concepts.

Before:

After:

Real-world impact: Better client experience, cleaner documentation, more predictable retry/caching behavior, and APIs that survive backend refactors without feeling like they changed personality every sprint.


Learning Objectives

By the end of this session, you will be able to:

  1. Model an API around resources rather than internal methods - Distinguish stable domain entities from transient backend operations.
  2. Use HTTP semantics deliberately - Relate methods and status codes to safety, idempotency, and expected behavior.
  3. Know when to bend away from pure resource modeling - Recognize when a command, job, or workflow endpoint is the more honest contract.

Core Concepts Explained

Concept 1: Start with Stable Resources and Relationships

Imagine the learning platform needs to expose course data and learner progress. The first design move should not be “what endpoints do we need?” It should be “what are the stable resources the client is trying to see or manipulate?”

That might produce a model like:

/courses/{courseId}
/courses/{courseId}/lessons/{lessonId}
/users/{userId}/enrollments
/users/{userId}/progress/{lessonId}

This matters because resources are longer-lived than backend functions. The backend may internally call three services and a queue to answer one request, but the client usually does not want to think in those terms. The client wants a stable handle on domain concepts it understands.

Once relationships are clear, the API becomes easier to navigate, document, and extend. Subresources like enrollments or lesson progress feel natural because they express ownership and identity in the domain, not because they happened to match one controller class.

The trade-off is clarity versus convenience for the server author. Resource thinking may feel slower at first, but it produces a contract that is much more stable than simply exporting whichever backend methods already exist.

Concept 2: HTTP Methods Are Behavioral Semantics, Not Mere Routing Labels

After the resource model is clear, HTTP methods stop being arbitrary verbs and start carrying useful expectations.

For example:

GET    /courses/42
POST   /courses/42/enrollments
PATCH  /users/7/progress/lesson-3
DELETE /courses/42/drafts/3

Those choices matter because they say different things:

Clients, proxies, retries, and caches all benefit when those expectations are consistent. If everything becomes POST, the interface may still function, but much of HTTP’s built-in meaning becomes unusable.

The trade-off is convenience versus predictability. Using one method everywhere may feel easier inside the backend, but using method semantics honestly makes the contract easier to understand and operate from the outside.

Concept 3: REST Is Strong for Resources, but Some Operations Are Better Modeled as Commands or Jobs

Good REST design is not a purity contest. Some operations are naturally resource-oriented. Others are more honestly described as commands, workflows, or asynchronous jobs.

Suppose the learning platform offers “generate a certificate preview.” That may not fit neatly as a durable resource mutation. It might be better modeled as a job creation or command-style endpoint that returns a task resource:

POST /certificate-preview-jobs
GET  /certificate-preview-jobs/{jobId}

That is still resource-oriented in spirit because it models the long-running workflow honestly, instead of pretending the API is simply flipping a field on an existing entity. The lesson is that REST should clarify reality, not distort it.

This is also where many mature APIs land: resources for stable domain entities, and explicit job or command resources where the domain really contains operations with longer-running semantics or special side effects.

The trade-off is elegance versus honesty. Forcing every action into an unnatural noun can make the API worse. Strong API design uses REST where it clarifies the contract and bends when the real workflow demands a different shape.


Troubleshooting

Issue: Verbs spread across URLs because the backend is designed around functions or handlers.

Why it happens / is confusing: Server implementation details are the easiest thing for backend authors to see, so the API drifts toward internal method names.

Clarification / Fix: Step back and ask what stable client-visible entities exist. Let HTTP methods carry more of the action semantics, and only introduce explicit command/job resources when the workflow truly calls for them.

Issue: REST guidelines get applied dogmatically.

Why it happens / is confusing: Style guides often turn into checklists, which makes API design feel like a purity test instead of a contract-design exercise.

Clarification / Fix: Optimize for honest semantics. Use resources where the domain is resource-shaped. Use command or job resources where the domain is workflow-shaped. The goal is clarity, not ceremony.


Advanced Connections

Connection 1: REST ↔ HTTP Infrastructure

The parallel: Resource-oriented APIs benefit from existing HTTP semantics around caching, conditional requests, status codes, and safe retries when methods are used consistently.

Real-world case: Read-heavy catalog endpoints are easier to cache and reason about when they are modeled as stable resources with honest GET behavior.

Connection 2: REST ↔ Domain Modeling

The parallel: Strong REST design usually reflects a domain model that is already clear about entities, identity, and lifecycle.

Real-world case: APIs become awkward when the backend itself has fuzzy boundaries between durable entities and transient commands.


Resources

Optional Deepening Resources


Key Insights

  1. REST starts with stable resources - The main design question is what the client needs to identify and manipulate over time.
  2. HTTP methods carry real semantics - Safety, idempotency, and cache behavior matter to the contract, not just to the transport.
  3. Good API design is honest, not dogmatic - Use resource modeling where it clarifies the domain, and use job or command resources when that is the more truthful abstraction.

Knowledge Check (Test Questions)

  1. What is the strongest sign that an API is thinking in resources rather than in backend functions?

    • A) URLs identify stable domain entities, while HTTP methods express the kind of interaction.
    • B) Every endpoint name begins with a verb.
    • C) The API uses POST for all requests.
  2. Why do HTTP method semantics matter beyond style?

    • A) Because clients and infrastructure rely on expectations about safety, idempotency, and cacheability.
    • B) Because methods are mostly cosmetic and interchangeable.
    • C) Because status codes remove the need for method meaning.
  3. When is it reasonable to step away from pure resource-style endpoints?

    • A) When the contract is more honestly modeled as a command, job, or asynchronous workflow.
    • B) Whenever REST feels unfamiliar.
    • C) Only for private internal APIs.

Answers

1. A: Resource-oriented APIs identify stable client-visible entities and let the method carry much of the action meaning.

2. A: HTTP semantics affect retries, caching, correctness expectations, and how predictable the API feels to clients and intermediaries.

3. A: Good API design cares more about honest contracts than about forcing every workflow into an unnatural resource shape.



← Back to Learning