Skip to content

Apply

In REST APIs, it is customary to make a PUT request to a resource’s URI (for example, /v1/publishers/{publisher_id}/books/{book_id}) in order to create or replace a resource.

Resource-oriented design honors this pattern through the Apply method. These operations accept the resource and its path, which it uses to create or replace the resource. The operation returns the final resource.

Also see the update method, with guidance on how to implement PATCH requests.

APIs should provide an apply method for a resource unless it is not valuable for users to do so. Clients should also consider using update methods instead to ensure forwards compatible requests (see PATCH and PUT).

  • If a field in the request is not present, the service must not modify this field.

Apply methods are specified using the following pattern:

  • The HTTP verb must be PUT.
  • Some resources take longer to be applied than is reasonable for a regular API request. In this situation, the API should use a long-running operation.
  • The operation must have strong consistency.
  • The HTTP URI path of the PUT method must be the resource path.
rpc ApplyBook ( ApplyBookRequest ) returns ( Book ) {
option (google.api.http) = {
put: "/{path=publishers/*/books/*}",
body: "book"
};
}
  • The request message must match the method name, with a Request suffix.

  • There must be a body key in the google.api.http annotation, and it must map to the resource field in the request message.

    • All remaining fields should map to URI query parameters.
  • There should be exactly one google.api.method_signature annotation, with a value of "parent,{resource},id", or “"parent,{resource}" if the resource ID is not required.

  • The method’s name must begin with the word Apply. The remainder of the method name should be the singular form of the resource being applied.

  • The request’s path field must map to the URI path.

  • The path field must be the only variable in the URI path.

Apply methods implement a common request message pattern:

  • The resource must be included and must map to the HTTP request body.
  • The request schema must not contain any other required fields and should not contain other optional fields except those described in this or another AEP.
message ApplyBookRequest {
// The globally unique identifier for the resource
string path = 10018 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = { type: "bookstore.example.com/book" }
];
// The resource to perform the operation on.
Book book = 10015 [(google.api.field_behavior) = REQUIRED];
}
  • A path field specifying the path of the resource must be included.
  • The response must be the resource itself. There is no separate response schema.
    • The response should include the fully-populated resource, and must include any fields that were provided unless they are input only (see field behavior).
message Book {
option (google.api.resource) = {
type: "bookstore.example.com/book",
pattern: [ "publishers/{publisher_id}/books/{book_id}" ],
plural: "books",
singular: "book"
};
// A Author.
message Author {
// Field for given_name.
string given_name = 1 [json_name = "given_name"];
// Field for family_name.
string family_name = 2 [json_name = "family_name"];
}
// Field for isbn.
repeated string isbn = 1 [(google.api.field_behavior) = REQUIRED];
// Field for price.
int32 price = 2 [(google.api.field_behavior) = REQUIRED];
// Field for published.
bool published = 3 [(google.api.field_behavior) = REQUIRED];
// Field for edition.
int32 edition = 4 [(google.api.field_behavior) = REQUIRED];
// Field for author.
repeated Author author = 5;
// Field for path.
string path = 10018;
}

If an resource does not have a field set which is labeled with required (either the protobuf field behavior or present in the JsonSchema required field), the request must fail with “INVALID_ARGUMENT / 400 Bad Request`.

For additional guidance, see errors, in particular when to use PERMISSION_DENIED and NOT_FOUND errors.

PUT requests with fields missing in the resource may result in overwriting values in the resource with existing values. Specifically in protobuf, the fields that do not have the optional annotation will use their default zero value, overwriting any previous value. This gap does not exist in an update, where the field_mask field helps clarify which fields to overwrite.

As such AEP-compliant clients should use the PATCH HTTP verb.

See AEP-134’s patch and put for more information.

rpc ApplyBook ( ApplyBookRequest ) returns ( Book ) {
option (google.api.http) = {
put: "/{path=publishers/*/books/*}",
body: "book"
};
}
message ApplyBookRequest {
// The globally unique identifier for the resource
string path = 10018 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = { type: "bookstore.example.com/book" }
];
// The resource to perform the operation on.
Book book = 10015 [(google.api.field_behavior) = REQUIRED];
}
message Book {
option (google.api.resource) = {
type: "bookstore.example.com/book",
pattern: [ "publishers/{publisher_id}/books/{book_id}" ],
plural: "books",
singular: "book"
};
// A Author.
message Author {
// Field for given_name.
string given_name = 1 [json_name = "given_name"];
// Field for family_name.
string family_name = 2 [json_name = "family_name"];
}
// Field for isbn.
repeated string isbn = 1 [(google.api.field_behavior) = REQUIRED];
// Field for price.
int32 price = 2 [(google.api.field_behavior) = REQUIRED];
// Field for published.
bool published = 3 [(google.api.field_behavior) = REQUIRED];
// Field for edition.
int32 edition = 4 [(google.api.field_behavior) = REQUIRED];
// Field for author.
repeated Author author = 5;
// Field for path.
string path = 10018;
}
  • For ensuring idempotency in Apply methods, see idempotency.
  • For naming resources involving Unicode, see unicode.