Skip to content

Resource paths

Most APIs expose resources (their primary nouns) which users are able to create, retrieve, and manipulate. Additionally, resources have paths: each resource has a unique (within the API service) identifying path that users use to reference that resource, and these paths are what users should store as the canonical identifier for the resources.

Guidance

All resource paths defined by an API must be unique within that API. (See the section on full resource paths below for more information on referring to resources across APIs.)

Resource paths are formatted according to the URI path schema, but without the leading slash:

publishers/123/books/les-miserables users/vhugo1802

  • Resource path components must alternate between collection identifiers (example: publishers, books, users) and resource IDs (example: 123, les-miserables, vhugo1802), except when singleton resources are present.
  • Resource paths must use the / character to separate individual segments of the resource path.
  • Each segment of a resource path must not contain a / character.
  • Resource paths should only use characters available in DNS names, as defined by RFC-1123.
    • Additionally, resource IDs should not use upper-case letters.
    • If additional characters are necessary, resource paths should not use characters that require URL-escaping, or characters outside of ASCII.
    • If Unicode characters can not be avoided, resource paths must be stored in Normalization Form C (see AEP-210).
  • Each resource must expose a path field that contains its resource path.
    • Resources may provide the resource ID, i.e. the last segment of the path, as a separate field named id.
    • Resources must not expose tuples, self-links, or other forms of resource identification.
    • All ID fields must be strings.

Collection identifiers

The collection identifier segments in a resource path must be the plural form of the noun used for the resource. (For example, a collection of Publisher resources is called publishers in the resource path.)

  • Collection identifiers must be concise American English terms.
  • Collection identifiers must be in kebab-case.
  • Collection identifiers must begin with a lower-cased letter and contain only lower-case ASCII letters, numbers. and hyphens (/[a-z][a-z0-9-]*/).
  • Collection identifiers must be plural.
  • In situations where there is no plural word (“info”), or where the singular and plural terms are the same (“moose”), the non-pluralized (singular) form is correct. Collection segments must not “coin” words by adding “s” in such cases (e.g. avoid “infos”).

Nested collections

If a resource path contains multiple levels of a hierarchy, and a parent collection’s path is used as a prefix for the child resource’s path, the child collection’s path may omit the prefix. For example, given a collection of UserEvent resources that would normally be nested underneath users:

users/vhugo1802/user-events/birthday-dinner-226/user-event-guests/123

An API may use the less-redundant form:

users/vhugo1802/events/birthday-dinner-226/guests/123

In this situation, the message is still called UserEvent or UserEventGuest; only the collection name is shortened.

Resource ID segments

A resource ID segment identifies the resource within its parent collection. In the resource path publishers/123/books/les-miserables, 123 is the resource ID for the publisher, and les-miserables is the resource ID for the book.

  • Resource IDs may be either always set by users (required on resource creation), optionally set by users (optional on resource creation, server-generated if unset), or never set by users (not accepted at resource creation). They must be immutable once created.
  • If resource IDs are user-settable, the API must document and/or annotate the field with the allowed formats. User-settable resource IDs should conform to RFC-1034; which restricts to letters, numbers, and hyphen, with the first character a letter, the last a letter or a number, and a 63 character maximum.
    • Additionally, user-settable resource IDs should restrict letters to lower-case (^[a-z]([a-z0-9-]{0,61}[a-z0-9])?$).
    • Characters outside of ASCII should not be permitted; however, if Unicode characters are necessary, APIs must follow guidance in AEP-210.
    • User-settable IDs should not be permitted to be a UUID (or any value that syntactically appears to be a UUID).
    • Field annotations should use protovalidate in protobuf and JSON Schema keywords like pattern with OAS/JSON Schema.
  • If resource IDs are not user-settable, the API should document the basic format, and any upper boundaries (for example, “at most 63 characters”).
  • For more information, see the create standard method.

Resource ID aliases

It is sometimes valuable to provide an alias for common lookup patterns for resource IDs. For example, an API with users at the top of its resource hierarchy may wish to provide users/me as a shortcut for retrieving information for the authenticated user.

