Design APIs around resources, contracts, and HTTP semantics rather than controller method names.
Course navigationPhase 05⌄
HTTP, REST & API Engineering
Design HTTP APIs using resources, methods, status codes, idempotency, errors, caching semantics, and versionable contracts.
Phase outcome and project increment
Learning outcome
Design HTTP APIs using resources, methods, status codes, idempotency, errors, caching semantics, and versionable contracts.
Concrete deliverable
A written TaskFlow API contract for tasks with request/response examples and deliberate error semantics.
Principles to keep while coding
Use status codes consistently so clients can distinguish validation, authentication, authorization, and missing resources.
Make request and response contracts explicit enough that frontend and backend can evolve safely.
Treat idempotency, pagination, errors, and concurrency as API design concerns, not afterthoughts.
Guided phase lab
Do these in order. Each step should end with evidence before the next one starts.
- 01
Write the task resource shape before writing controller code.
- 02
Design collection and item URIs and justify GET/POST/PATCH/DELETE choices.
- 03
Define success and failure status codes for create, read, update, delete, validation, auth, forbidden, and missing-resource cases.
- 04
Use curl or an API client to inspect raw headers and bodies rather than only frontend behavior.
- 05
Repeat safe/idempotent requests and reason about what should or should not change.
- 06
Write an error envelope that the frontend can parse consistently.
curl -i http://localhost:4000/healthPredict what each command proves before running it. A command is useful only when its output answers a question.
Failures you should know how to diagnose
Using 200 for every outcome
Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.
Encoding actions into routes when resource semantics are clearer
Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.
Returning database rows as accidental public contracts
Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.
Confusing authentication failures with authorization failures
Predict the symptom, capture evidence at the nearest boundary, change one variable, and verify the same reproduction after the fix.
Lessons
The source chapters come first. Every phase now ends with a guided build, a debugging workshop, and an independent challenge so reading turns into transferable skill.
HTTP Mental Model
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 HTTP Mental Model VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS HTTP Mental Model Client, server, resource, representation and contract HTTP is the
HTTP Request Response Anatomy
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 HTTP Request and Response Anatomy VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS HTTP Request and Response Anatomy Methods, targets, headers, conten
HTTP Methods Status Codes and Idempotency
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 HTTP Methods, Status Codes and Idempotency VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS HTTP Methods, Status Codes and Idempotency Choose protocol
REST Resource and Route Design
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 REST Resource and Route Design VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS REST Resource and Route Design Collections, members, paths, query para
Build the In Memory Todo API
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 Build the In-Memory Todo API VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS Build the In-Memory Todo API Turn HTTP semantics into observable GET, PO
PowerShell API Testing and Contracts
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 PowerShell API Testing and Contracts VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS PowerShell API Testing and Contracts Exercise TaskFlow HTTP dire
HTTP Error Semantics and Debugging
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 HTTP Error Semantics and Debugging VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS HTTP Error Semantics and Debugging Diagnose method, route, represe
API Design Decisions and Anti Patterns
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 API Design Decisions and Anti-Patterns VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS API Design Decisions and Anti-Patterns Professional contract c
Exercises and Phase Exit
FULL_STACK_DEVELOPER_2026_COMPLETE - Phase 05 Exercises and Phase Exit VOLUME 02 - FRONTEND + BACKEND FOUNDATIONS Exercises and Phase Exit Hands-on HTTP labs, debugging drills and the Phase
Guided Build Lab
Purpose Design HTTP APIs using resources, methods, status codes, idempotency, errors, caching semantics, and versionable contracts.
Debugging Workshop
Goal Learn to diagnose this phase's failures systematically instead of reinstalling packages, changing random configuration, or copying a fix without understanding it.
Phase Synthesis & Independent Challenge
Mission Rebuild the capability of Phase 05 without following the exact code line-by-line. The goal is transfer: can you use the ideas when the variable names, UI, or route shape changes?
Mastery Capstone Lab
Integrate Phase 05 without following a transcript.
Exercises that increase independence
Write the task resource shape before writing controller code.
Define success and failure status codes for create, read, update, delete, validation, auth, forbidden, and missing-resource cases.
reproduce and diagnose — Using 200 for every outcome.
deliver A written TaskFlow API contract for tasks with request/response examples and deliberate error semantics.
Can design a resource-oriented route set and Can choose meaningful status codes.
Do not leave the phase only because you reached the bottom
Phase exit criteria
Scenario and concept quiz
These questions test engineering choices rather than whether you remember a lesson title.
Reference files
Attempt the work first. Use snapshots to compare a checkpoint, not as a substitute for understanding.
reference/TaskFlow_HTTP_API_Snapshot/package.json
{
"name": "api",
"private": true,
"scripts": {
"build": "nest build",
"start": "nest start",
"start:dev": "nest start --watch"
},
"dependencies": {
"@nestjs/common": "12.0.3",
"@nestjs/core": "12.0.3",
"@nestjs/platform-fastify": "12.0.3",
"reflect-metadata": "^0.2.2",
"rxjs": "^7.8.2"
},
"devDependencies": {
"@nestjs/cli": "12.0.3",
"@nestjs/schematics": "12.0.3",
"@nestjs/testing": "12.0.3",
"typescript": "~6.0.2"reference/TaskFlow_HTTP_API_Snapshot/src/app.module.ts
import { Module } from '@nestjs/common';
import { HealthModule } from './health/health.module.js';
import { TodosModule } from './todos/todos.module.js';
@Module({
imports: [HealthModule, TodosModule],
})
export class AppModule {}reference/TaskFlow_HTTP_API_Snapshot/src/health/health.controller.ts
import { Controller, Get } from '@nestjs/common';
import { HealthService } from './health.service.js';
@Controller('health')
export class HealthController {
constructor(private readonly healthService: HealthService) {}
@Get()
getHealth() {
return this.healthService.getStatus();
}
}reference/TaskFlow_HTTP_API_Snapshot/src/health/health.module.ts
import { Module } from '@nestjs/common';
import { HealthController } from './health.controller.js';
import { HealthService } from './health.service.js';
@Module({
controllers: [HealthController],
providers: [HealthService],
})
export class HealthModule {}reference/TaskFlow_HTTP_API_Snapshot/src/health/health.service.ts
import { Injectable } from '@nestjs/common';
@Injectable()
export class HealthService {
getStatus() {
return {
status: 'ok',
service: 'taskflow-api',
};
}
}reference/TaskFlow_HTTP_API_Snapshot/src/main.ts
import { NestFactory } from '@nestjs/core';
import { FastifyAdapter, NestFastifyApplication } from '@nestjs/platform-fastify';
import { AppModule } from './app.module.js';
async function bootstrap() {
const app = await NestFactory.create<NestFastifyApplication>(
AppModule,
new FastifyAdapter(),
);
app.enableShutdownHooks();
const port = Number(process.env.PORT ?? 4000);
await app.listen(port, '127.0.0.1');
}
void bootstrap();reference/TaskFlow_HTTP_API_Snapshot/src/todos/todos.controller.ts
import {
BadRequestException,
Body,
Controller,
Delete,
Get,
HttpCode,
Param,
Patch,
Post,
} from '@nestjs/common';
import { TodosService } from './todos.service.js';
@Controller('todos')
export class TodosController {
constructor(private readonly todosService: TodosService) {}
@Get()
findAll() {
return this.todosService.findAll();reference/TaskFlow_HTTP_API_Snapshot/src/todos/todos.module.ts
import { Module } from '@nestjs/common';
import { TodosController } from './todos.controller.js';
import { TodosService } from './todos.service.js';
@Module({
controllers: [TodosController],
providers: [TodosService],
})
export class TodosModule {}reference/TaskFlow_HTTP_API_Snapshot/src/todos/todos.service.ts
import { Injectable, NotFoundException } from '@nestjs/common';
interface Todo {
id: number;
title: string;
completed: boolean;
}
@Injectable()
export class TodosService {
private nextId = 3;
private readonly todos: Todo[] = [
{ id: 1, title: 'Learn HTTP', completed: false },
{ id: 2, title: 'Build the API contract', completed: false },
];
findAll() {
return this.todos;
}