Skip to content

Custom methods

Resource oriented design (AEP-121) uses custom methods to provide a means to express actions that are difficult to model using only the standard methods. Custom methods are important because they provide a means for an API’s vocabulary to adhere to user intent.

Guidance

Custom methods should only be used for functionality that can not be expressed via standard methods; prefer standard methods if possible, due to their consistent semantics. However, APIs should not contort things to endeavor to make the standard methods “sort of work”.

While custom methods vary widely in how they are designed, many principles apply consistently:

  • The HTTP method for custom methods should be selected based on the semantics described by RFC 7231 section 4.3 and RFC 5789 for PATCH. In practice, the vast majority of custom methods should use POST or GET.
    • Custom methods that serve as an alternative to get or list methods (such as Search) should use GET, and require no request body. These methods must be idempotent and have no state changes or side effects (they should be safe as defined in RFC 7231 section 4.2.1).
    • Custom methods should not use PATCH or DELETE.
  • The HTTP URI must use a : character followed by the custom verb (:archive in the above example), and the verb in the URI must match the verb in the name of the RPC.
    • If word separation is required, camelCase must be used.
rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) {
option (google.api.http) = {
post: "/v1/{path=publishers/*/books/*}:archive"
body: "*"
};
}
  • The name of the RPC should be a verb followed by a noun.
    • The name must not contain prepositions (“for”, “with”, etc.).
  • The body clause in the google.api.http annotation should be "*".
    • However, if using GET or DELETE, the body clause must be absent.
  • Custom methods must take a request message exactly matching the RPC name, with a Request suffix. For example, ArchiveBookRequest.
  • Custom methods should return a response message exactly matching the RPC name, with a Response suffix. For example, ArchiveBookResponse.
    • When operating on a specific resource, a custom method may return the resource itself.

Resource-based custom methods

Custom methods must operate on a resource if the API can be modeled as such:

rpc ArchiveBook(ArchiveBookRequest) returns (ArchiveBookResponse) {
option (google.api.http) = {
post: "/v1/{path=publishers/*/books/*}:archive"
body: "*"
};
}
  • The parameter for the resource’s path must be called path, and must be the only variable in the URI path.

Collection-based custom methods

While most custom methods operate on a single resource, some custom methods may operate on a collection instead:

rpc SortBooks(SortBooksRequest) returns (SortBooksResponse) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books:sort"
body: "*"
};
}
  • If the collection has a parent, the field name in the request message should be parent.
  • The collection key (books in the above example) must be literal.

Stateless methods

Some custom methods are not attached to resources at all. These methods are generally stateless: they accept a request and return a response, and have no permanent effect on data within the API.

rpc TranslateText(TranslateTextRequest) returns (TranslateTextResponse) {
option (google.api.http) = {
post: "/v1/{project=projects/*}:translateText"
body: "*"
};
}
  • If the method runs in a particular scope (such as a project, as in the above example), the field name in the request message should be the name of the scope resource. If word separators are necessary, snake_case must be used.
  • The URI should place both the verb and noun after the : separator (avoid a “faux collection key” in the URI in this case, as there is no collection). For example, :translateText is preferable to text:translate.
  • Stateless methods must use POST if they involve billing.

Usage in declarative clients

APIs should not employ custom methods for functionality that is intended to be used in a declarative client. Declarative clients use create,read,update,and delete operations to apply desired state, and integration of custom methods is manual and results in client-side complexity around state management to determine when the custom method should be invoked.

AEP’s supported declarative clients cannot support custom methods.