AIP-133
Standard methods: Create
In REST APIs, it is customary to make a POST
request to a collection's URI
(for example, /v1/publishers/{publisher}/books
) in order to create a new
resource within that collection.
Resource-oriented design (AIP-121) honors this pattern through the Create
method. These RPCs accept the parent collection and the resource to create (and
potentially some other parameters), and return the created resource.
Guidance
APIs should generally provide a create method for resources unless it is not valuable for users to do so. The purpose of the create method is to create a new resource in an already-existing collection.
Create methods are specified using the following pattern:
rpc CreateBook(CreateBookRequest) returns (Book) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books"
body: "book"
};
option (google.api.method_signature) = "parent,book";
}
- The RPC's name must begin with the word
Create
. The remainder of the RPC name should be the singular form of the resource being created. - The request message must match the RPC name, with a
Request
suffix. - The response message must be the resource itself. There is no
CreateBookResponse
.- The response should include the fully-populated resource, and must include any fields that were provided unless they are input only (see AIP-203).
- If the create RPC is long-running, the response
message must be a
google.longrunning.Operation
which resolves to the resource itself.
- The HTTP verb must be
POST
. - The collection where the resource is being added should map to the URI
path.
- The collection's parent resource should be called
parent
, and should be the only variable in the URI path. - The collection identifier (
books
in the above example) must be a literal string.
- The collection's parent resource should be called
- There must be a
body
key in thegoogle.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},{resource}_id"
, or ""parent,{resource}"
if the resource ID is not required. - If the API is operating on the management plane, the operation should have strong consistency: the completion of a create operation must mean that all user-settable values and the existence of the resource have reached a steady-state and reading resource state returns a consistent response.
Request message
Create methods implement a common request message pattern:
message CreateBookRequest {
// The parent resource where this book will be created.
// Format: publishers/{publisher}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
child_type: "library.googleapis.com/Book"
}];
// The ID to use for the book, which will become the final component of
// the book's resource name.
//
// This value should be 4-63 characters, and valid characters
// are /[a-z][0-9]-/.
string book_id = 2 [(google.api.field_behavior) = REQUIRED];
// The book to create.
Book book = 3 [(google.api.field_behavior) = REQUIRED];
}
- A
parent
field must be included unless the resource being created is a top-level resource. It should be calledparent
.- The field should be annotated as required.
- The field must identify the resource type of the resource being created.
- A
{resource}_id
field must be included for management plane resources, and should be included for data plane resources. - The resource field must be included and must map to the POST body.
- The request message must not contain any other required fields and should not contain other optional fields except those described in this or another AIP.
Long-running create
Some resources take longer to create a resource than is reasonable for a regular API request. In this situation, the API should use a long-running operation (AIP-151) instead:
rpc CreateBook(CreateBookRequest) returns (google.longrunning.Operation) {
option (google.api.http) = {
post: "/v1/{parent=publishers/*}/books"
body: "book"
};
option (google.longrunning.operation_info) = {
response_type: "Book"
metadata_type: "OperationMetadata"
};
}
- The response type must be set to the resource (what the return type would be if the RPC was not long-running).
- Both the
response_type
andmetadata_type
fields must be specified.
Important: Declarative-friendly resources (AIP-128) should use long-running operations. The service may return an LRO that is already set to done if the request is effectively immediate.
User-specified IDs
An API must allow a user to specify the ID component of a resource (the last segment of the resource name) on creation if the API is operating on the management plane.
On the data plane, an API should allow a user to specify the ID. Exceptional cases should have the following behavior:
- The data plane resource allows identical records without a need to disambiguate between the two (e.g. rows in a table with no primary key).
- The data plane resource will not be exposed in Declarative clients.
An API
may allow the {resource}_id
field have the field_behavior OPTIONAL
,
and generate a system-generated ID if one is not specified.
For example:
// Using user-specified IDs.
publishers/lacroix/books/les-miserables
// Using system-generated IDs.
publishers/012345678-abcd-cdef/books/12341234-5678-abcd
- The
{resource}_id
field must exist on the request message, not the resource itself.- The field may be required or optional. If it is required, it should include the corresponding annotation.
- The
name
field on the resource must be ignored. - There should be exactly one
google.api.method_signature
annotation on the RPC, with a value of"parent,{resource},{resource}_id"
if the resource being created is not a top-level resource, or with a value of"{resource},{resource}_id"
if the resource being created is a top-level resource. - The documentation should explain what the acceptable format is, and the format should follow the guidance for resource name formatting in AIP-122.
- If a user tries to create a resource with an ID that would result in a
duplicate resource name, the service must error with
ALREADY_EXISTS
.- However, if the user making the call does not have permission to see the
duplicate resource, the service must error with
PERMISSION_DENIED
instead.
- However, if the user making the call does not have permission to see the
duplicate resource, the service must error with
Note: For REST APIs, the user-specified ID field, {resource}_id
,
is provided as a query parameters on the request URI.
Errors
See errors, in particular when to use PERMISSION_DENIED and NOT_FOUND errors.
Further reading
- For ensuring idempotency in
Create
methods, see AIP-155. - For naming resources involving Unicode, see AIP-210.
Rationale
Requiring user-specified ids
Declarative clients use the resource ID as a way to identify a resource for applying updates and for conflict resolution. The lack of a user-specified ID means a client is unable to find the resource unless they store the identifier locally, and can result in re-creating the resource. This in turn has a downstream effect on all resources that reference it, forcing them to update to the ID of the newly-created resource.
Having a user-specified ID also means the client can precalculate the resource name and use it in references from other resources.
Changelog
- 2023-10-20: Clarify that {resource}_id is only required for management plane resources.
- 2023-08-24: Adding consistency requirement.
- 2023-05-11: Changing guidance around resource_id to a must.
- 2022-11-04: Referencing aggregated error guidance in AIP-193, similar to other CRUDL AIPs.
- 2022-06-02: Changed suffix descriptions to eliminate superfluous "-".
- 2020-10-06: Added declarative-friendly guidance.
- 2020-08-14: Updated error guidance to use permission denied over forbidden.
- 2020-06-08: Added guidance on returning the full resource.
- 2019-11-22: Added clarification on what error to use if a duplicate name is sent.
- 2019-10-18: Added guidance on annotations.
- 2019-08-01: Changed the examples from "shelves" to "publishers", to present a better example of resource ownership.
- 2019-06-10: Added guidance for long-running create.
- 2019-05-29: Added an explicit prohibition on arbitrary fields in standard methods.