AIP-127

HTTP and gRPC Transcoding

APIs that follow resource-oriented design are defined using RPCs, but the resource-oriented design framework allows them to also be presented as APIs that largely follow REST/JSON conventions. This is important in order to help developers use their existing knowledge: over 80% of the public APIs available follow most REST conventions, and developers are accustomed to that pattern.

Guidance

APIs must provide HTTP definitions for each RPC that they define, except for bi-directional streaming RPCs, which can not be natively supported using HTTP/1.1. When providing a bi-directional streaming method, an API should also offer an alternative method that does not rely on bi-directional streaming.

HTTP method and path

When using protocol buffers, each RPC must define the HTTP method and path using the google.api.http annotation:

rpc CreateBook(CreateBookRequest) returns (Book) {
  option (google.api.http) = {
    post: "/v1/{parent=publishers/*}/books"
    body: "book"
  };
}

message CreateBookRequest {
  // The publisher who will publish this book.
  // When using HTTP/JSON, this field is automatically populated based
  // on the URI, because of the `{parent=publishers/*}` syntax.
  string parent = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      child_type: "library.googleapis.com/Book"
    }];

  // The book to create.
  // When using HTTP/JSON, this field is populated based on the HTTP body,
  // because of the `body: "book"` syntax.
  Book book = 2 [(google.api.field_behavior) = REQUIRED];

  // The user-specified ID for the book.
  // When using HTTP/JSON, this field is populated based on a query string
  // argument, such as `?bookId=foo`. This is the fallback for fields that
  // are not included in either the URI or the body.
  // Note that clients use camelCase format to communicate the field names
  // to the service.
  string book_id = 3;
}
  • The first key (post in this example) corresponds to the HTTP method. RPCs may use get, post, patch, or delete.
    • RPCs must use the prescribed HTTP verb for each standard method, as discussed in AIP-131, AIP-132, AIP-133, AIP-134, and AIP-135
    • RPCs should use the prescribed HTTP verb for custom methods, as discussed in AIP-136.
    • RPCs should not use put or custom.
  • The corresponding value represents the URI.
    • URIs must use the {foo=bar/*} syntax to represent a variable that should be populated in the request proto. When extracting a resource name, the variable must include the entire resource name, not just the ID component.
    • URIs may use nested fields for their variable names. (Additionally, AIP-134 mandates this for Update requests.)
    • URIs must use the * character to represent ID components, which matches all URI-safe characters except for /. URIs may use ** as the final segment of a URI if matching / is required.
  • The body key defines which single top-level field in the request will be sent as the HTTP body. If the body is *, then this indicates that the request object itself is the HTTP body. The request body is encoded as JSON as defined by protocol buffers' canonical JSON encoding.
    • RPCs must not define a body at all for RPCs that use the GET or DELETE HTTP verbs.
    • RPCs must use the prescribed body for Create (AIP-133) and Update (AIP-134) requests.
    • RPCs should use the prescribed body for custom methods (AIP-136).
    • The body must not contain a nested field (or use the . character),
    • The body must not be the same as a URI parameter.
    • The body must not be a repeated field.
    • Fields should not use the json_name annotation to alter the field name in JSON, unless doing so for backwards-compatibility reasons.
  • Request fields that are not bound to the URL path or the HTTP body are passed as URL query parameters.

Note: For the detailed transcoding behavior for the entire request (including how fields are bound across the URL path, HTTP request body, and URL query parameters), refer to the google.api.http documentation. For information on how fields and types are encoded—including query parameters and well-known types—refer to the Protocol Buffers canonical JSON encoding.

Note: Bi-directional streaming RPCs should not include a google.api.http annotation at all. If feasible, the service should provide non-streaming equivalent RPCs.

Multiple URI bindings

Occasionally, an RPC needs to correspond to more than one URI:

rpc CreateBook(CreateBookRequest) returns (Book) {
  option (google.api.http) = {
    post: "/v1/{parent=publishers/*}/books"
    body: "book"
    additional_bindings: {
      post: "/v1/{parent=authors/*}/books"
      body: "book"
    }
    additional_bindings: {
      post: "/v1/books"
      body: "book"
    }
  };
}
  • RPCs may define any number of additional bindings. The structure is identical to the google.api.http annotation (in fact, it is a recursive reference).
  • RPCs must not define an additional binding within an additional binding.
  • The body clause must be identical in the top-level annotation and each additional binding.

Changelog

  • 2026-10-14: Added general note referencing google.api.http transcoding documentation and Protocol Buffers JSON encoding for request fields and well-known types.
  • 2022-08-18: Added the comment that query string parameter names are in camelCase.
  • 2021-01-06: Added clarification around body and nested fields.
  • 2019-09-23: Added a statement about request body encoding, and guidance discouraging json_name.