google API Design Guide

来源:互联网 发布:混凝土配合比软件 编辑:程序博客网 时间:2024/06/07 10:32

Introduction

This is a general design guide for networked APIs. It has been used inside Google since 2014 and is the guide we follow when designing Cloud APIs and other Google APIs. It is shared here to inform outside developers and to make it easier for us all to work together.

Google Cloud Endpoints developers may find this guide particularly useful when designing gRPC APIs, and we strongly recommend such developers use these design principles. However, we don't mandate its use for any non-Google developer and you can use Cloud Endpoints and/or gRPC without following the guide.

This guide applies to both REST APIs and RPC APIs, with specific focus on gRPC APIs. gRPC APIs use Protocol Buffers to define their API surface and API Service Configuration to configure their API services, including HTTP mapping, logging, and monitoring. HTTP mapping features are used by Google APIs and Cloud Endpoints gRPC APIs for JSON/HTTP to Protocol Buffers/RPC transcoding.

This guide is a living document and additions to it will be made over time as new style and design patterns are adopted and approved. In that spirit, it is never going to be complete and there will always be ample room for the art and craft of API design.

Conventions Used in This Document

The requirement level keywords "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" used in this document are to be interpreted as described in RFC 2119.

In this document, such keywords are highlighted using bold font.


Resource Oriented Design

The goal for this Design Guide is to help developers design simple, consistent and easy-to-use networked APIs. At the same time, it also helps converging designs of socket-based RPC APIs with HTTP-based REST APIs.

Traditionally, people design RPC APIs in terms of API interfaces and methods, such as CORBA and Windows COM. As time goes by, more and more interfaces and methods are introduced. The end result can be an overwhelming number of interfaces and methods, each of them different from the others. Developers have to learn each one carefully in order to use it correctly, which can be both time consuming and error prone.

The architectural style of REST was first introduced in 2000, primarily designed to work well with HTTP/1.1. Its core principle is to define named resources that can be manipulated using a small number of methods. The resources and methods are known as nouns and verbs of APIs. With the HTTP protocol, the resource names naturally map to URLs, and methods naturally map to HTTP methods POST, GET, PUT, PATCH, and DELETE.

On the Internet, HTTP REST APIs have been recently hugely successful. In 2010, about 74% of public network APIs were HTTP REST APIs.

While HTTP REST APIs are very popular on the Internet, the amount of traffic they carry is smaller than traditional RPC APIs. For example, about half of Internet traffic in America at peak time is video content, and few people would consider using REST APIs to deliver such content for performance reasons. Inside data centers, many companies use socket-based RPC APIs to carry most network traffic, which can be orders of magnitude higher than public REST APIs.

In reality, both RPC APIs and HTTP REST APIs are needed for various reasons. Ideally, an API platform should provide best support for all APIs. This Design Guide helps you design and build APIs that conform to this principle. It does so by applying resource-oriented design principles to general API design, and defines many common design patterns to improve usability and reduce complexity.

NOTE: This Design Guide explains how to apply REST principles to API designs independent of programming language, operating system, or network protocol. It is NOT a guide solely to creating REST APIs.

What is a REST API?

A REST API is modeled as collections of individually-addressable resources (the nouns of the API). Resources are referenced with their resource names and manipulated via a small set of methods (also known as verbs or operations).

Standard methods for REST Google APIs (also known as REST methods) are List, Get, Create, Update, and Delete. Custom methods (also known as custom verbs or custom operations) are also available to API designers for functionality that doesn't easily map to one of the standard methods, such as database transactions.

NOTE: Custom verbs does not mean creating custom HTTP verbs to support custom methods. For HTTP-based APIs, they simply map to the most suitable HTTP verbs.

Design flow

The Design Guide suggests taking the following steps when designing resource- oriented APIs (more details are covered in specific sections below):

  • Determine what types of resources an API provides.
  • Determine the relationships between resources.
  • Decide the resource name schemes based on types and relationships.
  • Decide the resource schemas.
  • Attach minimum set of methods to resources.

Resources

A resource-oriented API is generally modeled as a resource hierarchy, where each node is either a simple resource or a collection resource. For convenience, they are often called as a resource and a collection, respectively.

  • A collection contains a list of resources of the same type.For example, a user has a collection of contacts.
  • A resource has some state and zero or more sub-resources.Each sub-resource can be either a simple resource or a collection resource.

For example, Gmail API has a collection of users, each user has a collection of messages, a collection of threads, a collection of labels, a profile resource, and several setting resources.

While there is some conceptual alignment between storage systems and REST APIs, a service with a resource-oriented API is not necessarily a database, and has enormous flexibility in how it interprets resources and methods. For example, creating a calendar event (resource) may create additional events for attendees, send email invitations to attendees, reserve conference rooms, and update video conference schedules.

Methods

The key characteristic of a resource-oriented API is that it emphasizes resources (data model) over the methods performed on the resources (functionality). A typical resource-oriented API exposes a large number of resources with a small number of methods. The methods can be either the standard methods or custom methods. For this guide, the standard methods are: List, Get, Create, Update, and Delete.

Where API functionality naturally maps to one of the standard methods, that method should be used in the API design. For functionality that does not naturally map to one of the standard methods, custom methods may be used. Custom methods offer the same design freedom as traditional RPC APIs, which can be used to implement common programming patterns, such as database transactions or data analysis.

Examples

The following sections present some real world examples on how to apply resource-oriented API design to large scale services.

Gmail API

