hectoday
DocsCoursesChangelog GitHub
DocsCoursesChangelog GitHub

Access Required

Enter your access code to view courses.

Invalid code

← All courses REST API Design with @hectoday/http

What Makes an API RESTful

  • APIs are contracts
  • Project setup
  • Resources, not actions

HTTP Methods

  • GET, POST, PUT, PATCH, DELETE
  • Idempotency
  • Method safety and side effects

Status Codes

  • The status codes that matter
  • Error responses

Resource Design

  • Modeling resources
  • Partial responses and field selection
  • Pagination
  • Filtering, sorting, and searching

API Lifecycle

  • Versioning
  • Content negotiation
  • Rate limiting and quotas

Advanced Patterns

  • Bulk operations
  • Long-running operations
  • HATEOAS and discoverability

Putting It All Together

  • API design checklist
  • Summary

Summary

What we built

Over the past 19 lessons, we designed and built a complete bookstore API. We started with the idea that an API is a contract, and we followed that principle through every decision. Let’s look at everything the API can do.

PatternWhere it appears
Resource-based URLs/books, /authors, /reviews
HTTP methodsGET, POST, PUT, PATCH, DELETE on each resource
IdempotencyPUT and DELETE are idempotent, POST supports idempotency keys
Safe methodsGET never modifies data
Status codes200, 201, 204, 400, 404, 409, 422, 429
Error formatConsistent { error: { code, message, details? } }
Nested resources/books/:id/reviews
EmbeddingBook responses include author summary
Field selection?fields=id,title,author.name
Cursor pagination?cursor=...&limit=20
Filtering?genre=fiction&authorId=author-1
Sorting?sort=-publishedAt
Searching?q=hemingway
Versioning/v1/books
Content negotiationJSON default, CSV export
Rate limitingPer-client with headers
Bulk operationsPOST /books/bulk with partial success
Long-running opsPOST /reports, then poll for status
HATEOAS_links on resources and pagination

The principles behind every decision

Every choice we made in this API traces back to a principle.

URLs are resources. /books, not /getBooks. The HTTP method provides the verb. The URL provides the noun.

Status codes are meaningful. 201 for created, 204 for deleted, 409 for duplicates. Not 200 for everything. Every status code tells the client something specific.

Errors are consistent. Every error has a code and a message, using the same shape. Consumers write one error handler and it works everywhere.

Lists are paginated. Cursor-based by default. The limit is capped. Responses are wrapped in an object so metadata can be added without breaking changes.

Filters compose. ?genre=fiction&sort=-publishedAt&q=sea&limit=5. Each parameter is independent and optional. They all work together.

Changes are additive. New fields are added alongside old ones. Breaking changes get a version bump. Consumers migrate on their own schedule.

Abuse is limited. Rate limiting with transparent headers. Clients know their quota. 429 with Retry-After when they exceed it.

Long work is asynchronous. 202 Accepted for operations that take more than a few seconds. Poll for status. Retry-After tells the client when to check back.

These principles are not specific to bookstores. They work for any API. The domain changes, but the design stays the same.

What is the single most important principle from this course?

A client sends POST /books with an Idempotency-Key header. The server creates the book but the response is lost. The client retries with the same key. What should happen?

← API design checklist Back to course →

© 2026 hectoday. All rights reserved.