Files
Hugo/content/blog/rest-api-design.md
T

74 lines
2.2 KiB
Markdown

---
title: "REST API Design: Mistakes I've Made So You Don't Have To"
date: 2026-05-13T09:00:00+08:00
draft: false
description: "Lessons from real-world API design. Why version early, paginate everything, standardize error responses, and add idempotency keys. Plus a practical deprecation strategy with Sunset headers."
tags:
- API
- REST
- Backend
---
I've designed, built, and maintained enough REST APIs to have made most of the classic mistakes. Here's what I wish someone had told me upfront.
## 1. Versioning Early
Don't wait until you need it. Version your API from day one, either in the URL (`/v1/users`) or via the `Accept` header. Retrofitting versioning onto an unversioned API is painful for everyone involved.
My preference: **URL-based versioning**. It's visible, impossible to forget, and trivially cacheable.
## 2. Pagination by Default
Every list endpoint should be paginated. Every. Single. One.
```json
{
"data": [...],
"pagination": {
"cursor": "eyJpZCI6MTIzfQ==",
"has_more": true,
"total": 847
}
}
```
I've moved from offset-based to cursor-based pagination almost everywhere. Cursors handle real-time data changes gracefully and perform better on large datasets.
## 3. Error Responses Should Be Consistent
A predictable error shape means less client-side code:
```json
{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Account balance too low for this transaction",
"details": {
"required": 29.99,
"available": 12.50
}
}
}
```
Never expose stack traces in production. Never leak internal IDs without intent.
## 4. Idempotency Keys
For any mutating endpoint, support an `Idempotency-Key` header. Your payment team will thank you, and so will your users when a retry doesn't double-charge them.
## 5. Think in Terms of Deprecation
Add a `Deprecation` and `Sunset` header to old endpoints:
```
Deprecation: true
Sunset: Sat, 01 Aug 2026 00:00:00 GMT
```
Give consumers time to migrate, then actually follow through on removal. Keeping deprecated endpoints around "just in case" is technical debt with interest.
---
Good API design is mostly about **empathy for the consumer**. Ask yourself: would *you* enjoy integrating with this?