The Gmail API service implements the Gmail API and exposes most of Gmail functionality. It has the following resource model:

  • The Gmail API service: gmail.googleapis.com
  • A collection of users: users/*. Each user has the following resources.
    • A collection of messages: users/*/messages/*.
    • A collection of threads: users/*/threads/*.
    • A collection of labels: users/*/labels/*.
    • A collection of change history: users/*/history/*.
    • A resource representing the user profile: users/*/profile.
    • A resource representing user settings: users/*/settings.

Google Cloud Pub/Sub API

The pubsub.googleapis.com service implements the Google Cloud Pub/Sub API, which defines the following resource model:

  • The API service: pubsub.googleapis.com
  • A collection of topics: projects/*/topics/*.
  • A collection of subscriptions: projects/*/subscriptions/*.

NOTE: Other implementations of the Pub/Sub API may choose different resource naming schemes.


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 NameCollection IDResource IDCollection IDResource 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 NameCollection IDResource IDResource IDResource 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 non-empty URI segment (segment-nz-nc) identifying the resource within its parent resource, see above examples.

The trailing resource ID in a resource name may have more than one URI segment. For example:

Collection IDResource IDfiles/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 generated client libraries, they must conform to the following requirements:

  • Must be valid C/C++ identifiers.
  • Must be in plural form with lowerCamel case.
  • Must use clear and concise English terms.
  • Overly general terms should be avoided or qualified. For example, 
    RowValue is preferred to Value. The following terms should be avoided without qualification:
    • Element
    • Entry
    • Instance
    • Item
    • Object
    • Resource
    • Type
    • Value

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 versions of APIs and via different API protocols. The full resource name does not specify such information, so it must be mapped to a specific protocol and API version 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 strings, unless backward compatibility is an issue. Resource names should be handled much like normal file paths, and they do not support %-encoding.

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

Note: Other name-related fields should be qualified to avoid confusion, such as display_name, first_name, last_name, full_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/*}".


  • Cloud APIs

Standard Methods

This chapter defines the concept of standard methods, which are List, Get, Create, Update, and Delete. The reason to have standard methods is that many API methods across wide range of APIs have very similar semantics. By converging these similar APIs into standard methods, we can significantly reduce complexity and increase consistency. For API methods in the Google APIs repository, over 70% of them are standard methods, which makes them much easier to learn and use.

The following table describes how to map them to REST methods, also known as CRUD methods:

MethodHTTP MappingHTTP Request BodyHTTP Response BodyListGET <collection URL>EmptyResource* listGetGET <resource URL>EmptyResource*CreatePOST <collection URL>ResourceResource*UpdatePUT or PATCH <resource URL>ResourceResource*DeleteDELETE <resource URL>EmptyEmpty**

*The resource returned from List, Get, Create, and Update methods may contain partial data if the methods support field masks, which specify a subset of fields to be returned. In some cases, the API platform natively supports field masks for all methods.

**The response returned from a Delete method that doesn't immediately remove the resource (such as updating a flag or creating a long-running delete operation) should contain either the long-running operation or the modified resource.

A standard method may also return a long running operation for requests that do not complete within the time-span of the single API call.

The following sections describe each of the standard methods in details. The examples show the methods defined in .proto files with special annotations for the HTTP mappings. You can find many examples of using standard methods in products in the Google APIs repository.

List

The List method takes a collection name and zero or more parameters as input, and returns a list of resources that match the input. It is commonly used to Search for resources as well.

List is suited to data from a single collection that is bounded in size and not cached. For broader cases, the custom method Search should be used.

A batch get (such as a method that takes multiple resource ids and returns an object for each of those ids) should be implemented as a custom BatchGet method, rather than a List. However, if you have an already-existing List method that provides the same functionality, you may reuse the List method for this purpose instead. If you are using a custom BatchGet method, it should be mapped to HTTP GET.

Applicable common patterns: pagination, result ordering.

Applicable naming conventions: filter field, results field

HTTP mapping:

  • The List method must use an HTTP GET verb.
  • The request message field(s) receiving the name of the collection whose resources are being listed shouldmap to the URL path. If the collection name maps to the URL path, the last segment of the URL template (the collection ID) must be literal.
  • All remaining request message fields shall map to the URL query parameters.
  • There is no request body; the API configuration must not declare a body clause.
  • The response body should contain a list of resources along with optional metadata.
// Lists all the books on a given shelf.
rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {
 
// List method maps to HTTP GET.
 
option (google.api.http) = {
   
// The `parent` captures the parent resource name, such as "shelves/shelf1".
    get
: "/v1/{parent=shelves/*}/books"
 
};
}

message ListBooksRequest {
 
// The parent resource name, for example, "shelves/shelf1".
 
string parent = 1;

 
// The maximum number of items to return.
 
int32 page_size = 2;

 
// The next_page_token value returned from a previous List request, if any.
 
string page_token = 3;
}

message ListBooksResponse {
 
// The field name should match the noun "books" in the method name.  There
 
// will be a maximum number of items returned based on the page_size field
 
// in the request.
 
repeated Book books = 1;

 
// Token to retrieve the next page of results, or empty if there are no
 
// more results in the list.
 
string next_page_token = 2;
}

Get

The Get method takes a resource name, zero or more parameters, and returns the specified resource.

HTTP mapping:

  • The Get method must use an HTTP GET verb.
  • The request message field(s) receiving the resource name should map to the URL path.
  • All remaining request message fields shall map to the URL query parameters.
  • There is no request body; the API configuration must not declare a body clause.
  • The returned resource shall map to the entire response body.
// Gets the specified book.
rpc GetBook(GetBookRequest) returns (Book) {
 
// Get maps to HTTP GET. Resource name is mapped to the URL. No body.
 
option (google.api.http) = {
   
// Note the URL template variable which captures the multi-segment resource
   
// name of the requested book, such as "shelves/shelf1/books/book2"
    get
: "/v1/{name=shelves/*/books/*}"
 
};
}

message GetBookRequest {
 
// The field will contain name of the resource requested, for example:
 
// "shelves/shelf1/books/book2"
 
string name = 1;
}

Create

The Create method takes a collection name, a resource, and zero or more parameters. It creates a new resource in the specified collection, and returns the newly created resource.

If the API supports creating resources, it should have a Create method for each type of resource that can be created.

HTTP mapping:

  • The Create method must use an HTTP POST verb.
  • The request message should have a field named parent to receive the parent resource name where the resource to be created.
  • All remaining request message fields shall map to the URL query parameters.
  • The request may contain a field named <resource>_id to allow callers to select a client assigned id. This field must map to the URL query parameters.
  • The request message field containing the resource should map to the request body. If the body HTTP configuration clause is used for the Create method, the body: "<resource_field>" form must be used.
  • The returned resource shall map to the entire response body.

If the Create method supports client-assigned resource name and the resource already exists, it should either fail (error google.rpc.Code.ALREADY_EXISTS is recommended) or use a different server-assigned resource name and the documentation should be clear that the created resource name may be different from that passed in.

rpc CreateBook(CreateBookRequest) returns (Book) {
 
// Create maps to HTTP POST. URL path as the collection name.
 
// HTTP request body contains the resource.
 
option (google.api.http) = {
   
// The `parent` captures the parent resource name, such as "shelves/1".
    post
: "/v1/{parent=shelves/*}/books"
    body
: "book"
 
};
}

message CreateBookRequest {
 
// The parent resource name where the book to be created.
 
string parent = 1;

 
// The book id to use for this book.
 
string book_id = 3;

 
// The book resource to create.
 
// The field name should match the Noun in the method name.
 
Book book = 2;
}

rpc CreateShelf(CreateShelfRequest) returns (Shelf) {
 
option (google.api.http) = {
    post
: "/v1/shelves"
    body
: "shelf"
 
};
}

message CreateShelfRequest {
 
Shelf shelf = 1;
}

Update

The Update method takes a request message containing a resource and zero or more parameters. It updates the specified resource and its properties, and returns the updated resource.

Mutable resource properties should be mutable by the Update method, except the properties that contain the resource's name or parent. Any functionality to rename or move a resource must not happen in the Updatemethod and instead shall be handled by a custom method.

HTTP mapping:

  • The standard Update method should support partial resource update, and use HTTP verb PATCH with a FieldMask field named update_mask.
  • An Update method that requires more advanced patching semantics, such as appending to a repeated field, should be made available by a custom method.
  • If the Update method only supports full resource update, it must use HTTP verb PUT. However, it is highly discouraged because it has backwards compatibility issues when adding new resource fields.
  • The message field receiving the resource name must map to the URL path. The field may be in the resource message itself.
  • The request message field containing the resource must map to the request body.
  • All remaining request message fields must map to the URL query parameters.
  • The response message must be the updated resource itself.

If the API accepts client-assigned resource names, the server may allow the client to specify a non-existent resource name and create a new resource. Otherwise, the Update method should fail with non-existent resource name. The error code NOT_FOUND should be used if it is the only error condition.

An API with Update method which also supports resource creation should also provide Create method. Rationale is that it is not clear how to create resources if the Update method is the only way to do it.

rpc UpdateBook(UpdateBookRequest) returns (Book) {
 
// Update maps to HTTP PATCH. Resource name is mapped to a URL path.
 
// Resource is contained in the HTTP request body.
 
option (google.api.http) = {
   
// Note the URL template variable which captures the resource name of the
   
// book to update.
    patch
: "/v1/{book.name=shelves/*/books/*}"
    body
: "book"
 
};
}

message UpdateBookRequest {
 
// The book resource which replaces the resource on the server.
 
Book book = 1;

 
// The update mask applies to the resource. For the `FieldMask` definition,
 
// see https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#fieldmask
 
FieldMask update_mask = 2;
}

Delete

The Delete method takes a resource name and zero or more parameters, and deletes or schedules for deletion the specified resource. The Delete method should return google.protobuf.Empty.

Note that an API should not rely on any information returned by a Delete method, as it cannot be invoked repeatedly.

HTTP mapping:

  • The Delete method must use an HTTP DELETE verb
  • The request message field(s) receiving the resource name should map to the URL path
  • All remaining request message fields shall map to the URL query parameters
  • There is no request body; the API configuration must not declare a body clause
  • If the Delete method immediately removes the resource, it should return an empty response.
  • If the Delete method initiates a long-running operation, it should return the long-running operation.
  • If the Delete method only marks the resource as being deleted, it should return the updated resource.

Calls to the Delete method should be idempotent in effect, but do not need to yield the same response. Any number of Delete requests should result in a resource being (eventually) deleted, but only the first request should result in a success code, subsequent requests should result in a google.rpc.Code.NOT_FOUND.

rpc DeleteBook(DeleteBookRequest) returns (google.protobuf.Empty) {
 
// Delete maps to HTTP DELETE. Resource name maps to the URL path.
 
// There is no request body.
 
option (google.api.http) = {
   
// Note the URL template variable capturing the multi-segment name of the
   
// book resource to be deleted, such as "shelves/shelf1/books/book2"
    delete
: "/v1/{name=shelves/*/books/*}"
 
};
}

message DeleteBookRequest {
 
// The resource name of the book to be deleted, for example:
 
// "shelves/shelf1/books/book2"
 
string name = 1;
}

Custom Methods

This chapter will discuss how to use custom methods for API designs.

Custom methods refer to API methods besides the 5 standard methods. They should only be used for functionality that cannot be easily expressed via standard methods. In general, API designers should choose standard methods over custom methods whenever feasible. Standard Methods have simpler and well-defined semantics that most developers are familiar with, so they are easier to use and less error prone. Another advantage of standard methods is the API platform has better understanding and support for standard methods, such as billing, error handling, logging, monitoring.

A custom method can be associated with a resource, a collection, or a service. It may take an arbitrary request and return an arbitrary response, and also supports streaming request and response.

HTTP mapping

For custom methods, they should use the following generic HTTP mapping:

https://service.name/v1/some/resource/name:customVerb

The reason to use : instead of / to separate the custom verb from the resource name is to support arbitrary paths. For example, undelete a file can map to POST /files/a/long/file/name:undelete

The following guidelines shall be applied when choosing the HTTP mapping:

  • Custom methods should use HTTP POST verb since it has the most flexible semantics.
  • Custom methods may use other HTTP verbs. In such cases, the methods must follow the standard HTTP semantics for that verb.
  • Notably, custom methods using HTTP GET must be idempotent and have no side effects. For example custom methods that implement special views on the resource should use HTTP GET.
  • The request message field(s) receiving the resource name of the resource or collection with which the custom method is associated should map to the URL path.
  • The URL path must end with a suffix consisting of a colon followed by the custom verb.
  • If the HTTP verb used for the custom method allows an HTTP request body (POST, PUT, PATCH, or a custom HTTP verb), the HTTP configuration of such custom method must use the body: "*" clause and all remaining request message fields shall map to the HTTP request body.
  • If the HTTP verb used for the custom method does not accept an HTTP request body (GET, DELETE), the HTTP configuration of such method must not use the body clause at all, and all remaining request message fields shall map to the URL query parameters.

WARNING: If a service implements multiple APIs, the API producer must carefully create the service configuration to avoid custom verb conflicts between APIs.

// This is a service level custom method.
rpc Watch(WatchRequest) returns (WatchResponse) {
 
// Custom method maps to HTTP POST. All request parameters go into body.
 
option (google.api.http) = {
    post
: "/v1:watch"
    body
: "*"
 
};
}

// This is a collection level custom method.
rpc ClearEvents(ClearEventsRequest) returns (ClearEventsResponse) {
 
option (google.api.http) = {
    post
: "/v3/events:clear"
    body
: "*"
 
};
}

// This is a resource level custom method.
rpc CancelEvent(CancelEventRequest) returns (CancelEventResponse) {
 
option (google.api.http) = {
    post
: "/v3/{name=events/*}:cancel"
    body
: "*"
 
};
}

// This is a batch get custom method.
rpc BatchGetEvents(BatchGetEventsRequest) returns (BatchGetEventsResponse) {
 
// The batch get method maps to HTTP GET verb.
 
option (google.api.http) = {
    get
: "/v3/events:batchGet"
 
};
}

Use Cases

Some additional scenarios where custom methods may be the right choice:

  • Reboot a virtual machine The design alternatives could be "create a reboot resource in collection of reboots" which feels disproportionately complex, or "virtual machine has a mutable state which the client can updated from RUNNING to RESTARTING" which would open questions as to which other state transitions are possible. Moreover, reboot is a well-known concept that can translate well to a custom method which intuitively meets developer expectations.
  • Send mail Creating an email message should not necessarily send it (draft). Compared to the design alternative (move a message to an "Outbox" collection) custom method has the advantage of being more discoverable by the API user and models the concept more directly.
  • Promote an employee (corpeng) If implemented as a standard update, the client would have to replicate the corporate policies governing the promotion process to ensure the promotion happens to the correct level, within the same career ladder etc.

Few examples where standard method is a better fit than a custom method:

  • Query resources with different query parameters (use standard list method with standard list filtering).
  • Simple resource property change (use standard update method with field mask).
  • Dismiss a notification (use standard delete method).

Common Custom Methods

The curated list of commonly used or useful custom method names is below. API designers should consider these names before introducing their own to facilitate consistency across APIs.

Method NameCustom verbHTTP verbNoteCancel:cancelPOSTCancel an outstanding operation (build, computation etc.)BatchGet<plural noun>:batchGetGETBatch get of multiple resources. (See details in the description of List)Move:movePOSTMove a resource from one parent to another.Search:searchGETAlternative to List for fetching data that does not adhere to List semantics.Undelete:undeletePOSTRestore a resource that was previously deleted. The recommended retention period is 30-day.

Standard Fields

This section describes a set of standard message field definitions that should be used when similar concepts are needed. This will ensure the same concept has the same name and semantics across different APIs.

NameTypeDescriptionnamestringThe name field should contain the relative resource name.parentstringFor resource definitions and List/Create requests, the parent field should contain the parent relative resource name.create_timeTimestampThe creation timestamp of an entity.update_timeTimestampThe last update timestamp of an entity. Note: update_time is updated when create/patch/delete operation is performed.delete_timeTimestampThe deletion timestamp of an entity, only if it supports retention.time_zonestringThe time zone name. It should be an IANA TZ name, such as "America/Los_Angeles". For more information, see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones.region_codestringThe Unicode country/region code (CLDR) of a location, such as "US" and "419". For more information, see http://www.unicode.org/reports/tr35/#unicode_region_subtag.language_codestringThe BCP-47 language code, such as "en-US" or "sr-Latn". For more information, see http://www.unicode.org/reports/tr35/#Unicode_locale_identifier.display_namestringThe display name of an entity.titlestringThe official name of an entity, such as company name. It should be treated as the formal version of display_name.descriptionstringOne or more paragraphs of text description of an entity.filterstringThe standard filter parameter for List methods.querystringThe same as filter if being applied to a search method (ie :search)page_tokenstringThe pagination token in the List request.page_sizeint32The pagination size in the List request.total_sizeint32The total count of items in the list irrespective of pagination.next_page_tokenstringThe next pagination token in the List response. It should be used as page_token for the following request. An empty value means no more result.resume_tokenstringAn opaque token used for resuming a streaming request.labelsmap<string,string>Represents Cloud resource labels.deletedboolIf a resource allows undelete behavior, it must have a deleted field indicating the resource is deleted.show_deletedboolIf a resource allows undelete behavior, the corresponding List method must have a show_deleted field so client can discover the deleted resources.update_maskFieldMaskIt is used for Update request message for performing partial update on a resource.validate_onlyboolIf true, it indicates that the given request should only be validated, not executed.

Errors

This chapter provides an overview of the Google APIs error model as well as general guidance to developers on how to properly generate and handle errors.

Google APIs use a simple protocol-agnostic error model, which allows us to expose a consistent experience across different APIs, API protocols such as gRPC or HTTP, and error contexts (for instance, asynchronous, batch, or workflow errors).

Error Model

The error model is logically defined by google.rpc.Status, an instance of which is returned to the client when an API error occurs. The following code snippet shows the overall design of the error model:

package google.rpc;

message Status {
 
// A simple error code that can be easily handled by the client. The
 
// actual error code is defined by `google.rpc.Code`.
 
int32 code = 1;

 
// A developer-facing human-readable error message in English. It should
 
// both explain the error and offer an actionable resolution to it.
 
string message = 2;

 
// Additional error information that the client code can use to handle
 
// the error, such as retry delay or a help link.
 
repeated google.protobuf.Any details = 3;
}

Because most Google APIs use resource-oriented API design, the error handling follows the same design principle by using a small set of standard errors with a large number of resources. For example, instead of defining different kinds of "not found" errors, the server uses one standard google.rpc.Code.NOT_FOUND error code and tells the client which specific resource was not found. The smaller state space reduces the complexity of documentation, affords better idiomatic mappings in client libraries, and reduces client logic complexity while not restricting the inclusion of actionable information.

Error Codes

Google APIs must use the canonical error codes defined by google.rpc.Code. Individual APIs should avoid defining additional error codes, since developers are very unlikely to write logic to handle a large number of error codes. For reference, handling an average of 3 error codes per API call would mean most application logic would just be for error handling, which would not be a good developer experience.

Error Messages

The error message should help users understand and resolve the API error easily and quickly. In general, consider the following guidelines when writing error messages:

  • Do not assume the user is an expert user of your API. Users could be client developers, operations people, IT staff, or end-users of apps.
  • Do not assume the user knows anything about your service implementation or is familiar with the context of the errors (such as log analysis).
  • When possible, error messages should be constructed such that a technical user (but not necessarily a developer of your API) can respond to the error and correct it.
  • Keep the error message brief. If needed, provide a link where a confused reader can ask questions, give feedback, or get more information that doesn't cleanly fit in an error message. Otherwise, use the details field to expand.

Error Details

Google APIs define a set of standard error payloads for error details, which you can find ingoogle/rpc/error_details.proto. These cover the most common needs for API errors, such as quota failure and invalid parameters. Like error codes, error details should use these standard payloads whenever possible.

Additional error detail types should only be introduced if they can assist application code to handle the errors. If the error information can only be handled by humans, rely on the error message content and let developers handle it manually rather than introducing new error detail types. Note that if additional error detail types are introduced, they must be explicitly registered.

Here are some example error_details payloads:

  • RetryInfo Describes when clients can retry a failed request, may be returned on Code.UNAVAILABLE or Code.ABORTED
  • QuotaFailure Describes how a quota check failed, may be returned on Code.RESOURCE_EXHAUSTED
  • BadRequest Describes violations in a client request, may be returned on Code.INVALID_ARGUMENT

HTTP Mapping

While proto3 messages have native JSON encoding, Google's API Platform uses the following JSON representation for direct HTTP-JSON error responses to allow for backward compatibility:

{
 
"error": {
   
"code": 401,
   
"message": "Request had invalid credentials.",
   
"status": "UNAUTHENTICATED",
   
"details": [{
     
"@type": "type.googleapis.com/google.rpc.RetryInfo",
     
...
   
}]
 
}
}
FieldDescriptionerrorThe extra layer is for backward compatibility with Google API client library. It also makes the JSON representation more readable to humans.codeThe HTTP status code mapping for Status.codemessageThis corresponds to Status.messagestatusThis corresponds to Status.codedetailsThis corresponds to Status.details

RPC Mapping

Different RPC protocols map the error model differently. For gRPC, the error model is natively supported by the generated code and the runtime library in each supported language. You can find out more in gRPC's API documentation (for example, see gRPC Java's io.grpc.Status).

Client Library Mapping

Google client libraries may choose to surface errors differently per language to be consistent with established idioms. For example, the google-cloud-go library will return an error that implements the same interface asgoogle.rpc.Status, while google-cloud-java will raise an Exception.

Error Localization

The message field in google.rpc.Status is developer-facing and must be in English.

If a user-facing error message is needed, use google.rpc.LocalizedMessage as your details field. While the message field in google.rpc.LocalizedMessage can be localized, ensure that the message field ingoogle.rpc.Status is in English.

By default, the API service should use the authenticated user’s locale or HTTP Accept-Language header to determine the language for the localization.

Handling Errors

Below is a table containing all of the gRPC error codes defined in google.rpc.Code and a short description of their cause. To handle an error, you can check the description for the returned status code and modify your call accordingly.

HTTPRPCDescription200OKNo error.400INVALID_ARGUMENTClient specified an invalid argument. Check error message and error details for more information.400FAILED_PRECONDITIONRequest can not be executed in the current system state, such as deleting a non-empty directory.400OUT_OF_RANGEClient specified an invalid range.401UNAUTHENTICATEDRequest not authenticated due to missing, invalid, or expired OAuth token.403PERMISSION_DENIEDClient does not have sufficient permission. This can happen because the OAuth token does not have the right scopes, the client doesn't have permission, or the API has not been enabled for the client project.404NOT_FOUNDA specified resource is not found, or the request is rejected by undisclosed reasons, such as whitelisting.409ABORTEDConcurrency conflict, such as read-modify-write conflict.409ALREADY_EXISTSThe resource that a client tried to create already exists.429RESOURCE_EXHAUSTEDEither out of resource quota or reaching rate limiting. The client should look for google.rpc.QuotaFailure error detail for more information.499CANCELLEDRequest cancelled by the client.500DATA_LOSSUnrecoverable data loss or data corruption. The client should report the error to the user.500UNKNOWNUnknown server error. Typically a server bug.500INTERNALInternal server error. Typically a server bug.501NOT_IMPLEMENTEDAPI method not implemented by the server.503UNAVAILABLEService unavailable. Typically the server is down.504DEADLINE_EXCEEDEDRequest deadline exceeded. If it happens repeatedly, consider reducing the request complexity.

Error Retries

Clients should retry on 500, 503, and 504 errors with exponential backoff. The minimum delay should be 1s unless it is documented otherwise. For 429 errors, the client may retry with minimum 30s delay. For all other errors, retry may not be applicable - first ensure your request is idempotent, and see the error message for guidance.

Error Propagation

If your API service depends on other services, you should not blindly propagate errors from those services to your clients. When translating errors, we suggest the following:

  • Hide implementation details and confidential information.
  • Adjust the party responsible for the error. For example, a server that receives an INVALID_ARGUMENT error from another service should propagate an INTERNAL to its own caller.

Generating Errors

If you are a server developer, you should generate errors with enough information to help client developers understand and address the problem. At the same time, you must be aware of the security and privacy of the user data, and avoid disclosing sensitive information in the error message and error details, since errors are often logged and may be accessible by others. For example, an error message like "Client IP address is not on whitelist 128.0.0.0/8" exposes information about the server-side policy, which may not be accessible to the user.

To generate proper errors, you first need to be familiar with google.rpc.Code to choose the most suitable error code for each error condition. A server application may check multiple error conditions in parallel, and return the first one.

The following table lists each error code and an example of a good error message.

HTTPRPCExample Error Message400INVALID_ARGUMENTRequest field x.y.z is xxx, expected one of [yyy, zzz].400FAILED_PRECONDITIONResource xxx is a non-empty directory, so it cannot be deleted.400OUT_OF_RANGEParameter 'age' is out of range [0, 125].401UNAUTHENTICATEDInvalid authentication credentials.403PERMISSION_DENIEDPermission 'xxx' denied on file 'yyy'.404NOT_FOUNDResource 'xxx' not found.409ABORTEDCouldn’t acquire lock on resource ‘xxx’.409ALREADY_EXISTSResource 'xxx' already exists.429RESOURCE_EXHAUSTEDQuota limit 'xxx' exceeded.499CANCELLEDRequest cancelled by the client.500DATA_LOSSSee note.500UNKNOWNSee note.500INTERNALSee note.501NOT_IMPLEMENTEDMethod 'xxx' not implemented.503UNAVAILABLESee note.504DEADLINE_EXCEEDEDSee note.

NOTE: Since the client cannot fix the server error, it is not useful to generate additional error details. To avoid leaking sensitive information under error conditions, it is recommended not to generate any error message and only generate google.rpc.DebugInfo error details. The DebugInfo is specially designed only for server-side logging, and must not be sent to client.

The google.rpc package defines a set of standard error payloads, which are preferred to custom error payloads. The following table lists each error code and its matching standard error payload, if applicable.


HTTPRPCRecommended Error Detail400INVALID_ARGUMENTgoogle.rpc.BadRequest400FAILED_PRECONDITIONgoogle.rpc.PreconditionFailure400OUT_OF_RANGEgoogle.rpc.BadRequest401UNAUTHENTICATED 403PERMISSION_DENIED 404NOT_FOUND 409ABORTED 409ALREADY_EXISTS 429RESOURCE_EXHAUSTEDgoogle.rpc.QuotaFailure499CANCELLED 500DATA_LOSS 500UNKNOWN 500INTERNAL 501NOT_IMPLEMENTED 503UNAVAILABLE 504DEADLINE_EXCEEDED

Naming Conventions

In order to provide consistent developer experience across many APIs and over a long period of time, all names used by an API should be:

  • simple
  • intuitive
  • consistent

This includes names of interfaces, resources, collections, methods, and messages.

Since many developers are not native English speakers, one goal of these naming conventions is to ensure that the majority of developers can easily understand an API. It does this by encouraging the use of a simple, consistent, and small vocabulary when naming methods and resources.

  • Names used in APIs should be in correct American English. For example, license (instead of licence), color (instead of colour).
  • Commonly accepted short forms or abbreviations of long words may be used for brevity. For example, API is preferred over Application Programming Interface.
  • Use intuitive, familiar terminology where possible. For example, when describing removing (and destroying) a resource, delete is preferred over erase.
  • Use the same name or term for the same concept, including for concepts shared across APIs.
  • Avoid name overloading. Use different names for different concepts.
  • Avoid overly general names that are ambiguous within the context of the API and the larger ecosystem of Google APIs. They can lead to misunderstanding of API concepts. Rather, choose specific names that accurately describe the API concept. This is particularly important for names that define first-order API elements, such as resources. There is no definitive list of names to avoid, as every name must be evaluated in the context of other names. Instance, info, and service are examples of names that have been problematic in the past. Names chosen should describe the API concept clearly (for example: instance of what?) and distinguish it from other relevant concepts (for example: does "alert" mean the rule, the signal, or the notification?).
  • Carefully consider use of names that may conflict with keywords in common programming languages. Such names may be used but will likely trigger additional scrutiny during API review. Use them judiciously and sparingly.

Product names

Product names refer to the product marketing names of APIs, such as Google Calendar API. Product names should be consistently used by APIs, UIs, documentation, Terms of Service, billing statements, commercial contracts, etc.

Google APIs must use product names starting with Google unless they are offered under different brands, such as Gmail, Nest, YouTube. In general, Product names should be decided by product and marketing teams.

The table below shows examples of all related API names and their consistency. See further below on this page for more details on the respective names and their conventions.

API NameExampleProduct NameGoogle Calendar APIService Namecalendar.googleapis.comPackage Namegoogle.calendar.v3Interface Namegoogle.calendar.v3.CalendarServiceSource Directory//google/calendar/v3API Namecalendar

Service names

Service names should be syntactically valid DNS names (as per RFC 1035) which can be resolved to one or more network addresses. The service names of public Google APIs follow the pattern: xxx.googleapis.com. For example, the service name of the Google Calendar is calendar.googleapis.com.

If an API is composed of several services they should be named in a way to help discoverability. One way to do this is for the Service Names to share a common prefix. For example the services build.googleapis.com andbuildresults.googleapis.com are both services that are part of the Google Build API.

Package names

Package names declared in the API .proto files should be consistent with Product and Service Names. Package names for APIs that have a version must end with the version. For example:

// Google Calendar API
package google.calendar.v3;

An abstract API that isn't directly associated with a service, such as Google Watcher API, should use proto package names consistent with the Product name:

// Google Watcher API
package google.watcher.v1;

Java package names specified in the API .proto files must match the proto package names with standard Java package name prefix (com., edu., net., etc). For example:

package google.calendar.v3;

// Specifies Java package name, using the standard prefix "com."
option java_package = "com.google.calendar.v3";

Collection IDs

Collection IDs should use plural form and lowerCamelCase, and American English spelling and semantics. For example: events, children, or deletedEvents.

Interface names

To avoid confusion with Service Names such as pubsub.googleapis.com, the term interface name refers to the name used when defining a service in a .proto file:

// Library is the interface name.
service Library {
 
rpc ListBooks(...) returns (...);
 
rpc ...
}

You can think of the service name as a reference to the actual implementation of a set of APIs, while the interface name refers to the abstract definition of an API.

An interface name should use an intuitive noun such as Calendar or Blob. The name should not conflict with any well-established concepts in programming languages and their runtime libraries (for example, File).

In the rare case where an interface name would conflict with another name within the API, a suffix (for example Api or Service) should be used to disambiguate.

Method names

A service may, in its IDL specification, define one or more RPC methods that correspond to methods on collections and resources. The method names should follow the naming convention of VerbNoun in upper camel case, where the noun is typically the resource type.

VerbNounMethod nameRequest messageResponse messageListBookListBooksListBooksRequestListBooksResponseGetBookGetBookGetBookRequestBookCreateBookCreateBookCreateBookRequestBookUpdateBookUpdateBookUpdateBookRequestBookRenameBookRenameBookRenameBookRequestRenameBookResponseDeleteBookDeleteBookDeleteBookRequestgoogle.protobuf.Empty

Message names

The request and response messages for RPC methods should be named after the method names with the suffix Request and Response, respectively, unless the method request or response type is:

  • an empty message (use google.protobuf.Empty),
  • a resource type, or
  • a resource representing an operation

This typically applies to requests or responses used in standard methods Get, Create, Update, or Delete.

Enum names

Enum types must use UpperCamelCase names.

Enum values must use CAPITALIZED_NAMES_WITH_UNDERSCORES. Each enum value must end with a semicolon, not a comma. The first value should be named ENUM_TYPE_UNSPECIFIED as it is returned when an enum value is not explicitly specified.

enum FooBar {
 
// The first value represents the default and must be == 0.
  FOO_BAR_UNSPECIFIED
= 0;
  FIRST_VALUE
= 1;
  SECOND_VALUE
= 2;
}

Field names

Field definitions in the .proto files must use lower_case_underscore_separated_names. These names will be mapped to the native naming convention in generated code for each programming language.

Repeated field names

Repeated fields in APIs must use proper plural forms. This matches the convention of existing Google APIs, and the common expectation of external developers.

Time and Duration

To represent a point in time independent of any time zone or calendar, google.protobuf.Timestamp should be used, and the field name should end with time, such as start_time and end_time.

If the time refers to an activity, the field name should have the form of verb_time, such as create_time, update_time. Avoid using use past tense for the verb, such as created_time or last_updated_time.

To represent a span of time between two points in time independent of any calendar and concepts like "day" or "month", google.protobuf.Duration. should be used.

message FlightRecord {
  google
.protobuf.Timestamp takeoff_time = 1;
  google
.protobuf.Duration flight_duration = 2;
}

If you have to represent time-related fields using an integer type for legacy or compatibility reasons, including wall-clock time, duration, delay and latency, the field names must have the following form:

xxx_{time|duration|delay|latency}_{seconds|millis|micros|nanos}
message Email {
 
int64 send_time_millis = 1;
 
int64 receive_time_millis = 2;
}

If you have to represent timestamp using string type for legacy or compatibility reasons, the field names should not include any unit suffix. The string representation should use RFC 3339 format, e.g. "2014-07-30T10:43:17Z".

Date and Time of Day

For dates that are independent of time zone and time of day, google.type.Date should be used and it should have the suffix _date. If a date must be represented as a string, it should be in the ISO 8601 date format YYYY-MM-DD, e.g. 2014-07-30.

For times of day that are independent of time zone and date, google.type.TimeOfDay should be used and should have the suffix _time. If a time of day must be represented as a string, it should be in the ISO 8601 24-hour time format HH:MM:SS[.FFF], e.g. 14:55:01.672.

message StoreOpening {
  google
.type.Date opening_date = 1;
  google
.type.TimeOfDay opening_time = 2;
}

Quantities

Quantities represented by an integer type must include the unit of measurement.

xxx_{bytes|width_pixels|meters}

If the quantity is a number of items, then the field should have the suffix _count, for example node_count.

List filter field

If an API supports filtering of resources returned by the List method, the field containing the filter expression should be named filter. For example:

message ListBooksRequest {
 
// The parent resource name.
 
string parent = 1;

 
// The filter expression.
 
string filter = 2;
}

List response

The name of the field in the List method's response message, which contains the list of resources must be a plural form of the resource name itself. For example, a method CalendarApi.ListEvents() must define a response message ListEventsResponse with a repeated field called events for the list of returned resources.

service CalendarApi {
 
rpc ListEvents(ListEventsRequest) returns (ListEventsResponse) {
   
option (google.api.http) = {
      get
: "/v3/{parent=calendars/*}/events";
   
};
 
}
}

message ListEventsRequest {
 
string parent = 1;
 
int32 page_size = 2;
 
string page_token = 3;
}

message ListEventsResponse {
 
repeated Event events = 1;
 
string next_page_token = 2;
}

Camel case

Except for field names and enum values, all definitions inside .proto files must use UpperCamelCase names, as defined by Google Java Style.

Name abbreviation

For well known name abbreviations among software developers, such as config and spec, the abbreviations should be used in API definitions instead of the full spelling. This will make the source code easy to read and write. In formal documentations, the full spelling should be used. Examples:

  • config (configuration)
  • id (identifier)
  • spec (specification)
  • stats (statistics)

Common Design Patterns

Empty Responses

The standard Delete method must return google.protobuf.Empty for global consistency. It also prevents clients from depending on additional metadata that would not be available during retry. For custom methods, they must have their own XxxResponse messages even they are empty, because it is very likely their functionality will grow over time and need to return additional data.

Representing Ranges

Fields that represent ranges should use half-open intervals with naming convention [start_xxx, end_xxx), such as [start_key, end_key) or [start_time, end_time). Half-open interval semantics is commonly used by C++ STL library and Java standard library. APIs should avoid using other ways of representing ranges, such as (index, count), or [first, last].

Resource Labels

In a resource-oriented API, the resource schema is defined by the API. To let the client attach small amount of simple metadata to the resources (for example, tagging a virtual machine resource as a database server), APIs should use the resource labels design pattern described in google.api.LabelDescriptor.

To do so, the API design should add a field map<string, string> labels to the resource definition.

message Book {
 
string name = 1;
  map
<string, string> labels = 2;
}

Long Running Operations

If an API method typically takes a long time to complete, it can be designed to return a Long Running Operation resource to the client, which the client can use to track the progress and receive the result. The Operation defines a standard interface to work with long running operations. Individual APIs must not define their own interfaces for long running operations to avoid inconsistency.

The operation resource must be returned directly as the response message and any immediate consequence of the operation should be reflected in the API. For example, when creating a resource, that resource should appear in LIST and GET methods though the resource should indicate that it is not ready for use. When the operation is complete, the Operation.response field should contain the message that would have been returned directly, if the method was not long running.

List Pagination

Listable collections should support pagination, even if results are typically small.

Rationale: Even though adding pagination support to an existing API is purely additive from API surface perspective, it is a behavior-breaking change. Existing clients unaware of pagination will incorrectly assume that they received complete list result where they only receive the first page instead.

To support pagination (returning list results in pages) in a List method, the API shall:

  • define a string field page_token in the List method's request message. The client uses this field to request a specific page of the list results.
  • define an int32 field page_size in the List method's request message. Clients use this field to specify the maximum number of results to be returned by the server. The server may further constrain the maximum number of results returned in a single page. If the page_size is 0, the server will decide the number of results to be returned.
  • define a string field next_page_token in the List method's response message. This field represents the pagination token to retrieve the next page of results. If the value is "", it means no further results for the request.

To retrieve the next page of results, client shall pass the value of response's next_page_token in the subsequent List method call (in the request message's page_token field):

rpc ListBooks(ListBooksRequest) returns (ListBooksResponse);

message ListBooksRequest {
 
string name = 1;
 
int32 page_size = 2;
 
string page_token = 3;
}

message ListBooksResponse {
 
repeated Book books = 1;
 
string next_page_token = 2;
}

When clients pass in query parameters in addition to a page token, the service must fail the request if the query parameters are not consistent with the page token.

Page token contents should be a web-safe base64 encoded protocol buffer. This allows the contents to evolve without compatibility issues. If the page token contains potentially sensitive information, that information should be encrypted. Services must prevent tampering with page tokens from exposing unintended data through one of the following methods:

  • require query parameters to be respecifed on follow up requests.
  • only reference server-side session state in the page token.
  • encrypt and sign the query parameters in the page token and revalidate and reauthorize these parameters on every call.

An implementation of pagination may also provide the total count of items in an int32 field named total_size.

List Sub-Collections

Sometimes, an API needs to let a client List/Search across sub- collections. For example, the Library API has a collection of shelves, and each shelf has a collection of books, and a client wants to search for a book across all shelves. In such cases, it is recommended to use standard List on the sub-collection and specify the wildcard collection id "-" for the parent collection(s). For the Library API example, we can use the following REST API request:

GET https://library.googleapis.com/v1/shelves/-/books?filter=xxx

NOTE: the reason to choose "-" instead of "*" is to avoid the need for URL escaping.

Get Unique Resource From Sub-Collection

Sometimes, a resource within a sub-collection has an identifier that is unique within its parent collection(s). In this case, it may be useful to allow a Get to retrieve that resource without knowing which parent collection contains it. In such cases, it is recommended to use a standard Get on the resource and specify the wildcard collection id"-" for all parent collections within which the resource is unique. For example, in the Library API, we can use the following REST API request, if the book is unique among all books on all shelves:

GET https://library.googleapis.com/v1/shelves/-/books/{id}

The resource name in the response to this call must use the canonical name of the resource, with actual parent collection identifiers instead of "-" for each parent collection. For example, the request above should return a resource with a name like shelves/shelf713/books/book8141, not shelves/-/books/book8141.

Sorting Order

If an API method lets client specify sorting order for list results, the request message should contain a field:

string order_by = ...;

The string value should follow SQL syntax: comma separated list of fields. For example: "foo,bar". The default sorting order is ascending. To specify descending order for a field, a suffix " desc" should be appended to the field name. For example: "foo desc,bar".

Redundant space characters in the syntax are insignificant. "foo,bar desc" and "  foo ,  bar  desc  "are equivalent.

Request Validation

If an API method has side effects and there is a need to validate the request without causing such side effects, the request message should contain a field:

bool validate_only = ...;

If this field is set to true, the server must not execute any side effects and only perform implementation-specific validation consistent with the full request.

If validation succeeds, google.rpc.Code.OK must be returned and any full request using the same request message should not return google.rpc.Code.INVALID_ARGUMENT. Note that the request may still fail due to other errors such as google.rpc.Code.ALREADY_EXISTS or because of race conditions.

Request Duplication

For network APIs, idempotent API methods are highly preferred, because they can be safely retried after network failures. However, some API methods cannot easily be idempotent, such as creating a resource, and there is a need to avoid unnecessary duplication. For such use cases, the request message should contain a unique ID, like a UUID, which the server will use to detect duplication and make sure the request is only processed once.

// A unique request ID for server to detect duplicated requests.
// This field **should** be named as `request_id`.
string request_id = ...;

If a duplicate request is detected, the server should return the response for the previously successful request, because the client most likely did not receive the previous response.

Enum Default Value

Every enum definition must start with a 0 valued entry, which shall be used when an enum value is not explicitly specified. APIs must document how 0 values are handled.

If there is a common default behavior, then the enum value 0 should be used, and the API should document the expected behavior.

If there is no common default behavior, then the enum value 0 should be named as ENUM_TYPE_UNSPECIFIEDand should be rejected with error INVALID_ARGUMENT when used.

enum Isolation {
 
// Not specified.
  ISOLATION_UNSPECIFIED
= 0;
 
// Reads from a snapshot. Collisions occur if all reads and writes cannot be
 
// logically serialized with concurrent transactions.
  SERIALIZABLE
= 1;
 
// Reads from a snapshot. Collisions occur if concurrent transactions write
 
// to the same rows.
  SNAPSHOT
= 2;
 
...
}

// When unspecified, the server will use an isolation level of SNAPSHOT or
// better.
Isolation level = 1;

An idiomatic name may be used for the 0 value. For example, google.rpc.Code.OK is the idiomatic way of specifying the absence of an error code. In this case, OK is semantically equivalent to UNSPECIFIED in the context of the enum type.

In cases where an intrinsically sensible and safe default exists, that value may be used for the '0' value. For example, BASIC is the '0' value in the Resource View enum.

Grammar Syntax

In some API designs, it is necessary to define simple grammars for certain data formats, such as acceptable text input. To provide a consistent developer experience across APIs and reduce learning curve, API designers must use the ISO 14977 Extended Backus-Naur Form (EBNF) syntax to define such grammars:

Production  = name "=" [ Expression ] ";" ;
Expression  = Alternative { "|" Alternative } ;
Alternative = Term { Term } ;
Term        = name | TOKEN | Group | Option | Repetition ;
Group       = "(" Expression ")" ;
Option      = "[" Expression "]" ;
Repetition  = "{" Expression "}" ;

NOTE: TOKEN represents terminals defined outside the grammar.

Integer Types

In API designs, unsigned integer types such as uint32 and fixed32 should not be used because some important programming languages and systems don't support them well, such as Java, JavaScript and OpenAPI. And they are more likely to cause overflow errors. Another issue is that different APIs are very likely to use mismatched signed and unsigned types for the same thing.

When signed integer types are used for things where the negative values are not meaningful, such as size or timeout, the value -1 (and only -1) may be used to indicate special meaning, such as end of file (EOF), infinite timeout, unlimited quota limit, or unknown age. Such usages must be clearly documented to avoid confusion. API producers should also document the behavior of the implicit default value 0 if it is not very obvious.

Partial Response

Sometimes an API client only needs a specific subset of data in the response message. To support such use cases, some API platforms provide native support for partial responses. Google API Platform supports it through response field mask. For any REST API call, there is an implicit system query parameter $fields, which is the JSON representation of a google.protobuf.FieldMask value. The response message will be filtered by the $fields before being sent back to the client. This logic is handled automatically for all API methods by the API Platform.

GET https://library.googleapis.com/v1/shelves?$fields=name

Resource View

To reduce network traffic, it is sometimes useful to allow the client to limit which parts of the resource the server should return in its responses, returning a view of the resource instead of the full resource representation. The resource view support in an API is implemented by adding a parameter to the method request which allows the client to specify which view of the resource it wants to receive in the response.

The parameter:

  • should be of an enum type
  • must be named view

Each value of the enumeration defines which parts of the resource (which fields) will be returned in the server's response. Exactly what is returned for each view value is implementation-defined and should be specified in the API documentation.

package google.example.library.v1;

service Library {
 
rpc ListBooks(ListBooksRequest) returns (ListBooksResponse) {
   
option (google.api.http) = {
      get
: "/v1/{name=shelves/*}/books"
   
}
 
};
}

enum BookView {
 
// Server responses only include author, title, ISBN and unique book ID.
 
// The default value.
  BASIC
= 0;

 
// Full representation of the book is returned in server responses,
 
// including contents of the book.
  FULL
= 1;
}

message ListBooksRequest {
 
string name = 1;

 
// Specifies which parts of the book resource should be returned
 
// in the response.
 
BookView view = 2;
}

This construct will be mapped to URLs such as:

GET https://library.googleapis.com/v1/shelves/shelf1/books?view=BASIC

You can find out more about defining methods, requests, and responses in the Standard Methods chapter of this Design Guide.

ETags

An ETag is an opaque identifier allowing a client to make conditional requests. To support ETags, an API should include a string field etag in the resource definition, and its semantics must match the common usage of ETag. Normally, etag contains the fingerprint of the resource computed by the server. See Wikipedia and RFC 7232 for more details.

ETags can be either strongly or weakly validated, where weakly validated ETags are prefixed with W/. In this context, strong validation means that two resources bearing the same ETag have both byte-for-byte identical content and identical extra fields (ie, Content-Type). This means that strongly validated ETags permit for caching of partial responses to be assembled later.

Conversely, resources bearing the same weakly validated ETag value means that the representations are semantically equivalent, but not necessarily byte-for-byte identical, and therefore not suitable for response caching of byte-range requests.

For example:

// This is a strong ETag, including the quotes.
"1a2f3e4d5b6c7c"
// This is a weak ETag, including the prefix and quotes.
W
/"1a2b3c4d5ef"

Output Fields

APIs may want to distinguish between fields that are provided by the client as inputs and fields that are only returned by the server on output on a particular resource. For fields that are output only, the field attribute shall be documented.

Note that if output only fields are set in the request by the client or the client specifies a google.protobuf.FieldMask with output only fields, the server must accept the request without error. This means that the server must ignore the presence of output only fields and any indication of it. The reason for this recommendation is because clients will commonly reuse resources returned by the server as another request input, e.g. a retrieved Book will be later reused in an UPDATE method. If output only fields are validated against, then this places extra work on the client to clear out output only fields.

message Book {
 
string name = 1;
 
// Output only.
 
Timestamp create_time = 2;
}

Documentation

This section provides guidelines for adding inline documentation to your API. Most APIs will also have overviews, tutorials, and higher-level reference documentation, which are outside the scope of this Design Guide. For information on API, resource, and method naming, see Naming Conventions.

Comment format

Add comments to your .proto file using the usual Protocol Buffers // comment format.

// Creates a shelf in the library, and returns the new Shelf.
rpc CreateShelf(CreateShelfRequest) returns (Shelf) {
 
option (google.api.http) = { post: "/v1/shelves" body: "shelf" };
}

Comments in service configuration

As an alternative to adding documentation comments to your .proto file, you can add inline documentation to your API in its YAML service configuration file. Documentation in this file will take precedence over documentation in your .proto if the same element is documented in both files.

documentation:
  summary: Gets and lists social activities
 
overview: A simple example service that lets you get and list possible social activities
 
rules:
  - selector: google.social.Social.GetActivity
   
description: Gets a social activity. If the activity does not exist, returns Code.NOT_FOUND.
...

You may need to use this approach if you have multiple services that use the same .proto files and want to provide service-specific documentation. YAML documentation rules also let you add a more detailed overviewto your API description. However, in general adding documentation comments to your .proto is preferred.

As with .proto comments, you can use Markdown to provide additional formatting in your YAML file comments.

API description

The API description is a phrase starting with an active verb that describes what you can do with the API. In your .proto file, an API description is added as a comment to the corresponding service, as in the following example:

// Manages books and shelves in a simple digital library.
service LibraryService {
...
}

Here are some more example API descriptions:

  • Shares updates, photos, videos, and more with your friends around the world.
  • Accesses a cloud-hosted machine learning service that makes it easy to build smart apps that respond to streams of data.

Resource description

A resource description is a partial sentence that describes what the resource represents. If you need to add more detail, use additional sentences. In your .proto file, a resource description is added as a comment to the corresponding message type, as in the following example:

// A book resource in the Library API.
message Book {
 
...
}

Here are some example resource descriptions:

  • A task on the user's to-do list. Each task has a unique priority.
  • An event on the user's calendar.

Field and parameter descriptions

A noun phrase that describes a field or parameter definition, as shown in the following examples:

  • The number of topics in this series.
  • The accuracy of the latitude and longitude coordinates, in meters. Must be non-negative.
  • Flag governing whether attachment URL values are returned for submission resources in this series. The default value for series.insert is true.
  • The container for voting information. Present only when voting information is recorded.
  • Not currently used or deprecated.

Field and parameter descriptions

  • Must describe the boundaries clearly (that is, be clear about what is valid and what is not valid. Remember that engineers will do their best to break any service, and won't be able to read the underlying code to clarify any unclear information.)
  • Must specify any default value or default behavior; in other words, what the server will do if no value is provided.
  • If it's a string, such as a name or path, describe the syntax and list permissible characters, and any required encoding. For example:
    • 1-255 characters in the set [A-a0-9]
    • A valid URL path string starting with / that follows the RFC 2332 conventions. Max length is 500 characters.
  • Should provide an example value whenever feasible.
  • If the field value is required, input only, output only, it must be documented at the start of the field description. By default, all fields and parameters are optional. For example:
message Table {
 
// Required. The resource name of the table.
 
string name = 1;
 
// Input only. Whether to dry run the table creation.
 
bool dryrun = 2;
 
// Output only. The timestamp when the table was created. Assigned by
 
// the server.
 
Timestamp create_time = 3;
 
// The display name of the table.
 
string display_name = 4;
}

Method description

A method description is a sentence indicating what effect the method has and what resource it operates on. It usually starts with a third-person, present tense verb (ie a "verb ending in s"). If you need to add more detail, use additional sentences. Here are some examples:

  • Lists calendar events for the authenticated user.
  • Updates a calendar event with the data included in the request.
  • Deletes a location record from the authenticated user's location history.
  • Creates or updates a location record in the authenticated user's location history using the data included in the request. If a location resource already exists with the same timestamp value, the data provided overwrites the existing data.

Checklist for all descriptions

Make sure each description is brief but complete and can be understood by users who don't have additional information about the API. In most cases, there's more to say than just restating the obvious; for example, the description of the series.insert method shouldn't just say "Inserts a series." — while your naming should be informative, most readers are reading your descriptions because they want more information than the names themselves provide. If you're not sure what else to say in a description, try answering all of the following questions that are relevant:

  • What is it?
  • What does it do if it succeeds? What does it do if it fails? What can cause it to fail, and how?
  • Is it idempotent?
  • What are the units? (Examples: meters, degrees, pixels.)
  • What range of values does it accept? Is the range inclusive or exclusive?
  • What are the side effects?
  • How do you use it?
  • What are common errors that may break it?
  • Is it always present? (For example: "Container for voting information. Present only when voting information is recorded.")
  • Does it have a default setting?

Conventions

This section lists some usage conventions for textual descriptions and documentation. For example, use "ID" (all caps), rather than "Id" or "id" when talking about identifiers. Use "JSON" rather than "Json" or "json" when referring to that data format. Show all field/parameter names in code font. Put literal string values in code font and quotes.

  • ID
  • JSON
  • RPC
  • REST
  • property_name or "string_literal"
  • true / false

Language style

As in our naming conventions, we recommend using a simple, consistent vocabulary and style when writing doc comments. Comments should be understandable by readers who don't speak English natively, so avoid jargon, slang, complex metaphors, pop culture references, or anything else that won't easily translate. Use a friendly, professional style that speaks directly to the developers reading your comments, and keep things as concise as possible. Remember, most readers want to find out how to do something with your API, not read your documentation!

Protocol Buffers v3

This chapter will discuss how to use Protocol Buffers with API design. To simplify developer experience and improve runtime efficiency, gRPC APIs should use Protocol Buffers version 3 (proto3) for API definition.

Protocol Buffers is a simple language-neutral and platform-neutral Interface Definition Language (IDL) for defining data structure schemas and programming interfaces. It supports both binary and text wire formats, and works with many different wire protocols on different platforms.

Proto3 is the latest version of Protocol Buffers and includes the following changes from proto2:

  • Field presence, also known as hasField, is not available for primitive fields. An unset primitive field has a language-defined default value.
    • Presence of a message field is still available, which can be tested using the compiler generated hasField method, or compare to null, or the sentinel value defined by the implementation.
  • User-defined default value for fields is no longer available.
  • Enum definitions must start with enum value zero.
  • Required fields are no longer available.
  • Extensions are no longer available. Use google.protobuf.Any instead.
    • Special exception is granted for google/protobuf/descriptor.proto for backward and runtime compatibility reasons.
  • Group syntax is removed.

The reason for removing these features is to make API designs simpler, more stable, and more performant. For example, it is often necessary to filter some fields before logging a message, such as removing sensitive information. This would not be possible if the fields are required.

Versioning

This chapter provides the versioning guidelines for networked APIs. Since one API service may provide multiple API interfaces, the API versioning strategy applies at API interface level, not at the API service level. For convenience, the term APIs refers to API interfaces in the following sections.

Networked APIs should use Semantic Versioning. Given a version number MAJOR.MINOR.PATCH, increment the:

  1. MAJOR version when you make incompatible API changes,
  2. MINOR version when you add functionality in a backwards-compatible manner,
  3. PATCH version when you make backwards-compatible bug fixes.

Different rules apply for specifying the major version number depending on the API version:

  • For version 1 (v1) of an API, its major version number should be encoded in the proto package name, for example google.pubsub.v1. The major version may be omitted from the proto package if the package contains stable types and interfaces that don't expect to have breaking changes, for examplegoogle.protobuf and google.longrunning.
  • For all versions of the API other than v1, the major version number must be encoded in the proto package name. For example, google.pubsub.v2.

For pre-GA releases, such as alpha and beta, it is recommended to append a suffix to the version number. The suffix should consist of the pre-release version name (e.g. alpha, beta), and an optional pre-release version number.

Examples of version progression:

VersionProto PackageDescriptionv1alphav1alpha1The v1 alpha release.v1beta1v1beta1The v1 beta 1 release.v1beta2v1beta2The second beta release of v1.v1testv1testAn internal test release with dummy data.v1v1The v1 major version, general availability.v1.1beta1v1p1beta1The first beta release for minor changes to v1.v1.1v1The minor update to v1.1 release.v2beta1v2beta1The v2 beta 1 release.v2v2The v2 major version, general availability.

The minor and patch numbers should be reflected in the API configuration and documentation, they must not be encoded in the proto package name.

NOTE: Google API Platform does not natively support minor and patch version at this time. For each major API version, there is only one set of documentation and client libraries. API owners need to manually document them via API documentation and release notes.

A new major version of an API must not depend on a previous major version of the same API. An API may depend on other APIs with the understanding of dependency and stability risk associated with those APIs. A stable API version must only depend on the latest stable version of other APIs.

For some period of time, different versions of the same API must be able to work at the same time within a single client application. This is to help the client smoothly transition from the older version to the newer version of the API.

An older API version should only be removed after its deprecation period is over.

Common and stable data types that are shared by many APIs, such as date and time, should be defined in a separate proto package. If a breaking change ever becomes necessary, either a new type name, or a package name with a new major version must be introduced.

Backwards compatibility

Determining want counts as a backwards-compatible change can be difficult.

The lists below are a quick-reference starting point, but if you're in any doubt, see the dedicated Compatibility section for more details.

Backwards-compatible (non-breaking) changes

  • Adding an API interface to an API service
  • Adding a method to an API interface
  • Adding an HTTP binding to a method
  • Adding a field to a request message
  • Adding a field to a response message
  • Adding a value to an enum
  • Adding an output-only resource field

Backwards-incompatible (breaking) changes

  • Removing or renaming a service, interface, field, method or enum value
  • Changing an HTTP binding
  • Changing the type of a field
  • Changing a resource name format
  • Changing visible behavior of existing requests
  • Changing the URL format in the HTTP definition
  • Adding a read/write field to a resource message

Compatibility

This page provides more detailed explanations for the list of breaking and non-breaking changes given in the Versioning section.

It's not always absolutely clear what counts as a breaking (incompatible) change. The guidance here should be treated as indicative rather than a comprehensive list of every possible change.

The rules listed here are only concerned with client compatibiity. It is expected that API producers are aware of their own requirements with respect to deployment, including changes in implementation details.

The general aim is that clients should not be broken by a service updating to a new minor version or patch. The kinds of breakages under consideration are:

  • Source compatibility: code written against 1.0 failing to compile against 1.1
  • Binary compatibility: code compiled against 1.0 failing to link/run against a 1.1 client library. (Exact details depend on the client platform; there are variants of this in different situations.)
  • Wire compatibility: an application built against 1.0 failing to communicate with a 1.1 server
  • Semantic compatibility: everything runs but yields unintended or surprising results

To put it another way: old clients should be able to work against newer servers within the same major version number, and when they want to update to a new minor version (for example to take advantage of a new feature) they should be able to do so easily.

As well as theoretical, protocol-based considerations, there are practical considerations due to the existence of client libraries involving both generated code and hand-written code. Wherever possible, test changes you're considering by generating new versions of client libraries and making sure their tests still pass.

The discussion below divides proto messages into three categories:

  • Request messages (such as GetBookRequest)
  • Response messages (such as ListBooksResponse)
  • Resource messages (such as Book, and including any messages which are used within other resource messages)

These categories have different rules, as request messages are only ever sent from the client to the server, response messages are only ever sent from the server to the client, but typically resource messages are sent both ways. In particular, resources that can be updated need to be considered in terms of a read/modify/write cycle.

Backwards-compatible (non-breaking) changes

Adding an API interface to an API service definition

From a protocol perspective, this is always safe. The only caveat is that client libraries may have already used your new API interface name within hand-written code. If your new interface is entirely orthogonal to existing ones, this is unlikely; if it's a simplified version of an existing interface, that's more likely to cause a conflict.

Adding a method to an API interface

Unless you add a method which conflicts with a method which is already being generated in client libraries, this should be fine.

(Example where it could be breaking: if you have a GetFoo method, the C# code generator will already create GetFoo and GetFooAsync methods. Adding a GetFooAsync method in your API interface would therefore be a breaking change from a client library perspective.)

Adding an HTTP binding to a method

Assuming the binding doesn't introduce any ambiguities, making the server respond to a URL it previously would have rejected is safe. This may be done when making an existing operation apply to a new resource name pattern.

Adding a field to a request message

Adding request fields can be non-breaking, so long as clients that don't specify the field will be treated the same in the new version as in the old version.

The most obvious example of where this can be done incorrectly is with pagination: if v1.0 of the API does not include pagination for a collection, it cannot be added in v1.1 unless the default page_size is treated as infinite (which is generally a bad idea). Otherwise, v1.0 clients who expect to get complete results from a single request could receive truncated results, with no awareness that the collection contains more resources.

Adding a field to a response message

A response message that is not a resource (e.g. a ListBooksResponse) can be expanded without breaking clients, so long as this does not change the behavior of other response fields. Any field that was previously populated in a response should continue to be populated with the same semantics, even if this introduces redundancy.

For example, a query response in 1.0 might have a boolean field of contained_duplicates to indicate that some results were omitted due to duplication. In 1.1, we might provide more detailed information in aduplicate_count field. Even though it's redundant from a 1.1 perspective, the contained_duplicates field must still be populated.

Adding a value to an enum

An enum that is only used in a request message can freely be expanded to include new elements. For example, using the Resource View pattern, a new view can be added in a new minor version. Clients never need to receive this enum, so they don't have to be aware of values that they don't care about.

For resource messages and response messages, the default assumption is that clients should handle enum values they're not aware of. However, API producers should be aware that writing applications to correctly handle new enum elements may be difficult. API owners should document expected client behavior when encountering an unknown enum value.

Proto3 allows clients to receive a value they are unaware of and reserialize the message maintaining the same value, so this does not break the read/modify/write cycle. The JSON format allows a numeric value to be sent where the "name" for the value is unknown, but the server will typically not know whether or not the client actually knows about a particular value. JSON clients may therefore be aware that they have received a value that was previously-unknown to them, but they will only see either the name or the number - they won't know both. Returning the same value back to the server in a read/modify/write cycle should not modify that field, as the server should understand both forms.

Adding an output-only resource field

Fields in a resource entity that are only supplied by the server may be added. The server may validate that any client-supplied value in a request is valid, but it must not fail if the value is omitted.

Backwards-incompatible (breaking) changes

Removing or renaming a service, field, method or enum value

Fundamentally, if client code could refer to something, then removing or renaming it is a breaking change and must result in a major version increase. Code referring to the old name will cause failures at compile-time for some languages (such as C# and Java) and may cause execution-time failures or data loss in other languages. Wire format compatibility is irrelevant here.

Changing an HTTP binding

"Change" here is effectively "delete and add". For example, if you decide that you really want to support PATCH but your published version supports PUT, or you've used the wrong custom verb name, you may add the new binding, but you must not remove the old binding for all the same reasons as removing a service method is a breaking change.

Changing the type of a field

Even when the new type is wire-format compatible, this could change the generated code for client libraries and therefore must result in a major version increase. For compiled, statically-typed languages this can easily introduce compile-time errors.

Changing a resource name format

A resource must not change its name - which means collection names cannot be changed.

Unlike most breaking changes, this affects major versions as well: if a client can expect to use v2.0 access a resource that was created in v1.0 or vice versa, the same resource name should be used in both versions.

More subtly, the set of valid resource names should not change either, for the following reasons:

  • If it becomes more restrictive, a request that would previously have succeeded will now fail.
  • If it becomes less restrictive than previously documented, then clients making assumptions based on the previous documentation may be broken. Clients are very likely to store resource names elsewhere, in ways that may be sensitive to the set of permitted characters and the length of the name. Alternatively, clients may well be performing their own resource name validation to follow the documentation. (For example,Amazon gave customers a lot of warning and had a migration period when they started allowing longer EC2 resource IDs.)

Note that such a change may only be visible in the documentation of a proto. Therefore, when reviewing a CL for breakage, it is not sufficient to review non-comment changes.

Changing visible behavior of existing requests

Clients will often depend on API behavior and semantics, even when such behavior is not explicitly supported or documented. Therefore, in most cases changing the behavior or semantics of API data will be seen as breaking by consumers. If the behavior is not cryptographically hidden, you should assume that users have discovered it and will depend on it. For example, users have reverse engineered AWS EC2 resource identifiers.

It is also a good idea to encrypt pagination tokens for this reason (even when the data is uninteresting), to prevent users from creating their own tokens and potentially being broken when the token behavior changes.

Changing the URL format in the HTTP definition

There are two kinds of change to consider here, beyond the resource name changes listed above:

  • Custom method names: Although not part of the resource name, a custom method name is part of the URL being posted to by REST clients. Changing a custom method name shouldn't break gRPC clients, but public APIs must assume they have REST clients.
  • Resource parameter names: A change from v1/shelves/{shelf}/books/{book} tov1/shelves/{shelf_id}/books/{book_id} does not affect the substituted resource name, but may affect code generation.

Adding a read/write field to a resource message

Clients will often perform read/modify/write operations. Most clients will not supply values for fields they are not aware of, and proto3 in particular does not support this. You could specify that any missing fields of message types (rather than primitive types) mean an update is not applied to those fields, but this makes it harder to explicitly remove such a field value from an entity. Primitive types (including string and bytes) simply cannot be handled this way, as there is no difference in proto3 between explicitly specifying an int32 field as 0 and not specifying it at all.

If all updates are performed using a field mask, this isn't a problem as the client won't implicitly overwrite fields it isn't aware of. However, that would be an unusual API decision: most APIs allow "whole resource" updates.

Directory Structure

API services typically use .proto files to define the API surface and .yaml files to configure the API service.

Each API service must have an API directory inside an API repository that contains its definition files and build scripts.

The API directory should have the following standard layout:

  • API directory

  • Configuration files

    • {service}.yaml - Main service config file, which is the YAML representation of the google.api.Serviceproto message.
    • prod.yaml - Prod delta service config file.
    • staging.yaml - Staging delta service config file.
    • test.yaml - Test delta service config file.
    • local.yaml - Local delta service config file.
    *   Interface definitions

       
    -   `v[0-9]*/*` - Each such directory contains a major version of the
            API
    , mainly the proto files and build scripts.
       
    -   `{subapi}/v[0-9]*/*` - Each `{subapi}` directory contains interface
            definition of a
    sub-API. Each sub-API may have its own
            independent major version
    .
       
    -   `type/*` - proto files containing types that are shared between
            different
    APIs, different versions of the same API, or between
            the API
    and service implementation. Type definitions under `type/*`
           
    **should** not have breaking changes once they are released.
  • File Structure

    gRPC APIs should be defined in .proto file(s) using the proto3 IDL.

    The file structure must put higher level and more important definitions before lower level and less important items. In each proto file, the applicable sections should be in the following order:

    • Copyright and license notice if needed.
    • Proto syntax, package, option and import statements in that order.
    • The API overview documentation which prepares the readers for the rest of the file.
    • The API proto service definitions, in decreasing order of importance.
    • The resource message definitions. A parent resource must be defined before its child resource(s).
    • The RPC request and response message definitions, in the same order of the corresponding methods. Each request message must precede its corresponding response message, if any.

    If a single proto file contains the entire API surface, it should be named after the API:

    APIProtoLibrarylibrary.protoCalendarcalendar.proto

    Large .proto files may be split into multiple files. The services, resource messages, and request/response messages should be moved into separate files as needed.

    We recommend one file per service with its corresponding request and responses. Consider naming this file <enclosed service name>.proto. For proto files with only resources, consider naming this file simply asresources.proto.

    Proto File Names

    Proto file names should use lower_case_underscore_separated_names and must use the extension .proto. For example: service_controller.proto.

    Proto Options

    In order to generate consistent client libraries across different APIs, API developers must use consistent proto options in their .proto files. API definitions that conform to this guide must use the following file-level proto options:

    syntax = "proto3";

    // The package name should start with the company name and end with
    // the major version.
    package google.abc.xyz.v1;

    // This option specifies the namespace to be used in C# code. This defaults
    // to the PascalCased version of the proto package, which is fine if the
    // package name consists of single-word segments.
    // For example, a package name of "google.shopping.pets.v1" would use a C#
    // namespace of "Google.Shopping.Pets.V1".
    // However, if any segment of a package name consists of multiple words,
    // this option needs to be specified to avoid only the first word being
    // capitalized. For example, a Google Pet Store API might have a package name of
    // "google.shopping.petstore.v1", which would mean a C# namespace of
    // "Google.Shopping.Petstore.V1". Instead, the option should be used to
    // capitalize it properly as "Google.Shopping.PetStore.V1".
    // For more detail on C#/.NET capitalization rules, see the [Framework Design
    // Guidelines](https://msdn.microsoft.com/en-us/library/ms229043).
    option csharp_namespace = "Google.Abc.Xyz.V1";

    // This option lets the proto compiler generate Java code inside the package
    // name (see below) instead of inside an outer class. It creates a simpler
    // developer experience by reducing one-level of name nesting and be
    // consistent with most programming languages that don't support outer classes.
    option java_multiple_files = true;

    // The Java outer classname should be the filename in UpperCamelCase. This
    // class is only used to hold proto descriptor, so developers don't need to
    // work with it directly.
    option java_outer_classname = "XyzProto";

    // The Java package name must be proto package name with proper prefix.
    option java_package = "com.google.abc.xyz.v1";

    // A reasonable prefix for the Objective-C symbols generated from the package.
    // It should at a minimum be 3 characters long, all uppercase, and convention
    // is to use an abbreviation of the package name. Something short, but
    // hopefully unique enough to not conflict with things that may come along in
    // the future. 'GPB' is reserved for the protocol buffer implementation itself.
    option objc_class_prefix = "GABCX";

    HTTP Verbs

    Networked APIs can be accessed via multiple transport protocols, including HTTP. For that reason, every API method must comply with the requirements of HTTP protocol based on the specific HTTP Verb to which the API method maps. For details, please refer to the Hypertext Transfer Protocol specification and the PATCH Method RFC.

    Safe Methods, such as HTTP GET (and HEAD) should not represent action other than retrieval. Specifically, HTTP GET ought to be considered safe and should not have any client-visible side-effects.

    Idempotence in HTTP means that the side-effects of multiple identical requests are the same as for a single request. GET, PUT, and DELETE are the idempotent HTTP methods relevant to the style guide. Note that idempotence is only expressed in terms of server side-effects and does not specify anything about the response. In particular DELETE for non-existing resources should return 404 (Not Found).

    HTTP POST and PATCH are neither safe nor idempotent. (PATCH was introduced in RFC 5789)


    HTTP VerbSafeIdempotentGETYesYesPUT YesDELETE YesPOST  PATCH 

    Glossary

    Networked APIs

    • Application Programming Interfaces that operate across a network of computers. They communicate using network protocols including HTTP, and are frequently produced by different organizations than the ones that consume them.

    Google APIs

    • Networked APIs exposed by Google services. Most of them are hosted on googleapis.com domain. It does not include other types of APIs, such as client libraries and SDKs.

    API Interface

    • A Protocol Buffers service definition. It is typically mapped to an interface in most programming languages. An API interface can be implemented by any number of API Services.

    API Version

    • The version of an API interface or a group of API interfaces if they are defined together. An API version is often represented by a string, such as "v1", and presents in API requests and Protocol Buffers package names.

    API Method

    • An individual operation within an API Interface. It is represented in Protocol Buffers by an rpc definition, and is typically mapped to a function in the API Interface in most programming languages.

    API Request

    • A single invocation of an API Method. It is often used as the unit for billing, logging, monitoring, and rate limiting.

    API Service

    • A deployed implementation of one or more API interface(s), exposed on one or more network endpoints. An API service is identified by its service name that is compatible with RFC 1035 DNS, such ascalendar.googleapis.com.

    API Endpoint

    • Refers to a network address that an API service uses to service the actual API requests, such as pubsub.googleapis.com and content-pubsub.googleapis.com.

    API Product

    • An API Service plus related components, such as Terms of Service, documentation, client libraries, and service support, are collectively presented to customers as a product. For example, Google Calendar API. NOTE: people sometimes refer to an API Product simply as an API.

    API Service Definition

    • The combination of API Interface definitions (.proto files) and API Service configurations (.yaml files) used to define an API Service.

    API Consumer

    • The entity who consumes an API Service. For Google APIs, it typically is a Google project that owns the client application or the server resource.

    API Producer

    • The entity produces an API Service. For Google APIs, it typically is a Google project that owns the API service.

    API Backend

    • A set of servers plus related infrastructure that implements the business logics for an API Service.

    API Frontend

    • A set of servers plus related infrastructure that implements provide common functionality across API Services, such as load balance and authentication. NOTE: the API frontend and the API backend may run next to each other or far away from each other. In some cases, they can be compiled into a single application binary and run inside a single process.


    0 0
    原创粉丝点击