RESTful API Best Practices

2025/5/7

# Use HTTP Methods Correctly

HTTP Method Behavior Idempotent Safe Cacheable
GET Retrieves a resource. 获取资源 Yes Yes Yes
POST Sends data to create/update a resource. 创建资源 No No No
PUT Replaces or updates a resource. 更新资源(全量更新) Yes No No
PATCH Partial updates a resource. 更新资源(部分更新)
DELETE Deletes a resource. Yes No No
HEAD Retrieves headers only, without body. Yes Yes Yes
OPTIONS Describes communication options for a resource. Yes Yes No
TRACE Echoes received request for diagnostic purposes. Yes Yes No
CONNECT Establishes a tunnel, often used for HTTPS. Yes No No

# Use Standard HTTP Response Codes Consistently

Category Range Description Examples
Informational 1xx Indicates that the request has been received and is being processed. 100 Continue
101 Switching Protocols
Successful 2xx Indicates that the request was successfully received, understood, and accepted. 200 OK:成功
201 Created:创建成功
204 No Content:删除成功
Redirection 3xx Indicates that further action is needed to fulfill the request. 301 Moved Permanently
302 Found
304 Not Modified
Client Error 4xx Indicates that there was an error with the request. 400 Bad Request:请求错误
401 Unauthorized:未认证
403 Forbidden:无权限
404 Not Found:资源不存在
Server Error 5xx Indicates that the server failed to fulfill a valid request. 500 Internal Server Error:服务器错误
502 Bad Gateway
503 Service Unavailable

# Use Consistent Naming Conventions and URL Structure

  • Use nouns for resource names (使用名词而非动词). URIs should represent resources, not actions. Use nouns for endpoints and avoid verbs. This structure aligns with the HTTP specification, which emphasizes resource-oriented design. For example, use /orders instead of /create-order. The verbal action on a URI is already implied by the HTTP GET, POST, PUT, PATCH, and DELETE methods.

    GET /books  				// Use this
    
    GET /getBooks			// DO NOT use this
    
    1
    2
    3
  • Use plural nouns to name collection URIs (使用复数形式). For example, /customers is the path to the customer's collection, and /customers/5 is the path to the customer with ID equal to 5.

    GET /users/{userId}/orders/{orderId}  // Recommended 
    
    GET /orders/{orderId}?userId=123     // Do not use this
    
    1
    2
    3
  • Consider the relationships between different types of resources and how you might expose these associations (使用层级关系表示不同资源). For example, the /customers/5/orders might represent all of the orders for customer 5. You could also go in the other direction, and represent the association from an order back to a customer with a URI such as /orders/99/customer.

  • Keep relationships simple and flexible. In more complex systems, it can be tempting to provide URIs that allow the client to navigate through several levels of relationships, such as /customers/1/orders/99/products. However, this level of complexity can be difficult to maintain and is inflexible if the relationships between resources change in the future. Instead, try to keep URIs relatively simple. Once an application has a reference to a resource, it should be possible to use this reference to find items related to that resource. The preceding query can be replaced with the URI /customers/1/orders to find all the orders for customer 1, and then /orders/99/products to find the products in this order.

  • 使用小写字母. Consistent lowercase URIs are preferred to ensure compatibility across systems as some environments treat URIs as case-sensitive. Mixing uppercase and lowercase characters introduces the possibility of errors.

    GET /categories/technology    // Use this
    
    GET /Categories/Technology   // DO NOT use this
    
    1
    2
    3
  • 使用连字符而不是下划线

# Implement Pagination, Filtering, Sorting, and Field selection

  • Pagination (分页) divides large datasets into smaller, manageable chunks. Use query parameters to specify the number of items to return (limit) and the starting point (offset). Make sure to also provide meaningful defaults for limit and offset (e.g., limit=25, offset=0). For example:

    GET /orders?limit=25&offset=50
    
    1
    • limit: Specifies the maximum number of items to return.
    • offset: Specifies the starting index for the data.
  • Filtering (过滤) allows clients to refine the dataset by applying conditions. The API can allow the client to pass filter in the query string of the URI:

    GET /orders?minCost=100&status=shipped
    
    1
  • Sorting (排序): Allow clients to sort data using a sort parameter (e.g., sort=price).

    GET /customers?sort=name:asc,age:desc
    
    1
  • Field selection for client-defined projections (字段选择): Enable clients to specify only the fields they need by using a fields parameter (e.g., fields=id,name). For example, you could use a query string parameter that accepts a comma-delimited list of fields, such as /orders?fields=ProductID,Quantity.

    GET /orders?fields=ProductID,Quantity
    
    1

# Handle API Versioning Gracefully

  • URI Versioning. Include the version number in the URI. This approach provides clear and explicit versioning and simplifies client requests. However, it can lead to URI bloat and may require changes to existing URIs for new versions.

    GET /api/v1/resources
    
    1
  • Query string versioning. Rather than providing multiple URIs, you can specify the version of the resource by using a parameter within the query string appended to the HTTP request

    GET /api/resources?version=1
    
    1
  • Header Versioning. Utilizing a custom header to indicate the desired version. This approach requires clients to manage headers and can be less intuitive for those unfamiliar with header manipulation.

    GET /api/resources
    X-API-Version: v1
    
    1
    2
  • Content Negotiation. Allowing clients to specify the version in the Accept header. In this approach, clients must understand how to use content negotiation effectively.

    GET /api/resources
    Accept: application/vnd.example.v1+json
    
    1
    2

# Reference

https://learn.microsoft.com/en-us/azure/architecture/best-practices/api-design (opens new window)

https://restfulapi.net/rest-api-best-practices/ (opens new window)

https://stackoverflow.blog/2020/03/02/best-practices-for-rest-api-design/ (opens new window)

https://daily.dev/blog/restful-api-design-best-practices-guide-2024 (opens new window)

https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Methods (opens new window)

https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers (opens new window)

https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status (opens new window)