Guidelines For Uri Design

Master the fundamental principles of crafting intuitive, consistent, and developer-friendly URIs for REST APIs

Understanding URI Design Fundamentals

URI design is one of the most foundational yet frequently overlooked aspects of web API development. A well-designed URI is intuitive, memorable, and self-documenting--allowing developers to understand your API's structure at a glance. Conversely, poorly designed URIs create confusion, increase integration time, and signal deeper architectural problems. For teams building modern web applications, clean URI design is essential for creating maintainable, developer-friendly interfaces.

What Makes a Good URI

A good URI should be predictable and follow consistent patterns across your entire API. The structure should reveal resource hierarchy without requiring developers to consult documentation--each endpoint tells a story about what it returns. According to Microsoft's API design guidance, URIs should be human-readable and convey meaning at a glance, making API exploration intuitive and efficient.

The key differentiators between good and poor URIs include:

  • Predictability: Following established patterns so developers can guess endpoint names
  • Self-documentation: Clear resource names that explain what the endpoint represents
  • Consistency: Uniform conventions applied across all endpoints
  • Simplicity: Avoiding unnecessary complexity while maintaining descriptive clarity

URI Components Explained

Every URI consists of distinct components that serve specific purposes in identifying resources:

  • Scheme (https://): Establishes secure communication between client and server
  • Host (api.example.com): Identifies the server hosting the API
  • Path segments (/users/{id}/orders): Define the resource hierarchy and structure
  • Query parameters (?status=active&page=1): Enable filtering, sorting, and pagination

Understanding these components helps you make informed decisions about where to place different aspects of your resource identification strategy. Path segments should represent essential resource identity, while optional modifications belong in query parameters.

URI Anatomy Diagram A well-structured URI showing all key components: scheme, host, path, and query parameters

Resource Naming Conventions

Use Nouns, Not Verbs

The most fundamental principle of RESTful URI design is using nouns to represent resources rather than verbs to describe actions. HTTP methods (GET, POST, PUT, DELETE) already convey the action--embedding verbs in URIs creates redundancy and inconsistency. As Stack Overflow's API design guide explains, this separation of concerns makes your API more expressive and easier to understand. When designing RESTful APIs, this principle ensures your endpoints remain consistent and predictable.

Good Examples:

  • GET /users - Retrieve all users
  • POST /users - Create a new user
  • GET /users/{id} - Retrieve specific user
  • PUT /users/{id} - Update a user
  • DELETE /users/{id} - Delete a user

Anti-Patterns to Avoid:

  • /getUsers - Verb in path
  • /createUser - Verb in path
  • /deleteUserById - Verb in path

Plural Nouns for Collections

Use plural nouns for collection resources. This convention provides consistency whether you're requesting one item or many, and avoids the awkward singular/plural ambiguity that arises when dealing with single resources within collections. Microsoft's Azure Architecture Center recommends plural forms for better predictability across different HTTP methods.

  • GET /products - All products
  • GET /products/{id} - Single product
  • GET /orders/{orderId}/items - Items in an order

Case Sensitivity and Formatting

Maintain consistency in URI casing using lowercase letters with hyphens separating words. This improves readability and ensures compatibility across different clients and platforms. Some servers treat URIs as case-sensitive, so consistency prevents broken links and confusion.

Recommended Format:

  • GET /user-preferences (lowercase with hyphens)
  • GET /order-confirmation-number (descriptive multi-word paths)

Avoid:

  • /UserPreferences (PascalCase creates inconsistencies)
  • /user_preferences (snake_case reduces readability in some contexts)
  • /userPreferences (camelCase varies across programming languages)

Avoid Special Characters and File Extensions

Exclude file extensions (.json, .xml) from URIs--content type negotiation should occur through HTTP headers, not URI structure. Similarly, avoid special characters that require encoding and can cause interoperability issues across different platforms. Keep your URIs clean, readable, and focused on resource identification rather than implementation details.

Before: /api/getUserData.json?id=123 After: /api/users/123 (with Accept header specifying JSON response)

RESTful CRUD Operations
GET /api/v1/products # List all products
POST /api/v1/products # Create new product
GET /api/v1/products/{id} # Get specific product
PUT /api/v1/products/{id} # Update product (full)
PATCH /api/v1/products/{id} # Update product (partial)
DELETE /api/v1/products/{id} # Delete product

Hierarchical Resource Organization

Logical Resource Relationships

When one resource belongs to or is contained within another, reflect this relationship in the URI structure. As Stack Overflow's API design best practices note, this creates intuitive, navigable API endpoints that mirror real-world relationships and make your API self-documenting.

Common Hierarchies:

  • /users/{userId}/posts - Posts belonging to a user
  • /posts/{postId}/comments - Comments on a post
  • /customers/{customerId}/orders - Orders for a customer
  • /companies/{companyId}/employees - Employees at a company

Nesting Depth Limits

Avoid deep nesting beyond two to three levels. Each additional level increases complexity and makes URIs harder to understand and maintain. Microsoft recommends limiting nesting depth to prevent overly complex endpoint structures.

Recommended Maximum:

  • /customers/{customerId}/orders/{orderId} - Two levels (acceptable)
  • /customers/{customerId}/orders/{orderId}/items/{itemId} - Three levels (use sparingly)

Refactor Deeply Nested URIs: Instead of: /customers/{customerId}/orders/{orderId}/items/{itemId}/reviews/{reviewId} Consider: /reviews/{reviewId} with query parameters like ?itemId={itemId}&customerId={customerId}

When to Use Independent Resources

Not all resources require hierarchical placement. If a resource can exist independently, expose it at the top level rather than forcing artificial relationships. This flexibility prevents over-complication and simplifies your API surface. For example, while comments belong to posts, they can also exist independently--if a comment exists without a post context, expose /comments/{id} as a top-level endpoint while maintaining /posts/{postId}/comments/{id} for convenience.

Query Parameters for Flexibility

Filtering and Search

Use query parameters when filtering, searching, or paginating resources. This keeps the URI path focused on resource identity while parameters control the result set. Stack Overflow's API guidance recommends separating resource identity from result modification through query parameters.

Common Query Parameter Patterns:

  • /products?category=electronics&minPrice=100 - Filter by category and price
  • /users?status=active&sort=name - Filter by status and sort results
  • /search?q=api+design&limit=10 - Search with result limits
  • /orders?customerId=123&status=shipped - Cross-reference filtering

Sorting and Pagination

Implement standard pagination using page and limit parameters, or cursor-based pagination for large datasets. Include metadata in responses to help clients navigate results efficiently.

Offset-Based Pagination:

  • /products?page=3&limit=20 - Get 20 items starting at offset 40

Cursor-Based Pagination (recommended for large datasets):

  • /products?cursor=abc123&limit=50 - Get 50 items after cursor

Response metadata should include:

  • Total count of matching results
  • Current page or cursor position
  • Links to next/previous pages
  • Total number of pages

Optional Attributes and Field Selection

Allow clients to request specific fields using a fields parameter, reducing payload size for bandwidth-constrained environments or when clients only need partial data.

Example: /users?fields=id,name,email&status=active

This returns only the specified fields, improving performance and reducing unnecessary data transfer--particularly valuable for mobile applications and high-volume integrations.

API Versioning in URIs

URL Path Versioning

The most common and explicit versioning approach places the version number directly in the path. DocuWriter.ai's API design best practices note that this makes the version immediately visible and simplifies routing, debugging, and client integration.

Examples:

  • /api/v1/users
  • /api/v2/products
  • /v3/orders

Alternative Versioning Strategies

While URL path versioning is most common, other strategies exist with different trade-offs:

Header-Based Versioning:

  • GET /users with Accept: application/vnd.api.v1+json
  • Pros: Keeps URIs clean
  • Cons: Hidden versioning, harder to debug

Query Parameter Versioning:

  • /users?version=1
  • Pros: Simple to implement
  • Cons: Can be accidentally cached with wrong version

No Versioning (Immutable APIs):

  • Never break existing responses, only add
  • Pros: Ultimate stability for consumers
  • Cons: Can lead to bloated APIs over time

When to Introduce Versions

Version your API when introducing breaking changes--modifying field names, changing response structures, or removing endpoints. Non-breaking additions (new optional fields, new endpoints) don't require new versions.

Deprecation Communication

When deprecating versions, provide clear timelines and migration guidance. Include deprecation warnings in responses and maintain old versions for a reasonable transition period (typically 12-18 months). Notify consumers through multiple channels: API documentation, response headers, and direct communication.

Common Anti-Patterns and Solutions

Exposing Internal Structure

Avoid mirroring database table or column names in URIs. Your API is an abstraction layer--translate technical identifiers into meaningful resource names that make sense to API consumers.

Instead of: /tbl_users or /db.customer.users Use: /users

Instead of: /user_account_tbl_primary_key Use: /accounts/{accountId}

Inconsistent Naming

Establish naming conventions early and apply them consistently across all endpoints. Inconsistency forces developers to constantly consult documentation and creates integration friction. Following established web development best practices helps maintain consistency across your API surface.

Common Inconsistencies to Avoid:

  • Mixing singular and plural nouns (/user vs /users)
  • Inconsistent casing (/user-preferences vs /userPreferences)
  • Varying path structures (/products/all vs /products)

Verbose or Cryptic URIs

Keep URIs concise but descriptive. Avoid unnecessary words, redundant information, or cryptic abbreviations that obscure meaning.

Before: /api/v1/get-all-active-customers-with-orders-in-last-30-days After: /customers?status=active&hasOrders=true&orderDate=last30days

Mixing Concepts

Each URI should represent one clear resource or collection. Avoid combining multiple concepts in a single endpoint, which creates confusion and limits flexibility.

Anti-Pattern: /users-with-active-subscriptions-and-recent-activity Better: /users?status=active&subscription=active&activity=recent

CRUD Operations in URIs

Never include HTTP method names or CRUD action words in your URI paths. The HTTP method itself conveys the action--doubling up creates redundancy and breaks REST principles.

Before: /users/create, /users/update, /users/delete After: POST /users, PUT /users/{id}, DELETE /users/{id}

Complete URI Design Examples
# Related Resources
GET /api/v1/products/{id}/reviews # Get product reviews
GET /api/v1/products/{id}/variants # Get product variants
GET /api/v1/users/{id}/orders # Get user orders

# Filtering and Search
GET /api/v1/products?category=shoes&brand=nike
GET /api/v1/products?in_stock=true&sort=price,desc
GET /api/v1/search?q=web+development&page=1&limit=20

# Complex Queries
GET /api/v1/orders?status=shipped&date_from=2024-01-01&date_to=2024-12-31
GET /api/v1/users?role=admin&has_active_subscription=true

# Field Selection
GET /api/v1/users?fields=id,name,email&status=active
Key URI Design Principles

Nouns Over Verbs

Use nouns to represent resources, letting HTTP methods convey actions for cleaner, more consistent endpoints

Consistent Naming

Apply the same conventions across all endpoints--plural nouns, lowercase, hyphens--for predictable API behavior

Shallow Nesting

Limit resource hierarchy to 2-3 levels maximum to maintain clarity and prevent overly complex URIs

Version Strategy

Include version numbers in paths for breaking changes, with clear deprecation timelines for consumers

Frequently Asked Questions

Build Better APIs with Digital Thrive

Our web development team specializes in designing intuitive, scalable APIs that developers love to use. From RESTful URI design to complete API architecture, we help you build APIs that stand the test of time.

Sources

  1. Microsoft Azure Architecture Center - Web API Design Best Practices - Authoritative Microsoft guidance covering RESTful URI naming conventions, resource organization, and HTTP method alignment.
  2. Stack Overflow Blog - Best Practices for REST API Design - Practical developer-focused guidance on endpoint design, error handling, and consistent URI patterns.
  3. DocuWriter.ai - 8 Crucial API Design Best Practices for 2025 - Modern API design including versioning strategies, security, and performance optimization.