Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Latest commit

 

History

History
151 lines (99 loc) · 9.14 KB

guiding-principles.md

File metadata and controls

151 lines (99 loc) · 9.14 KB

📣 Announcement: New documentation location

The documentation for WooCommerce Blocks has moved to the WooCommerce monorepo.

Please refer to the documentation in the new location as the files in this repository will no longer be updated and the repository will be archived.


Store API Guiding principles

Table of Contents

The following principles should be considered when extending, creating, or updating endpoints in the Store API.

Routes must include a well-defined JSON schema

Each route/endpoint requires a particular structure of input data and should return data using a defined and predictable structure. This is defined in the JSON schema, which contains a comprehensive list of all of the properties the API can return and which input parameters it can accept.

Well-defined schema also provides a layer of security, as it enables us to validate and sanitize the requests being made to the API.

When defining schema, take note of the WordPress REST API handbook which documents available properties and types, as well as the JSON schema standard. In addition to this:

  • Properties should use snake_case 🐍
  • Ambiguous terms should be avoided, and property names should try to use understandable language, rather than “WooCommerce” terminology or setting names
  • Properties should be defined using US English, but the descriptions of fields should be localized
  • Multiple types are permitted, for example, using a null type if a value is not applicable
  • sanitize_callback and validate_callback are encouraged where possible to ensure data is received in the correct format before processing requests

If you’re struggling to define a consistent schema, your approach may be flawed. A common real-world example of this would be representing something like Post Tags. It may be tempting to use the Slug as the property field name in the response:

tags: [
  "my-tag": {
    // ...tag data
  },
  "my-other-tag": {
    // ...tag data
  }
]

However, this is difficult to represent in Schema and is not predictable for the client. A better approach would be to use an array of data, with one of the properties being the Slug:

tags: [
  {
    "slug": "my-tag",
    // ...tag data
  },
  {
    "slug": "my-other-tag",
    // ...tag data
  }
]

Routes should be designed around resources with a single type of schema

Routes should be designed around resources (nouns) rather than operations (verbs). Routes should also return only one type of data defined by their Schema. For example:

Route Resource type Expected data
wc/store/v1/cart Cart A cart object
wc/store/v1/cart/items Cart Item A list of cart item objects
wc/store/v1/products Product A list of product objects
wc/store/v1/products/1 Product A product object

There are 2 notable exceptions to this rule in the Store API; Errors and Cart Operations.

Error Handling

Errors, including validation errors, should return an error response code (4xx or 5xx) and a WP_Error object. The AbstractRoute class will handle the conversion of the WP_Error object into a valid JSON response.

Error messages should be localized, but do not need to be written with language aimed at customers (clients should use the given error code to create customer-facing notices as needed).

Error codes should have the prefix woocommerce_rest_.

Cart Operations

Some endpoints are designed around operations to avoid clients needing to make multiple round trips to the API. This is purely for convenience.

An example would be the wc/store/v1/cart/add-item endpoint which accepts a quantity and product ID, but returns a full cart object, rather than just an updated list of items.

Exposed data must belong to the current user or be non-sensitive

Resources, including customer and order data, should reflect only the current session. Do not return data for other customers as this would be a breach of privacy and security issue.

Store data such as settings (for example, store currency) is permitted in responses, but private or sensitive data must be avoided. To allow more extensive access to data, you must use the authenticated WC REST API.

Data returned from the API should not be escaped (this is left to the client rendering it), but it should be sanitized. For example, HTML should be run through wp_kses_post.

It is the client’s responsibility to properly escape data that comes from the API, but we should try to avoid returning data that is potentially unsafe.

Collections of resources should be paginated

Large volumes of data should be paginated to avoid overwhelming the server. For example, returning a collection of products.

  • Use the response Headers X-WP-Total, X-WP-TotalPages, and Link to indicate available resources.
  • Use parameters page and per_page to retrieve certain pages.
  • The maximum allowed value for per_page is 100.

API Responses should use standard HTTP status codes

When returning content, use a valid HTTP response code such as:

  • 200 OK for successful responses (this is the default response code).
  • 201 Created when creating a resource, for example, adding a new cart item or applying a new coupon.
  • 204 No Content for successful deletes.
  • 400 Bad Request when a required parameter is not set.
  • 403 Forbidden when a request is not allowed, for example, if the provided security nonce is invalid.
  • 404 Not Found if a resource does not exist.
  • 409 Conflict if a resource cannot be updated, for example, if something in the cart is invalid and removed during the request.

A note on DELETE requests, a common pattern in the WordPress REST API is to return the deleted object. In the case of the Store API, we opt to return an empty response with status code 204 No Content instead. This is more efficient.

A full list of HTTP status codes can be found here.

Breaking changes should be avoided where possible

The Store API establishes a contract between itself and API consumers via the use of Schema. This contract should not be broken unless absolutely necessary. If a breaking change were necessary, a new version of the Store API would need to be released.

A breaking change is anything that changes the format of existing Schema, removes a Schema property, removes an existing route, or makes a backwards-incompatible change to anything public that may already be in use by consumers. Breaking changes can be avoided by deprecating existing properties rather than removing them, or deprecating routes and replacing them with a different route if major changes are needed.

Non-breaking changes are always permitted without the need to increase the API version. Some examples of these include:

  • Adding new properties to schema
  • Adding new routes, endpoints, methods
  • Adding optional request parameters
  • Re-ordering response fields

The version will not increase for bug fixes unless the scope of the bug causes a backwards-incompatible change. Fixes would not be rolled back to past API versions with the exception of security issues that require backporting.


We're hiring! Come work with us!

🐞 Found a mistake, or have a suggestion? Leave feedback about this document here.