
REST URL Design Patterns and Best Practices
Learn professional URL design patterns for REST APIs. Master versioning, pagination, filtering, searching, and consistent naming conventions.
REST URL Design Patterns and Best Practices
A well-designed API URL is like a well-organized filing system — anyone can find what they need without reading the manual. In this lesson, we will cover professional URL design patterns used by companies like Stripe, GitHub, and Twilio.
1. API Versioning
APIs evolve over time. Versioning prevents existing clients from breaking when you make changes.
URL Path Versioning (Most Common)
https://api.example.com/v1/users
https://api.example.com/v2/users
Header Versioning
curl -H "API-Version: 2" https://api.example.com/users
Query Parameter Versioning
https://api.example.com/users?version=2
Recommendation: Use URL path versioning. It is the most visible, cacheable, and universally supported approach.
When to Bump the Version
| Change | Version Bump? |
|---|---|
| Adding a new optional field | No |
| Adding a new endpoint | No |
| Removing a field | Yes — breaking |
| Renaming a field | Yes — breaking |
| Changing a field's type | Yes — breaking |
| Changing the URL structure | Yes — breaking |
2. Pagination Patterns
When a collection has thousands of items, returning all of them is impractical. Pagination breaks results into manageable pages.
Offset-Based Pagination
# Page 1 (items 1-20)
curl "https://api.example.com/products?page=1&limit=20"
# Page 2 (items 21-40)
curl "https://api.example.com/products?page=2&limit=20"
Response:
{
"data": [...],
"pagination": {
"page": 2,
"limit": 20,
"total": 500,
"totalPages": 25,
"hasNextPage": true,
"hasPreviousPage": true
}
}
Cursor-Based Pagination
Used by Twitter, Facebook, and APIs with frequently changing data:
# First page
curl "https://api.example.com/feed?limit=20"
# Next page (using cursor from previous response)
curl "https://api.example.com/feed?limit=20&cursor=eyJpZCI6MjB9"
Response:
{
"data": [...],
"cursors": {
"next": "eyJpZCI6NDB9",
"previous": "eyJpZCI6MjF9"
},
"hasMore": true
}
Which to Use?
| Type | Pros | Cons | Best For |
|---|---|---|---|
| Offset | Simple, "jump to page N" | Slow for large datasets | Admin dashboards |
| Cursor | Consistent, performant | No "jump to page" | Social feeds, logs |
3. Filtering and Searching
Simple Filtering
# Filter by exact value
curl "https://api.example.com/products?category=electronics"
# Filter by multiple values
curl "https://api.example.com/products?category=electronics&brand=apple"
# Filter by boolean
curl "https://api.example.com/products?inStock=true"
Range Filtering
# Price range
curl "https://api.example.com/products?minPrice=10&maxPrice=100"
# Date range
curl "https://api.example.com/orders?from=2026-01-01&to=2026-02-22"
Full-Text Search
curl "https://api.example.com/products?q=wireless+headphones"
Advanced Filtering (Bracket Notation)
Some APIs use bracket notation for complex filters:
# Products where status is active and price > 50
curl "https://api.example.com/products?filter[status]=active&filter[price][gt]=50"
4. Sorting
# Sort by price ascending
curl "https://api.example.com/products?sort=price&order=asc"
# Sort by date descending (newest first)
curl "https://api.example.com/products?sort=created_at&order=desc"
# Multiple sort fields
curl "https://api.example.com/products?sort=category,price&order=asc,desc"
GitHub-Style Sorting
GitHub uses a common pattern:
curl "https://api.github.com/search/repositories?q=rest+api&sort=stars&order=desc"
5. Field Selection (Sparse Fieldsets)
To reduce response size, some APIs let you specify which fields to return:
# Only return name and email
curl "https://api.example.com/users?fields=name,email"
# Return all user fields plus their posts
curl "https://api.example.com/users?include=posts"
Response without field selection:
{"id":1,"name":"John","email":"j@test.com","age":30,"address":{...},"phone":"..."}
Response with ?fields=name,email:
{"name":"John","email":"j@test.com"}
6. Real-World URL Design: Case Study
Let us study the Stripe API — widely considered the gold standard of API design:
# Core Resources
GET /v1/customers
POST /v1/customers
GET /v1/customers/:id
PUT /v1/customers/:id
DELETE /v1/customers/:id
# Nested Resources
GET /v1/customers/:id/payment_methods
POST /v1/customers/:id/subscriptions
# Specialized Actions
POST /v1/payment_intents/:id/confirm
POST /v1/payment_intents/:id/cancel
POST /v1/refunds
# Filtering and Pagination
GET /v1/charges?customer=cus_123&limit=10&starting_after=ch_abc
What Makes This Good
- Versioned (
/v1/) - Consistent plural nouns (
customers,charges) - Snake_case naming (their convention)
- Clear nested relationships
- Actions as verbs only when needed (
/confirm,/cancel) - Cursor-based pagination with
starting_after
7. Anti-Patterns to Avoid
| Anti-Pattern | Example | Why It Is Bad | Better |
|---|---|---|---|
| Verbs in URLs | /getUsers | Action is in the method | GET /users |
| Inconsistent pluralization | /user, /posts | Confusing | /users, /posts |
| Deep nesting | /a/1/b/2/c/3/d/4 | Unmanageable | Flatten with query params |
| File extensions | /users.json | Format goes in Accept header | /users |
| CRUD in URL | /create-user | Redundant with POST | POST /users |
| Mixed casing | /userProfiles | Inconsistent | /user-profiles |
| Using IDs in POST | POST /users/42 | Server assigns IDs | POST /users |
Summary and Key Takeaways
- Version your API with
/v1/in the URL path. - Use offset pagination for simple cases, cursor pagination for large/dynamic data.
- Filter with query parameters:
?category=electronics&inStock=true. - Sort with
?sort=field&order=asc|desc. - Select fields with
?fields=name,emailto reduce payload size. - Study APIs like Stripe and GitHub for design inspiration.
- Avoid anti-patterns: no verbs, no deep nesting, no inconsistent naming.
Lesson Review Quiz
?Knowledge Check
Which pagination method is better for a social media feed that changes frequently?
?Knowledge Check
When should you increment your API version (e.g., from v1 to v2)?
?Knowledge Check
Which URL pattern is the best practice for filtering products by category?