REST URL Design Patterns and Best Practices

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

ChangeVersion Bump?
Adding a new optional fieldNo
Adding a new endpointNo
Removing a fieldYes — breaking
Renaming a fieldYes — breaking
Changing a field's typeYes — breaking
Changing the URL structureYes — 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?

TypeProsConsBest For
OffsetSimple, "jump to page N"Slow for large datasetsAdmin dashboards
CursorConsistent, performantNo "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

  1. Versioned (/v1/)
  2. Consistent plural nouns (customers, charges)
  3. Snake_case naming (their convention)
  4. Clear nested relationships
  5. Actions as verbs only when needed (/confirm, /cancel)
  6. Cursor-based pagination with starting_after

7. Anti-Patterns to Avoid

Anti-PatternExampleWhy It Is BadBetter
Verbs in URLs/getUsersAction is in the methodGET /users
Inconsistent pluralization/user, /postsConfusing/users, /posts
Deep nesting/a/1/b/2/c/3/d/4UnmanageableFlatten with query params
File extensions/users.jsonFormat goes in Accept header/users
CRUD in URL/create-userRedundant with POSTPOST /users
Mixed casing/userProfilesInconsistent/user-profiles
Using IDs in POSTPOST /users/42Server assigns IDsPOST /users

Summary and Key Takeaways

  1. Version your API with /v1/ in the URL path.
  2. Use offset pagination for simple cases, cursor pagination for large/dynamic data.
  3. Filter with query parameters: ?category=electronics&inStock=true.
  4. Sort with ?sort=field&order=asc|desc.
  5. Select fields with ?fields=name,email to reduce payload size.
  6. Study APIs like Stripe and GitHub for design inspiration.
  7. 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?

Subscribe to our newsletter

Get the latest posts delivered right to your inbox.

Subscribe on LinkedIn