Custom methods

This chapter will discuss how to use custom methods for API designs.

Custom methods refer to API methods besides the 5 standard methods. They should only be used for functionality that cannot be easily expressed via standard methods. In general, API designers should choose standard methods over custom methods whenever feasible. Standard Methods have simpler and well-defined semantics that most developers are familiar with, so they are easier to use and less error prone. Another advantage of standard methods is the API platform has better understanding and support for standard methods, such as billing, error handling, logging, monitoring.

A custom method can be associated with a resource, a collection, or a service. It may take an arbitrary request and return an arbitrary response, and also supports streaming request and response.

Custom method names must follow method naming conventions.

HTTP mapping

For custom methods, they should use the following generic HTTP mapping:

https://service.name/v1/some/resource/name:customVerb

The reason to use : instead of / to separate the custom verb from the resource name is to support arbitrary paths. For example, undelete a file can map to POST /files/a/long/file/name:undelete

The following guidelines shall be applied when choosing the HTTP mapping:

  • Custom methods should use HTTP POST verb since it has the most flexible semantics, except for methods serving as an alternative get or list which may use GET when possible. (See third bullet for specifics.)
  • Custom methods should not use HTTP PATCH, but may use other HTTP verbs. In such cases, the methods must follow the standard HTTP semantics for that verb.
  • Notably, custom methods using HTTP GET must be idempotent and have no side effects. For example custom methods that implement special views on the resource should use HTTP GET.
  • The request message field(s) receiving the resource name of the resource or collection with which the custom method is associated should map to the URL path.
  • The URL path must end with a suffix consisting of a colon followed by the custom verb.
  • If the HTTP verb used for the custom method allows an HTTP request body (this applies to POST, PUT, PATCH, or a custom HTTP verb), the HTTP configuration of that custom method must use the body: "*" clause and all remaining request message fields shall map to the HTTP request body.
  • If the HTTP verb used for the custom method does not accept an HTTP request body (GET, DELETE), the HTTP configuration of such method must not use the body clause at all, and all remaining request message fields shall map to the URL query parameters.

WARNING: If a service implements multiple APIs, the API producer must carefully create the service configuration to avoid custom verb conflicts between APIs.

// This is a service level custom method.
rpc Watch(WatchRequest) returns (WatchResponse) {
  // Custom method maps to HTTP POST. All request parameters go into body.
  option (google.api.http) = {
    post: "/v1:watch"
    body: "*"
  };
}

// This is a collection level custom method.
rpc ClearEvents(ClearEventsRequest) returns (ClearEventsResponse) {
  option (google.api.http) = {
    post: "/v3/events:clear"
    body: "*"
  };
}

// This is a resource level custom method.
rpc CancelEvent(CancelEventRequest) returns (CancelEventResponse) {
  option (google.api.http) = {
    post: "/v3/{name=events/*}:cancel"
    body: "*"
  };
}

// This is a batch get custom method.
rpc BatchGetEvents(BatchGetEventsRequest) returns (BatchGetEventsResponse) {
  // The batch get method maps to HTTP GET verb.
  option (google.api.http) = {
    get: "/v3/events:batchGet"
  };
}

Use Cases

Some additional scenarios where custom methods may be the right choice:

  • Reboot a virtual machine. The design alternatives could be "create a reboot resource in collection of reboots" which feels disproportionately complex, or "virtual machine has a mutable state which the client can update from RUNNING to RESTARTING" which would open questions as to which other state transitions are possible. Moreover, reboot is a well-known concept that can translate well to a custom method which intuitively meets developer expectations.
  • Send mail. Creating an email message should not necessarily send it (draft). Compared to the design alternative (move a message to an "Outbox" collection) custom method has the advantage of being more discoverable by the API user and models the concept more directly.
  • Promote an employee. If implemented as a standard update, the client would have to replicate the corporate policies governing the promotion process to ensure the promotion happens to the correct level, within the same career ladder etc.
  • Batch methods. For performance critical methods, it may be useful to provide custom batch methods to reduce per-request overhead. For example, accounts.locations.batchGet.

A few examples where a standard method is a better fit than a custom method:

  • Query resources with different query parameters (use standard list method with standard list filtering).
  • Simple resource property change (use standard update method with field mask).
  • Dismiss a notification (use standard delete method).

Common Custom Methods

The curated list of commonly used or useful custom method names is below. API designers should consider these names before introducing their own to facilitate consistency across APIs.

Method Name Custom verb HTTP verb Note
Cancel :cancel POST Cancel an outstanding operation, such as operations.cancel.
BatchGet :batchGet GET Batch get of multiple resources. See details in the description of List.
Move :move POST Move a resource from one parent to another, such as folders.move.
Search :search GET Alternative to List for fetching data that does not adhere to List semantics, such as services.search.
Undelete :undelete POST Restore a resource that was previously deleted, such as services.undelete. The recommended retention period is 30-day.