GitBook: [master] 102 pages and one asset modified

This commit is contained in:
apidesigner
2018-07-23 07:49:01 +00:00
committed by gitbook-bot
parent af88d15fd0
commit 3b81882249
68 changed files with 850 additions and 712 deletions

View File

@@ -0,0 +1,4 @@
# API Clients
This section contains the recommended practices for API consumersclients.

View File

@@ -0,0 +1,6 @@
# Loose Coupling
In addition to the [robustness principle](https://github.com/adidas-group/api-guidelines/tree/af88d15fd04ef18d6724fa65943901aab7328e7f/rest/clients/core-principles/robustness.md), API consumers \(clients\) **MUST** **operate independently** on API implementation's internals. Similarly the API consumers **MUST NOT** **assume** or **rely on** any knowledge of the API service internal implementation.
Where available, the clients **SHOULD** utilize **hypermedia controls as the engine of the application state**, and rely on the **protocol, message and vocabulary semantics**.

View File

@@ -0,0 +1,4 @@
# Core Principles
This section outlines the foundation upon which the API Guidelines are built.

View File

@@ -0,0 +1,12 @@
# API Design Platform
1. [Apiary](https://apiary.io/) is the primary platform supporting [API first approach](https://github.com/adidas-group/api-guidelines/tree/af88d15fd04ef18d6724fa65943901aab7328e7f/rest/core-principles/api-first.md). Apiary **MUST** be used during API Design.
2. Every API description **MUST** be stored in [Apiary](https://apiary.io/) under the ADIDAS GROUP team.
3. Apiary **MUST** be the **single source of truth** to learn about existing APIs within the organization.
> NOTE: Apiary supports API-first approach in multiple ways:
> a. Validates API description for correctness and automatically generates API documentation to drive the discussion between stakeholders. \(No more emails with API description flying between stakeholders\)
>
> NOTE: The synchronization between the version control system and adidas [API Description platform](apiary.md)
> should be automated using CI/CD framework.

View File

@@ -0,0 +1,18 @@
# Design Maturity
## API Design Maturity
> How to design an API
Every API design **MUST** be **resource-centric** \([Web API Design Maturity Model Level 2](http://amundsen.com/talks/2016-11-apistrat-wadm/2016-11-apistrat-wadm.pdf)\). That is an API design **MUST** revolve around Web-styled _resources_, _relations_ between the resources and the _actions_ the resources may afford.
An API design **MAY** be **affordance-centric** \([Web API Design Maturity Model Level 3](http://amundsen.com/talks/2016-11-apistrat-wadm/2016-11-apistrat-wadm.pdf)\).
## API Design Implementation Maturity
> How to implement the API design
Every API design implementation using the HTTP protocol **MUST** use the appropriate **HTTP Request Method** \([Richardson Maturity Model Level 2](https://martinfowler.com/articles/richardsonMaturityModel.html#level2)\) to implement an action afforded by a resource.
An API design implementation **SHOULD** include **hypermedia controls** \(HATEOAS\) \([Richardson Maturity Model Level 3](https://martinfowler.com/articles/richardsonMaturityModel.html#level3)\).

View File

@@ -0,0 +1,10 @@
# OpenAPI Specification
Every API **MUST** be described using an API description format. The API description format used MUST be the [OpenAPI Specification \(formerly known as Swagger Specification\) version 2.0](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md).
Every API description **MUST** be published in adidas [API design platform](apiary.md) and it **SHOULD** be stored in version control system \(Bitbucket, GitHub\) in the same repository as the API implementation.
## Language
The API description MUST be written in **American English**.

View File

@@ -0,0 +1,6 @@
# Testing
Every API description \(contract\) using HTTP\(S\) protocol **MUST** be tested against its API implementation. The tests **MUST** be executed using the [Dredd testing framework](https://github.com/apiaryio/dredd). The Dredd **MUST** [report the test results to Apiary](https://help.apiary.io/tools/automated-testing/testing-reporter/).
In addition to local runs, the tests **SHOULD** be an integral part the API implementation's CI/CD pipeline. The CI/CD pipeline **SHOULD** be configured to run the test whenever there is a change to either API description \(contract\) or its implementation.

View File

@@ -0,0 +1,2 @@
# Functionality

View File

@@ -0,0 +1,6 @@
# Application
Every API SHOULD use company terms for resource names, relation names and representation message field names.
Also, every API MUST follow the [naming conventions](./).

View File

@@ -0,0 +1,45 @@
# Common Data Types
## Date and Time Format
Date and Time **MUST** always conform to the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) format e.g.: `2017-06-21T14:07:17Z` \(date time\) or `2017-06-21` \(date\), it **MUST** use the UTC \(without time offsets\).
## Duration Format
Duration format **MUST** conform to the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard e.g.: `P3Y6M4DT12H30M5S` \(three years, six months, four days, twelve hours, thirty minutes, and five seconds\).
## Time Interval Format
Time Interval format **MUST** conform to the [ISO 8601](https://en.wikipedia.org/wiki/ISO_8601) standard e.g.: `2007-03-01T13:00:00Z/2008-05-11T15:30:00Z`.
## Standard Time Stamps
Where applicable, a resource representation **SHOULD** contain the standard timestamps:
* `createdAt`
* `updatedAt`
* `finishedAt`
### Example
```javascript
{
"createdAt": "2017-01-01T12:00:00Z",
"updatedAt": "2017-01-01T13:00:00Z",
...
}
```
## Language Code Format
Language codes **MUST** conform to the [ISO 639](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes) e.g.: `en` for English.
## Country Code Format
Country codes **MUST** conform to the [ISO 3166-1 alpha-2](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) e.g.: `DE` for Germany.
## Currency Format
Currency codes **MUST** conform to the [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) e.g.: `EUR` for Euro.

View File

@@ -0,0 +1,10 @@
# Corporate Data Model
The design of application data model **MUST** consider the application use cases, as well as the upstream and downstream systems, use cases.
The design of the data model of an application **MUST** consider the [adidas Corporate Data Model](https://collaboration.adidas-group.com/sites/CS-GDM/Corporate%20Data%20Dictionary/Data%20Dictionary.htm) \(internal link\).
Different names for entities and attributes **MAY** be used **ONLY** if the **CDM** is not including them. If a different name is introduced then it **MUST** be included in the **CDM**.
The consistency of the names of entities and attributes across the whole application **MUST** be maintained.

View File

@@ -0,0 +1,4 @@
# Message
This section covers the message format governance.

View File

@@ -0,0 +1,30 @@
# Content Negotiation
Every API **MUST** implement and every API Consumer **MUST** use the [HTTP content negotiation](https://tools.ietf.org/html/rfc7231#section-3.4) where a representation of a resource is requested.
> NOTE: The content negotiation plays the key role in evolving an API, **change management and versioning**.
## Example
A client is programmed to understand the `application/vnd.example.resource+json; version=2` message format semantics. The client requests a representation of the `/greeting` resource in desired the media type \(including its version\) from the server:
```text
GET /greeting HTTP/1.1
Accept: application/vnd.example.resource+json; version=2
...
```
The server can provide only a newer version of the requested media type `version=2.1.3`. But since the newer version is backward compatible with the requested `version=2` \(related: Changes & Versioning\) it can satisfy the request and responds:
```text
HTTP/1.1 200 OK
Content-Type: application/vnd.example.resource+json; version=2.1.3
...
```
> NOTE: A server that doesn't have the requested representation media type available MUST respond with the HTTP Status Code **406 Not Acceptable**.
>
> NOTE: A server MAY have multiple choices available and MAY respond with the **300 Multiple Choices** response. In which case client SHOULD choose from the presented choices.
>
> You can read more about content negotiation at [MDN Content negotiation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Content_negotiation).

View File

@@ -0,0 +1,126 @@
# Problem Detail
The [`application/problem+json`](https://tools.ietf.org/html/rfc7807) \(Problem Detail\) **MUST** be used to communicate details about an error.
Problem Detail is intended for use with the HTTP status codes 4xx and 5xx. Problem Detail **MUST NOT** be used with 2xx status code responses.
At the minimum, any Problem Detail response **MUST** have the `title` and `detail` fields.
### Example
```javascript
{
"title": "Authentication required",
"detail": "Missing authentication credentials for the Greeting resource."
}
```
## Optional Fields
It **SHOULD** has the `type` field with the identifier of the error, besides it **MAY** have the `instance` field with the URI of the resource in question. If the Problem Detail response has the `status` field it **MUST** have the same value as HTTP Status code from of the response.
```javascript
{
"type": "https://adidas-group.com/problems/scv/unauthorized",
"title": "Authentication required",
"detail": "Missing authentication credentials for the Greeting resource.",
"instance": "/greeting",
"status": 401
}
```
> NOTE: The `type` field is an identifier, and as such it **MAY** be used to denote additional error codes. Keep in mind that the identifier should be a URI.
## Additional Fields
If needed, the Problem Detail **MAY** include additional fields, refer to [RFC7807](https://tools.ietf.org/html/rfc7807) for details.
## Validation Errors
When necessary, a Problem Detail response **MAY** include additional error details about the problems that have occurred.
These additional errors **MUST** be under the `errors` and **MUST** follow the Problem Detail structure.
### Example
Request:
```text
POST /my-resource HTTP/1.1
Content-Type: application/json
{
"age": -32,
"color": "cyan"
}
```
Response:
```text
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://example.net/validation_error",
"title": "Your request parameters didn't validate.",
"instance": "/my-resource",
"status": 400,
"errors": [
{
"type": "https://example.net/invalid_params",
"instance": "/age",
"title": "Invalid Parameter",
"detail": "age must be a positive integer"
},
{
"type": "https://example.net/invalid_params",
"instance": "/color",
"title": "Invalid Parameter",
"detail": "color must be 'green', 'red' or 'blue'"
}
]
}
```
## Problem Detail and Content Negotiation
### Example
A request is made to retrieve a resource representation:
```text
GET /greeting HTTP/1.1
Accept: application/hal+json
```
However, in order to make this request, the client needs to be authorized. Since the request is made without the authorization credentials the **401 Unauthorized** response is returned together with details using the `application/problem+json` media type:
```text
HTTP/1.1 401 Unauthorized
Content-Type: application/problem+json
Content-Language: en
{
"type": "https://adidas-group.com/problems/scv/unauthorized",
"title": "Authentication required",
"detail": "Missing authentication credentials for the Greeting resource.",
"instance": "/greeting",
"status": 401
}
```
## No Stack Traces or Server Logs
> _Problem details are not a debugging tool for the underlying implementation; rather, they are a way to expose greater detail about the HTTP interface itself._
>
> __ [_RFC7807_](https://tools.ietf.org/html/rfc7807)
A Problem Detail response **MUST NOT** contain a program stack trace or server log for debugging purposes. Instead, provide a `logref` field with reference to the particular server log.
## Working with Problem Detail
There are a whole plethora of libraries working with Problem Detail, for example, see [Zalando / Problem](https://github.com/zalando/problem) \(Java\).

View File

@@ -0,0 +1,72 @@
# Foreign Key Relations
## Link or Embed Foreign Key Relation
When a resource representation includes relation with another \(foreign\) resource, the relation **MUST** be expressed as a link relation or embed the related resource.
### Example
Use:
```javascript
{
"_links": {
"author": { "href": "/users/john" }
...
}
...
}
```
or:
```javascript
{
...
"_embedded": {
"author": {
"_links": { "self": "/users/john" },
"name": "John Appleseed",
"email": "john@apple.com"
}
}
}
```
instead:
```javascript
{
...
"authorHref": "/users/john"
}
```
## Nest Foreign Key Relation
If a foreign object has another identifier, but URI or the foreign object isn't a resource, the object **MUST** be nested.
### Example
Use:
```javascript
{
"author": {
"id": "1234",
"name": "John Appleseed",
"email": "john@apple.com"
}
}
```
instead:
```javascript
{
"authorId": "1234"
}
```
> NOTE: As a rule of thumb, in an HTTP message body, there SHOULD NOT be any field with trailing "\_id," "\_href," "\_url" etc. in its name.

View File

@@ -0,0 +1,119 @@
# HAL
The [`application/hal+json`](http://stateless.co/hal_specification.html) \(HAL\) **MUST** be used as the representation format of a resource.
## Introduction to HAL
> _HAL is a simple format that gives a consistent and easy way to hyperlink between resources in your API._
This document is an informal introduction to the HAL media type. For more details see [HAL - Hypertext Application Language Specification](http://stateless.co/hal_specification.html).
## Simple Document Example
The simplest Hal document looks like an empty JSON \(it is an empty JSON!\):
```javascript
{
}
```
A document representing a "Greeting" resource might look like:
```javascript
{
"message": "Hello World!",
"_links": {
"self": {
"href": "/greeting"
}
}
}
```
The field `_links` has a special meaning in HAL. It denotes a list of link relations - a pair of a relation identifier and a link \(URI\).
These link relations are used to express the relation of a resource with other resources.
In our case the "Greeting" resource isn't related to other resources but itself, hence the `self` relation pointing to the Greeting resource.
> NOTE: It is **customary** for every resource representation to include the `self` link relation.
>
> NOTE: The href **MUST** always be **relative path to the API root** \(e.g. without the host and scheme\).
## Relation Example
A more complex document example could be an "Order" resource that has a related resource "Author" \(a person who created the order. It might look like:
```javascript
{
"_links": {
"self": {
"href": "/orders/1234"
},
"author": {
"href": "/users/john"
}
},
"orderNumber": 1234,
"itemCount": 42,
"status": "pending"
}
```
## Embedding Example
Let's assume there is an "Orders" resource which is a collection of all orders from different authors. There is the relation between the Orders resource and possibly many Order resources.
We could express this in the `_links` object using the `order` relation, but sometimes it is practical to "embed" \(entirely or partially\) related resources representations in the originating resource representation. For a scenario like this HAL offers the `_embedded` field.
The `_embedded` field's object just contains the related resources HAL representations:
```javascript
{
"_links": {
"self": { "href": "/orders" }
},
"_embedded": {
"order": [
{
"_links": {
"self": { "href": "/orders/1" }
},
"orderNumber": "1",
"status": "pending"
},
{
"_links": {
"self": { "href": "/orders/2" }
},
"orderNumber": "2",
"status": "cancelled"
}
]
}
}
```
It is important to understand that embedded resource representation might be only **partial** and might also contain their own embedded resources.
The embedded resource representation should be used as a **convenience** function \(e.g. to reduce the initial number of calls needed at application launch\).
Where a full and up-to-date representation of a resource is needed the link relation should exercise the affordance \(e.g. `GET /orders/2`\).
#### Real-world Examples
Some APIs using HAL:
* [Amazon AppStream REST API](http://docs.aws.amazon.com/appstream/latest/developerguide/appstream-api-rest.html)
* [FoxyCart](https://wiki.foxycart.com/v/2.0/start)
* [Clarify.io](http://docs.clarify.io/overview/)
* [University of Oxford / Mobile Oxford](http://api.m.ox.ac.uk/browser/#/)
## Working with HAL
Refer to the [extensive list of libraries that work with HAL](https://github.com/mikekelly/hal_specification/wiki/Libraries).
### Spring Framework
Spring framework supports HAL out of the box. More info can be found in [Spring Documentation](https://spring.io/guides/gs/rest-hateoas/) and [examples](https://github.com/spring-guides/gs-rest-hateoas).

View File

@@ -0,0 +1,16 @@
# Message Formats
## Response Message Format
All **response** messages **MUST** support an [`application/hal+json`](http://stateless.co/hal_specification.html) \(HAL\) format.
### Error Response Format
The [`application/problem+json`](https://tools.ietf.org/html/rfc7807) \(Problem Detail\) **MUST** be used to communicate details about an error.
## Request Message Format
**Request** messages with body **SHOULD** support a [`application/json`](http://www.json.org) \(JSON\) format. Where applicable, request message **SHOULD** also support the [`application/hal+json`](http://stateless.co/hal_specification.html) format.
**Request** messages **MAY** also support the [`application/x-www-form-urlencoded`](https://tools.ietf.org/html/rfc1866#section-8.2.1) \(URL Encoded\) format.

View File

@@ -0,0 +1,4 @@
# Protocol
This section outlines the protocol-level semantics and guidelines.

View File

@@ -0,0 +1,36 @@
# HTTP
Every API MUST support [HTTP/1.1](https://tools.ietf.org/html/rfc7230) and **MUST** adhere to its **semantic**.
## HTTP Protocol Quick Start
The understanding of HTTP starts with the understanding of [HTTP message](https://developer.mozilla.org/en-US/docs/Web/HTTP/Messages) and its routing.
Once you are familiar with the **HTTP message structure** learn about the **HTTP request methods**, **HTTP response status codes** and **HTTP headers**.
Each HTTP request method, status code, and header have its semantics defined, and every API **MUST** strictly adhere to it.
Follow the [Robustness Principle](https://github.com/adidas-group/api-guidelines/tree/af88d15fd04ef18d6724fa65943901aab7328e7f/rest/protocol/core-principles/robustness.md). Use only the HTTP request methods, response codes and HTTP headers you understand, be liberal in accepting others.
## Know HTTP
The following documents are great overview of the HTTP protocol and related standards:
* [HTTP Headers](https://github.com/for-GET/know-your-http-well/blob/master/headers.md)
* [HTTP Request Methods](https://github.com/for-GET/know-your-http-well/blob/master/methods.md)
* [HTTP Response Status Codes](https://github.com/for-GET/know-your-http-well/blob/master/status-codes.md)
* [HTTP Link Relations](https://github.com/for-GET/know-your-http-well/blob/master/relations.md)
Alternatively, you can download HTTP cheat sheets at [HTTP posters](https://github.com/bigcompany/know-your-http).
## RFCs
The HTTP protocol semantics is defined in the following RFCs:
> 1. [RFC 7230, HTTP/1.1: Message Syntax and Routing](https://tools.ietf.org/html/rfc7230)
> 2. [RFC 7231, HTTP/1.1: Semantics and Content](https://tools.ietf.org/html/rfc7231)
> 3. [RFC 7232, HTTP/1.1: Conditional Requests](https://tools.ietf.org/html/rfc7232)
> 4. [RFC 7233, HTTP/1.1: Range Requests](https://tools.ietf.org/html/rfc7233)
> 5. [RFC 7234, HTTP/1.1: Caching](https://tools.ietf.org/html/rfc7234)
> 6. [RFC 7235, HTTP/1.1: Authentication](https://tools.ietf.org/html/rfc7234)

View File

@@ -0,0 +1,49 @@
# Separate Concerns
Every API using HTTP/S API **MUST** precisely follow the concern separation of an HTTP message:
1. A _resource identifier_URI **MUST** be used to indicate **identity** only
2. _HTTP request method_ **MUST** be used to communicate the **action semantics** \(intent and safety\)
3. _HTTP response status_ code **MUST** be used to communicate the **information about the result** of the attempt to understand and satisfy the request
4. _HTTP message body_ **MUST** be used to transfer the **message content**
5. _HTTP message headers_ **MUST** be used to transfer the **metadata** about the message and its content
6. _URI query parameter_ **SHOULD NOT** be used to transfer metadata
## Example 1
The rule
> A resource identifierURI **MUST** be used to indicate identity only
implies there **MUST NOT** be any information about the representation media type, version of the resource or anything else in the URI.
For example, URIs `/greeting.json` or `/v2.1.3/greeting` are **illegal** as they are not used for identification of a resource only but they convey the information about representation format or version. URIs are not meant to carry any other information but the identifier of the resource.
## Example 2
The rule
> HTTP message body MUST be used to transfer the message content
Implies an HTTP GET request **MUST NOT** use HTTP message body to identify the resource. For example a request:
```text
GET /greeting HTTP/1.1
Content-Type: application/json
...
{
"filter": "string"
"depth": 3
}
```
is **not acceptable** \(ignoring the fact that HTTP GET method shouldn't have the body\). To express identity use URI and query parameters instead e.g. `/greeting?filter=string&depth=3`.
> _Keep things simple while designing by separating the concerns between the different parts of the request and response cycle. Keeping simple rules here allows for greater focus on larger and harder problems._
>
> _Requests and responses will be made to address a particular resource or collection. Use the path to indicate identity, the body to transfer the contents and headers to communicate metadata. Query params may be used as a means to pass header information also in edge cases, but headers are preferred as they are more flexible and can convey more diverse information._
>
> __ [_Heroku HTTP API Design Guide_](https://geemus.gitbooks.io/http-api-design/content/en/foundations/separate-concerns.html)

View File

@@ -0,0 +1,6 @@
# TLS
Every API **MUST** require secure connections with **TLS 1.2**. That is, an API using the HTTP protocol **MUST** use **HTTPS**.
Any non-TLS requests **SHOULD** be ignored. In **HTTP** environments where this is not possible, a non-TLS request **SHOULD** result in the **403 Forbidden** response.

View File

@@ -0,0 +1,44 @@
# Request Methods
Every API **MUST** use appropriate [HTTP request methods](https://github.com/for-GET/know-your-http-well/blob/master/methods.md) for every operation.
Every API designer, implementer and consumer **MUST** understand the semantic of the HTTP METHOD she is using.
At a minimum everyone **MUST** be familiar with the semantics of ["Common" HTTP Request Methods](https://github.com/for-GET/know-your-http-well/blob/master/methods.md#common): **DELETE**, **GET**, **HEAD**, **PUT**, **POST** and the [**PATCH** HTTP Request Method](https://tools.ietf.org/html/rfc5789#section-2). In addition, everyone **MUST** be aware which methods are **Safe**, **Idempotent** and **Cacheable**.
## Safe Methods
As per HTTP specification, the **GET** and **HEAD** methods should be used only for retrieval of resource representations and they do not update/delete the resource on the server. Both methods are said to be considered “safe“. This allows user agents to represent other methods, such as POST, PUT and DELETE, in a special way, so that the user is made aware of the fact that a possibly unsafe action is being requested and they can update/delete the resource on the server and so should be used carefully.
## Idempotent Methods
The term idempotent is used more comprehensively to describe an operation that will produce the same results if executed once or multiple times. This is a beneficial property in many situations, as it means that a transaction can be repeated or retried as often as necessary without causing unintended effects. With non-idempotent operations, the algorithm may have to keep track of whether the operation was already performed or not. In HTTP specification, The methods **GET**, **HEAD**, **PUT** and **DELETE** are declared idempotent methods. Other methods OPTIONS and TRACE **SHOULD NOT** have side effects, so both are also inherently idempotent.
## Cacheable Methods
Request methods are considered "cacheable" if it is possible and useful to answer a current client request with a stored response from a prior request. **GET** and **HEAD** are defined to be cacheable.
### Example 1
> GET /user/new Description: Creates new user
Using GET for unsafe non-idempotent operations is **not acceptable**.
### Example 2
> POST /status Description: Updates the status of a user approval request \(to “Approved” or “Rejected”\)
Using the POST method for a status update is **not acceptable** \(use PATCH\).
### Example 3
> PUT /user Description: Creates a new user
Using the PUT method for creating a new resource is **not acceptable** \(use POST\).
### Example 4
> PUT: /user Description: Updates some user details
Using the PUT method for a partial update is **not acceptable** \(use PATCH\).

View File

@@ -0,0 +1,48 @@
# Status Codes
Every API **MUST** use the appropriate [HTTP Status Codes](https://github.com/for-GET/know-your-http-well/blob/master/status-codes.md) to communicate the result of a request operation.
Every API designer, implementer and consumer **MUST** understand the semantic of the HTTP Status Code she is using.
At a minimum everyone **MUST** be familiar with the semantics of ["Common" HTTP Status Codes](https://github.com/for-GET/know-your-http-well/blob/master/status-codes.md#common).
## Example
## Use Codes 4xx or 5xx to Communicate Errors
A request:
```text
GET /orders/1234 HTTP/1.1
...
```
resulting in the **200 OK** response, when the requested resource \(as identified by request URI\) couldn't be found:
```text
HTTP/1.1 200 OK
Content-Type: application/json
...
{
"code": "NOT_FOUND_ERR_CODE"
"message" "Order 1234 wasn't found"
}
```
is **not acceptable**.
Instead the
```text
HTTP/1.1 404 Not Found
...
```
should be returned.
## Recommended Reading
* [How to Think About HTTP Status Codes](https://www.mnot.net/blog/2017/05/11/status_codes)

View File

@@ -0,0 +1,11 @@
# Guides
API-related guides:
* [API Design Process](https://tools.adidas-group.com/confluence/display/EA/API+Design+Process)
* Migration of Legacy Services \(SOAP\)
* API Testing with Dredd
* Continuous Integration / Deployment / Delivery
* [Apiary](https://help.apiary.io/api_101/understanding-apiary/)
* API Management

View File

@@ -0,0 +1,102 @@
# API Testing CI Environment
This guide describes steps necessary for testing an API described in a swagger file with the [Dredd API Testing Framework](https://github.com/apiaryio/dredd) in a CI Environment \(Jenkins, TeamCity\).
## Environment Prerequisites
The following must be available in the CI environment before testing:
1. **Node.js** runtime MUST be available in the CI environment:
```text
$ node -v
v7.5.0
```
2. **Ruby** runtime MUST be available in the CI environment:
```text
$ ruby -v
ruby 2.4.0p0 (2016-12-24 revision 57164) [x86_64-darwin16]
```
3. [**Dredd**](https://github.com/apiaryio/dredd) MUST be installed globally in the CI environment:
```text
$ npm install -g dredd --no-optional
```
```text
$ dredd --version
dredd v2.2.5 (Darwin 16.4.0; x64)
```
4. [**Apiary CLI Tool**](https://help.apiary.io/tools/apiary-cli) MUST be installed globally in the CI environment:
```text
$ gem install apiaryio
```
```text
$ apiary version
0.8.0
```
5. **Apiary API Key** MUST be set in the CI Environment environment variables:
```text
$ export APIARY_API_KEY=xyz
```
To obtain an Apiary API key, head to [https://login.apiary.io/tokens](https://login.apiary.io/tokens) \(NOTE: You will need the "ALL" Scope\)
## Testing an API
### Test Run Prerequisites
To test an API within the CI environment provisioned as mentioned in the environment prerequisites, you will need the following:
1. The name \(subdomain\) of API project at Apiary
```text
$ export APIARY_API_NAME=bomapi3
```
> See [How to find the Apiary API name](https://help.apiary.io/faq/find-api-name/) for more details.
2. A `swagger.yaml` file with the description of API being tested
To fetch the swagger.yaml file from Apiary run the following command before the test:
```text
$ apiary fetch --api-name=$APIARY_API_NAME --output="swagger.yaml"
```
The swagger document for Apiary project `bomapi3` was saved as local file `./swagger.yaml`.
> See [Fetching Published Documentation](https://help.apiary.io/tools/apiary-cli/#fetching-published-documentation).
3. The host \(address\) of the service being tested
```text
$ export API_HOST=http://deheremap7336.emea.adsint.biz:8004`
```
### Running the Test
With all of the above \(`APIARY_API_KEY`, `APIARY_API_NAME`, `API_HOST`, set up and `swagger.yaml` file present in the current directory\), run:
```text
$ dredd swagger.yaml $API_HOST -r apiary
```
> See [Dredd Command-line Interface](https://dredd.readthedocs.io/en/latest/usage-cli/).
The Dredd will perform the tests and exits usually if the tests have passed. You can check the test result as with any other Unix tools with:
```text
$ echo $?
```
Everything else but `0` should break the build. The test results will be visible in the CLI \(log\) as well as in Apiary.

View File

@@ -0,0 +1,112 @@
# Complete API Development
1. **Design the API**
1. Analyze business requirements
2. Identify affordances
> e.g.: Create user, Submit order, Search for an article
3. Identify resources
> e.g.: User, Order, Article
4. Identify relations
> e.g.: User has many Orders via order relation, all of the required affordances should be mapped to relations.
5. Formalize the design in the [Open API Specification](http://swagger.io/specification/) \(OAS, formerly known as "Swagger"\) format
6. Follow the [adidas API guidelines](https://adidas-group.gitbooks.io/api-guidelines/content/)
7. Put the OAS file into [Apiary adidas group](https://apiary.io)
8. Make sure the OAS file passes all adidas API Apiary style guide checks
9. Verify the design using Apiary Documentation and Apiary Mock Service
10. Review the API Design
11. Put the OAS file in a version control system \(VCS\) repository
12. Set up a CD pipeline to push OAS file from VCS to Apiary, whenever the file is changed
2. **Develop the API**
1. Check out the VCS repository with the OAS file
2. Set up the [Dredd API testing tool](https://github.com/apiaryio/dredd) locally
3. Configure the Dredd for your project
```text
$ dredd init
```
4. Run the Dredd test locally
> Against locally running API implementation, Every test should fail.
5. Implement the API
> Keep running the Dredd locally to see the progress.
6. Set up a [CI/CD pipeline](https://adidas-group.gitbooks.io/api-guidelines/content/guides/api-testing-ci-environment.html) to execute the Dredd tests automatically
> NOTE: Both TeamCity and Jenkins environments are available, contact adidas API evangelist for details.
3. **Deploy the API**
1. Deploy the service
2. Update the OAS file to add the deployment HOST
> ```text
> host: adidas.api.mashery.com
> basePath: /demo-approval-api
> ```
3. Verify the deployment with Dredd
> Use Dredd pointed towards the deployment host, be careful NOT to run it against the production OR using real production credentials.
4. Monitor the API usage "From performance and technical standpoint."
4. **Expose the API using Mashery**
1. **API**
1. Create new API Definition in Mashery
2. Create a new API Endpoint the API Definition
> Set the "Your Endpoint Address" to the internal deployment HOST.
3. Create a new API Package in Mashery
4. Create a new API Plan within the API Package
5. Use Mashery API Designer to add the newly created API Definitions' API Endpoint to the API Plan
6. Revisit the API Plan's API key default settings
7. Revisit the API Plan's API default rate limits
8. Revisit the API Plan's access policy/authorization
9. **API Documentation**
1. Create new adidas API developer's portal page in the Mashery
> Manage > Content > Documentation > APIs
2. [Embed Apiary documentation](https://help.apiary.io/tools/embed/#apiary-embed-api-reference) on the newly created API Page
3. Revisit the API documentation access policy/authorization
5. **Use the API**
> This step can be done at the same time as "Develop the API" thank Apiary hosted Mock, Inspector, and Documentation.
1. Read API documentation at Apiary
2. Use API mock service provided by Apiary
3. Use API call inspector provided by Apiary
4. Obtain your API key
> The key is part of the API Plan created in Mashery and can be requested from your dashboard in the adidas API developer's portal.
5. When available use API implementation via Apiary proxy to debug the API calls
6. Use production deployment
6. **Analyze the API**
1. Examine the use of production API Using Mashery
2. Analyze the technical performance metrics
3. Collect the feedback from users
7. **Update API Design**
> Based on the analysis, new or changing business requirements
1. Create a new branch in the VCS repository with OAS file
2. Create a new project \(alternative\) in Apiary
3. Make sure the CI/CD pipeline is:
1. Set to push the OAS file to Apiary but make sure to modify the Apiary project name
2. Set to run Dredd test in the CI/CD
4. Modify the design \(OAS file\) accordingly, follow the "Design API" step
5. Follow the [**rules for extending**](https://adidas-group.gitbooks.io/api-guidelines/content/core-principles/rules-for-extending.html) and [**adidas API guidelines versioning policies**](https://adidas-group.gitbooks.io/api-guidelines/content/evolution/versioning.html)
6. Use VCS pull request \(PR\) to propose the change to review
7. After the API Design change is verified, reviewed and approved, continue with the "Develop the API" phase
8. Eventually, when the updated design is ready to be deployed for production, merge the branch into the production branch
9. Follow this guide from "Expose the API using Mashery" step

View File

@@ -0,0 +1,5 @@
# Further References
* [Product tokens](https://tools.ietf.org/html/draft-ietf-httpbis-p1-messaging-16#section-6.3)
* [Deprecating "X-"](https://tools.ietf.org/html/rfc6648)

View File

@@ -0,0 +1,4 @@
# Quality

View File

@@ -0,0 +1,4 @@
# Evolution
Evolution qualities, such as testability, maintainability, extensibility, and scalability.

View File

@@ -0,0 +1,132 @@
# Naming Conventions
## General Naming Rules
* Use American English
* Don't use acronyms
* Use `camelCase` unless stated otherwise
* Reconcile terms with adidas CDM
Every identifier **MUST** be in American English and written in `lowercase`. An identifier **SHOULD NOT** contain acronyms. CamelCase \(`camelCase`\) **MUST** be used to delimit combined words.
## URI
Every URI **MUST** follow the General Rules except for the `camelCase` rule. Instead, a hyphen \(`-`\) **SHOULD** be used to delimit combined words \(kebab-case\). Besides, a URI **MUST NOT** end with a trailing slash \(`/`\).
#### Example
A well-formed URI:
```text
/system-orders/1234/author
```
### Query Parameters and Path Fragments
Every URI query parameter or fragment **MUST** follow the General Rules. Also, they **MUST NOT** clash with the [reserved query parameter names](https://tools.adidas-group.com/confluence/display/EA/API+Interaction#APIInteraction-Query_Parameters).
### URI Template Variables
In addition to General Naming Rules, URI Template Variable names **MUST** follow the [RFC6570](https://tools.ietf.org/html/rfc6570#section-2.3). That is, the variable names can consist only from `ALPHA / DIGIT / "_" / pct-encoded`.
> NOTE: Per RFC6570 Hyphen \(`-`\) is NOT legal URI Template variable name character.
#### Example
A well-formed URI Template Variable:
```text
/system-orders/{orderId}/author
```
## Representation Format Fields
Every representation format field **MUST** conform to the General Naming Rules.
#### Example
A well-formed resource representation:
```javascript
{
"_links": {
"self": {
"href": "/orders/1234"
},
"author": {
"href": "/users/john"
}
},
"orderNumber": 1234,
"itemCount": 42,
"status": "pending"
}
```
## Relation Type Identifier
Every custom [relation identifier](https://github.com/for-GET/know-your-http-well/blob/master/relations.md) **MUST** be in `lowercase` with words separated by the hyphen \(`-`\).
#### Example
A well-formed resource representation with custom relation `fulfillment-provider`:
```javascript
{
"_links": {
"fulfillment-provider": {
"href": "/users/natalie"
}
}
}
```
## HTTP Headers
Every HTTP Header should use `Hyphenated-Pascal-Case`. A custom HTTP Header **SHOULD NOT** start with `X-` \([RFC6648](https://tools.ietf.org/html/rfc6648)\).
#### Example
```text
Order-Metadata-Header: 42
```
## API Description
Naming conventions within API Description document.
### API Name
Every API Description API name **MUST** start with API domain enclosed in square brackets \(e.g. `[API Domain] My API`\). Words **MUST** be separated by space.
#### Example
```yaml
swagger: '2.0'
info:
version: '1.0.0'
title: '[Demo] Orders API'
```
### Resource Name
Every resource **MUST** have a name \(defined by `x-summary` field\). Resource name **MUST** be in `Title Case`. Words **MUST** be separated by a space.
#### Example
```yaml
/orders:
x-summary: List of Orders
```
### Action Name
Every action \(operation\) **MUST** have a name \(defined by `summary` field\). Action name **MUST** be in `Title Case`. Words **MUST** be separated by a space.
#### Example
```yaml
get:
summary: Retrieve List of Orders
```

View File

@@ -0,0 +1,16 @@
# Reserved Identifiers
The list of all reserved identifiers or identifiers with special meaning.
## Representation Format Fields
* `_links` - [HAL](https://adidas-group.gitbooks.io/api-guidelines/content/message/hal.html)
* `_embedded` - [HAL](https://adidas-group.gitbooks.io/api-guidelines/content/message/hal.html)
## Query Parameters
* `fields`- [Choosing Fields & Embedded Resources](https://adidas-group.gitbooks.io/api-guidelines/content/execution/choosing-fields-and-embedded-resoruces.html)
* `embedded` - [Choosing Fields & Embedded Resources](https://adidas-group.gitbooks.io/api-guidelines/content/execution/choosing-fields-and-embedded-resoruces.html)
* `offset` - [Pagination](reserved-identifiers.md)
* `limit`- [Pagination](reserved-identifiers.md)

View File

@@ -0,0 +1,4 @@
# Testing Enviroments
Every API implementation **SHOULD** aim to provide a consistent, seamless way to create **test accounts** and access **test fixtures** to facilitate the development of API client applications.

View File

@@ -0,0 +1,10 @@
# URI Structure
URI is meant to express a **identity of a resource**. URI is an identifier and it **MUST NOT** convey any other information.
The API design process **MUST NOT** start with the design of URIs. Contrary, the URI **SHOULD** be amongst the last few things added to the API design.
At adidas, URIs are subject to [naming conventions](https://adidas-group.gitbooks.io/api-guidelines/content/evolution/naming-conventions.html).
To read more about the problematics refer to [RFC 7320: URI Design and Ownership](https://tools.ietf.org/html/rfc7320).

View File

@@ -0,0 +1,100 @@
# Changes and Versioning
> _The fundamental principle is that you cant break existing clients, because you dont know what they implement, and you dont control them. In doing so, you need to turn a backwards-incompatible change into a compatible one._
>
> __ [_Mark Nottingham_](https://www.mnot.net/blog/2011/10/25/web_api_versioning_smackdown)
Any change to an API **MUST NOT** break existing clients.
Any change to:
1. **Resource identifier** \(resource name / URI\) including any **query parameters** and their semantics
1. **Resource metadata** \(e.g. HTTP headers\)
1. **Action** the resource affords \(e.g. available HTTP Methods\)
1. **Relation** with other resources \(e.g Links\)
1. **Representation format** \(e.g. HTTP request and response bodies\)
**MUST** follow the [**Rules for Extending**](https://adidas-group.gitbooks.io/api-guidelines/content/core-principles/rules-for-extending.html).
## Identifier Stability \(No URI Versioning\)
A change **MUST NOT** affect **existing** resource identifiers \(name / URI\). Furthermore, a resource identifier **MUST NOT** contain a semantic version to convey a version of resource or its representation format.
> _The reason to make a real REST API is to get evolvability … a "v1" is a .... to your API customers, indicating RPC/HTTP \(not REST\)_
>
> __ [_Roy T. Fielding_](https://twitter.com/fielding/status/376835835670167552)
#### Example
Adding a new action to existing resource with identifier `/greeting` doesn't change its identifier to `/v2/greeting` \(or `/greeting-with-new-action` etc.\).
## Backward-incompatible Changes
A change to _resource identifier_, _resource metadata_, _resource actions_ and _resource relations_ that can't follow the [Rules for Extending](https://adidas-group.gitbooks.io/api-guidelines/content/core-principles/rules-for-extending.html) **MUST** result into a **new resource variant**. Existing resource variant **MUST** be preserved.
A change to _representation format_ **SHOULD NOT** result into a new resource variant.
#### Example
Currently, optional URI Query Parameter `first` on an existing resource `/greeting?first=John&last=Appleseed` needs to be made required. Since this change violates the 3rd rule of extending and could break existing clients a new variant of the resource is created with different URI `/named-greeting?first=John&last=Appleseed`.
### Representation Format Changes
> A representation format is the serialization format \(media type\) used in request and response bodies, and typically it represents a resource or its part, possibly with additional hypermedia controls.
If a change can't follow the Rules for Extending the representation format media type **MUST** be changed. If the media type has been changed the previous media type, **MUST** be available via [Content Negotiation](https://adidas-group.gitbooks.io/api-guidelines/content/message/content-negotiation.html).
If the media type conveys the version parameter, the version parameter **SHOULD** follow [Semantic versioning](http://semver.org/).
#### Example
Media type _before_ a breaking change:
```text
application/vnd.example.resource+json; version=2
```
Media type _after_ a breaking change:
```text
application/vnd.example.resource+json; version=3
```
> NOTE: In the case of technical limitations with semi-colon separated HTTP header values, the semantic version MAY be incorporated in the media type identifier, for example: `application/vnd.example.resource.v2+json` However, the use of semicolon-separated version information is preferred.
## API Description Versioning
API Description in the OpenAPI specification format **MUST** have the `version` field. The `version` field **MUST** follow [Semantic versioning](http://semver.org/):
> Given a version number MAJOR.MINOR.PATCH, increment the:
>
> * MAJOR version when you make **incompatible** API changes,
> * MINOR version when you add functionality in a **backwards-compatible** manner
> * PATCH version when you make **backwards-compatible bug fixes**
The API Description version **SHOULD** be updated accordingly to API design change.
#### Example
Following API Description
```yaml
swagger: '2.0'
info:
version: '2.1.3'
title: '[Demo] Inventory API'
description: 'Inventory service API'
```
Has MAJOR version 2, MINOR version 1 and PATCH version 3.
#### Demo
API description \(OAS2\) files demonstrating a proposal of an backward-incompatible change turned into a backward compatible change are available at [Bitbucket \(diff\) ](https://bitbucket.org/apidesigner/demo-versioning-api/pull-requests/1/add-name-parameter/diff)and documented in Apiary:
* [Production version](https://demoversioningproduction.docs.apiary.io/#) as being consumed by clients
* [Development version](https://demoversioningdevelopment.docs.apiary.io/#) proposing a backward incompatible change
#### Recommended Reading
* [Evolving HTTP APIs](https://www.mnot.net/blog/2012/12/04/api-evolution)

View File

@@ -0,0 +1,4 @@
# Execution
Performance qualities, such as security and usability, which are observable at run time.

View File

@@ -0,0 +1,28 @@
# Asynchronous Tasks
If an API operation is asynchronous, but a client could track its progress, the response to such an asynchronous operation **MUST** return, in the case of success, the **202 Accepted** status code together with an `application/hal+json` representation of a new **task-tracking resource**.
## Task Tracking Resource
The task-tracking resource **SHOULD** convey the information about the status of an asynchronous task.
Retrieval of such a resource using the HTTP GET Request Method **SHOULD** be designed as follows:
1. Task is Still Processing
Return **200 OK** and representation of the current status.
2. Task Successfully Completed
Return **303 See Other** together with [HTTP Location Header](https://tools.ietf.org/html/rfc7231#section-7.1.2) with URI or a outcome resource.
3. Task Failed
Return **200 OK** and `application/problem+json` with the problem detail information on the task has failed.
## Design Note
The asynchronous operation task-tracking resource can be either **polled** by client or the client might initially provide a **callback** to be executed when the operation finishes.
In the case of callback, the API and its client MUST agree on what HTTP method and request format is used for the callback invitation. If built within adidas, the "client" API is also the subject of the adidas API guidelines.

View File

@@ -0,0 +1,135 @@
# Batch Operations
## Processing Similar Resources
An operation that needs to process several related resources in bulk **SHOULD** use a collection resource with the appropriate HTTP Request Method. When processing existing resource the request message body **MUST** contain the URLs of the respective resources being processed.
### Example
#### Create Multiple Orders at Once
```text
POST /orders
Content-Type: application/json
{
"order": [
{
"itemCount": 42
},
{
"itemCount": 2
}
]
}
```
#### Update Multiple Orders at Once
> NOTE: The self-link relation identifies the existing resource being edited.
```text
PATCH /orders
Content-Type: application/json
{
"order": [
{
"_links": {
"self": { "href": "/order/1"}
},
"itemCount": 42
},
{
"_links": {
"self": { "href": "/order/2"}
},
"itemCount": 2
}
]
}
```
## Results of Bulk Operation
Every bulk operation **MUST** be atomic and treated as any other operation.
> _The server must implement bulk requests as atomic. If the request is for creating ten addresses, the server should create all ten addresses before returning a successful response code. The server should not commit changes partially in the case of failures._
## DO NOT USE "POST Tunneling."
Every API **MUST** avoid tunneling multiple HTTP Request using one POST request. Instead, provide an application-specific resource to process the batch request.
## Non-atomic Bulk Operations
Non-atomic bulk operations are **strongly discouraged** as they bring additional burden and confusion to the client and are difficult to consume, debug, maintain and evolve over the time.
The suggestion is to **split** a non-atomic operation into several atomic operations. The cost of few more calls will be greatly outweighed but the cleaner design, clarity and easier maintainability.
However, in such an operation has to be provided such a non-atomic bulk operation **MUST** conform to the following guidelines.
1. Non-atomic bulk operation **MUST** return a success status code \(e.g. **200 OK**\) only if every and all sub-operation succeeded.
2. If any single one sub-operation fails the whole non-atomic bulk operation **MUST** return the respective **4xx** or **5xx** status code.
3. In the case of a failure the response **MUST** contain the [problem detail](https://adidas-group.gitbooks.io/api-guidelines/content/message/error-reporting.html) information about every sub-operation that has failed.
4. **The client MUST be aware that the operation is non-atomic and the even the operation might have failed some sub-operations were processed successfully.**
### Example
Non-atomic request for creating four orders:
```text
POST /orders
Content-Type: application/json
{
"order": [
{
"itemCount": 42
},
{
"itemCount": -100
},
{
"itemCount": 42
},
{
"itemCount": 1.3232
}
]
}
```
And the error response:
```text
HTTP/1.1 400 Bad Request
Content-Type: application/problem+json
{
"type": "https://example.net/partial_operation_failure",
"title": "Partial Failure",
"detail": "Some orders couldn't be created, other orders were created.",
"errors": [
{
"type": "https://example.net/invalid-params",
"instance": "/orders/1",
"title": "Invalid Parameter",
"detail": "itemCount must be a positive integer",
"status": 400
},
{
"type": "https://example.net/invalid-params",
"instance": "/orders/3",
"title": "Invalid Parameter",
"detail": "itemCount must be a positive integer",
"status": 400
}
],
"processed": ...
}
```
The `processed` field should contain the result of processed sub-operations as if they were returned in a 200 OK.

View File

@@ -0,0 +1,52 @@
# Caching
Every API implementation **SHOULD** return both the cache expiry information \([`Cache-Control` HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control)\) and specific resource version information \([`ETag` HTTP Header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag)\).
## Cache-Control
Every API implementation's response **SHOULD** include information about cache-ability and cache expiration of the response. For HTTP 1.1 this is achieved using the `Cache-Control` header.
### Common Cache-Control Scenarios
Two, most common scenarios for controlling the cache-ability of a response includes \(1\) Setting expiration and revalidation and \(2\) disabling the caching of a response. Refer to the [Cache-Control Documentation](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Cache-Control) for additional controls.
#### 1. Cache Expiration & Revalidation
The common scenario to set cache expiration and revalidation policy is to use the `max-age` and `must-revalidate` directives:
```text
HTTP/1.1 200 OK
Date: Mon, 19 Aug 2017 00:00:00 CEST
Last-Modified: Mon, 19 Aug 2017 00:00:00 CEST
Cache-Control: max-age=3600,must-revalidate
Content-Type: application/hal+json; charset=UTF-8
...
```
#### 2. Disabling Cache
To disable caching completely API implementation **SHOULD** use the `no-cache` and `no-store` directives:
```text
HTTP/1.1 200 OK
Date: Mon, 19 Aug 2017 00:00:00 CEST
Last-Modified: Mon, 19 Aug 2017 00:00:00 CEST
Cache-Control: no-cache, no-store, must-revalidate
Content-Type: application/hal+json; charset=UTF-8
...
```
## ETag
Every API implementation's response to a [cacheable request](https://github.com/for-GET/know-your-http-well/blob/master/methods.md#cacheable) **SHOULD** include the [`ETag` HTTP Header](https://tools.ietf.org/html/rfc7232#section-2.3) to identify the specific version of the returned resource.
Every API client **SHOULD** use [`If-None-Match` HTTP header](https://tools.ietf.org/html/rfc7232#section-3.2) whenever it's performing a cacheable request. The value of `If-None-Match` should be the value of the `ETag` header stored from a previous request. The client **MUST** be ready to handle the **304 Not Modified** response from the server to use the legal copy.
#### How ETag works
ETags are unique identifiers for a particular version of a resource found by a URL. They are used for cache validation, to check for modifications quickly.
A client requests a resource from the server at a particular URI. The server responds with the specific ETag value in the HTTP ETag header field. ETag and the resource will be stored locally by the client. Subsequent requests from the client are done with the If-None-Match header, which now contains the ETag value from the previous request. The server now compares the values. If they are the same, it responds with HTTP Status Code 304 Not Modified. If not, the resource is sent.

View File

@@ -0,0 +1,88 @@
# Choosing Fields and Embedded Resources
## Response Message Fields
Every request that may result in a response with a non-trivial body **SHOULD** implement the `fields` query parameter. If provided, the value of this parameter must be a comma-separated list of top-level response message fields.
Upon receiving such a request, in the event of a 2xx response, the service **SHOULD** respond with a message that includes only top-level fields specified in the `fields` parameter. That includes HAL-specific fields \(`_links` and `_embedded`\).
### Example
Retrieve only some details of an Order resource:
HTTP Request
```text
GET /order/1234?fields=_links,orderNumber,status HTTP/1.1
Accept: application/hal+json
```
HTTP Response
```text
HTTP/1.1 200 OK
Content-Type: application/hal+json
{
"_links": {
"self": { "href": "/orders/1234" },
"author": { "href": "/users/john" },
"items": [ ... ]
},
"orderNumber": 1234,
"status": "pending"
}
```
## Embedded Resources
Similarly to the `fields` query parameter, every request that might result in a response containing related embedded resource representations **SHOULD** implement the `embedded` query parameter. If, provided the value of the `embedded` query parameter **MUST** be a comma-separated list of relation identifiers.
Upon receiving such a request, in the event of a 2xx response, the service **SHOULD** respond with a message that "embeds" \(see HAL `_embedded` field\) only the related resources specified in the `embedded` parameter.
### Example
Embed only information about the Author of an Order resource. We are not interested in Items that are in this order.
HTTP Request
```text
GET /order/1234?embed=author HTTP/1.1
Accept: application/hal+json
```
HTTP Response
```text
HTTP/1.1 200 OK
Content-Type: application/hal+json
{
"_links": {
"self": { "href": "/orders/1234" },
"author": { "href": "/users/john" },
"items": [ ... ]
},
"orderNumber": 1234,
"itemCount": 42,
"status": "pending",
"_embedded": {
"author": {
"_links": { "self": "/users/john" },
"name": "John Appleseed",
"email": "john@apple.com"
}
}
}
```
## Reasonable Defaults
When `fields` and `embedded` parameters are not provided or not implemented the server **SHOULD** return reasonable default field and/or embedded resources. The defaults **MUST** always contain the `_links` field, where available.
## Resource Variants
The facility of `fields` and `embedded` parameters doesn't impose any restriction of creating new resource variants.
It is OK to create a new resource just as a compound resource only to provide selected fields or blend-embed some existing resources together.

View File

@@ -0,0 +1,41 @@
# Localization
## Language Variants
If a resource has multiple language variants and the difference between variants is only in the language of human-readable fields, then the [`Accept-Language`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language) request HTTP header **SHOULD** be used to select the desired language variant.
### Example
```text
GET /article HTTP/1.1
Accept-Language: en,en-US,fr;q=0.6
```
```text
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
Content-Language: en
Vary: Accept-Language
...
```
## Language or Country-specific Data Structure
If the difference between language or country specific variants of a resource is bigger than just in the content of human readable strings, for example, the data structure of the resource representation is different, then a query parameter **SHOULD** be used to communicate the requested variant.
### Example
```text
GET /article?market=en_US HTTP/1.1
```
```text
HTTP/1.1 200 OK
Content-Type: application/hal+json;charset=UTF-8
Content-Language: en
Vary: Accept-Language
...
```

View File

@@ -0,0 +1,29 @@
# Pagination
A collection resource **SHOULD** provide the [`first`, `last`, `next` and `prev` link](https://tools.ietf.org/html/rfc5988#section-6.2.2)s for navigation within the collection.
## Example
The Collection of Orders using the collection navigation link and `offset` and `limit` query parameters:
```javascript
{
"_links": {
"self": { "href": "/orders?offset=100&limit=10" },
"prev": { "href": "/orders?offset=90&limit=10" },
"next": { "href": "/orders?offset=110&limit=10" },
"first": { "href": "/orders?limit=10" },
"last": { "href": "/orders?offset=900&limit=10" }
},
"total_count": 910,
"_embedded": {
"order": [
{ ... },
{ ... },
...
]
}
}
```

View File

@@ -0,0 +1,17 @@
# Query Requests with Large Inputs
While HTTP doesn't impose any limit on the length of a URI, some implementation of server or client might have difficulties handling long URIs \(usually URIs with many or large query parameters\).
Every endpoint with such a URI **MUST** use the HTTP **POST** Request Method and send the query string in HTTP Request Message body using the `application/x-www-form-urlencoded` media type.
## Example
```text
POST /orders HTTP/1.1
Content-Type: application/x-www-form-urlencoded
search=attributes&color=white&size=56&...
```
> _NOTE: Since this operation is safe and idempotent, using the POST method violates the HTTP protocol semantics and results in loss of cache-ability._

View File

@@ -0,0 +1,69 @@
# Rate Limiting
The API rate limiting is provided by the selected adidas API management platform Mashery.
Rate limit information is provided in the for of HTTP headers. There are two types of rate limits: **Quota** and **Throttle**. The quota is a limit enforced per a longer period \(typically a day\). The throttle is the limit of calls per second.
## Quota Limit
The limit on the number of calls per a period \(day\). The default quota limit is 5000 calls per day.
### Example
Example response to a request over the quota limit:
```text
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
X-Error-Detail-Header: Account Over Rate Limit
X-Mashery-Error-Code: ERR_403_DEVELOPER_OVER_RATE
{
"title": "Rate Limit Exceeded",
"detail": "Account Over Rate Limit"
}
```
## Throttle Limit
The limit on the number of calls per second. The default throttle limit is two calls per second.
### Example
Example response to a request over the throttle limit:
```text
HTTP/1.1 403 Forbidden
Content-Type: application/problem+json
Retry-After: 1
X-Error-Detail-Header: Account Over Queries Per Second Limit
X-Mashery-Error-Code: ERR_403_DEVELOPER_OVER_QPS
{
"title": "Quota Limit Exceeded",
"detail": "Account Over Queries Per Second Limit"
}
```
> NOTE: The `Retry-After` gives a hint how long before the same request should be repeated \(in seconds\).
## Detail Information
By default, the headers do not contain details about the current usage and quotas. The default can be changed in the API management.
### Example
A successful response with the details about throttle \(`X-Plan-QPS`\) and quota \(`X-Plan-Quota`\) rate limits:
```text
HTTP/1.1 200 OK
X-Plan-QPS-Allotted: 10
X-Plan-QPS-Current: 1
X-Plan-Quota-Allotted: 1000
X-Plan-Quota-Current: 2
X-Plan-Quota-Reset: Tuesday, June 6, 2017 12:00:00 AM GMT
```

View File

@@ -0,0 +1,65 @@
# Search Requests
A search \(filter\) operation on a collection resource **SHOULD** be defined as safe, idempotent and cacheable, therefore using the [GET HTTP request method](https://adidas-group.gitbooks.io/api-guidelines/content/protocol/use-appropriate-methods.html).
Every search parameter **SHOULD** be provided in the form of a query parameter. In the case of search parameters being mutually exclusive or require the presence of another parameter, the explanation **MUST** be part of operation's description.
### Example
A collection of orders can be filtered by either article id it includes or by article manufacturer id. The two parameters are mutually exclusive and cannot be used together. The API description for such a design should look as follows:
```yaml
paths:
/orders:
x-summary: Collection of Orders
get:
summary: Retrieve or Search in the Collection of Orders
description: |
This operation allows to retrieve a filtered list of orders based on multiple criteria:
1. **Filter Orders by Article Id**
2. **Filter Orders by Manufacturer Id**
parameters:
- name: article_id
in: query
description: |
Article Id. Denotes the id of an article that must be in the order.
**Mutually exclusive** with `manufacturer_id`.
required: false
type: string
x-example: article_id_1
- name: manufacturer_id
in: query
description: |
Manufacturer Id. Denotes an id of a manufacturer of an article that must be in the order.
**Mutually exclusive** with `article_id`.
required: false
type: string
x-example: manufacturer_id_1
```
## Alternative Design
When it would be beneficial \(e.g. one of the filter queries is more common than another one\) a separate resource for the particular query **SHOULD** be provided. In such a case, the pivotal search parameter **MAY** be in the form of a path variable.
### Example
Building on top of the example mentioned above, we will provide the filtering of orders by article id as a separate resource.
```yaml
paths:
/articles/{article_id}/orders:
x-summary: Collection of Orders for given Article
get:
summary: Retrieve the collection of Orders that contain given article.
```

View File

@@ -0,0 +1,43 @@
# Introduction
## ![](../.gitbook/assets/adidas-logo.svg)
## adidas REST API Guidelines
The adidas REST API Guidelines defines standards and guidelines for building REST APIs at adidas. **These Guidelines has to be followed in addition to the adidas** [**General API Guidelines.**](../general-guidelines/general-guidelines.md)
The REST API Guidelines are further split into the following parts:
* **Core Principles**
REST API Guidelines Core Principles defines the rules that **MUST** be followed at throughout the full API lifecycle.
* **Functionality Guidelines**
* [**Protocol level**](https://adidas-group.gitbooks.io/api-guidelines/content/protocol/)
Protocol guidelines define the protocols used within the organization.
* [**Message level**](https://adidas-group.gitbooks.io/api-guidelines/content/message/)
The Message guidelines define the structure and semantics of messages used to exchange information.
* [**Application level**](https://adidas-group.gitbooks.io/api-guidelines/content/application/)
The Application guidelines define the definition and use of application-specific semantics.
* **Quality Guidelines**
Evolution and Execution guidelines define the rules for achieving the desired architectural qualities of systems.
* [**Evolution**](https://adidas-group.gitbooks.io/api-guidelines/content/evolution/)
Evolution qualities governance, such as testability, maintainability, extensibility, and scalability.
* [**Execution**](https://adidas-group.gitbooks.io/api-guidelines/content/execution/)
Execution qualities governance, such as security and usability.
* **Guides** Guides and materials supporting the REST API Guidelines
* **API Clients**
Section dedicated to consumers of adidas APIs