├── _config.yml ├── resources ├── restresourcemodel.png └── resources.md ├── .gitattributes ├── .gitignore ├── faq └── faq.md ├── documentation └── documentation.md ├── type-formatting └── type-formatting.md ├── introduction └── introduction.md ├── security-and-authentication └── security-and-authentication.md ├── http-verbs └── http-verbs.md ├── general-guidelines └── general-guidelines.md ├── correlation-id └── correlation-id.md ├── SUMMARY.md ├── api-design-principles └── api-design-principles.md ├── search └── search.md ├── uri-components └── uri-components.md ├── http-status-codes └── http-status-codes.md ├── authorization └── authorization.md ├── relationships-and-sub-resources └── relationships-and-sub-resources.md ├── filtering-sorting-field-selection-and-paging └── filtering-sorting-field-selection-and-paging.md ├── hypermedia-and-rest └── hypermedia-and-rest.md ├── caching └── caching.md ├── error-handling └── error-handling.md ├── rest-principles └── rest-principles.md ├── api-design-review-process └── api-design-review-process.md ├── further-reading └── further-reading.md ├── api-design-process └── api-design-process.md ├── README.md ├── message-schema └── message-schema.md ├── response-format └── response-format.md ├── collection-resources └── collection-resources.md ├── LICENSE └── api-management └── api-management.md /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /resources/restresourcemodel.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Haufe-Lexware/api-style-guide/HEAD/resources/restresourcemodel.png -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | 4 | # Custom for Visual Studio 5 | *.cs diff=csharp 6 | 7 | # Standard to msysgit 8 | *.doc diff=astextplain 9 | *.DOC diff=astextplain 10 | *.docx diff=astextplain 11 | *.DOCX diff=astextplain 12 | *.dot diff=astextplain 13 | *.DOT diff=astextplain 14 | *.pdf diff=astextplain 15 | *.PDF diff=astextplain 16 | *.rtf diff=astextplain 17 | *.RTF diff=astextplain 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Windows image file caches 2 | Thumbs.db 3 | ehthumbs.db 4 | 5 | # Folder config file 6 | Desktop.ini 7 | 8 | # Recycle Bin used on file shares 9 | $RECYCLE.BIN/ 10 | 11 | # Windows Installer files 12 | *.cab 13 | *.msi 14 | *.msm 15 | *.msp 16 | 17 | # Windows shortcuts 18 | *.lnk 19 | 20 | # ========================= 21 | # Operating System Files 22 | # ========================= 23 | 24 | # OSX 25 | # ========================= 26 | 27 | .DS_Store 28 | .AppleDouble 29 | .LSOverride 30 | 31 | # Thumbnails 32 | ._* 33 | 34 | # Files that might appear on external disk 35 | .Spotlight-V100 36 | .Trashes 37 | 38 | # Directories potentially created on remote AFP share 39 | .AppleDB 40 | .AppleDesktop 41 | Network Trash Folder 42 | Temporary Items 43 | .apdisk 44 | -------------------------------------------------------------------------------- /faq/faq.md: -------------------------------------------------------------------------------- 1 | ## FAQ 2 | 3 | ### Composite Keys 4 | 5 | #### Question: Composite Keys 6 | 7 | Many existing web applications have to deal with mutliple ids (Composite Keys). 8 | Let's say, order 4711 and order line 42, whereas the order lines are exposed via the rest API. 9 | How do we apply this to the REST URL structure? 10 | 11 | 1) orderlines/4711/42 12 | or 13 | 2) orderlines(4711,42) 14 | 15 | Are there any guidelines? 16 | 17 | 18 | ##### Answer 19 | That is a good example for a subresource. 20 | You should design it like this: 21 | 22 | orders/4711/orderlines/42 23 | 24 | If you want to expose orderlines as a top level resource and the orderline key is not unique over all orderlines in your internal model, 25 | you should create a separate unique key (e.g. a UUID) as additional key. 26 | 27 | orderlines/56e94f2b-25ac-4c58-9828-f63b66220999 28 | -------------------------------------------------------------------------------- /documentation/documentation.md: -------------------------------------------------------------------------------- 1 | ## Documentation 2 | 3 | An API needs a proper documentation to help developers to use the API. 4 | 5 | It is important to have a short but meaningful description about the purpose of the API. 6 | 7 | Describe important use cases to give developers a quick headstart. 8 | 9 | The goal is to enable a developer to use your API as quickly as possible: 10 | 11 | - Enable a developer to use your API in 5 minutes 12 | - Documentation is non-negotiable! 13 | 14 | Use **Swagger** as description and definition language of your API. 15 | 16 | Use **Swagger** to create API reference documentation. 17 | 18 | We **strongly** advise against generating a API description from code. The only proper place for generating Swagger from code is for automated validation to validate that a API signature has not changed from one release to the next. See also [Generating Swagger from Code](http://dev.haufe-lexware.com/generate-swagger/) for some practical advice. 19 | 20 | Use an API Management Portal to allow developers to get familar and to test your API. 21 | -------------------------------------------------------------------------------- /type-formatting/type-formatting.md: -------------------------------------------------------------------------------- 1 | ## Type Formatting 2 | 3 | ### Boolean 4 | 5 | A boolean is represented with **true** or **false**. 6 | 7 | ### Dates and Times 8 | 9 | Use [**ISO 8601**](http://en.wikipedia.org/wiki/ISO_8601) format for passing in and out dates and times. Use [**UTC**](https://en.wikipedia.org/wiki/UTC) as timezone. 10 | 11 | |Date|2015-07-02| 12 | |---|---| 13 | |Combined date and time in [**UTC**](https://en.wikipedia.org/wiki/UTC)|2015-07-02T14:47:47Z| 14 | 15 | 16 | ### Currency 17 | 18 | Use [**3-character ISO-4217**](http://en.wikipedia.org/wiki/ISO_4217#Active_codes) codes for specifying currencies. 19 | 20 | ##### Samples 21 | EUR - Euro 22 | CHF - Swiss franc 23 | USD - US Dollar 24 | 25 | ### Country 26 | 27 | Use country codes defined by the [**ISO 3166-1-alpha-2**](https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2) code standard. 28 | 29 | ##### Samples 30 | AD - Andorra 31 | DE - Germany 32 | FR - France 33 | US - United States of America 34 | 35 | ### Amount 36 | 37 | Use the format [0-9]+(\.[0-9]+)? to represent an amount like money. 38 | Separate amount and currency in different fields. 39 | 40 | ##### Samples 41 | 12.23 42 | 3789.1 43 | 56782 44 | -12.02 45 | +231.98 46 | 47 | ### UUID 48 | 49 | A UUID or GUID is represented in the Format '**dddddddd-dddd-dddd-dddd-dddddddddddd**' where each `d` represents `[A-Fa-f0-9]`. 50 | 51 | ##### Samples 52 | 56e94f2b-25ac-4c58-9828-f63b66220999 53 | 2ABAD998-48F6-4847-9EB2-2A6B5328C51D 54 | -------------------------------------------------------------------------------- /resources/resources.md: -------------------------------------------------------------------------------- 1 | ## Resources 2 | 3 | The fundamental concept in any RESTful API is the **resource**. One of the first steps in developing a RESTful web service is designing the resource model. 4 | The resource model identifies and classifies all the resources the client uses to interact with the Server. 5 | 6 | **Design your API with the API consumer in mind!** 7 | 8 | Each resource MUST make sense from the perspective of the API consumer. 9 | Beware of simply copy your internal model. Do not leak irrelevant implementation details out to your API. 10 | 11 | A resource is an object with a type, associated data, relationships to other resources, and a set of methods that operate on it. HTTP verbs are used to manipulate the resources. 12 | 13 | Resources can be grouped into **collections**. Each collection is homogeneous so that it contains only one type of resource, and unordered. Resources can also exist outside any collection. In this case, we refer to these resources as singleton resources. Collections are themselves resources as well. 14 | 15 | Collections can exist globally at the top level of an API, but can also be contained inside a single resource. In the latter case, we refer to these collections as sub-collections. Sub-collections are usually used to express some kind of “contained in” relationship. We go into more detail on this in [Relationships and Sub-Resources](../relationships-and-sub-resources/relationships-and-sub-resources.md). 16 | 17 | The diagram below illustrates the key concepts in a RESTful API. 18 | 19 | ![Rest Resource Model](restresourcemodel.png) 20 | 21 | We call information that describes available resources types, their behavior, and their relationships the resource model of an API. The resource model can be viewed as the RESTful mapping of the application data model. 22 | 23 | Find more details in the chapters: 24 | 25 | - [Collection Resources](../collection-resources/collection-resources.md) 26 | - [Filtering, sorting, field selection and paging](../filtering-sorting-field-selection-and-paging/filtering-sorting-field-selection-and-paging.md) 27 | -------------------------------------------------------------------------------- /introduction/introduction.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | Haufe-Lexware's software architecture centers around decoupled (micro)services that provide functionality via RESTful APIs. Our APIs most purely express what our systems do, and are therefore highly valuable business assets. Designing high-quality, long-lasting APIs has become even more critical for us since we started developing our new open platform strategy, which transforms Haufe-Lexware from individual and closely coupled silos into business enablementplatform. Our strategy emphasizes using API's to expose and make accessible our services for our product teams and external business partners. 4 | 5 | With this in mind, we’ve adopted “API First” as one of our key engineering principles. (Micro)Service development begins with API definition outside the code and ideally involves ample peer-review feedback to achieve high-quality APIs. API First encompasses a set of quality-related standards and fosters a peer review culture including a lightweight review procedure. 6 | We encourage our teams to follow them to ensure that our APIs: 7 | 8 | - are easy to understand and learn 9 | - are general and abstracted from specific implementation and use cases 10 | - are robust and easy to use 11 | - have a common look and feel 12 | - follow a consistent RESTful style and syntax 13 | - are consistent with other teams’ APIs and our global architecture 14 | 15 | Ideally, all of our APIs will look like the same author created them. 16 | 17 | ## Haufe-Lexware specific information 18 | 19 | The purpose of our “RESTful API guidelines” is to define standards to successfully establish “consistent API look and feel” quality. The CTO Team drafted and owns this guidelines. Teams are responsible to fulfill these guidelines during API development and are encouraged to contribute to guideline evolution via pull requests. 20 | 21 | Furthermore, teams should take part in [API review process](../api-design-review-process/api-design-review-process.md). 22 | 23 | Note: These guidelines will, to some extent, remain work in progress as our work evolves, but teams can confidently follow and trust them. 24 | 25 | --- 26 | This chapter was adopted from the [Zalando API Styleguide](https://github.com/zalando/restful-api-guidelines/blob/master/Introduction.md) -------------------------------------------------------------------------------- /security-and-authentication/security-and-authentication.md: -------------------------------------------------------------------------------- 1 | ## Security and Authentication 2 | 3 | ### Authentication 4 | 5 | OAuth 2.0 is the de-facto standard for API security. OpenId Connect is a simple identity layer on top of the OAuth 2.0 authorization framework to enable Clients to verify the identify of the End-User. This means that Web or mobile apps exposing APIs don’t have to share passwords. It allows the API provider to revoke tokens for an individual user for an entire app, without requiring the user to change their original password. This is critical, if a mobile device is compromised or if a rogue app is discovered. 6 | 7 | Overall, OAuth 2.0 will mean improved security by dropping the use of signatures and cryptography and relies on TLS for securing data in transit, which makes it transport dependent. This leads to a better end-user and consumer experiences with Web and mobile apps. 8 | 9 | Don't do something *like* OAuth, but different. It will be frustrating for app developers if they can't use an OAuth library in their language because of your variation. 10 | 11 | For more information on Authentication and Authorization see the section on [API Management](../api-management/api-management.md); it contains information on specific scenarios where certain OAuth2.0 flows can and MUST be applied. API Management solutions can help implementing these scenarios in a more generic and decoupled way. 12 | 13 | ### SSL everywhere - All the time 14 | 15 | Always use SSL. No exceptions. Today, your web APIs can get accessed from anywhere where internet is given (like libraries, coffee shops, airports among others). Not all of these access points are secure. Many don't encrypt communications at all, allowing for easy eavesdropping or impersonation if authentication credentials are hijacked. 16 | 17 | Another advantage of always using SSL is that guaranteed encrypted communications simplifies authentication efforts - you can get away with simple access tokens instead of having to sign each API request. 18 | 19 | One thing to watch out for is non-SSL access to API URLs. Do not redirect these to their SSL counterparts. Throw a hard error instead! The last thing you want is for poorly configured clients to send requests to an unencrypted endpoint, just to be silently redirected to the actual encrypted endpoint. 20 | -------------------------------------------------------------------------------- /http-verbs/http-verbs.md: -------------------------------------------------------------------------------- 1 | ## HTTP Verbs 2 | 3 | Just like the HTTP status codes, there are many more verbs in the HTTP standard that, although they are in theory OK to use for your Web API, you can get by with just a few that helps to keep your API simple, and self-explanatory to its clients. 4 | 5 | The full list of HTTP verbs from the spec can be found HERE, but we are going to focus on how to interpret the verbs and the actions that should be executed for each on in the context of a well-defined REST Web API. In the table there is also the result set that standard clients expect when they make requests with such VERBs. To better understand their proper use, we’ll use a sample resource endpoint called Users, where the (you guessed it) “Users” of our app are exposed via our Web API. 6 | 7 | | Resource Sample| | GET (Read) | POST (Insert) | PUT (update) | DELETE | Patch (partial update) | 8 | |----------------|-------------|---------------------|------------------------|------------------------------------|------------------------|---------------------------| 9 | | api/users | Action | Get a list of users | Creates a user | Batch update | Error | Batch update the users only with the attributes present in the request | 10 | | | Return | List of users | New user | No payload, only HTTP Status Code | Error HTTP Status Code | | 11 | | | | | | | | | 12 | | api/users/123 | Action | Get a single user | Error | Updates the user | Deletes the user | Partially updates the user only with the attributes present in the request | 13 | | | Return | Single user | Error HTTP Status code | Updated user | No payload, only | | 14 | 15 | 16 | 17 | 18 | And this is how you properly use the HTTP Verbs in a REST Web API. 19 | 20 | > :information_source: This paragraph is mainly a copy from http://micheltriana.com/2013/09/30/http-verbs-in-a-rest-web-api/. Thanks to Michel Triana. 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /general-guidelines/general-guidelines.md: -------------------------------------------------------------------------------- 1 | ## General Guidelines 2 | 3 | ### You should think of an API like a product. Indeed a Business API is a product. 4 | 5 | Like a product it should follow these rules: 6 | 7 | - Easy to learn 8 | - Hard to misuse 9 | - Easy to read and maintain it 10 | - Audience oriented 11 | 12 | ### Design your API with a customer, or at least with a customer in mind and actively seek feedback. 13 | 14 | Every API should be designed as if it were an external API for paying customers. Design your API with the API consumer in mind! 15 | 16 | Each resource MUST make sense from the perspective of the API consumer. Beware of simply copy your internal model. Do not leak irrelevant implementation details out to your API. 17 | 18 | **We believe that APIs are products**. We will provide these APIs to other business units and partners. The future is unpredictable. The conviction that an API is only internally or in one Business unit of use, can rapidly change. Therefore APIs should be designed like external APIs. Last but not least we learn to design better APIs. 19 | 20 | ### Do not invent or implement API Management 21 | 22 | We have a list of appropriate API management solutions we like to standardize on. If our existing solutions and blueprints do not fit, we work with you to find one which does. Refer to [API Management](../api-management/api-management.md) for details. 23 | 24 | ### Every API MUST be described using a formal API description language 25 | 26 | While we recognize the existence of various languages ([RAML](https://raml.org/), [API Blueprint](https://apiblueprint.org/)) we standardize on [Swagger](https://swagger.io) as the most commonly used language. API documentation has to be generated from its Swagger definition to ensure inherent consistency. Swagger is used to provide access to the API via API management tooling. 27 | 28 | Reserve time to create documentation. Use [Swagger](http://swagger.io/) to document. Refer to [Documentation](../documentation/documentation.md) for details. 29 | 30 | ### API clients MUST use an API Key 31 | 32 | Different SLA’s CAN be offered by the API provider. API clients are identified by API keys obtained from the API Portal. **No API access without a corresponding and valid API key** (Exception for pubsub notification APIs which only contain the link to the resource but not the resource itself). 33 | -------------------------------------------------------------------------------- /correlation-id/correlation-id.md: -------------------------------------------------------------------------------- 1 | ## Correlation Id ## 2 | 3 | It is extremely hard to analyse incorrect and faulty behaviour in a distributed system environment. Systems are calling other systems either synchronous or ansynchronous to fulfill a request. Each system logs to its own logging target. Manually analyzing the way of a request is a nightmare. To set up automated failure analytics is errorprone and brittle. 4 | The [Correlation Pattern](http://www.enterpriseintegrationpatterns.com/patterns/messaging/CorrelationIdentifier.html), which depends on the use of Correlation ID is a well documented Enterprise Integration Pattern. Its target is to correlate requests over multiple systems and responses to another. 5 | 6 | A Correlation ID is a unique identifier value that is attached to requests and messages that allow reference to a particular transaction or event chain. Attaching a Correlation ID to a request is arbitrary. You don’t have to use one. But if you are designing a distributed system that incorporates message queues and asynchronous processing, you will do well to include a Correlation ID in your messages. And even in synchronous chains it helps you to follow the call squence over different systems. 7 | 8 | The Correlation Id is build by the client or as early as possible in the request chain. If a request contains no Correlation Id header it is up to each system to create and add it to the header. 9 | It is the responsibility of each part/service/system in the chain to extract the Correlation Id from the request and use it in log entries. Calls to subsequent subsystems must contain the Correlation Id. 10 | 11 | Currently there is no standard that fixes the field name for the Correlation Id. X-Headers are deprecated, see [https://tools.ietf.org/html/rfc6648](https://tools.ietf.org/html/rfc6648) and [https://tools.ietf.org/html/rfc7231#section-8.3.1](https://tools.ietf.org/html/rfc7231#section-8.3.1). 12 | 13 | We chose the name **Correlation-Id**. 14 | It is recommended to use a **UUID** as Correlation Id. That allows our systems to validate the Correlation Id with a regular expression and therefore prevent against log forging attacks. 15 | 16 | { 17 | "Correlation-Id": 18 | } 19 | 20 | > :information_source: [Kong plugins](https://getkong.org/plugins/correlation-id/) 21 | 22 | ## Create Correlation Id with Wicked ## 23 | 24 | Haufes [API Management Solution Wicked](http://wicked.haufe.io/) supports the creation of Correlation Id. 25 | Read more [at](http://wickedhaufeio.readthedocs.io/en/stable/configuring-kong-plugins/). 26 | -------------------------------------------------------------------------------- /SUMMARY.md: -------------------------------------------------------------------------------- 1 | # Summary 2 | * [Why a Haufe API Styleguide](README.md) 3 | * [Introduction](introduction/introduction.md) 4 | * [General Guidlines](general-guidelines/general-guidelines.md) 5 | 6 | ## Designing APIs 7 | * [API Design Principles](api-design-principles/api-design-principles.md) 8 | * [API Design Process](api-design-process/api-design-process.md) 9 | * [API Design Review Process](api-design-review-process/api-design-review-process.md) 10 | * [API Documentation](documentation/documentation.md) 11 | 12 | ## Using REST 13 | * [REST Principles](rest-principles/rest-principles.md) 14 | * [Hypermedia and REST](hypermedia-and-rest/hypermedia-and-rest.md) 15 | * [Hypermedia Formats](response-format/response-format.md) 16 | 17 | ## Using HTTP 18 | * [URI Components and Versioning](uri-components/uri-components.md) 19 | * [Filtering, sorting, field selection and paging](filtering-sorting-field-selection-and-paging/filtering-sorting-field-selection-and-paging.md) 20 | * [Search](search/search.md) 21 | * [HTTP Verbs](http-verbs/http-verbs.md) 22 | * [HTTP Status Codes](http-status-codes/http-status-codes.md) 23 | * [Error handling](error-handling/error-handling.md) 24 | * [Caching](caching/caching.md) 25 | 26 | ## Respresenting Resources 27 | * [Resources](resources/resources.md) 28 | * [Relationships and Sub-Resources](relationships-and-sub-resources/relationships-and-sub-resources.md) 29 | * [Resource Collections](collection-resources/collection-resources.md) 30 | * [Resource Schema and Postels Law](message-schema/message-schema.md) 31 | * [Resource Type Formatting](type-formatting/type-formatting.md) 32 | 33 | ## Managing APIs 34 | * [Security and Authentication](security-and-authentication/security-and-authentication.md) 35 | * [Authorization](authorization/authorization.md) 36 | * [API Management](api-management/api-management.md) 37 | * [Azure API Management](api-management/api-management.md#azure-api-management) 38 | * [Haufe OSS API Management](api-management/api-management.md#haufe-oss-api-management) 39 | * [API Management Scenarios](api-management/api-management.md#api-management-scenarios) 40 | * [API Gateways](api-management/api-management.md#api-gateways) 41 | * [The `Forwarded` header](api-management/api-management.md#the-forwarded-header) 42 | * [API Portals](api-management/api-management.md#api-portals) 43 | * [Automating API Deployments](api-management/api-management.md#automating-api-deployments) 44 | 45 | ## Appendix 46 | * [FAQ](faq/faq.md) 47 | * [Further Reading](further-reading/further-reading.md) 48 | -------------------------------------------------------------------------------- /api-design-principles/api-design-principles.md: -------------------------------------------------------------------------------- 1 | # Design Principles 2 | 3 | To compare the interface design approaches of SOAP-based web services to those of REST services, the former tend to be centered around operations that are usually use-case specific and reveal service implementation details (inside-out perspective). This leads to closely coupled systems which tend to get brittle and fragile as complexity grows. In contrast, REST is all about (business) entities found in the system and exposed as resource endpoints — leading to interfaces which abstract away implementation details (outside-in perspective) and are thereby more broadly usable and longer lasting. . 4 | 5 | ## API Design Principles 6 | 7 | 1. We prefer REST-based APIs 8 | 2. We prefer systems to be truly RESTful 9 | 3. We strive to build interoperating distributed systems that different teams can evolve in parallel 10 | 11 | An important principle for (RESTful) API design and usage is Postel's Law, aka [the 12 | Robustness Principle](http://en.wikipedia.org/wiki/Robustness_principle) (RFC 1122): 13 | 14 | > “Be liberal in what you accept, be conservative in what you send.” 15 | 16 | The ability to extend service definitions after the initial release without affecting already deployed clients is key to preserve agility and evolvability of those services. For a more in-depth discussion regarding its applicability on API Design, please read the [Message Schema and Postel's Law](../message-schema/message-schema.md) chapter. 17 | 18 | Read the following to gain additional insight on the RESTful service architecture paradigm and general RESTful API design style: 19 | 20 | * Fielding Dissertation: [Architectural Styles and the Design of Network-Based Software 21 | Architectures](http://www.ics.uci.edu/~fielding/pubs/dissertation/top.htm) 22 | * Book: [REST in Practice: Hypermedia and Systems 23 | Architecture](http://www.amazon.de/REST-Practice-Hypermedia-Systems-Architecture/dp/0596805829) 24 | * Book: [A Practical Approach to API Design](https://leanpub.com/restful-api-design) 25 | * Book: [Build APIs You Won't 26 | Hate](https://leanpub.com/build-apis-you-wont-hate) 27 | * InfoQ eBook: [Web APIs: From Start to 28 | Finish](http://www.infoq.com/minibooks/emag-web-api) 29 | * Lessons-learned blog: [Thoughts on RESTful API 30 | Design](http://restful-api-design.readthedocs.org/en/latest/) 31 | 32 | We apply the RESTful web service principles to all kind of application components, whether they provide functionality via the Internet or via the intranet as larger application elements. We strive to build interoperating distributed systems that different teams can evolve in parallel. 33 | 34 | --- 35 | This chapter was adopted from the [Zalando API Styleguide](https://github.com/zalando/restful-api-guidelines/blob/master/Introduction.md) -------------------------------------------------------------------------------- /search/search.md: -------------------------------------------------------------------------------- 1 | ## Search 2 | 3 | ### Simple or scoped search 4 | 5 | A simple search could be modeled as a resourceful API by appending '`?`' after the path of the URL and adding query parameters. 6 | 7 | ##### Example 8 | 9 | /users?given_name="Mustermann" 10 | 11 | 12 | Please refer to the filtering section in [Filtering, sorting, field selection and paging](../filtering-sorting-field-selection-and-paging/filtering-sorting-field-selection-and-paging.md). 13 | 14 | ### Global search 15 | 16 | A more complex search across multiple resources requires a different design. 17 | 18 | This will sound familiar if you've read the topic about using verbs not nouns when results don't return a resource from the database - rather the result is some action or calculation. 19 | 20 | If you want to do a global search across resources, we suggest you follow the Google model: 21 | 22 | /search?q=fluffy+fur 23 | 24 | 25 | Here, `search` is the verb and `?q` represents the query. 26 | 27 | ### Using POST 28 | 29 | Another way to implement a RESTful search is to consider the search itself to be a resource. Then you can use the POST verb because you are creating a search. You do not have to literally create something in a database in order to use a POST. 30 | 31 | ##### Example 32 | 33 | Accept: application/json 34 | Content-Type: application/json 35 | POST http://example.com/user_management/v1/users/searches 36 | { 37 | "name": "Mustermann" 38 | } 39 | 40 | 41 | You are creating a search from the user's standpoint. The implementation details of this are irrelevant. Some RESTful APIs may not even need persistence. That is an implementation detail. 42 | 43 | For long running searches it is a good solution to split the the search request into the POST request to create the search and a GET request to retrieve the search results. 44 | 45 | Otherwise, it is ok to deliver the search results in the response of the POST call. This solution is more convenient for the client. 46 | 47 | ### Empty Result Sets 48 | 49 | Typically, when a search returns any results, the status code will be `200 OK` and the body of the response will contain a list of found items. 50 | 51 | But in case a search does **not** yield any results, there are two different ways to handle this situation: 52 | 53 | 1. HTTP status code is `200 OK` and the response body **MUST** be an empty list, e.g. `[]` in JSON 54 | 2. HTTP status code is `204 NO CONTENT` and the response body **MUST** be empty 55 | 56 | The first solution is preferred as the resulting interface (a list) is the same as with a non-empty result so no special case handling has to be implemented when parsing the response body. 57 | 58 | Empty search results **MUST NOT** make use of the HTTP status code `404 NOT FOUND` since that would indicate that the searched resource *itself* does not exist. 59 | -------------------------------------------------------------------------------- /uri-components/uri-components.md: -------------------------------------------------------------------------------- 1 | ## URI Components 2 | ### Hostname 3 | 4 | Make no assumption about the hostname. 5 | Assume that each API will have a different hostname. In particular do not assume a specific IP address. Services can be dynamically deployed or moved. 6 | DNS was invented to deal with that. 7 | 8 | ### Service namespace 9 | 10 | In any URI, the first noun (which may be singular or plural, depending on the situation) should be considered a “Service namespace”. Service namespaces should reflect the customer's perspective on the (business) service boundary. 11 | 12 | Do not use acronyms. Use small caps and underscore `_` for `` (governs all of the url and messages). 13 | 14 | ##### URI Template 15 | 16 | /{namespace}/ 17 | 18 | ##### Example 19 | 20 | /user_management/ 21 | 22 | ### Version 23 | 24 | The URI should include `/vN` with the major version (`N`) as a prefix. No major.minor syntax. URL-based versioning is utilized for it's simplicity of use for API consumers, versus the more complex header-based approach.[^1] 25 | 26 | [^1] See the following [brief overview of versioning methods](https://www.3scale.net/2016/06/api-versioning-methods-a-brief-reference/) 27 | 28 | Version is a single number and only to be incremented on ‘backward’ compatibility breaking. Adding fields or deprecating fileds are **NOT** breaking changes. API Clients need to be able to **ignore** additional elements. API Providers need to be able to use meaningful defaults for new fields not expected by existing clients. 29 | 30 | Please stick to the following rule: 31 | 32 | > In general do **NOT** increment the version of your API. Until you must. And it is really rare that you must. Only increment on breaking changes. Extending the API is not a breaking change. 33 | 34 | ##### URI Template 35 | 36 | /{namespace}/v{version}/ 37 | 38 | ##### Example 39 | 40 | /user_management/v1/ 41 | 42 | ### Resource References 43 | 44 | The URI references for resources should consistently use the same path components to refer to resources. Sub-namespace or sub-folders should be avoided, to maintain path consistency. This allows consumer developers to have a predictable experience in case they are building URIs in code. 45 | 46 | ##### URI Template 47 | 48 | /{namespace}/{version}/{resource}/{resource-id}/{sub-resource}/{sub-resource-id} 49 | 50 | 51 | ### baseurl 52 | 53 | In the following sections of the guide the term **baseurl** is often used to indicate an absolute URL. 54 | The **baseurl** is a replacement for the host, namespace and version. 55 | 56 | ##### URI Template 57 | 58 | baseurl = {scheme}://{host}/{namespace}/{version} 59 | 60 | ### Valid and invalid url 61 | 62 | Your rest endpoints normally end with a noun like 63 | 64 | {host}/user_management/v1/users 65 | 66 | There is no trailing slash. You CAN support a trailing slash. But it is not common. Do NOT support urls like `{host}/user_management/v1/users/?queryparams`. This is not valid syntax! 67 | -------------------------------------------------------------------------------- /http-status-codes/http-status-codes.md: -------------------------------------------------------------------------------- 1 | ## HTTP Status Codes 2 | The following table lists the HTTP response status codes for the `GET` (retrieve), `POST` (create), `PUT` (modify), and `DELETE` operations. 3 | 4 |
Response CodeHTTP OperationResponse Body ContentsDescription
200GET, PUT, DELETEResourceNo error, operation successful.
201 CreatedPOSTResource that was createdSuccessful creation of a resource. The Location HTTP Header can provide a link to the newly created resource.
204 No ContentPOST, PUT, DELETEN/AThe request was processed successfully, but no response body is needed.
304 Not Modifiedconditional GETN/AResource has not been modified. Used when HTTP caching headers are in play.
400 Bad RequestGET, POST, PUT, DELETEError MessageMalformed syntax or a bad query.
401 UnauthorizedGET, POST, PUT, DELETEError MessageAction requires user authentication.
403 ForbiddenGET, POST, PUT, DELETEError Message 5 | 6 | When authentication succeeded but authenticated user doesn't have access to the resource. 7 | 8 |
404 Not FoundGET, POST, PUT, DELETEError MessageResource not found.
405 Not AllowedGET, POST, PUT, DELETEError MessageMethod not allowed on resource.
406 Not AcceptableGETError MessageRequested representation not available for the resource.
408 Request TimeoutGET, POSTError MessageRequest has timed out.
409 Resource ConflictPUT, PUT, DELETEError MessageState of the resource doesn't permit request.
410 GoneGET, PUTError Message 9 | 10 | Indicates that the resource at this end point is no longer available. Useful as a blanket response for old API versions 11 | 12 |
411 Length RequiredPOST, PUTError MessageThe server needs to know the size of the entity body and it should be specified in the Content Length header.
412 Precondition failedGETError MessageOperation not completed because preconditions were not met.
415 Unsupported TypePOST, PUTError MessageRepresentation not supported for the resource.
422 Unprocessable EntityPOST, PUTError Message 13 | 14 | Used for validation errors 15 | 16 |
500 Server ErrorGET, POST, PUTError MessageInternal server error.
501 Not ImplementedPOST, PUT, DELETEError MessageRequested HTTP operation not supported.
17 | -------------------------------------------------------------------------------- /authorization/authorization.md: -------------------------------------------------------------------------------- 1 | ## Authorization 2 | 3 | After the user's identity has been established (authentication) we may have scenarios in which the user should be allowed or not to certain actions or information. 4 | 5 | Since authorization can be connected to a varied number of information sources and specific to each project (licenses, rights, roles, identity etc.) it should not be delegated to a centralized solution. 6 | 7 | ## Access Control 8 | 9 | There are multiple techniques that can be leveraged for access control. Depending on your scenario you may find you need one or maybe a combination of multiple methods. 10 | 11 | A couple of examples (_in order of complexity_): 12 | 13 | | Acronym | Name | Description | 14 | |--------- |------------------------------------ |-------------------------------------------------------------------------------------------------- | 15 | | ACL | Access Control List | Are you on the whitelist? | 16 | | RBAC | Role Based Access Control | Are you an admin? | 17 | | ABAC/PBAC | Attribute/Policy Based Access Control | Do you or the action or the resource have a certain value for a certain attribute ? | 18 | | RABAC | Risk Adaptive Based Access Control | Contextually going to determine a risk score and decide if to allow or deny based on that score. | 19 | 20 | Hybrid combinations of these approaches can be used. 21 | 22 | For example you may have broad access control using RBAC (_i.e only admins have access to the admin API_) followed by ABAC/PBAC for more fine grained rules on the actions available (_i.e only admins from a specific department can grant other people the role of admin_). 23 | 24 | ## Field-level access control 25 | 26 | In certain scenarios you might want to have different representations depending on who is making the call. 27 | 28 | i.e.: When I ask for my User entity I should see all fields but when someone else asks for my user they should see just a minimum amount of data that is not private. 29 | 30 | ```json5 31 | //representation for authorized user - GET /users/ 32 | { 33 | "firstName": "...", 34 | "lastName":"...", 35 | "age": "...", 36 | "sex":"...", 37 | "religion": "...", 38 | "politicalViews":"...", 39 | "avatarUrl": "...", 40 | "jobTitle":"...", 41 | "address": "...", 42 | "companyName":"..." 43 | } 44 | ``` 45 | ```json5 46 | //representation for other users - GET /users/ 47 | { 48 | "firstName": "...", 49 | "lastName":"...", 50 | "jobTitle": "...", 51 | "avatarUrl":"..." 52 | } 53 | ``` 54 | 55 | A direct consequence of this is that you need to mark the potentially blocked fields as optional in the API documentation. 56 | 57 | This in conjunction with the field selection approach via query parameters detailed in the [filtering, sorting, field selection and paging](../filtering-sorting-field-selection-and-paging/filtering-sorting-field-selection-and-paging.md#field-selection) section can lead to a more complex scenario where we must write authorization logic based on the fields requested. 58 | 59 | If one of the fields requested cannot be returned due to authorization rules then a `403 Forbidden` should be returned. 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /relationships-and-sub-resources/relationships-and-sub-resources.md: -------------------------------------------------------------------------------- 1 | ## Relationships and Sub-Resources 2 | A resource is the fundamental unit in RESTful API design. Resources model objects from the application data model. 3 | Resources almost always have relationships to other resources. 4 | 5 | Our Goal is to provide self describing APIs where links help the API consumer how to use the API. 6 | 7 | ### Hypermedia Support for relationships 8 | 9 | A response ... 10 | 11 | - MUST return a link element to **self** 12 | - MUST return links to **sub-resource** 13 | - SHOULD return links to **related objects** 14 | 15 | ##### Example Request 16 | 17 | GET /invoices/INV-567A89HG1 18 | 19 | 20 | ##### Example Response 21 | HAL response Format 22 | 23 | { 24 | "_links": 25 | { 26 | "self": { "href": "{baseurl}/invoices/INV-567A89HG1"}, 27 | "customer": { "href": "{baseurl}/customer/CUST-12ATCVWV"}, 28 | "collection/lineitems": { "href": "{baseurl}/invoices/INV-567A89HG1/lineitems"}, 29 | "collection/payments": { "href": "{baseurl}/invoices/INV-567A89HG1/payments"}, 30 | }, 31 | "id": "INV-567A89HG1", 32 | "number" : "627726", 33 | "total": 20.30, 34 | "date" : "2015-06-09 12:00:00", 35 | "customer_id": "CUST-12ATCVWV", 36 | "customer_name": "Max Mustermann" 37 | } 38 | 39 | ### Modeling Relationships 40 | 41 | Relationships are often modeled by a **sub-resource**. 42 | Use the following pattern for sub-resources. 43 | 44 | GET /{resource}/{resource-id}/{sub-resource} 45 | GET /{resource}/{resource-id}/{sub-resource}/{sub-resource-id} 46 | POST /{resource}/{resource-id}/{sub-resource} 47 | 48 | > :information_source: Limit the depth of your URIs to ony one sub-resource to keep the API clean and simple. 49 | 50 | ### When to use sub-resources 51 | 52 | #### Existantially dependent 53 | 54 | In case of a 1:N relationship, where the child object is existentially dependent on the parent object use a sub-resource. “Existentially dependent” means that a child object cannot exist without its parent. 55 | An example of such a relationship are lineitems of an invoice. 56 | 57 | GET /invoices/INV-567A89HG1/lineitems 58 | POST /invoices/INV-567A89HG1/lineitems 59 | 60 | #### Belongs to relationship 61 | 62 | If you have a "Belongs to" relationship use a sub-resource. 63 | 64 | Invoices belong to a customer. To get all invoices to a specific customer, or to create a new invoice for that customer, do a GET or a POST: 65 | 66 | GET /customers/CUST-12ATCVWV/invoices 67 | POST /customers/CUST-12ATCVWV/invoices 68 | 69 | Other samples are "A dog belongs to an owner", "a shirt belongs to a person". 70 | 71 | #### N:M relationship 72 | 73 | In case of a N:M relationship use a sub-resource. 74 | The sub-resource can be defined initially to support the lookup direction that you most often need to follow. 75 | If you need to query both sides of the relationship often, then two sub-resources can be defined, one on each linked object. 76 | 77 | A good example is a car pool. There are N drivers and M cars. 78 | 79 | GET /cars/CAR-3767FSHS/drivers 80 | GET /drivers/DRI-ZU99983/cars 81 | 82 | 83 | ### Using a query parameter instead of sub-resources 84 | 85 | Another valid option is to use query parameters instead of sub-resources in case of the Belongs to and N:M relationship. 86 | 87 | GET /invoices?customer_id=CUST-12ATCVWV 88 | POST /invoices 89 | 90 | GET /drivers?car_id=CAR-3767FSHS 91 | GET /cars?driver_id=DRI-ZU99983 92 | 93 | It is important to be consistent how to design your API. 94 | -------------------------------------------------------------------------------- /filtering-sorting-field-selection-and-paging/filtering-sorting-field-selection-and-paging.md: -------------------------------------------------------------------------------- 1 | ## Filtering, sorting, field selection and paging 2 | ### Filtering 3 | Use a unique query parameter for all fields or a query language for filtering. 4 | 5 | GET /cars?color=red Returns a list of red cars 6 | GET /cars?type=%2Avan%2A Returns a list of cars whose type contains the 'van' word (Minivan, Cargo Van...). %2A is the encoded form of the * wildcard. 7 | GET /cars?seats<=2 Returns a list of cars with a maximum of 2 seast 8 | 9 | ### Time selection 10 | 11 | `start_time` or `{property_name}_from`, `end_time` or `{property_name}_to` query parameters should be provided if time selection is needed. 12 | 13 | ### Sorting 14 | 15 | Allow ascending and descending sorting over multiple fields. 16 | 17 | GET /cars?sort=-manufactorer,+model 18 | 19 | 20 | This returns a list of cars sorted by descending manufacturers and ascending models. 21 | 22 | The sort order for each sort field **MUST** be specified with one of the following prefixes: 23 | 24 | - Plus (U+002B PLUS SIGN, "+") to request an ascending sort order. 25 | - Minus (U+002D HYPHEN-MINUS, "-") to request a descending sort order. 26 | 27 | ### Field selection 28 | 29 | Mobile clients display just a few attributes in a list. They don’t need all attributes of a resource. Give the API consumer the ability to choose returned fields. This will also reduce the network traffic and speed up the usage of the API. 30 | 31 | GET /cars?fields=manufacturer,model,id,color 32 | 33 | Nevertheless, you may choose that some fields would always be sent along with the requested fields, in the response payload. Like the `id` for example. 34 | 35 | If one of the fields requested does not exist, a `400 Bad Request` should be returned. 36 | 37 | As explained in the [Authorization](../authorization/authorization.md) chapter, in case the field requested should not be accessible to the calling user, a `403 Forbidden` should be returned. 38 | 39 | ### Paging 40 | 41 | There are two popular ways how to support paging. 42 | 43 | #### limit and offset style 44 | 45 | Use **limit** and **offset**. It is flexible for the user and common in API implementations (Facebook). The default should be limit=**20** and offset=**0**. 46 | 47 | GET /products?limit=25&offset=50 48 | 49 | 50 | ##### Response Fields 51 | { 52 | "limit": 25, 53 | "offset": 50, 54 | "total_count": 1634 55 | } 56 | 57 | |Name|Type|Description| 58 | |---|---|---| 59 | |offset|Integer|The offset used in the execution of the query.| 60 | |limit|Integer|The limit used in the execution of the query.| 61 | |total_count|Integer|The total number of records available.| 62 | 63 | #### Page style 64 | 65 | Pages of results should be referred to consistently by the query parameters `page` and `page_size`, where `page_size` refers to the amount of results per request, and `page` refers to the requested page. Additionally, responses should include `total_count` and `total_pages` whenever possible, where `total_count` indicates the total records in the requested collection, and `total_pages` is the number of pages (interpolated from `total_count`/`page_size`). 66 | 67 | The default should be `page=1` and `page_size=20`. 68 | 69 | GET /products?page=2&page_size=30 70 | 71 | 72 | ##### Response Fields 73 | 74 | { 75 | "page": 2, 76 | "page_size": 30, 77 | "total_count": 1634, 78 | "total_pages": 55 79 | } 80 | 81 | |Name|Type|Description| 82 | |---|---|---| 83 | |page|Integer|The page used in the execution of the query.| 84 | |page_size|Integer|The page_size used in the execution of the query.| 85 | |total_count|Integer|The total number of records available.| 86 | |total_pages|Integer|The total number of pages available| 87 | 88 | ### Hypermedia links 89 | 90 | Hypermedia links are high value in navigating paged resource collections, as `page`/`page_size` query parameters can be maintained while navigating pages of results. 91 | 92 | Links should be provided with `rels` of `next`, `previous`, `first`, `last` wherever appropriate. 93 | -------------------------------------------------------------------------------- /hypermedia-and-rest/hypermedia-and-rest.md: -------------------------------------------------------------------------------- 1 | ## Hypermedia and REST 2 | There are four different Levels in the REST API Evolution. They are described in the Richardson Maturity Model. You can find more information in [this](http://martinfowler.com/articles/richardsonMaturityModel.html) article from Martin Fowler. 3 | 4 | Hypermedia represents the links to your API. The main characteristics of Hypermedia are: 5 | 6 | - Decouple the Server and the Client 7 | - Links are to help developers know how to use the API 8 | - The developer interacts with the first URL 9 | - The Navigation is controlled by the server 10 | - API becomes self-describing 11 | - Links become the application state 12 | - HATEOAS 13 | 14 | > (**HATEOAS**) Hypermedia as the Engine of Application State. The principle of addressability just says that every 15 | > resource should have its own URL. If something is important to your application, it should have a unique name, a 16 | > URL, so that you and your users can refer to it unambiguously. 17 | 18 | The URI Templates for HATEOAS are covered in RFC 6570 and the Link Header in RFC 5988. 19 | 20 | At its core, HATEAOAS provides a way to interact with the REST API entirely through hyperlinks. With each call that you make to the API, we’ll return an array of links that allow you to request more information about a call and to further interact with the API. You no longer need to hard code the logic necessary to use the REST API. 21 | 22 | HATEOAS links are contextual, so you only get the information that is relative to a specific request. 23 | 24 | Details about Hypermedia formats are described in [Hypermedia Formats](../response-format/response-format.md). 25 | 26 | [On Choosing a Hypermedia Format](http://sookocheff.com/post/api/on-choosing-a-hypermedia-format/) provides a good overview and guide of Hypermedia Formats. 27 | 28 | ### Relative vs Absolute 29 | 30 | It is strongly recommended that the URLs generated by the API should be absolute URLs. 31 | 32 | The reason is mostly for ease of use by the client, so that it never has to find out the correct base URI for a resource, which is needed to interpret a relative URL. The [URL RFC](http://tools.ietf.org/html/rfc3986#section-5.1) specifies the algorithm for determining a base URL, which is rather complex. One of the options for finding the base URL is to use the URL of the resource that was requested. Since a resource may appear under multiple URLs (for example, as part of a collection, or stand-alone), it would be a significant overhead to a client to remember where he retrieved a representation from. By using absolute URLs, this problem doesn’t present itself. 33 | 34 | #### On determining which URI to return 35 | 36 | In [Hypermedia responses](../response-format/response-format.md), we require the use of absolute URLs (as stated in the above section). If your API lives behind an [API Management](../api-management/api-management.md), the actual URI of the (backend) API will be different from the URI which is the one to call, i.e. the one of the API management gateway. 37 | 38 | As a rule, the API Management gateway MUST pass an additional header with the call to the backend API containing the API Gateway base URL for the API at hand. This header must be named `Forwarded`, as described in [RFC 7239](https://tools.ietf.org/html/rfc7239). The two parameters `host` and `proto` are pre-defined in the RFC, whereas we need additional ones, which is explicitly allowed per Section 5.5 of the RFC: 39 | 40 | * `host`: Must contain the host name of the API Gateway; this is the host an API client uses to actually talk to the API. 41 | * `proto`: The protocol/schema to use. This MUST be `https` for all of our APIs (see [security and authentication](../security-and-authentication/security-and-authentication.md)) 42 | * Extension `port`: OPTIONAL - The port of the API Gateway. Usually this can be assumed to be `443` if `proto` equals `https`; use if deviating 43 | * Extension `prefix`: The base path of the API on the API Gateway, e.g. `/someapi/v1`. 44 | 45 | **Example**: A request goes to `https://api.contenthub.haufe.io/ingest/v1/bulk/63874638746834`, which is forwarded to the ingest service in the backend. The API Gateway must pass on this information in the following way: 46 | 47 | ``` 48 | Forwarded: proto=https;host=api.contenthub.haufe.io;port=443;prefix=/ingest/v1 49 | ``` 50 | 51 | If present, this header MUST be used to assemble hypermedia links in responses, so that an API consumer is directed to the right place. 52 | 53 | If this header is not present, the API backend SHOULD use its own absolute base URI as a fallback. 54 | -------------------------------------------------------------------------------- /caching/caching.md: -------------------------------------------------------------------------------- 1 | ## Caching 2 | 3 | There are some reasons why you have to consider to use Caching 4 | 5 | - improve speed 6 | - reduce latency 7 | - reduce server load 8 | - reduce network traffic 9 | 10 | Goal of caching is to never generate the same response twice. 11 | 12 | > Tip: For security reasons, do not allow sensitive data to be cached. 13 | Use server side mechanisms like setting `Cache-Control` to `no-store` in the response header. 14 | Additionally you should use HTTPS. 15 | 16 | 17 | #### Expires HTTP Header 18 | 19 | The `Expires` HTTP header is a basic means of controlling caches - it tells all caches how long the associated representation is fresh for. 20 | After that time, caches will always check back with the origin server to see, if a document is changed. 21 | `Expires` headers are supported by practically every cache. 22 | Expires headers are especially good for making static images (like navigation bars and buttons) cacheable. Because they don't change much, you can set extremely long expiry time on them, making your site appear much more responsive to your users. 23 | 24 | GET /user_management/v1/users/BE14A7269802498F992813885546D058 25 | 26 | HTTP/1.1 200 OK 27 | ... 28 | Expires: Fri, 30 Oct 2015 14:19:41 GMT 29 | Last-Modified: Mon, 29 Jun 2015 02:28:12 GMT 30 | Content-Type: text/json; charset=utf-8 31 | Content-Length: ... 32 | { "id": "BE14A7269802498F992813885546D058", "name": "Mustermann" } 33 | 34 | You can find more infos in: 35 | [https://www.mnot.net/cache_docs/#CACHE-CONTROL](https://www.mnot.net/cache_docs/#EXPIRES) 36 | 37 | #### Cache-Control Header 38 | 39 | Use `Cache-Control` header that indicates, whether the data in the body of the response can be safely cached by the client or an intermediate server. 40 | Use `max-age` to indicate after how many seconds the response should be considered out-of-date. 41 | The following example shows an HTTP GET request and the corresponding response that includes a Cache-Control header: 42 | 43 | GET /user_management/v1/users/BE14A7269802498F992813885546D058 44 | 45 | HTTP/1.1 200 OK 46 | ... 47 | Cache-Control: max-age=600, private 48 | Content-Type: text/json; charset=utf-8 49 | Content-Length: ... 50 | { "id": "BE14A7269802498F992813885546D058", "name": "Mustermann" } 51 | 52 | You can find a detailed explanation of the different `Cache-Control` opportunities in: 53 | [https://www.mnot.net/cache_docs/#CACHE-CONTROL](https://www.mnot.net/cache_docs/#CACHE-CONTROL) 54 | 55 | #### ETag 56 | 57 | You can use an `ETag` (Entity Tag) in the response header for entity data. 58 | An ETag is an opaque string indicating the version of a resource - each time a resource changes, the Etag is also modified. 59 | This ETag should be cached as part of the data by the client application. 60 | The ETag is primarily useful to save bandwidth. 61 | 62 | GET /user_management/v1/users/BE14A7269802498F992813885546D058 63 | 64 | HTTP/1.1 200 OK 65 | ... 66 | Cache-Control: max-age=600, private 67 | Content-Type: text/json; charset=utf-8 68 | ETag: "2147483648" 69 | Content-Length: ... 70 | { "id": "BE14A7269802498F992813885546D058", "name": "Mustermann" } 71 | 72 | The client constructs a GET request containing the `ETag` for the currently cached version of the resource referenced 73 | in an `If-None-Match` HTTP header: 74 | 75 | GET /user_management/v1/users/BE14A7269802498F992813885546D058 76 | If-None-Match: "2147483648" 77 | 78 | ##### ETag matches 79 | 80 | Return an HTTP response with an empty message body and a status code of `304 Not Modified`. 81 | 82 | ##### ETag does not match 83 | 84 | The data has changed and the web API should return an HTTP response with the new data in the message body and a status code of `200 OK`. 85 | 86 | ### Further reading 87 | 88 | Find below a list of great articles on the topic **Caching** 89 | 90 | [https://www.mnot.net/cache_docs/](https://www.mnot.net/cache_docs/) 91 | [http://restcookbook.com/Basics/caching/](http://restcookbook.com/Basics/caching/) 92 | [http://odino.org/rest-better-http-cache/](http://odino.org/rest-better-http-cache/) 93 | [https://www.subbu.org/blog/2005/01/http-Caching](https://www.subbu.org/blog/2005/01/http-Caching) 94 | 95 | Resources for implementation 96 | [https://github.com/mspnp/azure-guidance/blob/master/API-Implementation.md#considerations-for-optimizing-client-side-data-access](https://github.com/mspnp/azure-guidance/blob/master/API-Implementation.md#considerations-for-optimizing-client-side-data-access) 97 | 98 | 99 | > :bulb: Please give us Feedback which Caching strategy you chose and your experieneces. 100 | -------------------------------------------------------------------------------- /error-handling/error-handling.md: -------------------------------------------------------------------------------- 1 | ## Error handling 2 | 3 | Just like an HTML error page shows a useful error message to a visitor, an API should provide a useful error message in a known consumable format. The representation of an error should be no different than the representation of any resource, just with its own set of fields. 4 | 5 | The API should always return sensible HTTP status codes. API errors typically break down into 2 types: `4xx` series status codes for client issues & `5xx` series status codes for server issues. At a minimum, the API should standardize that all `4xx` series errors come with consumable JSON error representation. If possible (i.e. if load balancers & reverse proxies can create custom error bodies), this should extend to `5xx` series status codes. 6 | 7 | A JSON error body should provide a few things for the developer - a useful error message, a unique error type (that can be looked up for more details in the docs), possibly a detailed description, and an optional instance identifier that makes it possible to refer to this particular occurrence of the problem. (Typically, the instance identifier enables the service operators to look up the internal service logs that were written when the problem was detetcted.) Examples of JSON output representation for something like this would look like: 8 | 9 | { 10 | "code": 1234, 11 | "message": "Something bad happened :(", 12 | "description": "More details about the error here", 13 | "logref": "7673868d-231e-490d-9c4f-19288e7e668d" 14 | } 15 | 16 | or 17 | 18 | { 19 | "type": "http://your.service.namespace/error/types/3245", 20 | "message": "Something bad happened :(", 21 | "description": "More details about the error here", 22 | "instance": "urn:uuid:7673868d-231e-490d-9c4f-19288e7e668d" 23 | } 24 | 25 | 26 | Validation errors for PUT, PATCH and POST requests will need a field breakdown. This is best modeled by using a fixed top-level error code for validation failures and providing the detailed errors in an additional errors field, like so: 27 | 28 | { 29 | "code": 1024, 30 | "message": "Validation Failed", 31 | "errors": 32 | [ 33 | { 34 | "code": 5432, 35 | "field": "first_name", 36 | "message": "First name cannot have fancy characters" 37 | }, 38 | { 39 | "code": 5622, 40 | "field": "password", 41 | "message": "Password cannot be blank" 42 | } 43 | ], 44 | "logref": "7673868d-231e-490d-9c4f-19288e7e668d" 45 | } 46 | 47 | or 48 | 49 | { 50 | "type": "http://your.service.namespace/error/types/1024", 51 | "message": "Validation Failed", 52 | "errors": 53 | [ 54 | { 55 | "type": "http://your.service.namespace/error/types/5432", 56 | "field": "first_name", 57 | "message": "First name cannot have fancy characters" 58 | }, 59 | { 60 | "type": "http://your.service.namespace/error/types/5622", 61 | "field": "password", 62 | "message": "Password cannot be blank" 63 | } 64 | ] 65 | "instance": "urn:uuid:7673868d-231e-490d-9c4f-19288e7e668d" 66 | } 67 | 68 | > :information_source: Thanks to Vinay Sahni for this description http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api#errors. 69 | 70 | ### Error Response Format 71 | 72 | The examples given above implement different [Hypermedia error response formats](http://nocarrier.co.uk/the-error-hypermedia-type/): 73 | 74 | * [vnd.error draft](https://github.com/blongden/vnd.error) 75 | * [RFC 7807](https://tools.ietf.org/html/rfc7807): Problem Details for HTTP APIs 76 | 77 | The latter has the advantage (besides not being a draft anymore) that it defines an equivalent content type for XML-based APIs. 78 | 79 | Be aware that for security sensitive APIs like User Management the need to return meaningful errors is always in tension with not returning too much information to guide a potential attacker. Dictionary attacks can be devastatingly effective, if for instance the exact makeup of the password policy is revealed in the response. 80 | 81 | At the same time, nothing is more frustrating for a customer to try to create a matching password without knowing the password constrains. This is why in general one would only show the password policy during initial setup and during password change, but not in response to login failures. During login you would never distinguish between a wrong username or a right username and a wrong password. Both should return the exact same error as to not allow a more targeted attack. (Note: This is why there is usually only a single link to cover both forgotten passwords and usernames). 82 | 83 | When using either of the above mentioned error formats [vnd.error](https://github.com/blongden/vnd.error) or [RFC 7807](https://tools.ietf.org/html/rfc7807), we can indicate an error and provide a ‘help’ link with a human-readable description of the error. A client (with the appropriate sensibility to the security issues I describe above) can then decide to render the help link oder omit it. In this way the error description is decoupled from the actual client. Changes to the underlying business logic (ie. password policy) and corresponding human readable error descripton are entirely contained within the API provider without impacting any existing API clients. 84 | -------------------------------------------------------------------------------- /rest-principles/rest-principles.md: -------------------------------------------------------------------------------- 1 | ### Support Hypermedia 2 | 3 | All our REST APIs MUST support hypermedia. Refer to [Hypermedia and REST](../hypermedia-and-rest/hypermedia-and-rest.md) for a detailed explanation. 4 | > Our prefered way for hypermedia support is [HAL](http://stateless.co/hal_specification.html). Other formats like Atom are also a valid choice. It is strongly recommended that the URLs generated by the API should be absolute URLs. 5 | 6 | You can find more details about hypermedia formats in [Hypermedia Response Formats](../response-format/response-format.md). 7 | 8 | ### Use RESTful URLs and actions 9 | 10 | Separate your API in logical [resources](../resources/resources.md). 11 | 12 | There should be two base URIs per resource. The first URL is for a collection 13 | 14 | /products 15 | 16 | The second is for a specific element in the collection. 17 | 18 | /products/1234 19 | 20 | Use [HTTP verbs](../http-verbs/http-verbs.md) to operate on resources. 21 | Use [Sub-Resources](../relationships-and-sub-resources/relationships-and-sub-resources.md) for relations. 22 | Refer to [Collection Resources](../collection-resources/collection-resources.md) for more details. 23 | 24 | ### Nouns are good - Verbs are bad 25 | 26 | **Use Nouns not Verbs** when defining the API. The best is to have them in **plural form** because in most of the cases it returns a list or a couple of elements, not just one. 27 | 28 | ### Use HTTP verbs to operate on the collections and elements 29 | 30 | Use the [HTTP verbs](../http-verbs/http-verbs.md) `POST`, `GET`, `PUT`, and `DELETE`. 31 | Think of them as mapping to the acronym, CRUD (Create-Read-Update-Delete). 32 | 33 | ### Plural nouns and concrete names 34 | 35 | Given that the first thing most people probably do with a RESTful API is a GET, we think it reads more easily and is more intuitive to **use plural nouns**. 36 | 37 | Think about an API that exposes *employees*, *customers* and *suppliers*. An API that models everything at the highest level of abstraction and uses `/parties` is not intuitive. Developers do not understand how to use the API. It is more compelling and useful to see the resources listed as `/employees`, `/customers`, and `/suppliers`. 38 | 39 | The level of abstraction depends on your scenario. You also want to expose a manageable number of resources. Aim for **concrete naming** and to keep the number of resources between 12 and 24. 40 | 41 | ### Use sub-resources for Relations 42 | 43 | Use sub-resources for related resources. Limit the nesting to **one** sub-resource. 44 | 45 | Refer to [Relationships and Sub-Resources](../relationships-and-sub-resources/relationships-and-sub-resources.md) for details. 46 | 47 | ### Resource naming 48 | 49 | Should you use hyphens, underscores, or camelCase to delimit words in the URIs? 50 | 51 | There are many, many different articles and opinions about that. Finally we decided to go with underscores. This applies to URIs, field names, hypermedia labels and any other meta elements included in the response. 52 | 53 | > **Use underscores.** 54 | > **Do not use acronyms.** 55 | > **Use small caps.** 56 | 57 | The following link led us to our reasoning. [https://whathecode.wordpress.com/2011/02/10/camelcase-vs-underscores-scientific-showdown/](https://whathecode.wordpress.com/2011/02/10/camelcase-vs-underscores-scientific-showdown/). 58 | 59 | ### Version the API 60 | 61 | The URI should include `/vN/` with the major version (N) as a prefix. No major.minor syntax. 62 | 63 | > In general do **NOT** increment the version of your API. Until you must. And it is really rare that you really must. Only increment on breaking changes. Extending the API is **not** a breaking change. 64 | 65 | Refer to [URI components](../uri-components/uri-components.md) for details. See [Message Schema](../message-schema/message-schema.md) for a discussion of designing extensible message schemas. 66 | 67 | ### Protect your API 68 | 69 | You MUST protect your API. 70 | 71 | > Use appropriate standards for Authentication and Authorization. Use SSL everywhere - all the time 72 | 73 | Refer to [Security and Authentication](../security-and-authentication/security-and-authentication.md) for details. 74 | 75 | ### Provide descriptive errors codes and messages 76 | 77 | Use [HTTP status codes](../http-status-codes/http-status-codes.md). 78 | 79 | > Provide useful error message in a known consumable format 80 | 81 | Refer to [Error handling](../error-handling/error-handling.md) for details. 82 | 83 | ### Facilitate caching 84 | 85 | There are some reasons why you have to consider to use Caching 86 | 87 | - improve speed 88 | - reduce latency 89 | - reduce server load 90 | - reduce network traffic 91 | 92 | Refer to [Caching](../caching/caching.md) for details. 93 | 94 | ### Be consistent 95 | 96 | Being consistent allows developers to predict and guess the method calls as they learn to work with your API. Being consistent also means that someone working with your API will be able to work with all of our APIs. 97 | 98 | ### Things to avoid 99 | 100 | - Do **not** query args on an non-query/non-search resource. e.g. use `/conversations/conversation-12` over `/conversations/conversation.php?conversation_id=12` 101 | - Do **not** use mixed or upper-case in URIs. 102 | - Avoid extensions (avoid `.en` or `.fr`; avoid `.html` or `.htm` or `.php` or `.jsp`; avoid `.xml` or `.json`). 103 | - Do **not** use characters that require url encoding in URIs (e.g. spaces). 104 | -------------------------------------------------------------------------------- /api-design-review-process/api-design-review-process.md: -------------------------------------------------------------------------------- 1 | ## API Design Review Process 2 | 3 | ### Why 4 | We believe in APIs and in the API Economy. We are just at the beginning of our journey to an API driven company. There is no clear roadmap how to reach our goal. For sure it will be ways in which we stumble, sometimes fail but hopefully succeed in the end. 5 | 6 | There will be pros and cons how to handle and apply the style guide to real projects. There are many things to learn and to share with another. We have to keep improving the style guide, review process, and tools to capture our evolving knowledge and experience. 7 | 8 | To formalize the learning process we decided to establish the **API Design Review Process**. Each new or refactored API MUST be reviewed through this process. 9 | 10 | ### Feedback 11 | We have now done a couple of API design reviews. Please give us feedback how we can improve this process! 12 | 13 | ### Review process 14 | 15 | #### Who is responsible for scheduling the review? 16 | A representative of the project team that creates the service MUST contact the CTO office. In most cases the representative is the API designer/architect. 17 | 18 | #### How to plan the review? 19 | It is the responsibility of the team to plan their resources for the API review and to talk with the team leaders of CTO office to organize reviewers. Together they decide on the appropriate time box for the review. 20 | 21 | #### Tooling 22 | Currently we use a **private GitHub repo** for each API review. 23 | The `README.md` should contain the following informations: 24 | 25 | - Purpose of the API 26 | - Links to the API description 27 | - Start date of the review 28 | - End date of the review 29 | - Mandatory reviewers including state 30 | - State of the review itself 31 | - Conclusion 32 | 33 | #### API description 34 | It is necessary to provide a formal description of the API to review it. 35 | The API designer has to provide a Swagger description (prefered) or an equivalent description. Providing a running system or a mock to work with the API is highly appreciated. 36 | 37 | #### Reviewing the API 38 | It is up to the API designer and reviewer how to perform the review. It is a good idea to schedule a meeting and step through the API and talk with the reviewers about the functionality and intention. That's a good way to cut down review times because questions and missunderstandings can be solved immediately. Others prefer to review the API without a formal meeting. 39 | 40 | Changes requests are stored as issues in the GitHub repo. 41 | Each reviewer has to update his personal review state in GitHub. 42 | 43 | #### Mandatory vs optional reviewers 44 | During the review planning at least two reviewers will be fixed. 45 | The mandatory reviewers are explicitly named in the GitHub review repo. 46 | 47 | Each review is open for feedback from a wide group of other people. 48 | That includes all interested architects, team members, and clients that will use the API. The CTO office informs - per default - all architects on pending reviews. The team is free to add optional reviewers of its own. 49 | 50 | #### How issues should be raised and addressed 51 | We use the GitHub issue mechanism for a transparent communication during the review. Each issue must be categorized as follows: 52 | 53 | - Must change: Must be changed in the API design and implementation 54 | - Improvement: Should be changed. Depends on the team 55 | - Question: For Questions/Discussions and clarifications 56 | 57 | Please use Github labels for the classification. 58 | 59 | #### Time boxed reviews 60 | The review is time boxed. It starts at a given date and - more importantly - it ends at a predefined date. The outcome of the review is documented in the GitHub repo `README.md`. 61 | 62 | #### When is an API reviewed and can be implemented? 63 | After finishing the API review there will be some change requests for the API. 64 | Most of them might be easy to fix/change and the API designer should do that immediately during and after the review. Other changes may need more effort and planning how to address them. 65 | 66 | The next steps and the the conclusion how to proceed with the change requests is written down in the **conclusion** section of the GitHub repo `README.md`. 67 | The implementation can start after finishig the review. 68 | 69 | #### Learnings from the review and feedback to the style guide 70 | After each review the API designer/team should provide a feedback issue in the 71 | API style guide project and mark it with the label **feedback**. 72 | The feedback has to cover at least the topics 73 | 74 | - How helpful was the API style guide for your design process? 75 | - Which sections especially? 76 | - What did you learn for future API designs? 77 | - How to improve the style guide itself? 78 | - Which information do you miss? 79 | - Which guideline do you not agree with? 80 | - How to improve the API review process itself? 81 | - What can we improve regarding tooling, planning etc. 82 | 83 | #### How to measure success for the API review 84 | There are two goals in an API review 85 | 86 | ##### Improve the API itself 87 | It's not that easy to measure the improvement of the API. It is best to look at it from a client perspective. How costly (in time and effort) is the programming against the API for a developer? Can you quantify it and imporve on the KPI? 88 | 89 | ##### Learn to design APIs 90 | This is even harder to measure than the one above. If you can think of a good way to measure our ability to continously improve our API Deisgn skills and processes, we would love to hear it. 91 | -------------------------------------------------------------------------------- /further-reading/further-reading.md: -------------------------------------------------------------------------------- 1 | ## Blogs and Websites 2 | 3 | * [API Evangelist](https://apievangelist.com/blog/) - blog 4 | * [Nordic APIs](http://nordicapis.com/blog/) - blog 5 | * [API Academy](http://www.apiacademy.co/#) - blog 6 | * [API Stylebook](http://apistylebook.com) - aggregator 7 | * [Launchany](http://launchany.com/articles/) - blog 8 | * [Mike Ammundsen - Talks](http://mamund.site44.com/talks/) - presentations 9 | * [James Higginbotham - API Developer Weekly](http://launchany.com/subscribe/) - weekly email 10 | 11 | ## Conferences 12 | 13 | * [API Strategy and Practice](http://apistrat.com) 14 | * [Nordic API Summits](http://nordicapis.com) 15 | * [API Days](http://www.apidays.io) 16 | * [API World](http://apiworld.co/conference/schedule/) 17 | * [Restfest](http://www.restfest.org) (unconference organized by [Mike Ammundsen](https://twitter.com/mamund) and [Benjamin Young](https://twitter.com/bigbluehat)) 18 | * [I love APIs](http://iloveapis.com) (from Apigee) 19 | * [API360](http://www.apiacademy.co/api360/) (from CA, formerly Layer 7) 20 | 21 | ## Books 22 | 23 | * [A Practical Approach to API Design](https://leanpub.com/restful-api-design) - one of the best books on API design 24 | * [Microservice Architecture](http://shop.oreilly.com/product/0636920050308.do) - putting APIs into the Microservice context (complementary copy from CA [here](http://transform.ca.com/API-microservice-architecture-oreilly-book.html)) 25 | * [APIs: A Strategy Guide](http://shop.oreilly.com/product/0636920021223.do) - best intro to API strategy 26 | * [RESTful Web APIs](http://shop.oreilly.com/product/0636920028468.do) - good and practical intro to Hypermedia with examples 27 | * [The REST API Design Handbook](https://www.amazon.com/REST-API-Design-Handbook-ebook/dp/B00890OBFI) - very opinionated, but good API design practices 28 | * [RESTful Web Services Cookbook](http://shop.oreilly.com/product/9780596801694.do) 29 | * [REST API Design Rulebook](http://shop.oreilly.com/product/0636920021575.do) 30 | * [API Owner Manual](http://pages.3scale.net/rs/516-GHI-083/images/api-owners-manual.pdf) (from 3Scale, free PDF) 31 | * [API-driven DevOps](http://nordicapis.com/wp-content/uploads/api-driven-devops.pdf) (from Nordic APIs, free PDF) 32 | * [An introduction to APIs](https://zapier.com/learn/apis/) (from Zapier, free PDF) 33 | * [Getting Started with OAuth 2.0](http://shop.oreilly.com/product/0636920021810.do) - Good intro to OAuth concept 34 | * [API Design on the scale fo decades](http://nordicapis.com/api-ebooks/api-design-on-the-scale-of-decades/) (from Nordic API, free PDF) 35 | 36 | ## Learning Journeys 37 | 38 | * Paypal's API Journey: 39 | * In [Part 1](https://www.infoq.com/articles/paypal-api-first-part1) we talk about how implementing an API-first transformation in a large organization is as much a people problem as a technical one, 40 | * In [Part 2](https://www.infoq.com/articles/paypal-api-first-part2), we’ll go into how we used this infrastructure to help shape the API portfolio itself. A main goal of which was to establish clear boundaries between APIs that encourage decomposition of the monolith in a predictable, useful way., 41 | * In [Part 3](https://www.infoq.com/articles/paypal-api-first-part3), we’ll explore the importance of program management to align the organization, market the concept, provide training, and create various incentives that encourage adoption: 42 | 43 | ## Further Reading 44 | 45 | Additional information and guidance can be found in the following: 46 | 47 | * [https://pages.apigee.com/rs/apigee/images/api-design-ebook-2012-03.pdf](https://pages.apigee.com/rs/apigee/images/api-design-ebook-2012-03.pdf) 48 | * [https://github.com/restfulapi/api-strategy](https://github.com/restfulapi/api-strategy) 49 | * [https://apigility.org/documentation/api-primer/halprimer](https://apigility.org/documentation/api-primer/halprimer) 50 | * [http://restful-api-design.readthedocs.org/en/latest/scope.html](http://restful-api-design.readthedocs.org/en/latest/scope.html) 51 | * [http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven](http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven) 52 | * [http://www.infoq.com/articles/hypermedia-api-tutorial-part-one](http://www.infoq.com/articles/hypermedia-api-tutorial-part-one) 53 | * [http://codeplanet.io/principles-good-restful-api-design/](http://codeplanet.io/principles-good-restful-api-design/) 54 | * [http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api](http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api) 55 | * [http://jsonapi.org/](http://jsonapi.org/) 56 | * [http://micheltriana.com/2013/09/30/http-verbs-in-a-rest-web-api/](http://micheltriana.com/2013/09/30/http-verbs-in-a-rest-web-api/) 57 | * [https://github.com/WhiteHouse/api-Standards](https://github.com/WhiteHouse/api-Standards) 58 | * [http://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/](http://blog.mwaysolutions.com/2014/06/05/10-best-practices-for-better-restful-api/) 59 | * [http://blog.smartbear.com/readyapi/hypermedia-and-state-machines-restfest-2014/](http://blog.smartbear.com/readyapi/hypermedia-and-state-machines-restfest-2014/) 60 | * [http://sookocheff.com/posts/2014-03-11-on-choosing-a-hypermedia-format/](http://sookocheff.com/posts/2014-03-11-on-choosing-a-hypermedia-format/) 61 | * [https://tools.ietf.org/html/rfc7386](https://tools.ietf.org/html/rfc7386) 62 | * [http://rawgit.com/uber-hypermedia/specification/master/uber-hypermedia.html](http://rawgit.com/uber-hypermedia/specification/master/uber-hypermedia.html) 63 | * [https://github.com/NationalBankBelgium/REST-API-Design-Guide](https://github.com/NationalBankBelgium/REST-API-Design-Guide) 64 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /api-design-process/api-design-process.md: -------------------------------------------------------------------------------- 1 | ## API Modelling and Design Process 2 | 3 | The following API Modelling Process has been excerpted from chapter 4 and chapter 6 of [A Practical Approach to API Design](https://leanpub.com/restful-api-design) by D. Keith Casey Jr and James Higginbotham. (**This is just a brief summary for educational purpose - please consider buying the book to support their excellent work**) 4 | 5 | ### API Modelling Process 6 | API modeling consists of 5 activities that help identify the requirements of your API design: 1. Identify the participants, or actors, that will interact with your API 2. Identify the activities that participants wish to achieve 3. Separate the activities into steps that the participants will perform 4. Create a list of API methods from the steps, grouped into common resource groups 5. Validate the API by using scenarios to test the completeness of the API The goal of each step is to explore the requirements of the API from a variety of different perspectives: those involved (the participants), what they want to do (the activities), and how they will complete an activity (the steps). The modeling process will be iterative, so it should be expected that each modeling activity may require that you revisit the previous step as previously hidden details are exposed. 7 | ### API Design Process 8 | As you move from the modeling to the design phase, you will be faced with a variety of decisions. Some of these will resolve easily, while others will take time and deliberation. Just know that it is difficult to get your API design right the first time. This is why we encourage you to spend time designing and prototyping your API before you start implementing it. 9 | 10 | #### Building Your Resource Taxonomy 11 | To get started building your taxonomy, make a list of the resources you have modeled already. These are often identified as the nouns in your system. Keep in mind that some resources may belong as a child collection of another resource. 12 | 13 | #### How to Handle Resource Relationships and Composition 14 | Resources often contain child resources or reference other resources. In these cases, the API design must ensure that one can interact with the top-level resource as well as nested and related resources. To better design our API, we need to understand the three types of resource relationships: 15 | Relationship | Description --------------|------------- 16 | Independent | The resources exist stand alone without the other’s existence, but may reference each other 17 | Dependent | One resource cannot exist without the existence of the parent resource 18 | Associative | The resources exist independently, however their relationship contains or requires additional properties to describe it 19 | How you design your API around related resources can be determined based on a few questions. The answers to these questions will determine if your resources are independent, dependent, or associative: 20 | 1. Can both resources exist without the other? Then we have an ***Independent*** resource 2. Does one resource exist only when the other exists? Then we have a ***Dependent*** resource 3. Does the relationship between resources require more state than just the links between them? Then we have an ***Associative*** resource 21 | #### Defining Resource Lifecycles Once we have identified our RESTful API resources, it is time to start mapping them to our HTTP verbs. During the API Modelling Process, we were able to capture most activities using a specific list of actions: “list”, “clear”, “view”, etc. Depending on the verbs you commonly use during modeling, you will likely find that certain ones can be mapped directly to REST patterns. #### Mapping Response Codes For Success and Failure 22 | Please see [HTTP Status Codes](../http-status-codes/http-status-codes.md) for a more in depth discussion. #### Expanding Resources Through Hypermedia Linking As you move from resource identification, it is time to explore the links (relationships) each resource will provide. Resource links are just like links within a web page - they describe the options available for navigation. Links may be used for a variety of reasons: 23 | 1. To inform clients about the actions available given the resource’s current state 2. Provide hints to actions that are authorized for the current user 24 | 3. Allow clients to explore resource relationships 25 | 26 | The following is a quick summary of Hypermedia Linking 27 | 28 | * ***Link Thyself***: Every resource should define a link to itself. While this seems to be redundant, or perhaps wasteful, there is a valid reason for returning a link to a returned resource: clients should never have to track the link that returned a resource separate from the resource representation itself. 29 | * ***Resource State Linking***: Look for any constraints and state transitions that a resource may require. These constraints should be surfaced as links, offering insight into what actions are allowed and not allowed given the current state of a resource. 30 | * ***Relationship Linking***: Resources should include links to a parent resource, children, or related resources as identified during the previous taxonomy step. 31 | * ***Additional Navigation Links***: Most commonly used for collection responses, where you may need to offer pagination links for next and previous pages, and for navigation to other areas of the API. 32 | 33 | Please see [Hypermedia and Rest](../hypermedia-and-rest/hypermedia-and-rest.md) for a more in depth discussion of Hypermedia. 34 | 35 | --- 36 | 37 | A good reference book for APIs and API Design is the afore mentioned [A Practical Approach to API Design](https://leanpub.com/restful-api-design) by D. Keith Casey Jr and James Higginbotham. 38 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Haufe API style guide 2 | 3 | ### Purpose 4 | --- 5 | Great RESTful APIs look like they were designed by a single team. This promotes API adoption, reduces friction, and enables clients to use them properly. To build APIs that meet this standard, and to answer many common questions encountered along the way of RESTful API development, the Haufe-Lexware CTO team has created this comprehensive set of guidelines. We have shared it with you to inspire additional discussion and refinement within and among your teams, and contribute our learnings and suggestions to the tech community at large. 6 | 7 | 8 | ### Usage 9 | --- 10 | The API style guide MUST be used when you create an API, refactor or extend an API, no exeptions. Existing APIs might be subject to adapt if there is business value in it. 11 | 12 | It is the responsibility of the person implementing the API to apply the API Styleguide to a specific API and project! 13 | 14 | > Please follow the guidelines, but don't follow blindly! 15 | > You can break the rules by talking to us and providing justification. 16 | 17 | The style guide is work in progress. We’d love your feedback – whether you agree, disagree, or have some additional practices and tips to add. 18 | 19 | We encourage you to improve the style guide with modifications and extensions via the usual Fork/Pull Request dance. If your modification gets merged, it becomes part of the Styleguide. On the other hand if you don't bother, don't complain. 20 | 21 | ### API Design Review Process 22 | --- 23 | We are still at the beginning of our journey to an API driven company. 24 | 25 | There will be pros and cons how to handle and apply the style guide to real projects. There are many things to learn and to share with another. Feel free to reach out and ask and share on the `#apistrat` channel on our Haufe RocketChat. 26 | 27 | The [API Design Review Process](api-design-review-process/api-design-review-process.md) is **mandatory** for each new or refactored API at Haufe-Lexware. 28 | 29 | ### Content 30 | --- 31 | 32 | #### Most important chapters 33 | Please read the bold chapters beow. These chapters describe the intent, mindset and process how we want to design an API. 34 | 35 | Each section contains links to the chapters with more details. 36 | 37 | #### Table of Content 38 | The chapters are: 39 | 40 | - **[Introduction](introduction/introduction.md)** 41 | - **[General Guidlines](general-guidelines/general-guidelines.md)** 42 | - **[API Design Principles](api-design-principles/api-design-principles.md)** 43 | - **[API Design Process](api-design-process/api-design-process.md)** 44 | - **[API Design Review Process](api-design-review-process/api-design-review-process.md)** 45 | - **[REST Principles](rest-principles/rest-principles.md)** 46 | - [URI Components and Versioning](uri-components/uri-components.md) 47 | - [HTTP Verbs](http-verbs/http-verbs.md) 48 | - [Hypermedia and REST](hypermedia-and-rest/hypermedia-and-rest.md) 49 | - [Resources](resources/resources.md) 50 | - [Relationships and Sub-Resources](relationships-and-sub-resources/relationships-and-sub-resources.md) 51 | - [Collection Resources](collection-resources/collection-resources.md) 52 | - [Resource naming](collection-resources/collection-resources.md#resource-naming) 53 | - [Get List of resources](collection-resources/collection-resources.md#get-list-of-resources) 54 | - [Read Single Resource](collection-resources/collection-resources.md#read-single-resources) 55 | - [Update Single Ressource](collection-resources/collection-resources.md#update-single-ressource) 56 | - [Update Partial Single Resource](collection-resources/collection-resources.md#update-partial-single-resource) 57 | - [Delete Single Resource](collection-resources/collection-resources.md#delete-single-resource) 58 | - [Create New Resource](collection-resources/collection-resources.md#create-new-resource) 59 | - [Create New Resource - Consumer Supplied Identifier](collection-resources/collection-resources.md#create-new-resource---consumer-supplied-identifier) 60 | - [Filtering, sorting, field selection and paging](filtering-sorting-field-selection-and-paging/filtering-sorting-field-selection-and-paging.md) 61 | - [Hypermedia Response Format](response-format/response-format.md) 62 | - [Type Formatting](type-formatting/type-formatting.md) 63 | - [Message Schema and Postels Law](message-schema/message-schema.md) 64 | - [Security and Authentication](security-and-authentication/security-and-authentication.md) 65 | - [Search](search/search.md) 66 | - [Documentation](documentation/documentation.md) 67 | - [Error handling](error-handling/error-handling.md) 68 | - [HTTP Status Codes](http-status-codes/http-status-codes.md) 69 | - [Caching](caching/caching.md) 70 | - [Correlation-Id](correlation-id/correlation-id.md) 71 | - [API Management](api-management/api-management.md) 72 | - [FAQ](faq/faq.md) 73 | - [Further Reading](further-reading/further-reading.md) 74 | 75 | ### Credits 76 | --- 77 | 78 | For the creation of the style guide I took a lot of input from other authors and even copied whole passages. 79 | 80 | I want to gratefully thank these authors and hope that I marked the relevant passages. My resources are listed under [Further Reading](further-reading.md). Special thanks goes to 81 | 82 | [S.Stedman and G. Laforge from Paypal](https://github.com/paypal/api-standards/blob/master/api-style-guide.md) 83 | [Brian Mulloy](https://pages.apigee.com/rs/apigee/images/api-design-ebook-2012-03.pdf) 84 | [Geert Jansen](http://restful-api-design.readthedocs.org/en/latest/intro.html) 85 | [Vinay Sahni](http://www.vinaysahni.com/) 86 | [Michel Triana](http://micheltriana.com/2013/09/30/http-verbs-in-a-rest-web-api/) 87 | [Stefan Jauker](http://blog.mwaysolutions.com/author/stefan-jauker/) 88 | 89 | Another great inspiration were [Zalando's Restful API Guidelines](http://zalando.github.io/restful-api-guidelines/). 90 | 91 | -------------------------------------------------------------------------------- /message-schema/message-schema.md: -------------------------------------------------------------------------------- 1 | ## Resource Schema and Postel's Law 2 | 3 | One of the key best practices for creating robust services is embodied in the so called [Postels Law (or Robustness Principle)](https://en.wikipedia.org/wiki/Robustness_principle). It states that any protocol implementation should 4 | 5 | > be conservative in what you send, be liberal in what you accept. 6 | 7 | It focuses on the idea of gracefully adapting to communication that doesn't conform to the agreed specification/contract. It is important to notice though that it only talks about accepting potential misformed but otherwise sensible messages. It does not talk about if and how it should be processed (i.e. deliberately ignoring unknown fields or values is one valid approach). 8 | 9 | The ability to extend service definitions after the initial release without affecting already deployed clients is key to preserve agility and evolvability of those services. Well designed message schemas play a key part in either enabling or hindering a development team in evolving the service in the future. 10 | 11 | Unfortunately message schemas tend to be used for two different purposes at the same time. 12 | 13 | 1. for message-level security 14 | 2. as message-level contract 15 | 16 | Designing a schema for (1) results in strongly typed message structures, while designing it for (2) leads to the use of schema for auto-generated client code. 17 | 18 | The result is a service client, which is too strict to be extensible without providing the security we desire. If we were concerned about security, we would never use generated code but always curate the client. If we were concerned about extensibility, we would indicate the presence of a field without wanting to be pinned down on a particular type for eternity. 19 | 20 | The fallacy of Web Services was, that it promised *both* in one convenient package and resulted in the creation of tightly coupled systems out of convenience. 21 | 22 | If you use a schema to design the message contract, write the schema in such a way, that you enable extensibility and robustness. If you design it for message security, manually curate your client and do not auto-generate it. 23 | 24 | API design is one of the places, where a developer needs to be aware of the tradeoffs. We are inclined towards strongly typed schemas either for convenience (hey, I get the right code generated) or for security (an integer should never be a string) or a combination of both. It feels good to have our cake and eat it too. But what we loose is the ability to evolve the service contract after going live. 25 | 26 | This is why we should focus on creating a ‘good enough’ schema tailored for robust and evolvable message contracts, and not try to use it for security. Such a schema should have greatly relaxed constraints with deliberate extension points for possible later changes without impacting existing clients. 27 | 28 | As API designers, we should create a contract with our users (the client developer) as follows: 29 | 30 | 1. If you send me a message that looks like `{X}` I will provide you with a response that has a defined structure. This will always be true as long as I am available. 31 | 2. I promise **not** to change the location of the data you need within this structure. You can depend on that data existing in the location you see today, as long as this API version exists. 32 | 3. I promise **not** to change what these pieces of data mean. 33 | 4. You promise to ignore any data I provide that you did not expect. 34 | 35 | It is this 4th point, that is the important bit for client developers. It means that client apps must parse/serialize/marshall data in a way, that does not create a dependancy on messages with a static data structure. 36 | 37 | It is easy to sell this type of extensibility to client developers, when they work with weakly typed languages like JavaScript. However, it can be more difficult when our applications are written in languages like C# or Java. This may require more guidance and support. For example, explicit instructions on best practices for parsing might be required: don't use explicit parsing, use these specific options for Saxon/JAXB/whatever... 38 | 39 | The payoff for client application developers should be clear. Following your guidelines for extensilbity should create less work for them. If that isn't the case, then you will need to reconsider the cost-benefit for your particular application. In the same vein, if the cost of changing client applications is very low, evolvability is not an important architectural quality. 40 | 41 | Practical guidelines for robust and evolvable message schemas are 42 | 43 | * No type definitions with restriction on character sets or regular expressions. 44 | * Choose string over integer for elements like IDs that are likely to change its type. 45 | * Avoid type definitions with enumerations. 46 | * No upper bounds for lists. 47 | * All elements are optional. 48 | 49 | The following documentation might need to be added to the schema 50 | 51 | * To indicate which elements are usually part of a sensible message (formerly mandatory elements) 52 | * Semantics of the elements (we need this anyway as no formal syntax can convey the meaning) 53 | * To tell the client developers to prepare for additional elements or additional attributes 54 | 55 | From an implementation point of view, this might require the following 56 | 57 | * Input validation on the server side for character sets 58 | * Input validation for content that may open doors for SQL injections etc. 59 | * A protection against XML DOS attacks 60 | 61 | Auto-generating client and server side code might be permissable for as long as the following rules are met: 62 | 63 | * There is no direct marshalling/unmarshalling of the actual business entity but of a data transfer object. 64 | * It is assured that the code does not break, when new elements or attributes are added to the schema. 65 | 66 | Please note though that there might be benefits in allowing code-generation of some types like `xsd:date` for example. 67 | 68 | To address security, we need to consider both confidentiality of the message exchange and authentication of the message enpoints. The former will almost always be provided by TLS and the latter through certificate validation and/or token-based authentication like OAuth2. More details can be found in [Security and Authentication](../security-and-authentication/security-and-authentication.md). 69 | -------------------------------------------------------------------------------- /response-format/response-format.md: -------------------------------------------------------------------------------- 1 | ## Hypermedia Response Format 2 | > Use existing standard formats like JSON, ATOM, Collection-JSON, HAL (both JSON and XML) etc. over home made formats. 3 | 4 | The list here represents only a subset of possible formats. Refer to [On Choosing a Hypermedia Format](http://sookocheff.com/post/api/on-choosing-a-hypermedia-format/) for a more detailed overview of Hypermedia Formats. 5 | 6 | Regardless of your choice all formats need to support link relation elements. 7 | 8 | * Use **IANA** defined link relation attribute values by default - you can find the list of supported values [here](http://www.iana.org/assignments/link-relations/link-relations.xhtml). 9 | * if new link relation attributes are required, register them with IANA (alternative or fallback is the canonicalized list maintained by Haufe CTO Office). Please contact the CTO Office for the latter. 10 | 11 | A response SHOULD return related and valid link elements, and MUST return a link element to **self**. 12 | 13 | An API client should not hardcode any resource URL or make assumptions about an existing URL. Instead URL’s should be derived from link elements via the appropriate link relation Attribute. 14 | 15 | [Here](https://en.wikipedia.org/wiki/Internet_media_type) you can find a list of Content types. 16 | 17 | > Our prefered way for hypermedia support is HAL. Other formats like Atom are also a valid choice. It is strongly recommended that the URLs generated by the API should be absolute URLs. 18 | 19 | 20 | ###HAL – Hypermedia Application Language 21 | 22 | It has custom content and profile media type, the description of the data. 23 | 24 | The content types are: 25 | 26 | application/hal+json 27 | application/hal+xml 28 | 29 | More about it in their official [website](http://stateless.co/hal_specification.html). 30 | 31 | This is the desciption from the Website http://stateless.co/hal_specification.html. 32 | 33 | HAL provides a set of conventions for expressing hyperlinks in either JSON or XML. 34 | 35 | **The rest of a HAL document is just plain old JSON or XML with optional embedded resources** 36 | 37 | Instead of using ad-hoc structures - or spending valuable time designing your own format - you can adopt HAL's conventions and focus on building and documenting the data and transitions that make up your API. 38 | 39 | HAL is a little bit like HTML for machines, in that it is generic and designed to drive many different types of application via hyperlinks. The difference is that HTML has features for helping 'human actors' move through a web application to achieve their goals, whereas HAL is intended for helping 'automated actors' move through a web API to achieve their goals. 40 | 41 | Having said that, **HAL is actually very human-friendly too**. Its conventions make the documentation for an API discoverable from the API messages themselves. This makes it possible for developers to jump straight into a HAL-based API and explore its capabilities, without the cognitive overhead of having to map some out-of-band documentation onto their journey. 42 | 43 | ### ATOM 44 | Content-Type: application/Atom+XML 45 | 46 | Mike Amundsen described the format [here.](http://amundsen.com/hypermedia/atom/) The next paragraph is a copy from his page. 47 | 48 | > Atom is an XML-based document format that describes lists of related information known as "feeds". Feeds are composed of a number of items, known as "entries", each with an extensible set of attached metadata. For example, each entry has a title. The primary use case that Atom addresses is the syndication of Web content such as weblogs and news headlines to Web sites as well as directly to user agents. [[1]](http://amundsen.com/hypermedia/atom/#ref-atom "The Atom Syndication Format") 49 | 50 | > The Atom Publishing Protocol is an application-level protocol for publishing and editing Web Resources using HTTP [RFC2616] and XML 1.0\. The protocol supports the creation of Web Resources and provides facilities for: 1) Collections: Sets of Resources, which can be retrieved in whole or in part; 2) Services: Discovery and description of Collections; and 3) Editing: Creating, editing, and deleting Resources. [[2]](http://amundsen.com/hypermedia/atom/#ref-atompub "The Atom Publishing Protocol") 51 | 52 | ### Collection+JSON 53 | 54 | Content-Type: application/vnd.collection+json 55 | 56 | Mike Amundsen described the format [here](http://amundsen.com/media-types/collection/format/) in a clear and lucid way. The next paragraph is a copy from his page. 57 | 58 | > The [Collection+JSON](http://amundsen.com/media-types/collection/) hypermedia type is designed to support full read/write capability for simple lists (contacts, tasks, blog entries, etc.). The standard application semantics supported by this media type include Create, Read, Update, and Delete (CRUD) along w/ support for predefined queries including [query templates](http://amundsen.com/media-types/collection/format/#query-templates) (similar to HTML "GET" forms). Write operations are defined using a [template](http://amundsen.com/media-types/collection/format/#objects-template) object supplied by the server as part of the response representation. 59 | 60 | > Each [item](http://amundsen.com/media-types/collection/format/#arrays-items) in a [Collection+JSON](http://amundsen.com/media-types/collection/)[collection](http://amundsen.com/media-types/collection/format/#objects-collection) has an assigned URI (via the [href](http://amundsen.com/media-types/collection/format/#properties-href) property) and an optional array of one or more [data](http://amundsen.com/media-types/collection/format/#arrays-data) elements along with an optional array of one or more [link](http://amundsen.com/media-types/collection/format/#arrays-links) elements. Both arrays support a [name](http://amundsen.com/media-types/collection/format/#properties-name) property for each object in the collection in order to decorate these elements with domain-specific semantic information (e.g. `"data" : [{"name" : "first-name", ...},...]`). 61 | 62 | > The [Collection+JSON](http://amundsen.com/media-types/collection/) hypermedia type has a limited set of predefined [link relation](http://amundsen.com/media-types/collection/format/#link-relations) values and supports [additional values](http://amundsen.com/media-types/collection/format/#rels-other) applied by implementors in order to better describe the application domain to which the media type is applied. 63 | 64 | > The following sections describe the process of reading and writing data using the [Collection+JSON](http://amundsen.com/media-types/collection/) hypermedia type as well as the way to parse and execute [Query Templates](http://amundsen.com/media-types/collection/format/#query-templates). Additional examples can be found in the [Examples](http://amundsen.com/media-types/collection/examples/) section of this documentation. 65 | 66 | ### JSON 67 | 68 | [Here](https://en.wikipedia.org/wiki/JSON) you can find a more detailed explanation. 69 | 70 | Content-Type: application/json 71 | 72 | The following example shows a possible JSON representation describing a person. 73 | 74 | { 75 | "firstName": "John", 76 | "lastName": "Smith", 77 | "isAlive": true, 78 | "age": 25, 79 | "address": 80 | { 81 | "streetAddress": "21 2nd Street", 82 | "city": "New York", 83 | "state": "NY", 84 | "postalCode": "10021-3100" 85 | }, 86 | "phoneNumbers": 87 | [ 88 | { 89 | "type": "home", 90 | "number": "212 555-1234" 91 | }, 92 | { 93 | "type": "office", 94 | "number": "646 555-4567" 95 | } 96 | ], 97 | "children": [], 98 | "spouse": null 99 | } 100 | 101 | ### XML 102 | 103 | JSON has outrun XML as response format. However it is a good idea to support both. 104 | 105 | Content-Type: application/xml 106 | 107 | The following example shows a possible XML representation describing a person. 108 | 109 | 110 | John 111 | Smith 112 | 25 113 |
114 | 21 2nd Street 115 | New York 116 | NY 117 | 10021 118 |
119 | 120 | 121 | home 122 | 212 555-1234 123 | 124 | 125 | fax 126 | 646 555-4567 127 | 128 | 129 | 130 | male 131 | 132 |
133 | 134 | ### Hypermedia Link base URLs 135 | 136 | For a discussion of the `Forwarded` header and its usage, see [Hypermedia and REST](../hypermedia-and-rest/hypermedia-and-rest.md). 137 | -------------------------------------------------------------------------------- /collection-resources/collection-resources.md: -------------------------------------------------------------------------------- 1 | ## Collection Resources 2 | A list of all of the given resources, including any related metadata. Array of resources should be in the `_embedded` field. Fields like `total_items` and `total_pages` help provide context to paged results. Consistent naming of collection resource fields allow API clients to create generic handling for using the provided data across various resource collections. 3 | 4 | The GET verb should not affect the system, and should not change response on subsequent requests (unless the underlying data changes), i.e. it should be idempotent. Exceptions to 'changing the response' are typically instrumentation/logging-related. 5 | 6 | The list of data is presumed to be filtered based on the provided security context of the API client, this should not be a list of all resources in the domain. 7 | 8 | Providing a summarized, or minimized version of the data representation can reduce the bandwidth footprint, in cases where individual resources contain a large object. 9 | 10 | ### Resource naming 11 | 12 | Collection resource names should be plural nouns, e.g. `/users`. This helps visually disambiguate collections from singletons. 13 | Please have a look at [REST principles](../rest-principles/rest-principles.md) for naming Guidelines. 14 | 15 | ### Get List of resources 16 | 17 | ##### URI Template 18 | 19 | GET /{namespace}/{version}/{resource} 20 | 21 | 22 | ##### Example Request 23 | 24 | GET /user_management/v1/users 25 | 26 | 27 | ##### Example Response 28 | 29 | HAL response format 30 | 31 | { 32 | "_links": 33 | { 34 | "self": { "href": "{baseurl}/users"}, 35 | "first": { "href": "{baseurl}/users?page=1"}, 36 | "last": { "href": "{baseurl}/users?page=11"}, 37 | "next": { "href": "{baseurl}/users?page=2"}, 38 | "find": { "href": "{baseurl}/users{?id}", "templated": true} 39 | }, 40 | "page": 1, 41 | "page_size": 20, 42 | "total_pages" : 11, 43 | "total_count": 217, 44 | "_embedded": 45 | { 46 | "users": 47 | [ 48 | { 49 | "_links": { 50 | "self": { "href": "{baseurl}/users/A14DA7707FE2458DAE37C2CF81E8F9B1" } 51 | }, 52 | "id" : "A14DA7707FE2458DAE37C2CF81E8F9B1", 53 | "name" : "Mustermann" 54 | }, 55 | { 56 | "_links": { 57 | "self": { "href": "{baseurl}/users/BE14A7269802498F992813885546D058" } 58 | }, 59 | "id" : "BE14A7269802498F992813885546D058", 60 | "name" : "VIPUser" 61 | } 62 | ] 63 | } 64 | } 65 | 66 | 67 | 68 | #### HTTP Status 69 | 70 | If the collection is empty (0 items in response), `404 Not Found` is not appropriate. The corresponding array should just be empty, and collection metadata fields provided (e.g. `"total_count": 0`). Invalid query parameter values can result in 400 Bad Request. Otherwise `200 OK` is utilized for a successful response. 71 | 72 | ### Read Single Resource 73 | 74 | A single resource, typically derived from the parent collection of resources (often more detailed than the collection resource items). 75 | 76 | Executing GET should never affect the system, and should not change response on subsequent requests, i.e. it should be idempotent. 77 | 78 | > All identifiers for sensible resources (customers, individuals) should be non-sequential, and preferrably non-numeric. 79 | 80 | In scenarios where this data might be used as a subordinate to other data, immutable string identifiers should be utilized for easier readability and debugging (i.e. "NAME_OF_VALUE" vs 1421321). 81 | 82 | ##### URI Template 83 | 84 | GET /{namespace}/{version}/{resource}/{resource-id} 85 | 86 | 87 | ##### Example Request 88 | 89 | GET /user_management/v1/users/BE14A7269802498F992813885546D058 90 | 91 | 92 | ##### Example Response 93 | 94 | { 95 | "_links": 96 | { 97 | "self": { "href": "{baseurl}/users/BE14A7269802498F992813885546D058" }, 98 | } 99 | "id": "BE14A7269802498F992813885546D058", 100 | "name": "Mustermann" 101 | } 102 | 103 | 104 | ##### HTTP Status 105 | 106 | If the provided resource identifier is not found, responds `404 Not Found` HTTP status. Otherwise, `200 OK` HTTP status should be utilized when data is found. 107 | 108 | ### Update Single Resource 109 | 110 | Updates a single resource. The shape of the PUT request should maintain parity with the GET response for the selected resource. Fields in the request body can be optional or ignored during deserialization, such as `create_time` or other system-calculated values. 111 | 112 | ##### URI Template 113 | 114 | PUT /{namespace}/{version}/{resource}/{resource-id} 115 | 116 | 117 | ##### Example Request 118 | 119 | PUT /user_management/v1/users/BE14A7269802498F992813885546D058 120 | { 121 | "id": "BE14A7269802498F992813885546D058", 122 | "name": "Changed Name" 123 | } 124 | 125 | 126 | ##### HTTP Status 127 | 128 | Any failed request validation responds `400 Bad Request` HTTP status. If clients attempt to modify read-only fields, this is also a `400 Bad Request`. 129 | 130 | If there are business rules (more than data type/length/etc), it is best to provide a specific error code & message (in addition to the 400) for that validation. 131 | 132 | For situations which require interaction with APIs or processes outside of the current request, the `422 Unprocessable Entity` status code is appropriate. 133 | 134 | After successful update, PUT operations should respond with `204 No Content` status, with no response body. 135 | 136 | ### Update Partial Single Resource 137 | 138 | ##### Support of partial updates is optional. 139 | 140 | PATCH updates a part of a single resource. Unlike PUT, which requires parity with GET, PATCH merely changes the fields provided, and leaves the rest of the resource unaffected. 141 | 142 | HTTP PATCH method has been been formalized in [RFC 7386: JSON Merge Patch](https://tools.ietf.org/html/rfc7386). 143 | 144 | Response should be `204 No Content` and no response body. Because PATCH is often called frequently in interactive form UX design, returning the entire response could be irresponsible from a bandwidth perspective, especially in mobile scenarios. 145 | 146 | System generated values should be commonly changed by an update, 147 | 148 | ##### URI Template 149 | 150 | PATCH /{namespace}/{version}/{resource}/{resource-id} 151 | 152 | 153 | ##### Example Request 154 | 155 | PATCH /user_management/v1/users/BE14A7269802498F992813885546D058 156 | { 157 | "name" : "newname" 158 | } 159 | 160 | 161 | ##### Example Response 162 | 163 | 204 No Content 164 | 165 | ##### HTTP Status 166 | 167 | Status/response for PATCH is the same as PUT. 168 | 169 | ### Delete Single Resource 170 | 171 | Deletes a single resource. In order to enable retries (typically patchy connectivity), DELETE is treated as idempotent, so it should always respond with a `204 No Content` HTTP status. 172 | `404 Not Found` HTTP status should **not** be utilized here, as on a second retry a client might mistakenly think the resource never existed at all. GET can be utilized to verify the resources exists prior to DELETE. 173 | 174 | ##### URI Template 175 | 176 | DELETE /{namespace}/{version}/{resource}/{resource-id} 177 | 178 | ##### Example Request 179 | 180 | DELETE /user_management/v1/users/BE14A7269802498F992813885546D058 181 | 182 | ##### Example Response 183 | 184 | 204 No Content 185 | 186 | ### Create New Resource 187 | 188 | Creates a new resource in the collection. Request body may be somewhat different than GET/PUT response/request (typically fewer fields as the server will generate some values). 189 | 190 | In most cases, the API server produces an identifier for the resource. In cases where identifier is supplied by the API consumer, use [Create New Resource - Consumer Supplied Identifier](#create-new-resource---consumer-supplied-identifier) below. 191 | 192 | Once the POST has successfully completed, a new resource will be created. The identifier for this resource should be added to the resource collection URI. 193 | 194 | Hypermedia links provide an easy way to get the URL of the newly created resource, using the rel: self, in addition to other links for operations allowed for the new resource. Addionally a location header in the response can point to the newly created resource. 195 | 196 | ##### URI Template 197 | 198 | POST /{namespace}/{version}/{resource} 199 | 200 | ##### Example Request 201 | 202 | Note that server-generated values are not provided in the request. 203 | 204 | POST /user_management/v1/users 205 | 206 | { 207 | "name": "MyName123", 208 | } 209 | 210 | ##### Example Response 211 | 212 | 201 Created 213 | Location: http://api.haufe-lexware.com/user_management/v1/users/E75E30C0607446219C6EA31735C691B9 214 | 215 | { 216 | "_links": 217 | { 218 | "self": { "href": "{baseurl}/users/E75E30C0607446219C6EA31735C691B9" }, 219 | } 220 | "id": "E75E30C0607446219C6EA31735C691B9", 221 | "name": "MyName123" 222 | } 223 | 224 | ### Create New Resource - Consumer Supplied Identifier 225 | 226 | When an API consumer defines the resource identifier, the PUT verb should be utilized, as the operation is idempotent, even during creation. 227 | 228 | The same interaction as [Create New Resource](#create-new-resource) is used here. 201 + response body on resource creation, and 204 + no response body when an existing resource is updated. 229 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | -- 179 | 180 | Copyright 2017 Haufe-Lexware GmbH & Co.KG 181 | 182 | Licensed under the Apache License, Version 2.0 (the "License"); 183 | you may not use this file except in compliance with the License. 184 | You may obtain a copy of the License at 185 | 186 | http://www.apache.org/licenses/LICENSE-2.0 187 | 188 | Unless required by applicable law or agreed to in writing, software 189 | distributed under the License is distributed on an "AS IS" BASIS, 190 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 191 | See the License for the specific language governing permissions and 192 | limitations under the License. 193 | -------------------------------------------------------------------------------- /api-management/api-management.md: -------------------------------------------------------------------------------- 1 | ## API Management 2 | 3 | ### Recommended API Management solutions 4 | 5 | The recommended go-to API Management solution is our own API Management System [wicked.haufe.io](http://wicked.haufe.io) ([github](https://github.com/Haufe-Lexware/wicked.haufe.io)). It is based on [Mashape Kong](https://getkong.org) and provides both an API Gateway and a developer API Portal, implemented in node.js. 6 | 7 | The wicked.haufe.io API Portal enables most common scenarios and is also developed further both by internal developers and (in the future hopefully) by contributions from external developers. Wicked has been open sourced under the Apache 2.0 License. 8 | 9 | Some projects (especially those running on the Azure platform) have also successfully adopted Azure API Management. Azure API Management is a fully managed service, in contrast to wicked, which has to be operated by the team actually wanting to use it. 10 | 11 | #### Azure API Management 12 | 13 | Azure API Management is fully managed and is available in most Azure regions. It provides a stable API Gateway service and a functional, but not very flexible, API Portal. 14 | 15 | The main advantage of Azure APIm is that it's managed; the main drawback is that it is not built with CI/CD in mind. Creating deployment pipelines and configuration as code for Azure APIm is challenging. There exist efforts made by Haufe to make this easier, such as the [azure-apim-deployment-utils](https://github.com/Haufe-Lexware/azure-apim-deployment-utils). 16 | 17 | Running a production workload via Azure APIm requires the "Standard Tier" of Azure APIm, which can be quite costly (at around 500€/month) for smaller portals. 18 | 19 | #### Haufe OSS API Management 20 | 21 | In contrast to the fully managed service Azure APIm, our own open source API Management solution [wicked.haufe.io](http://wicked.haufe.io) is much more flexible in that it may run on any runtime which supports Docker (e.g. Docker Hosts, Docker Swarm, Kubernetes). But with flexibility also comes a price, and that's obviously that you need to operate it yourself. 22 | 23 | A prerequisite to successfully running wicked.haufe.io in production is the availability of a stable docker runtime. If you have already established this, choosing wicked as an APIm solution is easy, as you have already solved the difficult problems. 24 | 25 | A bonus on top of the flexibility of wicked is that it's built to tie in to deployment pipelines and to support CI/CD scenarios, also in terms of API Management, documentation and such. It's designed to support exactly those scenarios, the only offering to configuration is **configuration as code** (or in this case as `json`). 26 | 27 | At [wicked.haufe.io](http://wicked.haufe.io), you can find much more documentation on the system. 28 | 29 | ### API Management Scenarios 30 | 31 | There are many different scenarions in which API management can and must be used. The following sections describe some basic scenarios. 32 | 33 | The below sections are always to be read in the scope of APIs, not for communication between systems which are tightly coupled (which is to be avoided, granted, by cannot always be). 34 | 35 | #### Machine to Machine communication 36 | 37 | Machine to machine communication in the API sense is when two systems/machines communicate with each other and where the machines trust each other. This is the case for batch jobs or system jobs running in the background, or, if a user identity (authentication) and role (authorization) has already been established, and the participating systems trust each other to have established this beforehand. 38 | 39 | Machine to machine communication can be secured via the following means: 40 | 41 | * Secure transport (TLS/https, **mandatory**) 42 | * Using API Keys (as a header) to authenticate and authorize the client system with the provider system 43 | * **or** using the [OAuth2.0 Client Credentials Flow](https://tools.ietf.org/html/rfc6749), where client credentials (client ID and client Secret) are exchanged for an access token 44 | 45 | API Keys are directly supported by both Azure APIm and Wicked; the OAuth2.0 CC Flow is only supported out of the box by Wicked. TLS is provided by both. Wicked can be integrated with Let's Encrypt, Azure APIm cannot. 46 | 47 | Using API Management and an API Portal for these scenarios is beneficial if you potentially have more than one client for an API, and you may want to track usage and know your clients and clients' behaviour. 48 | 49 | #### API Usage with an end user context 50 | 51 | In many cases you need to get a user context into the API call, i.e. the backend service needs to know on behalf of which actual user an API call is done. 52 | 53 | The authentication and authorization of the user for the API should not be done by the actual API Backend implementation, but rather by the API Management/API Gateway in front of the implementation. By following this pattern, the API Backend can just trust the user identity and roles/rights and does not need to verify that type of information. 54 | 55 | We propose that the [OAuth2.0 Standards](https://tools.ietf.org/html/rfc6749) MUST be used for standard scenarios in terms of authentication and authorization, except where the SAML standard is appropriate for legacy integrations (such as to Atlantic). The important thing we want to stress here is that the API backend implementation MUST be separated from the Authentication and Authorization, so that this aspect can be changed without having to change the entire backend implementation. 56 | 57 | Instead, this is done in a decoupled way in a dedicated component: An Authorization Server. An Authorization Server has two distinct tasks: 58 | 59 | * Authenticate the end user against an identity provider (this can be most anything, the Authorization Server may under special circumstances also implement the authentication itself; e.g. Haufe Atlantic, Google, Github, Facebook,...) 60 | * Authorize the end user for the API Usage by deciding on "scopes" (approx. rights), depending on the identity/roles/properties of the user; this is highly project specific and can usually not be delegated to a generic implementation 61 | 62 | After the user is authenticated and (possibly) authorized, an access token is issued to the API client, which then carries the information on user identity and scopes; how this is done technically is an implementation detail, but the main two techniques are: 63 | 64 | * Using registered tokens which map to headers in the API Gateway 65 | * Usign JWT tokens, which are cryptographically signed and carry the above information in itself (thus they need not be registered with the API Gateway) 66 | 67 | On of the following standards MUST be used for authentication and authorization: 68 | 69 | * **Authentication**: OAuth2.0 Authorization Code Flow, OAuth2.0 Resource Owner Password Grant Flow, OAuth 1.0a, or SAML 2.0 (e.g. Atlantic); in some cases also REST calls to establish identity can be used (equivalent to Resource Owner Password Grant flow, e.g. using an existing SAML SSO Token) 70 | * **Authorization**: OAuth2.0 Authorization Code Flow, OAuth2.0 Resource Owner Password Grant Flow or OAuth2.0 Implicit Grant Flow 71 | 72 | Which OAuth2.0 Flow can be applied depends on the type of API Client: 73 | 74 | * Confidential Clients are able to keep secret/credentials confidential, i.e. server side. Traditional web sites are usually confidential clients. 75 | * Public Clients cannot keep secrets/credentials confidential, as those would be kept in a place with the actual end user; typical public clients are mobile apps (can be reverse engineered) or single page applications (JavaScript applications which do not have a stateful backend) 76 | 77 | ##### End user context - Confidential Clients 78 | 79 | Confidential Clients should use the OAuth2.0 Authorization Code grant to get access to APIs (in case the API supports this flow). 80 | 81 | The Authorization Code grant has the following positive aspects: 82 | 83 | * The Access Token needed to be able to call the API is never exposed to the end user, it is only transferred via the backend to the client application 84 | * The end user's real credentials are never present inside the client application, only the access token is used to call the API on behalf of the logged in user 85 | * Using the Authorization Code Flow also renders a refresh token which can be used to refresh a shortlived access token, without user interaction; this can greatly improve usability of the client application using the API 86 | 87 | Under certain circumstances, for trusted applications, the Resource Owner Password Grant flow may also be used. This must never be the case if the API is used by a third party application (implemented by somebody else than Haufe). This flow will also return both an access token and a refresh token, but the end user's username and password will need to be processed (temporarily) inside the client application. 88 | 89 | Wherever possible though, try to implement the Authorization Code Flow. 90 | 91 | ##### End user context - Public Clients 92 | 93 | For non-confidential clients, such as Single Page Application (aka Public clients), the OAuth 2.0 Implicit Grant Flow MUST be used. 94 | 95 | In order for the SPA/Public Client with a User Agent to retrieve an access token for API Access, the end user's User Agent (aka Browser) is redirected to the Authorization Server. The AS establishes identity (by a suitable means) and decides whether this particular user is granted access (authorized) to the API or not. 96 | 97 | The AS then issues an Access Token (either by crafting a JWT or registering/getting an opaque token from the API Gateway) which is then returned to the calling SPA via a fragment (`https://spa.com/#access_token=....`). 98 | 99 | This flow explicitly does NOT return a refresh token (which would need to be kept confidentially - not possible in an SPA), and the access token should also be very short lived (less than 24 hours, possibly only as little as 30 minutes). 100 | 101 | #### Mobile Clients 102 | 103 | Mobile Clients are a special case of public clients; some mobile app platforms support the use of User Agents (embedded browsers), which also in some case are able to re-use pre-established trust settings. For these cases, consider using the OAuth 2.0 Implicit Grant flow for retrieving access tokens for use in the mobile app. 104 | 105 | In case you are writing a trusted type of mobile app (we are writing our own native iOS app or similar), the Resource Owner Password Grant can also be used, in the following way: 106 | 107 | * The Mobile App collects username and password from the end user 108 | * The Mobile App's client ID (stored inside the app; the secret must not be!) and the username/password are used to call an Authorization Server via the OAuth 2.0 Resource Owner Password Grant 109 | * The Authorization Server verifies it knows the Mobile App's Client ID 110 | * The Authorization Server verifies the username and password against a suitable Identity Provider 111 | * The Authorization Server decides whether the authenticated user is granted access (can be authorized) or not 112 | * In case of success, the Authorization Server returns and Access Token and a Refresh Token to the mobile app 113 | * The Mobile App stores Access Token and Refresh Token in separate places inside the mobile devices storage; after that, it discards the username and password of the end user, so that this data is no longer present on the device (at least not in the context of this mobile app) 114 | * The Mobile App can now access the API, and also refresh the Token using the Refresh Token. 115 | 116 | This scenario may be implemented e.g. using the Wicked API Management system, using a custom Authorization Server implementation. 117 | 118 | Please note that such an implementation should ensure that a refresh token is usable only once, and is invalidated after use. Ideally, the end user SHOULD also have a possibility to review access/refresh tokens in use, e.g. using a separate web interface. 119 | 120 | **APIs without end user context**: Mobile Clients which want to use an API without actually having an end user context can still make use of a similar approach to getting access tokens to the API. By using a device ID or even a random number as client credentials, rate limiting and such can be applied to a specific device. The Authorization Server would then usually unconditionally accept the client's credentials and issue tokens. You would then still have the possibility to revoke or at least limit access to specific devices/IDs in your Authorization Server implementation. 121 | 122 | Please note that this technique does not actually prevent misuse of your API, but it at least raises the bar for the attacker. Establishing real user identity is a more reliable means of preventing API misuse. 123 | 124 | ### API Gateways 125 | 126 | #### The `Forwarded` header 127 | 128 | Whenever the API Gateway makes a call to a backend API service, it MUST add a `Forwarded` header (see [RFC 7239](https://tools.ietf.org/html/rfc7239)), which contains the "front end" visible host and URL data which can subsequently be used to assemble [hypermedia](response-format.md) links. 129 | 130 | See also [Hypermedia and REST](hypermedia-and-rest.md) for a discussion of this header. 131 | 132 | #### Implementation in Azure API Management 133 | 134 | By applying a custom policy on the Product or even Tenant level, you can insert this header automatically: 135 | 136 | ``` 137 | 138 | 139 | @("proto=" + context.Request.OriginalUrl.Scheme + ";host=" + context.Request.OriginalUrl.Host + ";prefix=" + context.Api.Path) 140 | 141 | 142 | 143 | ``` 144 | 145 | Example: Your end point is called at `https://api.contenthub.haufe.de/search/v1/query?q=Steuerhinterziehung`. The API prefix is `/search/v1`, and the operation is `/query`. In this case, the header will look as follows: 146 | 147 | ``` 148 | Forwarded: proto=https;host=api.contenthub.haufe.de;prefix=/search/v1 149 | ``` 150 | 151 | The use of `port=` is optional, but MUST be used in case the port is not the standard `443` port. The port MUST NOT be part of the `host=` statement. 152 | 153 | #### Implementation using the wicked API Portal 154 | 155 | In `config.json` of an API: 156 | 157 | ``` 158 | "plugins": [ 159 | { 160 | "name":"request-transformer", 161 | "config":{ 162 | "add": { 163 | "headers": [ 164 | "%%Forwarded" 165 | ] 166 | } 167 | } 168 | } 169 | ] 170 | ``` 171 | 172 | The special string `%%Forwarded` will dynamically be replaced with a suitable `Forwarded: ...` header for the specific API, API Host and schema. 173 | 174 | ### API Portals 175 | 176 | Our believe in the inherent adaptability and robustness of a loosly coupled and decentralized service landscape and infrastructure also applies to API Management (APIm). There is no central APIm instance in Haufe, but a set of APIm instances servicing distinct groups of contextual related API's. Keeping with the spirit of 'how the web is working', we provide a central API search engine (like Google) to find APIs across Haufe. 177 | 178 | The introduction of a new API management solution has to be discussed with the CTO office and is subject to review by the Architecture Review Board (ARB). 179 | 180 | We encourage that also the API management solution, or at least, the API serviced by the APIm solution, should be maintained and operated (in the DevOps sense) by the team which operates and maintains the underlying service. The API inside the API management solution is to be treated **as part of the service, it is not an addon**. 181 | 182 | Please adhere to the following naming schema: 183 | 184 | * `.haufe.io` points to the developer portal of a topic's API management solution. This is the URL the developers will use at design time of the consuming application 185 | * `api..haufe.io` points to the API gateway of the topic's API management solution. This is the URL the consuming clients will use at runtime. 186 | 187 | ##### Using `haufe.io` Certificates 188 | 189 | For the `*.haufe.io` domain, there exists a wildcard certificate which can be used for the developer portals. 190 | 191 | For `api.