Skip to content

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 (AEP-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 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.

Operation

Create methods are specified using the following pattern:

  • The HTTP verb must be POST.
  • Some resources take longer to be created than is reasonable for a regular API request. In this situation, the API should use a long-running operation.
rpc CreateBook ( CreateBookRequest ) returns ( Book ) {
option (google.api.http) = {
post: "/{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 collection’s parent resource must 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.
  • 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 operation must have strong consistency.

Requests

Create methods implement a common request message pattern:

  • An id field should be supported.
  • 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 AEP.
message CreateBookRequest {
// A field for the parent of book
string parent = 10013 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = { }
];
// An id that uniquely identifies the resource within the collection
string id = 10014;
// The resource to perform the operation on.
Book book = 10015 [(google.api.field_behavior) = REQUIRED];
}
  • A parent field must be included unless the resource being created is a top-level resource. It should be called parent.

Responses

message Book {
option (google.api.resource) = {
type: "bookstore.example.com/book",
pattern: [ "publishers/{publisher}/books/{book}" ],
plural: "books",
singular: "book"
};
// A Author.
message Author {
// Field for firstName.
string firstName = 1;
// Field for lastName.
string lastName = 2;
}
// Field for author.
repeated Author author = 5;
// Field for isbn.
repeated string isbn = 1 [(google.api.field_behavior) = REQUIRED];
// Field for price.
float price = 2 [(google.api.field_behavior) = REQUIRED];
// Field for published.
bool published = 3 [(google.api.field_behavior) = REQUIRED];
// Field for edition.
int32 edition = 4;
// Field for path.
string path = 10000;
}

Errors

See errors, in particular when to use PERMISSION_DENIED and NOT_FOUND errors.

User-specified IDs

An API should allow a user to specify the ID component of a resource: not doing so introduces a non-idempotent request in the API, as sending the same payload results in creating a new resource each time.

Exceptional cases should have the following behavior:

  • The resource allows identical records without a need to disambiguate between the two (e.g. rows in a table with no primary key).
  • The resource will not be exposed in Declarative clients.

An API may allow the id field to be optional, and give the resource 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 path field on the resource must be ignored.
  • The documentation should explain what the acceptable format is, and the format should follow the guidance for resource path formatting in AEP-122.
  • If a user tries to create a resource with an ID that would result in a duplicate resource path, 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.
  • There should be exactly one google.api.method_signature annotation on the RPC, with a value of "parent,{resource},id" if the resource being created is not a top-level resource, or with a value of "{resource},id" if the resource being created is a top-level resource.
  • The 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.

Interface Definitions

rpc CreateBook ( CreateBookRequest ) returns ( Book ) {
option (google.api.http) = {
post: "/{parent=publishers/*}/books",
body: "book"
};
option (google.api.method_signature) = "parent,book";
}
message CreateBookRequest {
// A field for the parent of book
string parent = 10013 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = { }
];
// An id that uniquely identifies the resource within the collection
string id = 10014;
// 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}/books/{book}" ],
plural: "books",
singular: "book"
};
// A Author.
message Author {
// Field for firstName.
string firstName = 1;
// Field for lastName.
string lastName = 2;
}
// Field for author.
repeated Author author = 5;
// Field for isbn.
repeated string isbn = 1 [(google.api.field_behavior) = REQUIRED];
// Field for price.
float price = 2 [(google.api.field_behavior) = REQUIRED];
// Field for published.
bool published = 3 [(google.api.field_behavior) = REQUIRED];
// Field for edition.
int32 edition = 4;
// Field for path.
string path = 10000;
}

Further reading

  • For ensuring idempotency in Create methods, see AEP-155.
  • For naming resources involving Unicode, see AEP-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 path and use it in references from other resources.