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

77 lines
2.3 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
title: "REST API Design: Mistakes I've Made So You Don't Have To"
date: 2026-05-13T09:00:00+08:00
draft: false
poet: |
Form follows function.
——Louis Sullivan,美国,1856–1924
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?