APIs may provide programmatic aliases for common lookup patterns. However, all data returned from the API must use the canonical resource path.

Full resource paths

In most cases, resource paths are used within a single API only, or else they are used in contexts where the owning API is clear (for example, string pubsub_topic).

However, sometimes it is necessary for services to refer to resources in an arbitrary API. In this situation, the service should use the full resource path, a schemeless URI with the owning API’s service endpoint, followed by the relative resource path:

apis.example.com/library/publishers/123/books/les-miserables
//apis.example.com/calendar/users/vhugo1802

Resource URIs

The full resource path is a schemeless URI, but slightly distinct from the full URIs we use to access a resource. The latter adds two components: the protocol (HTTPS) and the API version:

https://apis.example.com/library/v1/publishers/123/books/les-miserables
https://apis.example.com/calendar/v3/users/vhugo1802

The version is not included in the full resource path because the full resource path is expected to persist from version to version. Even though the API surface may change between major versions, multiple major versions of the same API are expected to use the same underlying data.

Fields representing resource paths

When defining a resource, the first field should be the resource path, which must be of type string and must be called path for the resource path. The message should include a google.api.resource annotation declaring the type (see AEP-4 for more on this).

// A representation of a book in the library.
message Book {
option (google.api.resource) = {
type: "apis.example.com/library/Book"
pattern: "publishers/{publisher}/books/{book}"
};
// The resource path of the book.
// Format: publishers/{publisher}/books/{book}
string path = 1;
// Other fields...
}

When defining a method that retrieves or acts on an already-existing resource (such as GetBook or ArchiveBook), the first field of the request message should be the resource path, which must be of type string and must be called path for the resource path. The field should also be annotated with the google.api.resource_reference annotation, referencing the resource type (AEP-4).

// Request message for ArchiveBook
message ArchiveBookRequest {
// The book to archive.
// Format: publishers/{publisher}/books/{book}
string path = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
type: "apis.example.com/library/Book"
}];
// Other fields...
}

Fields representing a resource’s parent

When defining a method that retrieves resources from a collection or adds a new resource to a collection (such as ListBooks or CreateBook), the first field of the request message should be of type string and should be called parent for the resource path of the collection. The parent field should also be annotated with the google.api.resource_reference annotation, referencing the parent’s resource type (AEP-4).

// Request message for ListBooks.
message ListBooksRequest {
// The publisher to list books from.
// Format: publishers/{publisher_id}
string parent = 1 [(google.api.resource_reference) = {
type: "apis.example.com/library/Publisher"
}];
// Other fields (e.g. max_page_size, page_token, filter, etc.)...
}

If there is more than one possible parent type, the parent field should be annotated with the child_type key on google.api.resource_reference instead:

// Request message for ListBooks.
message ListBooksRequest {
// The parent to list books from.
// Format:
// - publishers/{publisher_id}
// - authors/{author_id}
string parent = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {
child_type: "apis.example.com/library/Book"
}];
// Other fields (e.g. max_page_size, page_token, filter, etc.)...
}

Fields representing another resource

When referencing a resource path for a different resource, the field should be of type string for the resource path, and the field name should be equivalent to the corresponding message’s name in snake case.

  • Field names may include a leading adjective if appropriate (such as string dusty_book).
  • Field names should not use the _path suffix unless the field would be ambiguous without it (e.g., crypto_key_path)
  • Fields representing another resource should provide the google.api.resource_reference annotation with the resource type being referenced.
// A representation of a book in a library.
message Book {
option (google.api.resource) = {
type: "apis.example.com/library/Book"
pattern: "publishers/{publisher}/books/{book}"
};
// Path of the book.
// Format is `publishers/{publisher}/books/{book}`
string path = 1;
// The shelf where the book currently sits.
// Format is `shelves/{shelf}`.
string shelf = 2 [(google.api.resource_reference) = {
type: "apis.example.com/library/Shelf"
}];
// Other fields...
}

Further reading

  • For evolving resource paths over time, see AEP-180.
  • For resource types, see AEP-4.