Resource names

In resource-oriented APIs, resources are named entities, and resource names are their identifiers. Each resource must have its own unique resource name. The resource name is made up of the ID of the resource itself, the IDs of any parent resources, and its API service name. We'll look at resource IDs and how a resource name is constructed below.

gRPC APIs should use scheme-less URIs for resource names. They generally follow the REST URL conventions and behave much like network file paths. They can be easily mapped to REST URLs: see the Standard Methods section for details.

A collection is a special kind of resource that contains a list of sub-resources of identical type. For example, a directory is a collection of file resources. The resource ID for a collection is called collection ID.

The resource name is organized hierarchically using collection IDs and resource IDs, separated by forward slashes. If a resource contains a sub-resource, the sub-resource's name is formed by specifying the parent resource name followed by the sub-resource's ID - again, separated by forward slashes.

Example 1: A storage service has a collection of buckets, where each bucket has a collection of objects:

API Service Name Collection ID Resource ID Collection ID Resource ID
//storage.googleapis.com /buckets /bucket-id /objects /object-id

Example 2: An email service has a collection of users. Each user has a settings sub-resource, and the settings sub-resource has a number of other sub-resources, including customFrom:

API Service Name Collection ID Resource ID Resource ID Resource ID
//mail.googleapis.com /users /name@example.com /settings /customFrom

An API producer can choose any acceptable value for resource and collection IDs as long as they are unique within the resource hierarchy. You can find more guidelines for choosing appropriate resource and collection IDs below.

By splitting the resource name, such as name.split("/")[n], one can obtain the individual collection IDs and resource IDs, assuming none of the segments contains any forward slash.

Full Resource Name

A scheme-less URI consisting of a DNS-compatible API service name and a resource path. The resource path is also known as relative resource name. For example:

"//library.googleapis.com/shelves/shelf1/books/book2"

The API service name is for clients to locate the API service endpoint; it may be a fake DNS name for internal-only services. If the API service name is obvious from the context, relative resource names are often used.

Relative Resource Name

A URI path (path-noscheme) without the leading "/". It identifies a resource within the API service. For example:

"shelves/shelf1/books/book2"

Resource ID

A resource ID typically consists of one or more non-empty URI segments (segment-nz-nc) that identify the resource within its parent resource, see above examples. The non-trailing resource ID in a resource name must have exactly one URL segment, while the trailing resource ID in a resource name may have more than one URI segment. For example:

Collection ID Resource ID
files source/py/parser.py

API services should use URL-friendly resource IDs when feasible. Resource IDs must be clearly documented whether they are assigned by the client, the server, or either. For example, file names are typically assigned by clients, while email message IDs are typically assigned by servers.

Collection ID

A non-empty URI segment (segment-nz-nc) identifying the collection resource within its parent resource, see above examples.

Because collection IDs often appear in the generated client libraries, they must conform to the following requirements:

  • Must be valid C/C++ identifiers.
  • Must be in plural form with lowerCamel case. If the term doesn't have suitable plural form, such as "evidence" and "weather", the singular form should be used.
  • Must use clear and concise English terms.
  • Overly general terms should be avoided or qualified. For example, rowValues is preferred to values. The following terms should be avoided without qualification:
    • elements
    • entries
    • instances
    • items
    • objects
    • resources
    • types
    • values

Resource Name vs URL

While full resource names resemble normal URLs, they are not the same thing. A single resource can be exposed by different API versions, API protocols, or API network endpoints. The full resource name does not specify such information, so it must be mapped to a specific API version and API protocol for actual use.

To use a full resource name via REST APIs, it must be converted to a REST URL by adding the HTTPS scheme before the service name, adding the API major version before the resource path, and URL-escaping the resource path. For example:

// This is a calendar event resource name.
"//calendar.googleapis.com/users/john smith/events/123"

// This is the corresponding HTTP URL.
"https://calendar.googleapis.com/v3/users/john%20smith/events/123"

Resource Name as String

Google APIs must represent resource names using plain strings, unless backward compatibility is an issue. Resource names should be handled like normal file paths. When a resource name is passed between different components, it must be treated as an atomic value and must not have any data loss.

For resource definitions, the first field should be a string field for the resource name, and it should be called name.

For example:

service LibraryService {
  rpc GetBook(GetBookRequest) returns (Book) {
    option (google.api.http) = {
      get: "/v1/{name=shelves/*/books/*}"
    };
  };
  rpc CreateBook(CreateBookRequest) returns (Book) {
    option (google.api.http) = {
      post: "/v1/{parent=shelves/*}/books"
      body: "book"
    };
  };
}

message Book {
  // Resource name of the book. It must have the format of "shelves/*/books/*".
  // For example: "shelves/shelf1/books/book2".
  string name = 1;

  // ... other properties
}

message GetBookRequest {
  // Resource name of a book. For example: "shelves/shelf1/books/book2".
  string name = 1;
}

message CreateBookRequest {
  // Resource name of the parent resource where to create the book.
  // For example: "shelves/shelf1".
  string parent = 1;
  // The Book resource to be created. Client must not set the `Book.name` field.
  Book book = 2;
}

Note: For consistency of resource names, the leading forward slash must not be captured by any URL template variable. For example, URL template "/v1/{name=shelves/*/books/*}" must be used instead of "/v1{name=/shelves/*/books/*}".

Questions

Q: Why not use resource IDs to identify a resource?

For any large system, there are many kinds of resources. To use resource IDs to identify a resource, we actually use a resource-specific tuple to identify a resource, such as (bucket, object) or (user, album, photo). It creates several major problems:

  • Developers have to understand and remember such anonymous tuples.
  • Passing tuples is generally harder than passing strings.
  • Centralized infrastructures, such as logging and access control systems, don't understand specialized tuples.
  • Specialized tuples limit API design flexibility, such as providing reusable API interfaces. For example, Long Running Operations can work with many other API interfaces because they use flexible resource names.

Q: Why is the resource name field called name instead of id?

The resource name field is named after the concept of resource "name". In general, we find the concept of name is confusing to developers. For example, is filename really just the name or the full path? By reserving the standard field name, developers are forced to choose a more proper term, such as display_name or title or full_name.

Q: How should I generate and parse resource names?

Resource names behave like file paths. You can use printf() to generate resource names from resource ids. You can use split() to parse resource names into resource ids. Note that some trailing Resource ID can have multiple URI segments separated by /, like file path.