AIP-2510

Project identifiers

Historically, Google had two kinds of projects: API projects and App Engine projects. API projects used project numbers (e.g. 12345) as identifiers, and App Engine projects used project IDs (e.g. happy-armadillo-789) as identifiers. Later, Google converged API projects and App Engine projects, so now each project has both unique and immutable identifiers.

The two types of identifiers are used differently in different contexts, and create a lot of complexity for application development. One critical issue is that applications cannot reliably join data from different services, because different services use different project identifiers.

Guidance

TL;DR: The project number is the canonical identifier, and the project ID is an alias; however, unlike normal aliases, it should be returned if it is what the user sent. Additionally, third-party services are unable to accept project IDs.

The rationale for this is:

  • Each resource should always have one canonical identifier.
  • Because Google's privacy policy restricts the use of project IDs, both internally and with partners, only the project number can be the canonical identifier.
  • However, even though the project number is the canonical identifier, a policy of returning it even if the user sent a project ID has proven to be unfriendly to both humans and declarative tools.

Google APIs

Externally-facing Google APIs should accept both project IDs and project numbers for incoming API requests.

However, even though the project number is the canonical identifier as described in AIP-122, services should return whichever ID the user sent. The reason for this is because automatic translation between user-friendly project IDs and user-unfriendly project numbers has proven to cause real-world difficulty for users, and also for declarative tools (see AIP-128 for more on declarative-friendliness).

Two additional points:

  • Error responses must return the originally-provided value without modification. Error responses must not perform any translation between project IDs and project numbers.
  • If a service receives a resource name for a resource that the service does not own, it should not perform any translation between project IDs and project numbers for those resource names.

Internal Google services

Internal Google services must use project numbers for internal data storage and for output. Project identifiers are widely used as storage keys, which often appear in logs and metrics. Project IDs are user-settable and thus considered PII and user data, but project numbers are not.

Therefore, when an internal service calls an external Google APIs, it should use project numbers for making API requests.

Resource References

Project identifiers also appear in resource names. These resource names are used both to identify the resource itself and can refer to other resources (example).

When project identifiers are provided, the response should include the identifier as it occurred in the request: if the project ID was provided it should be returned, and if the project number was provided, that is what should be in the response.

For example, consider a Book resource,

message Book {
  option (google.api.resource) = {
    type: "pubsub.googleapis.com/Book"
    pattern: "projects/{project}/books/{book}"
  };

  // The resource name of the Book.
  string name = 1;

  // A reference to another resource, a Shelf.
  string shelf = 2 [(google.api.resource_reference) = {
    type: "library.googleapis.com/Shelf"
  }];

  // Other fields...
}

with the following book submitted from a previous create request (represented as JSON in this example),

{
  "name": "projects/my-project/books/les-miserables",
  "shelf": "projects/12345/shelves/top-shelf"
}

and a GetBookRequest,

message GetBookRequest {
  // The name of the Book to retrieve.
  // Format: projects/{project}/books/{book}
  string name = 1 [
    (google.api.field_behavior) = REQUIRED,
    (google.api.resource_reference) = {
      type: "library.googleapis.com/Book"
    }];
}

and if the value of name on such a request is,

projects/my-project/books/les-miserables

then the value of the field, name, returned for the Book, should match: the project ID and not the number should be returned. But, the value for the field, shelf should use the project number, as the create request had submitted a shelf with the project number in the resource name.

In other words, the following values should be returned:

book: projects/my-project/books/les-miserables
shelf: projects/12345/shelves/top-shelf

This guidance is to ensure that there is a minimal difference between user input and output.

Third-party services

Third-party services that are integrated with Google Cloud Platform must only store or provide project numbers. Google's privacy policy prohibits sharing project IDs with third-party services, or providing a service for third-party services to translate between project IDs and project numbers at runtime.

Project identifier format

Services must use project resource names as defined by the Resource Manager API to refer to projects, such as projects/123456. This allows the same API to work with other resources similar to projects, such as organizations and folders.

Changelog

  • 2022-10-19: Clarified guidance for project identifiers in resource references.
  • 2021-07-29: Reversed previous guidance on returning project IDs; this AIP now advocates returning what the user sent.
  • 2019-08-11: Add an exception for resources that a service does not own.
  • 2019-06-19: Clarify how error messages should be treated
  • 2019-06-10: Minor language and organization tweaks