- The core principle is to define named resources that can be manipulated using a small number of methods.
- resources and methods are nouns and verbs of the API
- resource names map to URLs and methods map to HTTP methods.
-
-
Save farhadkzm/fefffe35c7e4fd224cd8aeac759b61a7 to your computer and use it in GitHub Desktop.
Custom methods
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.
A custom method can be associated with a resource, a collection, or a service. 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.
Notes:
- Custom methods should use HTTP POST verb since it has the most flexible semantics.
- Notably, custom methods using HTTP GET must be idempotent and have no side effects.
Custom method has the advantage of being more discoverable by the API user and models the concept more directly.
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.
https://cloud.google.com/apis/design/standard_fields
Errors*
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.
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 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 in google.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.
Common Design Patterns
Long Running Operations
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. This is because 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.
List Sub-Collections
Sometimes, an API needs to let a client List/Search across sub- collections.
For the Library API example, we can use the following REST API request:
GET https://library.googleapis.com/v1/shelves/-/books?filter=xxx
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.
GET https://library.googleapis.com/v1/shelves/-/books/{id}
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"
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.
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.
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.
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.
Partial Response
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.
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
GET https://library.googleapis.com/v1/shelves/shelf1/books?view=BASIC
ETag
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.
ETags can be either strongly or weakly validated, where weakly validated ETags are prefixed with W/
.
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;
}```
Versioning
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.
Compatibility
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.
URI and URL
Further according to the contemporary view, the term "URL" does not refer to a formal partition of URI space; rather, URL is a useful but informal concept: a URL is a type of URI that identifies a resource via a representation of its primary access mechanism (e.g., its network "location"), rather than by some other attributes it may have. Thus as we noted, "http:" is a URI scheme. An http URI is a URL.
idempotent methods
Aside from error or expiration issues, the side-effects of N > 0 identical requests is the same as for a single request. The methods GET, HEAD, PUT and DELETE share this property. Also, the methods OPTIONS and TRACE SHOULD NOT have side effects, and so are inherently idempotent.
Note that idempotent calls can have different response.
https://tools.ietf.org/html/rfc2616#section-9.1.2