RESTful API Best Practices
HTTP Verbs
- GET: Retrieve resources (idempotent, safe)
- POST: Create new resources
- PUT: Replace entire resource (idempotent)
- PATCH: Partial update
- DELETE: Remove resource (idempotent)
Status Codes
| Code | Meaning | When to Use |
|---|---|---|
| 200 | OK | Successful GET, PUT, PATCH |
| 201 | Created | Successful POST |
| 204 | No Content | Successful DELETE |
| 400 | Bad Request | Invalid input |
| 401 | Unauthorized | Missing/invalid authentication |
| 403 | Forbidden | Authenticated but not authorized |
| 404 | Not Found | Resource doesn't exist |
| 409 | Conflict | Duplicate resource |
| 500 | Server Error | Unexpected error |
Resource Naming
✅ Good:
/api/products
/api/products/123
/api/products/123/reviews
/api/orders/456/items
❌ Bad:
/api/getProducts
/api/product/delete/123
/api/createOrder
Versioning
// URL versioning
app.MapGet("/api/v1/products", GetProductsV1);
app.MapGet("/api/v2/products", GetProductsV2);
// Header versioning
app.MapGet("/api/products", async (HttpContext context) =>
{
var version = context.Request.Headers["api-version"];
return version == "2.0" ? GetProductsV2() : GetProductsV1();
});
Pagination
public class PagedResult\<T\>
{
public List\<T\> Items { get; set; }
public int Page { get; set; }
public int PageSize { get; set; }
public int TotalCount { get; set; }
public int TotalPages => (int)Math.Ceiling(TotalCount / (double)PageSize);
}
app.MapGet("/api/products", (int page = 1, int pageSize = 10) =>
{
// Return paginated results
});