Building REST APIs That Last
Demo Creator
@seed-creator · muallif
URI Versioning
Prefix routes with /v1/ from day one. When breaking changes arrive, add /v2/ alongside. Clients migrate on their schedule; you deprecate the old version after a sunset period.
An unversioned API is a promise you cannot keep — every breaking change breaks your consumers.
Consistent Error Envelopes
Always return errors in the same shape: a short machine-readable message and a human-readable details field. Clients can parse errors generically without inspecting HTTP bodies per-endpoint.
Use HTTP status codes semantically. 404 means the resource does not exist, not just "something went wrong." 422 or 400 is for validation failures, not 500.
RBAC at the Route Level
Attach role requirements to routes as metadata, evaluated by a guard before the controller runs. Keep authorization logic out of services — services should assume the caller is authorized.
@Controller('articles')export class ArticlesController { @Post() @Roles('creator', 'admin') create(@Body() dto: CreateArticleDto, @CurrentUser() user: UserRow) { return this.articlesService.create(dto, user.id); } @Get(':slug') @Public() findBySlug(@Param('slug') slug: string) { return this.articlesService.findPublished(slug); }}
@Roles declares who may call this route; RolesGuard enforces it before the handler runs.