├── CONTRIBUTING.md ├── Guidelines.md ├── README.md └── lang └── ko ├── CONTRIBUTING.md ├── Guidelines.md └── README.md /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Microsoft REST API Guidelines 2 | The Microsoft REST API Guidelines is a Microsoft-wide initiative to develop consistent design guidelines for REST APIs. The initiative requires input and feedback from a variety of individuals both inside and outside of Microsoft. 3 | 4 | To provide feedback, please follow the guidance in this document. Please note that these are just guidelines, not rules. Use your best judgment and feel free to propose changes to anything in this repository, including the contribution guidance. 5 | 6 | Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. 7 | - [Creating issues](#creating-issues) 8 | - [Documentation styleguide](#documentation-styleguide) 9 | - [Commit messages](#commit-messages) 10 | - [Pull requests](#pull-requests) 11 | 12 | ## Creating issues 13 | - You can [create an issue][new-issue], but before doing that please read the bullets below and include as many details as possible. 14 | - Perform a [cursory search][issue-search] to see if a similar issue has already been submitted. 15 | - Reference the version of the Microsoft REST API Guidelines you are using. 16 | - Include the guidance you expected and other places you've seen that guidance, e.g. [White House Web API Standards][white-house-api-guidelines]. 17 | - Include sample requests and responses whenever possible. 18 | 19 | ### Related repositories 20 | This is the repository for Microsoft REST API Guidelines documentation only. Please ensure that you are opening issues in the right repository. 21 | 22 | ## Recommended setup for contributing 23 | - Install [Atom][atom] 24 | - Install [atom-beautify package][atom-beautify] 25 | - Install [markdown-toc package][markdown-toc] 26 | 27 | ## Documentation styleguide 28 | - Always prettify markdown with [atom-beautify][atom-beautify] before committing 29 | - Use [GitHub-flavored markdown][gfm] 30 | - Use syntax-highlighted examples liberally 31 | - Trim trailing empty lines from HTTP requests 32 | - Retain only essential headers for understanding the example 33 | - Use valid (e.g., member names quoted), pretty-printed JSON with a 2 space indent 34 | - Minimize JSON payloads by using ellipses 35 | 36 | ### Example 37 | #### Request 38 | 39 | ```http 40 | GET http://services.odata.org/V4/TripPinServiceRW/People HTTP/1.1 41 | Accept: application/json 42 | ``` 43 | 44 | #### Response 45 | 46 | ```http 47 | HTTP/1.1 200 OK 48 | Content-Type: application/json 49 | 50 | { 51 | "@nextLink":"http://services.odata.org/V4/TripPinServiceRW/People?$skiptoken=8", 52 | "value":[ 53 | { 54 | "userName":"russellwhyte", 55 | "firstName":"Russell", 56 | "lastName":"Whyte", 57 | "emails":[ 58 | "Russell@example.com", 59 | "Russell@contoso.com" 60 | ], 61 | "addressInfo":[ 62 | { 63 | "address":"187 Suffolk Ln.", 64 | "city":{ 65 | "countryRegion":"United States", 66 | "name":"Boise", 67 | "region":"ID" 68 | } 69 | } 70 | ], 71 | "gender":"Male", 72 | }, 73 | ... 74 | ] 75 | } 76 | ``` 77 | 78 | ## Commit messages 79 | - Use the present tense: "Change ...", not "Changed ..." 80 | - Use the imperative mood: "Change ...", not "Changes ..." 81 | - Limit the first line to 72 characters or less 82 | - Reference issues and pull requests liberally 83 | 84 | ## Pull requests 85 | Pull requests serve as the primary mechanism by which contributions are proposed and accepted. We recommend creating a [topic branch][topic-branch] and sending a pull request to the `master` branch from the topic branch. For additional guidance, read through the [GitHub Flow Guide][github-flow-guide]. 86 | 87 | Be prepared to address feedback on your pull request and iterate if necessary. 88 | 89 | [code-of-conduct]: https://opensource.microsoft.com/codeofconduct/ 90 | [new-issue]: https://github.com/Microsoft/api-guidelines/issues/new 91 | [issue-search]: https://github.com/Microsoft/api-guidelines/issues 92 | [white-house-api-guidelines]: https://github.com/WhiteHouse/api-standards/blob/master/README.md 93 | [topic-branch]: http://www.git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#Topic-Branches 94 | [gfm]: https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown 95 | [github-flow-guide]: https://guides.github.com/introduction/flow/ 96 | [atom-beautify]: https://atom.io/packages/atom-beautify 97 | [atom]: http://atom.io 98 | [markdown-toc]: https://atom.io/packages/markdown-toc 99 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Microsoft REST API Guidelines 2 | The [Microsoft REST API Guidelines](Guidelines.md), as a design principle, encourages application developers to have resources accessible to them via a RESTful HTTP interface. To provide the smoothest possible experience for developers on platforms following the Microsoft REST API Guidelines, REST APIs SHOULD follow consistent design guidelines to make using them easy and intuitive. 3 | 4 | ## Code of Conduct 5 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 6 | 7 | ## This repository 8 | This repository contains a collection of documents and related materials supporting the overall Microsoft REST API Guidelines initiative. To contribute to this repository, please see the [contribution guidance][contribution-guidance]. 9 | 10 | [contribution-guidance]: CONTRIBUTING.md 11 | -------------------------------------------------------------------------------- /lang/ko/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to the Microsoft REST API Guidelines 2 | The Microsoft REST API Guidelines is a Microsoft-wide initiative to develop consistent design guidelines for REST APIs. The initiative requires input and feedback from a variety of individuals both inside and outside of Microsoft. 3 | 4 | To provide feedback, please follow the guidance in this document. Please note that these are just guidelines, not rules. Use your best judgment and feel free to propose changes to anything in this repository, including the contribution guidance. 5 | 6 | Please note that this project is released with a [Contributor Code of Conduct][code-of-conduct]. By participating in this project you agree to abide by its terms. 7 | - [Creating issues](#creating-issues) 8 | - [Documentation styleguide](#documentation-styleguide) 9 | - [Commit messages](#commit-messages) 10 | - [Pull requests](#pull-requests) 11 | 12 | ## Creating issues 13 | - You can [create an issue][new-issue], but before doing that please read the bullets below and include as many details as possible. 14 | - Perform a [cursory search][issue-search] to see if a similar issue has already been submitted. 15 | - Reference the version of the Microsoft REST API Guidelines you are using. 16 | - Include the guidance you expected and other places you've seen that guidance, e.g. [White House Web API Standards][white-house-api-guidelines]. 17 | - Include sample requests and responses whenever possible. 18 | 19 | ### Related repositories 20 | This is the repository for Microsoft REST API Guidelines documentation only. Please ensure that you are opening issues in the right repository. 21 | 22 | ## Recommended setup for contributing 23 | - Install [Atom][atom] 24 | - Install [atom-beautify package][atom-beautify] 25 | - Install [markdown-toc package][markdown-toc] 26 | 27 | ## Documentation styleguide 28 | - Always prettify markdown with [atom-beautify][atom-beautify] before committing 29 | - Use [GitHub-flavored markdown][gfm] 30 | - Use syntax-highlighted examples liberally 31 | - Trim trailing empty lines from HTTP requests 32 | - Retain only essential headers for understanding the example 33 | - Use valid (e.g., member names quoted), pretty-printed JSON with a 2 space indent 34 | - Minimize JSON payloads by using ellipses 35 | 36 | ### Example 37 | #### Request 38 | 39 | ```http 40 | GET http://services.odata.org/V4/TripPinServiceRW/People HTTP/1.1 41 | Accept: application/json 42 | ``` 43 | 44 | #### Response 45 | 46 | ```http 47 | HTTP/1.1 200 OK 48 | Content-Type: application/json 49 | 50 | { 51 | "@nextLink":"http://services.odata.org/V4/TripPinServiceRW/People?$skiptoken=8", 52 | "value":[ 53 | { 54 | "userName":"russellwhyte", 55 | "firstName":"Russell", 56 | "lastName":"Whyte", 57 | "emails":[ 58 | "Russell@example.com", 59 | "Russell@contoso.com" 60 | ], 61 | "addressInfo":[ 62 | { 63 | "address":"187 Suffolk Ln.", 64 | "city":{ 65 | "countryRegion":"United States", 66 | "name":"Boise", 67 | "region":"ID" 68 | } 69 | } 70 | ], 71 | "gender":"Male", 72 | }, 73 | ... 74 | ] 75 | } 76 | ``` 77 | 78 | ## Commit messages 79 | - Use the present tense: "Change ...", not "Changed ..." 80 | - Use the imperative mood: "Change ...", not "Changes ..." 81 | - Limit the first line to 72 characters or less 82 | - Reference issues and pull requests liberally 83 | 84 | ## Pull requests 85 | Pull requests serve as the primary mechanism by which contributions are proposed and accepted. We recommend creating a [topic branch][topic-branch] and sending a pull request to the `master` branch from the topic branch. For additional guidance, read through the [GitHub Flow Guide][github-flow-guide]. 86 | 87 | Be prepared to address feedback on your pull request and iterate if necessary. 88 | 89 | [code-of-conduct]: https://opensource.microsoft.com/codeofconduct/ 90 | [new-issue]: https://github.com/Microsoft/api-guidelines/issues/new 91 | [issue-search]: https://github.com/Microsoft/api-guidelines/issues 92 | [white-house-api-guidelines]: https://github.com/WhiteHouse/api-standards/blob/master/README.md 93 | [topic-branch]: http://www.git-scm.com/book/en/v2/Git-Branching-Branching-Workflows#Topic-Branches 94 | [gfm]: https://guides.github.com/features/mastering-markdown/#GitHub-flavored-markdown 95 | [github-flow-guide]: https://guides.github.com/introduction/flow/ 96 | [atom-beautify]: https://atom.io/packages/atom-beautify 97 | [atom]: http://atom.io 98 | [markdown-toc]: https://atom.io/packages/markdown-toc 99 | -------------------------------------------------------------------------------- /lang/ko/Guidelines.md: -------------------------------------------------------------------------------- 1 | 2 | # 마이크로소프트 REST API 가이드라인 2.3 3 | 4 | 5 | ## 마이크로소프트 REST API 가이드라인 워킹 그룹 6 | 7 | | | | 8 | ---------------------------- | -------------------------------------- | ---------------------------------------- 9 | Dave Campbell (CTO C+E) | Rick Rashid (CTO ASG) | John Shewchuk (Technical Fellow, TED HQ) 10 | Mark Russinovich (CTO Azure) | Steve Lucco (Technical Fellow, DevDiv) | Murali Krishnaprasad (Azure App Plat) 11 | Rob Howard (ASG) | Peter Torr (OSG) | Chris Mullins (ASG) 12 | 13 |
14 | 편집진: John Gossman (C+E), Chris Mullins (ASG), Gareth Jones (ASG), Rob Dolin (C+E), Mark Stafford (C+E)
15 |
16 | 17 | 18 | 19 | # 마이크로소프트 REST API 가이드라인 20 | 21 | 22 | ## 1 요약 23 | 24 | 설계 원칙으로서 이 마이크로소프트 REST API 가이드라인은 애플리케이션 개발자들이 리소스를 개발할 때 RESTful HTTP 인터페이스를 통해 접근하기 쉽게 만드는 것을 장려한다. 가능한 한 편안한 개발 경험을 제공하기 위해서라면 REST API는 쉽고 직관적이어야 하며 이는 일관적인 설계 가이드라인을 따르는 것이 좋다. 25 | 26 | 이 문서는 마이크로소프트에서 제공하는 REST API가 지켜야 하는 가이드라인을 정립한다. 이를 통해 RESTful 인터페이스를 일관적으로 개발할 수 있게 한다. 27 | 28 | 29 | ## 2 목차 30 | 31 | 32 | 33 | - [마이크로소프트 REST API 가이드라인 2.3](#microsoft-rest-api-guidelines-23) 34 | - [마이크로소프트 REST API 가이드라인 워킹 그룹](#microsoft-rest-api-guidelines-working-group) 35 | - [마이크로소프트 REST API 가이드라인](#microsoft-rest-api-guidelines) 36 | - [1 요약](#1-abstract) 37 | - [2 목차](#2-table-of-contents) 38 | - [3 소개](#3-introduction) 39 | - [3.1 추천 문서](#31-recommended-reading) 40 | - [4 가이드라인 해석](#4-interpreting-the-guidelines) 41 | - [4.1 가이드라인 적용](#41-application-of-the-guidelines) 42 | - [4.2 기존 서비스와 서비스 버전 관리를 위한 가이드라인](#42-guidelines-for-existing-services-and-versioning-of-services) 43 | - [4.3 요구 언어](#43-requirements-language) 44 | - [4.4 라이센스](#44-license) 45 | - [5 Taxonomy](#5-taxonomy) 46 | - [5.1 Errors](#51-errors) 47 | - [5.2 Faults](#52-faults) 48 | - [5.3 Latency](#53-latency) 49 | - [5.4 Time to complete](#54-time-to-complete) 50 | - [5.5 Long running API faults](#55-long-running-api-faults) 51 | - [6 Client guidance](#6-client-guidance) 52 | - [6.1 Ignore rule](#61-ignore-rule) 53 | - [6.2 Variable order rule](#62-variable-order-rule) 54 | - [6.3 Silent fail rule](#63-silent-fail-rule) 55 | - [7 Consistency fundamentals](#7-consistency-fundamentals) 56 | - [7.1 URL structure](#71-url-structure) 57 | - [7.2 URL length](#72-url-length) 58 | - [7.3 Canonical identifier](#73-canonical-identifier) 59 | - [7.4 Supported methods](#74-supported-methods) 60 | - [7.5 Standard request headers](#75-standard-request-headers) 61 | - [7.6 Standard response headers](#76-standard-response-headers) 62 | - [7.7 Custom headers](#77-custom-headers) 63 | - [7.8 Specifying headers as query parameters](#78-specifying-headers-as-query-parameters) 64 | - [7.9 PII parameters](#79-pii-parameters) 65 | - [7.10 Response formats](#710-response-formats) 66 | - [7.11 HTTP Status Codes](#711-http-status-codes) 67 | - [7.12 Client library optional](#712-client-library-optional) 68 | - [8 CORS](#8-cors) 69 | - [8.1 Client guidance](#81-client-guidance) 70 | - [8.2 Service guidance](#82-service-guidance) 71 | - [9 Collections](#9-collections) 72 | - [9.1 Item keys](#91-item-keys) 73 | - [9.2 Serialization](#92-serialization) 74 | - [9.3 Collection URL patterns](#93-collection-url-patterns) 75 | - [9.4 Big collections](#94-big-collections) 76 | - [9.5 Changing collections](#95-changing-collections) 77 | - [9.6 Sorting collections](#96-sorting-collections) 78 | - [9.7 Filtering](#97-filtering) 79 | - [9.8 Pagination](#98-pagination) 80 | - [9.9 Compound collection operations](#99-compound-collection-operations) 81 | - [10 Delta queries](#10-delta-queries) 82 | - [10.1 Delta links](#101-delta-links) 83 | - [10.2 Entity representation](#102-entity-representation) 84 | - [10.3 Obtaining a delta link](#103-obtaining-a-delta-link) 85 | - [10.4 Contents of a delta link response](#104-contents-of-a-delta-link-response) 86 | - [10.5 Using a delta link](#105-using-a-delta-link) 87 | - [11 JSON standardizations](#11-json-standardizations) 88 | - [11.1 JSON formatting standardization for primitive types] (#111-json-formatting-standardization-for-primitive-types) 89 | - [11.2 Guidelines for dates and times] (#112-guidelines-for-dates-and-times) 90 | - [11.3 JSON serialization of dates and times] (#113-json-serialization-of-dates-and-times) 91 | - [11.4 Durations](#114-durations) 92 | - [11.5 Intervals](#115-intervals) 93 | - [11.6 Repeating intervals](#116-repeating-intervals) 94 | - [12 Versioning](#12-versioning) 95 | - [12.1 Versioning formats](#121-versioning-formats) 96 | - [12.2 When to version](#122-when-to-version) 97 | - [12.3 Definition of a breaking change](#123-definition-of-a-breaking-change) 98 | - [13 Long running operations](#13-long-running-operations) 99 | - [13.1 Resource based long running operations (RELO)](#131-resource-based-long-running-operations-relo) 100 | - [13.2 Stepwise long running operations](#132-stepwise-long-running-operations) 101 | - [13.3 Retention policy for operation results](#133-retention-policy-for-operation-results) 102 | - [14 Push notifications via webhooks] (#14-push-notifications-via-webhooks) 103 | - [14.1 Scope](#141-scope) 104 | - [14.2 Principles](#142-principles) 105 | - [14.3 Types of subscriptions](#143-types-of-subscriptions) 106 | - [14.4 Call sequences](#144-call-sequences) 107 | - [14.5 Verifying subscriptions](#145-verifying-subscriptions) 108 | - [14.6 Receiving notifications](#146-receiving-notifications) 109 | - [14.7 Managing subscriptions programmatically](#147-managing-subscriptions-programmatically) 110 | - [14.8 Security](#148-security) 111 | - [15 Unsupported requests](#15-unsupported-requests) 112 | - [15.1 Essential guidance](#151-essential-guidance) 113 | - [15.2 Feature allow list](#152-feature-allow-list) 114 | - [16 Appendix](#16-appendix) 115 | - [16.1 Sequence diagram notes](#161-sequence-diagram-notes) 116 | 117 | 118 | 119 | 120 | ## 3 소개 121 | 122 | 개발자는 대부분 HTTP 인터페이스를 통해 마이크로소프트 클라우드 플랫폼 리소스에 접속한다. 각 서비스는 보통 API를 사용하기 쉽게끔 언어별 프레임워크를 제공한다. 그렇긴 해도 결국 이것은 HTTP 리퀘스트의 집합으로 규정할 수 있다. 마이크로소프트는 반드시(MUST) 다양한 클라이언트와 서비스를 고려해야 하며 모든 개발환경에 사용 가능한 기능을 제공하는 리치 프레임워크에 의존해서는 안된다. 따라서 이 가이드라인은 기본적으로 HTTP 연결을 지원하는 어떤 클라이언트에서도 쉽고 일관적으로 마이크로소프트 REST API를 사용할 수 있게끔 하는데 있다. 123 | 124 | 가능한 한 편안한 개발 경험을 제공하기 위해서라면 가이드라인을 일관적으로 설계하는 것이 굉장히 중요하다. 그렇게 만들어진 가이드라인은 쉽고 직관적이다. 이 문서는 마이크로소프트 API 개발자들이 일관적으로 API를 개발할 수 있게끔 가이드라인을 제공한다. 125 | 126 | 가이드라인이 일관적이라면 다양한 잇점이 생긴다. 이러한 일관성은 우리가 코드, 패턴, 문서화, 설계와 관련해서 공통점을 이끌어내는데 도움을 준다. 127 | 128 | * 마이크로소프트가 제공하는 API 엔드포인트가 가져야 할 일정한 패턴과 관행을 정의하기. 129 | * 현업에서 대부분* 인정받은 REST/HTTP 사례들과 최대한 가깝게 맞추기. 130 | * 모든 애플리케이션 개발자들이 REST 인터페이스를 통해 마이크로소프트 서비스에 쉽게 접근할 수 있게끔 하기. 131 | * 다른 서비스에서 이미 구현하고 테스트하고 문서화한 REST 엔드포인트와 같은 형식으로 개발할 수 있게끔 하기. 132 | * 마이크로소프트 파트너가 직접 자신들만의 REST 엔드포인트를 설계할 때 이 가이드라인을 사용할 수 있게끔 하기. 133 | 134 | 이 가이드라인은 위와 같은 것들을 이룩할 수 있다. 135 | 136 | *참고: 이 가이드라인은 REST 아키텍처 스타일에 맞게 서비스를 만들고자 한다. 물론 서비스를 개발하는데 있어서 굳이 REST가 갖는 제약사항까지 따를 필요는 없다. 이 문서 전체를 통해 쓰인 "REST"라는 용어는 아래 언급할 책에서 다루는 REST 보다는 좀 더 REST가 보여주는 철학에 가깝다.* 137 | 138 | 139 | 140 | ### 3.1 추천 문서 141 | 142 | 좋은 HTTP 기반 서비스를 개발하기 위해서는 REST 아키텍처 스타일 이면의 철학을 이해하면 좋다. 만약 RESTful 설계가 낯설다면 읽어볼 만한 좋은 글이 몇가지 있다. 143 | 144 | 145 | [위키피디아 REST 항목][rest-on-wikipedia] -- REST 이면의 핵심 사상과 공통적인 정의에 대한 정리. 146 | 147 | [REST 논문][fielding] -- 네트워크 아키텍처에 대해 Roy Fielding이 쓴 논문인 "아키텍처 스타일과 네트워크 기반 아키텍처 설계" 에서 REST 관련 챕터. 148 | 149 | [RFC 7231 문서][rfc-7231] -- 공신력 있는 리소스로서 HTTP/1.1 시맨틱 관련 사양에 대한 정리. 150 | 151 | [REST 실무][rest-in-practice] -- REST 기초에 관한 책. 152 | 153 | 154 | 155 | ## 4 가이드라인 해석 156 | 157 | 158 | ### 4.1 가이드라인 적용 159 | 160 | 이 가이드라인은 마이크로소프트 또는 다른 제휴 서비스가 제공하는 모든 공개 API에 적용 가능하다. 사설 API 또는 내부 API 역시도 이 가이드라인을 따라야 한다(SHOULD). 그 이유는 내부 API 역시도 결국 언젠가는 공개 API로 바뀌기 때문이다. 일관성은 비단 외부 고객을 위해서만 중요한 것이 아니라 내부 고객에게도 중요한 가치가 된다. 따라서 이 가이드라인은 어떤 형태의 서비스라 하더라도 적용 가능한 최고 실무 사례를 제공한다. 161 | 162 | 물론 이 가이드라인에도 예외 사항은 있다. REST 서비스 외부에서 만들어진 REST API를 바탕으로 구현한다거나 외부 REST API와 호환성을 유지하기 위해서는 그쪽에 맞춰야하고 그럴 경우에는 이 가이드라인을 굳이 따를 필요는 없다. 예를 들어 바이너리 프로토콜과 같은 다른 형식을 요구한다든지 하는 식으로 성능과 관련한 특수한 요구사항이 있을 수도(MAY) 있기 때문이다. 163 | 164 | 165 | 166 | ### 4.2 기존 서비스와 서비스 버전 관리를 위한 가이드라인 167 | 168 | 단순히 이 가이드라인에 맞추기 위해 기존에 잘 운영하던 서비스를 뒤집을 필요는 없다. 해당 서비스는 다음 버전을 출시할 때마다 조금씩 가이드라인에 맞추면 된다(SHOULD). 새 API를 추가할 때 그 API는 반드시(SHOULD) 동일 버전의 다른 API와 같은 일관성을 유지해야 한다. 만약 가이드라인 1.0 버전에 맞춰 서비스를 개발했다면 새 API를 추가할 때 이 역시 가이드라인 1.0 버전에 맞춰야 한다(SHOULD). 그다음에 서비스의 차기 메이저 버전 업데이트 때 최신 가이드라인에 맞춰 점차 업그레이드를 하면 된다. 169 | 170 | 171 | 172 | ### 4.3 요구 언어 173 | 174 | 이 글에 괄호를 이용해 명시한 키워드 "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", "OPTIONAL" 등은 [RFC 2119](https://www.ietf.org/rfc/rfc2119.txt) 문서에 근거해서 해석한다. RFC 2119 문서의 한국어 번역본은 [이곳](http://techhtml.github.io/rfc/RFC2119.html)에서 확인할 수 있다. 175 | 176 | 177 | 178 | ### 4.4 라이센스 179 | 180 | 이 문서는 크리에이티브 커먼즈 저작자 표시 4.0 국제 라이센스에 따라 사용할 수 있다. 이 라이센스에 대해 좀 더 자세히 알고 싶다면 [http://creativecommons.org/licenses/by/4.0/](http://creativecommons.org/licenses/by/4.0/) 페이지를 참조하거나 이 주소(Creative Commons, PO Box 1866, Mountain View, CA 94042, USA)로 편지를 보내면 된다. 181 | 182 | 183 | ## 5 Taxonomy 184 | As part of onboarding to Microsoft REST API Guidelines, services MUST comply with the taxonomy defined below. 185 | 186 | ### 5.1 Errors 187 | Errors, or more specifically Service Errors, are defined as a client passing invalid data to the service and the service _correctly_ rejecting that data. Examples include invalid credentials, incorrect parameters, unknown version IDs, or similar. These are generally "4xx" HTTP error codes and are the result of a client passing incorrect or invalid data. 188 | 189 | Errors do _not_ contribute to overall API availability. 190 | 191 | ### 5.2 Faults 192 | Faults, or more specifically Service Faults, are defined as the service failing to correctly return in response to a valid client request. These are generally "5xx" HTTP error codes. 193 | 194 | Faults _do_ contribute to the overall API availability. 195 | 196 | Calls that fail due to rate limiting or quota failures MUST NOT count as faults. Calls that fail as the result of a service fast-failing requests (often for its own protection) do count as faults. 197 | 198 | ### 5.3 Latency 199 | Latency is defined as how long a particular API call takes to complete, measured as closely to the client as possible. This metric applies to both synchronous and asynchronous APIs in the same way. For long running calls, the latency is measured on the initial request and measures how long that call (not the overall operation) takes to complete. 200 | 201 | ### 5.4 Time to complete 202 | Services that expose long operations MUST track "Time to Complete" metrics around those operations. 203 | 204 | ### 5.5 Long running API faults 205 | For a Long Running API, it's possible for both the initial request to begin the operation and the request to retrieve the results to technically work (each passing back a 200), but for the underlying operation to have failed. Long Running faults MUST roll up as Faults into the overall Availability metrics. 206 | 207 | ## 6 Client guidance 208 | To ensure the best possible experience for clients talking to a REST service, clients SHOULD adhere to the following best practices: 209 | 210 | ### 6.1 Ignore rule 211 | For loosely coupled clients where the exact shape of the data is not known before the call, if the server returns something the client wasn't expecting, the client MUST safely ignore it. 212 | 213 | Some services MAY add fields to responses without changing versions numbers. Services that do so MUST make this clear in their documentation and clients MUST ignore unknown fields. 214 | 215 | ### 6.2 Variable order rule 216 | Clients MUST NOT rely on the order in which data appears in JSON service responses. For example, clients SHOULD be resilient to the reordering of fields within a JSON object. When supported by the service, clients MAY request that data be returned in a specific order. For example, services MAY support the use of the _$orderBy_ querystring parameter to specify the order of elements within a JSON array. Services MAY also explicitly specify the ordering of some elements as part of the service contract. For example, a service MAY always return a JSON object's "type" information as the first field in an object to simplify response parsing on the client. Clients MAY rely on ordering behavior explicitly identified by the service. 217 | 218 | ### 6.3 Silent fail rule 219 | Clients requesting OPTIONAL server functionality (such as optional headers) MUST be resilient to the server ignoring that particular functionality. 220 | 221 | ## 7 Consistency fundamentals 222 | ### 7.1 URL structure 223 | Humans SHOULD be able to easily read and construct URLs. 224 | 225 | This facilitates discovery and eases adoption on platforms without a well-supported client library. 226 | 227 | An example of a well-structured URL is: 228 | 229 | ``` 230 | https://api.contoso.com/v1.0/people/jdoe@contoso.com/inbox 231 | ``` 232 | 233 | An example URL that is not friendly is: 234 | 235 | ``` 236 | https://api.contoso.com/EWS/OData/Users('jdoe@microsoft.com')/Folders('AAMkADdiYzI1MjUzLTk4MjQtNDQ1Yy05YjJkLWNlMzMzYmIzNTY0MwAuAAAAAACzMsPHYH6HQoSwfdpDx-2bAQCXhUk6PC1dS7AERFluCgBfAAABo58UAAA=') 237 | ``` 238 | 239 | A frequent pattern that comes up is the use of URLs as values. Services MAY use URLs as values. For example, the following is acceptable: 240 | 241 | ``` 242 | https://api.contoso.com/v1.0/items?url=https://resources.contoso.com/shoes/fancy 243 | ``` 244 | 245 | ### 7.2 URL length 246 | The HTTP 1.1 message format, defined in RFC 7230, in section [3.1.1][rfc-7230-3-1-1], defines no length limit on the Request Line, which includes the target URL. From the RFC: 247 | 248 | > HTTP does not place a predefined limit on the length of a 249 | request-line. [...] A server that receives a request-target longer than any URI it wishes to parse MUST respond 250 | with a 414 (URI Too Long) status code. 251 | 252 | Services that can generate URLs longer than 2,083 characters MUST make accommodations for the clients they wish to support. Here are some sources for determining what target clients support: 253 | 254 | * [http://stackoverflow.com/a/417184](http://stackoverflow.com/a/417184) 255 | * [https://blogs.msdn.microsoft.com/ieinternals/2014/08/13/url-length-limits/](https://blogs.msdn.microsoft.com/ieinternals/2014/08/13/url-length-limits/) 256 | 257 | Also note that some technology stacks have hard and adjustable url limits, so keep this in mind as you design your services. 258 | 259 | ### 7.3 Canonical identifier 260 | In addition to friendly URLs, resources that can be moved or be renamed SHOULD expose a URL that contains a unique stable identifier. It MAY be necessary to interact with the service to obtain a stable URL from the friendly name for the resource, as in the case of the "/my" shortcut used by some services. 261 | 262 | The stable identifier is not required to be a GUID. 263 | 264 | An example of a URL containing a canonical identifier is: 265 | 266 | ``` 267 | https://api.contoso.com/v1.0/people/7011042402/inbox 268 | ``` 269 | 270 | ### 7.4 Supported methods 271 | Operations MUST use the proper HTTP methods whenever possible, and operation idempotency MUST be respected. HTTP methods are frequently referred to as the HTTP verbs. The terms are synonymous in this context, however the HTTP specification uses the term method. 272 | 273 | Below is a list of methods that Microsoft REST services SHOULD support. Not all resources will support all methods, but all resources using the methods below MUST conform to their usage. 274 | 275 | Method | Description | Is Idempotent 276 | ------- | -------------------------------------------------------------------------------------------------------------------------- | ------------- 277 | GET | Return the current value of an object | True 278 | PUT | Replace an object, or create a named object, when applicable | True 279 | DELETE | Delete an object | True 280 | POST | Create a new object based on the data provided, or submit a command | False 281 | HEAD | Return metadata of an object for a GET response. Resources that support the GET method MAY support the HEAD method as well | True 282 | PATCH | Apply a partial update to an object | False 283 | OPTIONS | Get information about a request; see below for details. | True 284 | 285 | Table 1 286 | 287 | #### 7.4.1 POST 288 | POST operations SHOULD support the Location response header to specify the location of any created resource that was not explicitly named, via the Location header. 289 | 290 | As an example, imagine a service that allows creation of hosted servers, which will be named by the service: 291 | 292 | ```http 293 | POST http://api.contoso.com/account1/servers 294 | ``` 295 | 296 | The response would be something like: 297 | 298 | ```http 299 | 201 Created 300 | Location: http://api.contoso.com/account1/servers/server321 301 | ``` 302 | 303 | Where "server321" is the service-allocated server name. 304 | 305 | Services MAY also return the full metadata for the created item in the response. 306 | 307 | #### 7.4.2 PATCH 308 | PATCH has been standardized by IETF as the method to be used for updating an existing object incrementally (see [RFC 5789][rfc-5789]). Microsoft REST API Guidelines compliant APIs SHOULD support PATCH. 309 | 310 | #### 7.4.3 Creating resources via PATCH (UPSERT semantics) 311 | Services that allow callers to specify key values on create SHOULD support UPSERT semantics, and those that do MUST support creating resources using PATCH. Because PUT is defined as a complete replacement of the content, it is dangerous for clients to use PUT to modify data. Clients that do not understand (and hence ignore) properties on a resource are not likely to provide them on a PUT when trying to update a resource, hence such properties MAY be inadvertently removed. Services MAY optionally support PUT to update existing resources, but if they do they MUST use replacement semantics (that is, after the PUT, the resource's properties MUST match what was provided in the request, including deleting any server properties that were not provided). 312 | 313 | Under UPSERT semantics, a PATCH call to a nonexistent resource is handled by the server as a "create," and a PATCH call to an existing resource is handled as an "update." To ensure that an update request is not treated as a create or vice-versa, the client MAY specify precondition HTTP headers in the request. The service MUST NOT treat a PATCH request as an insert if it contains an If-Match header and MUST NOT treat a PATCH request as an update if it contains an If-None-Match header with a value of "*". 314 | 315 | If a service does not support UPSERT, then a PATCH call against a resource that does not exist MUST result in an HTTP "409 Conflict" error. 316 | 317 | #### 7.4.4 Options and link headers 318 | OPTIONS allows a client to retrieve information about a resource, at a minimum by returning the Allow header denoting the valid methods for this resource. 319 | 320 | In addition, services SHOULD include a Link header (see [RFC 5988][rfc-5988]) to point to documentation for the resource in question: 321 | 322 | ```http 323 | Link: <{help}>; rel="help" 324 | ``` 325 | 326 | Where {help} is the URL to a documentation resource. 327 | 328 | For examples on use of OPTIONS, see [preflighting CORS cross-domain calls][cors-preflight]. 329 | 330 | ### 7.5 Standard request headers 331 | The table of request headers below SHOULD be used by Microsoft REST API Guidelines services. Using these headers is not mandated, but if used they MUST be used consistently. 332 | 333 | All header values MUST follow the syntax rules set forth in the specification where the header field is defined. Many HTTP headers are defined in [RFC7231][rfc-7231], however a complete list of approved headers can be found in the [IANA Header Registry][IANA-headers]." 334 | 335 | Header | Type | Description 336 | --------------------------------- | ------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 337 | Authorization | String | Authorization header for the request 338 | Date | Date | Timestamp of the request in [RFC 3339][rfc-3339] format 339 | Accept | Content type | The requested content type for the response such as: Per the HTTP guidelines, this is just a hint and responses MAY have a different content type, such as a blob fetch where a successful response will just be the blob stream as the payload. For services following OData, the preference order specified in OData SHOULD be followed. 340 | Accept-Encoding | Gzip, deflate | REST endpoints SHOULD support GZIP and DEFLATE encoding, when applicable. For very large resources, services MAY ignore and return uncompressed data. 341 | Accept-Language | "en", "es", etc. | Specifies the preferred language for the response. Services are not required to support this, but if a service supports localization it MUST do so through the Accept-Language header. 342 | Accept-Charset | Charset type like "UTF-8" | Default is UTF-8, but services SHOULD be able to handle ISO-8859-1. 343 | Content-Type | Content type | Mime type of request body (PUT/POST/PATCH) 344 | Prefer | return=minimal, return=representation | If the return=minimal preference is specified, services SHOULD return an empty body in response to a successful insert or update. If return=representation is specified, services SHOULD return the created or updated resource in the response. Services SHOULD support this header if they have scenarios where clients would sometimes benefit from responses, but sometimes the response would impose too much of a hit on bandwidth. 345 | If-Match, If-None-Match, If-Range | String | Services that support updates to resources using optimistic concurrency control MUST support the If-Match header to do so. Services MAY also use other headers related to ETags as long as they follow the HTTP specification. 346 | 347 | ### 7.6 Standard response headers 348 | Services SHOULD return the following response headers, except where noted in the "required" column. 349 | 350 | Response Header | Required | Description 351 | ------------------ | --------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 352 | Date | All responses | The date the request was processed, in [RFC 3339][rfc-3339] format 353 | Content-Type | All responses | The content type 354 | Content-Encoding | All responses | GZIP or DEFLATE, as appropriate 355 | Preference-Applied | When specified in request | Whether a preference indicated in the Prefer request header was applied 356 | ETag | When the requested resource has an entity tag | The ETag response-header field provides the current value of the entity tag for the requested variant. Used with If-Match, If-None-Match and If-Range to implement optimistic concurrency control. 357 | 358 | ### 7.7 Custom headers 359 | Custom headers MUST NOT be required for the basic operation of a given API. 360 | 361 | Some of the guidelines in this document prescribe the use of nonstandard HTTP headers. In addition, some services MAY need to add extra functionality, which is exposed via HTTP headers. The following guidelines help maintain consistency across usage of custom headers. 362 | 363 | Headers that are not standard HTTP headers MUST have one of two formats: 364 | 365 | 1. A generic format for headers that are registered as "provisional" with IANA ([RFC 3864][rfc-3864]) 366 | 2. A scoped format for headers that are too usage-specific for registration 367 | 368 | These two formats are described below. 369 | 370 | ### 7.8 Specifying headers as query parameters 371 | Some headers pose challenges for some scenarios such as AJAX clients, especially when making cross-domain calls where adding headers MAY not be supported. As such, some headers MAY be accepted as Query Parameters in addition to headers, with the same naming as the header: 372 | 373 | Not all headers make sense as query parameters, including most standard HTTP headers. 374 | 375 | The criteria for considering when to accept headers as parameters are: 376 | 377 | 1. Any custom headers MUST be also accepted as parameters. 378 | 2. Required standard headers MAY be accepted as parameters. 379 | 3. Required headers with security sensitivity (e.g., Authorization header) MIGHT NOT be appropriate as parameters; the service owner SHOULD evaluate these on a case-by-case basis. 380 | 381 | The one exception to this rule is the Accept header. It's common practice to use a scheme with simple names instead of the full functionality described in the HTTP specification for Accept. 382 | 383 | ### 7.9 PII parameters 384 | Consistent with their organization's privacy policy, clients SHOULD NOT transmit personally identifiable information (PII) parameters in the URL (as part of path or query string) because this information can be inadvertently exposed via client, network, and server logs and other mechanisms. 385 | 386 | Consequently, a service SHOULD accept PII parameters transmitted as headers. 387 | 388 | However, there are many scenarios where the above recommendations cannot be followed due to client or software limitations. To address these limitations, services SHOULD also accept these PII parameters as part of the URL consistent with the rest of these guidelines. 389 | 390 | Services that accept PII parameters -- whether in the URL or as headers -- SHOULD be compliant with privacy policy specified by their organization's engineering leadership. This will typically include recommending that clients prefer headers for transmission and implementations adhere to special precautions to ensure that logs and other service data collection are properly handled. 391 | 392 | ### 7.10 Response formats 393 | For organizations to have a successful platform, they must serve data in formats developers are accustomed to using, and in consistent ways that allow developers to handle responses with common code. 394 | 395 | Web-based communication, especially when a mobile or other low-bandwidth client is involved, has moved quickly in the direction of JSON for a variety of reasons, including its tendency to be lighter weight and its ease of consumption with JavaScript-based clients. 396 | 397 | JSON property names SHOULD be camelCased. 398 | 399 | Services SHOULD provide JSON as the default encoding. 400 | 401 | #### 7.10.1 Clients-specified response format 402 | In HTTP, response format SHOULD be requested by the client using the Accept header. This is a hint, and the server MAY ignore it if it chooses to, even if this isn't typical of well-behaved servers. Clients MAY send multiple Accept headers and the service MAY choose one of them. 403 | 404 | The default response format (no Accept header provided) SHOULD be application/json, and all services MUST support application/json. 405 | 406 | Accept Header | Response type | Notes 407 | ---------------- | ---------------------------------- | ------------------------------------------- 408 | application/json | Payload SHOULD be returned as JSON | Also accept text/javascript for JSONP cases 409 | 410 | ```http 411 | GET https://api.contoso.com/v1.0/products/user 412 | Accept: application/json 413 | ``` 414 | 415 | #### 7.10.2 Error condition responses 416 | For nonsuccess conditions, developers SHOULD be able to write one piece of code that handles errors consistently across different Microsoft REST API Guidelines services. This allows building of simple and reliable infrastructure to handle exceptions as a separate flow from successful responses. The following is based on the OData v4 JSON spec. However, it is very generic and does not require specific OData constructs. APIs SHOULD use this format even if they are not using other OData constructs. 417 | 418 | The error response MUST be a single JSON object. This object MUST have a name/value pair named "error." The value MUST be a JSON object. 419 | 420 | This object MUST contain name/value pairs with the names "code" and "message," and it MAY contain name/value pairs with the names "target," "details" and "innererror." 421 | 422 | The value for the "code" name/value pair is a language-independent string. Its value is a service-defined error code that SHOULD be human-readable. This code serves as a more specific indicator of the error than the HTTP error code specified in the response. Services SHOULD have a relatively small number (about 20) of possible values for "code," and all clients MUST be capable of handling all of them. Most services will require a much larger number of more specific error codes, which are not interesting to all clients. These error codes SHOULD be exposed in the "innererror" name/value pair as described below. Introducing a new value for "code" that is visible to existing clients is a breaking change and requires a version increase. Services can avoid breaking changes by adding new error codes to "innererror" instead. 423 | 424 | The value for the "message" name/value pair MUST be a human-readable representation of the error. It is intended as an aid to developers and is not suitable for exposure to end users. Services wanting to expose a suitable message for end users MUST do so through an [annotation][odata-json-annotations] or custom property. Services SHOULD NOT localize "message" for the end user, because doing so MAY make the value unreadable to the app developer who may be logging the value, as well as make the value less searchable on the Internet. 425 | 426 | The value for the "target" name/value pair is the target of the particular error (e.g., the name of the property in error). 427 | 428 | The value for the "details" name/value pair MUST be an array of JSON objects that MUST contain name/value pairs for "code" and "message," and MAY contain a name/value pair for "target," as described above. The objects in the "details" array usually represent distinct, related errors that occurred during the request. See example below. 429 | 430 | The value for the "innererror" name/value pair MUST be an object. The contents of this object are service-defined. Services wanting to return more specific errors than the root-level code MUST do so by including a name/value pair for "code" and a nested "innererror." Each nested "innererror" object represents a higher level of detail than its parent. When evaluating errors, clients MUST traverse through all of the nested "innererrors" and choose the deepest one that they understand. This scheme allows services to introduce new error codes anywhere in the hierarchy without breaking backwards compatibility, so long as old error codes still appear. The service MAY return different levels of depth and detail to different callers. For example, in development environments, the deepest "innererror" MAY contain internal information that can help debug the service. To guard against potential security concerns around information disclosure, services SHOULD take care not to expose too much detail unintentionally. Error objects MAY also include custom server-defined name/value pairs that MAY be specific to the code. Error types with custom server-defined properties SHOULD be declared in the service's metadata document. See example below. 431 | 432 | Error responses MAY contain [annotations][odata-json-annotations] in any of their JSON objects. 433 | 434 | We recommend that for any transient errors that may be retried, services SHOULD include a Retry-After HTTP header indicating the minimum number of seconds that clients SHOULD wait before attempting the operation again. 435 | 436 | ##### ErrorResponse : Object 437 | 438 | Property | Type | Required | Description 439 | -------- | ---- | -------- | ----------- 440 | `error` | Error | ✔ | The error object. 441 | 442 | ##### Error : Object 443 | 444 | Property | Type | Required | Description 445 | -------- | ---- | -------- | ----------- 446 | `code` | String (enumerated) | ✔ | One of a server-defined set of error codes. 447 | `message` | String | ✔ | A human-readable representation of the error. 448 | `target` | String | | The target of the error. 449 | `details` | Error[] | | An array of details about specific errors that led to this reported error. 450 | `innererror` | InnerError | | An object containing more specific information than the current object about the error. 451 | 452 | ##### InnerError : Object 453 | 454 | Property | Type | Required | Description 455 | -------- | ---- | -------- | ----------- 456 | `code` | String | | A more specific error code than was provided by the containing error. 457 | `innererror` | InnerError | | An object containing more specific information than the current object about the error. 458 | 459 | ##### Examples 460 | 461 | Example of "innererror": 462 | 463 | ```json 464 | { 465 | "error": { 466 | "code": "BadArgument", 467 | "message": "Previous passwords may not be reused", 468 | "target": "password", 469 | "innererror": { 470 | "code": "PasswordError", 471 | "innererror": { 472 | "code": "PasswordDoesNotMeetPolicy", 473 | "minLength": "6", 474 | "maxLength": "64", 475 | "characterTypes": ["lowerCase","upperCase","number","symbol"], 476 | "minDistinctCharacterTypes": "2", 477 | "innererror": { 478 | "code": "PasswordReuseNotAllowed" 479 | } 480 | } 481 | } 482 | } 483 | } 484 | ``` 485 | 486 | In this example, the most basic error code is "BadArgument," but for clients that are interested, there are more specific error codes in "innererror." The "PasswordReuseNotAllowed" code may have been added by the service at a later date, having previously only returned "PasswordDoesNotMeetPolicy." Existing clients do not break when the new error code is added, but new clients MAY take advantage of it. The "PasswordDoesNotMeetPolicy" error also includes additional name/value pairs that allow the client to determine the server's configuration, validate the user's input programmatically, or present the server's constraints to the user within the client's own localized messaging. 487 | 488 | Example of "details": 489 | 490 | ```json 491 | { 492 | "error": { 493 | "code": "BadArgument", 494 | "message": "Multiple errors in ContactInfo data", 495 | "target": "ContactInfo", 496 | "details": [ 497 | { 498 | "code": "NullValue", 499 | "target": "PhoneNumber", 500 | "message": "Phone number must not be null" 501 | }, 502 | { 503 | "code": "NullValue", 504 | "target": "LastName", 505 | "message": "Last name must not be null" 506 | }, 507 | { 508 | "code": "MalformedValue", 509 | "target": "Address", 510 | "message": "Address is not valid" 511 | } 512 | ] 513 | } 514 | } 515 | ``` 516 | 517 | In this example there were multiple problems with the request, with each individual error listed in "details." 518 | 519 | ### 7.11 HTTP Status Codes 520 | Standard HTTP Status Codes SHOULD be used; see the HTTP Status Code definitions for more information. 521 | 522 | ### 7.12 Client library optional 523 | Developers MUST be able to develop on a wide variety of platforms and languages, such as Windows, MacOS, Linux, C#, Python, Node.js, and Ruby. 524 | 525 | Services SHOULD be able to be accessed from simple HTTP tools such as curl without significant effort. 526 | 527 | Service developer portals SHOULD provide the equivalent of "Get Developer Token" to facilitate experimentation and curl support. 528 | 529 | ## 8 CORS 530 | Services compliant with the Microsoft REST API Guidelines MUST support [CORS (Cross Origin Resource Sharing)][cors]. Services SHOULD support an allowed origin of CORS * and enforce authorization through valid OAuth tokens. Services SHOULD NOT support user credentials with origin validation. There MAY be exceptions for special cases. 531 | 532 | ### 8.1 Client guidance 533 | Web developers usually don't need to do anything special to take advantage of CORS. All of the handshake steps happen invisibly as part of the standard XMLHttpRequest calls they make. 534 | 535 | Many other platforms, such as .NET, have integrated support for CORS. 536 | 537 | #### 8.1.1 Avoiding preflight 538 | Because the CORS protocol can trigger preflight requests that add additional round trips to the server, performance-critical apps might be interested in avoiding them. The spirit behind CORS is to avoid preflight for any simple cross-domain requests that old non-CORS-capable browsers were able to make. All other requests require preflight. 539 | 540 | A request is "simple" and avoids preflight if its method is GET, HEAD or POST, and if it doesn't contain any request headers besides Accept, Accept-Language and Content-Language. For POST requests, the Content-Type header is also allowed, but only if its value is "application/x-www-form-urlencoded," "multipart/form-data" or "text/plain." For any other headers or values, a preflight request will happen. 541 | 542 | ### 8.2 Service guidance 543 | At minimum, services MUST: 544 | - Understand the Origin request header that browsers send on cross-domain requests, and the Access-Control-Request-Method request header that they send on preflight OPTIONS requests that check for access. 545 | - If the Origin header is present in a request: 546 | - If the request uses the OPTIONS method and contains the Access-Control-Request-Method header, then it is a preflight request intended to probe for access before the actual request. Otherwise, it is an actual request. For preflight requests, beyond performing the steps below to add headers, services MUST perform no additional processing and MUST return a 200 OK. For non-preflight requests, the headers below are added in addition to the request's regular processing. 547 | - Add an Access-Control-Allow-Origin header to the response, containing the same value as the Origin request header. Note that this requires services to dynamically generate the header value. Resources that do not require cookies or any other form of [user credentials][cors-user-credentials] MAY respond with a wildcard asterisk (*) instead. Note that the wildcard is acceptable here only, and not for any of the other headers described below. 548 | - If the caller requires access to a response header that is not in the set of [simple response headers][cors-simple-headers] (Cache-Control, Content-Language, Content-Type, Expires, Last-Modified, Pragma), then add an Access-Control-Expose-Headers header containing the list of additional response header names the client should have access to. 549 | - If the request requires cookies, then add an Access-Control-Allow-Credentials header set to "true." 550 | - If the request was a preflight request (see first bullet), then the service MUST: 551 | - Add an Access-Control-Allow-Headers response header containing the list of request header names the client is permitted to use. This list need only contain headers that are not in the set of [simple request headers][cors-simple-headers] (Accept, Accept-Language, Content-Language). If there are no restrictions on headers the service accepts, the service MAY simply return the same value as the Access-Control-Request-Headers header sent by the client. 552 | - Add an Access-Control-Allow-Methods response header containing the list of HTTP methods the caller is permitted to use. 553 | 554 | Add an Access-Control-Max-Age pref response header containing the number of seconds for which this preflight response is valid (and hence can be avoided before subsequent actual requests). Note that while it is customary to use a large value like 2592000 (30 days), many browsers self-impose a much lower limit (e.g., five minutes). 555 | 556 | Because browser preflight response caches are notoriously weak, the additional round trip from a preflight response hurts performance. Services used by interactive Web clients where performance is critical SHOULD avoid patterns that cause a preflight request 557 | - For GET and HEAD calls, avoid requiring request headers that are not part of the simple set above. Allow them to be provided as query parameters instead. 558 | - The Authorization header is not part of the simple set, so the authentication token MUST be sent through the "access_token" query parameter instead, for resources requiring authentication. Note that passing authentication tokens in the URL is not recommended, because it can lead to the token getting recorded in server logs and exposed to anyone with access to those logs. Services that accept authentication tokens through the URL MUST take steps to mitigate the security risks, such as using short-lived authentication tokens, suppressing the auth token from getting logged, and controlling access to server logs. 559 | 560 | - Avoid requiring cookies. XmlHttpRequest will only send cookies on cross-domain requests if the "withCredentials" attribute is set; this also causes a preflight request. 561 | - Services that require cookie-based authentication MUST use a "dynamic canary" to secure all APIs that accept cookies. 562 | 563 | - For POST calls, prefer simple Content-Types in the set of ("application/x-www-form-urlencoded," "multipart/form-data," "text/plain") where applicable. Any other Content-Type will induce a preflight request. 564 | - Services MUST NOT contravene other API recommendations in the name of avoiding CORS preflight requests. In particular, in accordance with recommendations, most POST requests will actually require a preflight request due to the Content-Type. 565 | - If eliminating preflight is critical, then a service MAY support alternative mechanisms for data transfer, but the RECOMMENDED approach MUST also be supported. 566 | 567 | In addition, when appropriate services MAY support the JSONP pattern for simple, GET-only cross-domain access. In JSONP, services take a parameter indicating the format (_$format=json_) and a parameter indicating a callback (_$callback=someFunc_), and return a text/javascript document containing the JSON response wrapped in a function call with the indicated name. More on JSONP at Wikipedia: [JSONP](https://en.wikipedia.org/wiki/JSONP). 568 | 569 | ## 9 Collections 570 | ### 9.1 Item keys 571 | Services MAY support durable identifiers for each item in the collection, and that identifier SHOULD be represented in JSON as "id". These durable identifiers are often used as item keys. 572 | 573 | Collections that support durable identifiers MAY support delta queries. 574 | 575 | ### 9.2 Serialization 576 | Collections are represented in JSON using standard array notation. 577 | 578 | ### 9.3 Collection URL patterns 579 | Collections are located directly under the service root when they are top level, or as a segment under another resource when scoped to that resource. 580 | 581 | For example: 582 | 583 | ```http 584 | GET https://api.contoso.com/v1.0/people 585 | ``` 586 | 587 | Whenever possible, services MUST support the "/" pattern. For example: 588 | 589 | ```http 590 | GET https://{serviceRoot}/{collection}/{id} 591 | ``` 592 | 593 | Where: 594 | - {serviceRoot} – the combination of host (site URL) + the root path to the service 595 | - {collection} – the name of the collection, unabbreviated, pluralized 596 | - {id} – the value of the unique id property. When using the "/" pattern this MUST be the raw string/number/guid value with no quoting but properly escaped to fit in a URL segment. 597 | 598 | #### 9.3.1 Nested collections and properties 599 | Collection items MAY contain other collections. For example, a user collection MAY contain user resources that have multiple addresses: 600 | 601 | ```http 602 | GET https://api.contoso.com/v1.0/people/123/addresses 603 | ``` 604 | 605 | ```json 606 | { 607 | "value": [ 608 | { 609 | "id": 123, 610 | "name": "John", 611 | "addresses": [ 612 | {"street":"1st Avenue","city":"Seattle"}, 613 | {"street":"124th Ave NE","city":"Redmond"} 614 | ] 615 | } 616 | ] 617 | } 618 | ``` 619 | 620 | ### 9.4 Big collections 621 | As data grows, so do collections. Planning for pagination is important for all services. Therefore, when multiple pages are available, the serialization payload MUST contain the opaque URL for the next page as appropriate. Refer to the paging guidance for more details. 622 | 623 | Clients MUST be resilient to collection data being either paged or nonpaged for any given request. 624 | 625 | ```json 626 | { 627 | "value":[ 628 | { "id": "Item 1","price": 99.95,"sizes": null}, 629 | { … }, 630 | { … }, 631 | { "id": "Item 99","price": 59.99,"sizes": null} 632 | ], 633 | "@nextLink": "{opaqueUrl}" 634 | } 635 | ``` 636 | 637 | ### 9.5 Changing collections 638 | POST requests are not idempotent. This means that two POST requests sent to a collection resource with exactly the same payload MAY lead to multiple items being created in that collection. This is often the case for insert operations on items with a server-side generated id. 639 | 640 | For example, the following request: 641 | 642 | ```http 643 | POST https://api.contoso.com/v1.0/people 644 | ``` 645 | 646 | Would lead to a response indicating the location of the new collection item: 647 | 648 | ```http 649 | 201 Created 650 | Location: https://api.contoso.com/v1.0/people/123 651 | ``` 652 | 653 | And once executed again, would likely lead to another resource: 654 | 655 | ```http 656 | 201 Created 657 | Location: https://api.contoso.com/v1.0/people/124 658 | ``` 659 | 660 | While a PUT request would require the indication of the collection item with the corresponding key instead: 661 | 662 | ```http 663 | PUT https://api.contoso.com/v1.0/people/123 664 | ``` 665 | 666 | ### 9.6 Sorting collections 667 | The results of a collection query MAY be sorted based on property values. The property is determined by the value of the _$orderBy_ query parameter. 668 | 669 | The value of the _$orderBy_ parameter contains a comma-separated list of expressions used to sort the items. A special case of such an expression is a property path terminating on a primitive property. 670 | 671 | The expression MAY include the suffix "asc" for ascending or "desc" for descending, separated from the property name by one or more spaces. If "asc" or "desc" is not specified, the service MUST order by the specified property in ascending order. 672 | 673 | NULL values MUST sort as "less than" non-NULL values. 674 | 675 | Items MUST be sorted by the result values of the first expression, and then items with the same value for the first expression are sorted by the result value of the second expression, and so on. The sort order is the inherent order for the type of the property. 676 | 677 | For example: 678 | 679 | ```http 680 | GET https://api.contoso.com/v1.0/people?$orderBy=name 681 | ``` 682 | 683 | Will return all people sorted by name in ascending order. 684 | 685 | For example: 686 | 687 | ```http 688 | GET https://api.contoso.com/v1.0/people?$orderBy=name desc 689 | ``` 690 | 691 | Will return all people sorted by name in descending order. 692 | 693 | Sub-sorts can be specified by a comma-separated list of property names with OPTIONAL direction qualifier. 694 | 695 | For example: 696 | 697 | ```http 698 | GET https://api.contoso.com/v1.0/people?$orderBy=name desc,hireDate 699 | ``` 700 | 701 | Will return all people sorted by name in descending order and a secondary sort order of hireDate in ascending order. 702 | 703 | Sorting MUST compose with filtering such that: 704 | 705 | ```http 706 | GET https://api.contoso.com/v1.0/people?$filter=name eq 'david'&$orderBy=hireDate 707 | ``` 708 | 709 | Will return all people whose name is David sorted in ascending order by hireDate. 710 | 711 | #### 9.6.1 Interpreting a sorting expression 712 | Sorting parameters MUST be consistent across pages, as both client and server-side paging is fully compatible with sorting. 713 | 714 | If a service does not support sorting by a property named in a _$orderBy_ expression, the service MUST respond with an error message as defined in the Responding to Unsupported Requests section. 715 | 716 | ### 9.7 Filtering 717 | The _$filter_ querystring parameter allows clients to filter a collection of resources that are addressed by a request URL. The expression specified with _$filter_ is evaluated for each resource in the collection, and only items where the expression evaluates to true are included in the response. Resources for which the expression evaluates to false or to null, or which reference properties that are unavailable due to permissions, are omitted from the response. 718 | 719 | Example: return all Products whose Price is less than $10.00 720 | 721 | ```http 722 | GET https://api.contoso.com/v1.0/products?$filter=price lt 10.00 723 | ``` 724 | 725 | The value of the _$filter_ option is a Boolean expression. 726 | 727 | #### 9.7.1 Filter operations 728 | Services that support _$filter_ SHOULD support the following minimal set of operations. 729 | 730 | Operator | Description | Example 731 | -------------------- | --------------------- | ----------------------------------------------------- 732 | Comparison Operators | | 733 | eq | Equal | city eq 'Redmond' 734 | ne | Not equal | city ne 'London' 735 | gt | Greater than | price gt 20 736 | ge | Greater than or equal | price ge 10 737 | lt | Less than | price lt 20 738 | le | Less than or equal | price le 100 739 | Logical Operators | | 740 | and | Logical and | price le 200 and price gt 3.5 741 | or | Logical or | price le 3.5 or price gt 200 742 | not | Logical negation | not price le 3.5 743 | Grouping Operators | | 744 | ( ) | Precedence grouping | (priority eq 1 or city eq 'Redmond') and price gt 100 745 | 746 | #### 9.7.2 Operator examples 747 | The following examples illustrate the use and semantics of each of the logical operators. 748 | 749 | Example: all products with a name equal to 'Milk' 750 | 751 | ```http 752 | GET https://api.contoso.com/v1.0/products?$filter=name eq 'Milk' 753 | ``` 754 | 755 | Example: all products with a name not equal to 'Milk' 756 | 757 | ```http 758 | GET https://api.contoso.com/v1.0/products?$filter=name ne 'Milk' 759 | ``` 760 | 761 | Example: all products with the name 'Milk' that also have a price less than 2.55: 762 | 763 | ```http 764 | GET https://api.contoso.com/v1.0/products?$filter=name eq 'Milk' and price lt 2.55 765 | ``` 766 | 767 | Example: all products that either have the name 'Milk' or have a price less than 2.55: 768 | 769 | ```http 770 | GET https://api.contoso.com/v1.0/products?$filter=name eq 'Milk' or price lt 2.55 771 | ``` 772 | 773 | Example 54: all products that have the name 'Milk' or 'Eggs' and have a price less than 2.55: 774 | 775 | ```http 776 | GET https://api.contoso.com/v1.0/products?$filter=(name eq 'Milk' or name eq 'Eggs') and price lt 2.55 777 | ``` 778 | 779 | #### 9.7.3 Operator precedence 780 | Services MUST use the following operator precedence for supported operators when evaluating _$filter_ expressions. Operators are listed by category in order of precedence from highest to lowest. Operators in the same category have equal precedence: 781 | 782 | Group | Operator | Description 783 | --------------- | -------- | --------------------- 784 | Grouping | ( ) | Precedence grouping 785 | Unary | not | Logical Negation 786 | Relational | gt | Greater Than 787 | | ge | Greater than or Equal 788 | | lt | Less Than 789 | | le | Less than or Equal 790 | Equality | eq | Equal 791 | | ne | Not Equal 792 | Conditional AND | and | Logical And 793 | Conditional OR | or | Logical Or 794 | 795 | ### 9.8 Pagination 796 | RESTful APIs that return collections MAY return partial sets. Consumers of these services MUST expect partial result sets and correctly page through to retrieve an entire set. 797 | 798 | There are two forms of pagination that MAY be supported by RESTful APIs. Server-driven paging mitigates against denial-of-service attacks by forcibly paginating a request over multiple response payloads. Client-driven paging enables clients to request only the number of resources that it can use at a given time. 799 | 800 | Sorting and Filtering parameters MUST be consistent across pages, because both client- and server-side paging is fully compatible with both filtering and sorting. 801 | 802 | #### 9.8.1 Server-driven paging 803 | Paginated responses MUST indicate a partial result by including a continuation token in the response. The absence of a continuation token means that no additional pages are available. 804 | 805 | Clients MUST treat the continuation URL as opaque, which means that query options may not be changed while iterating over a set of partial results. 806 | 807 | Example: 808 | 809 | ```http 810 | GET http://api.contoso.com/v1.0/people HTTP/1.1 811 | Accept: application/json 812 | 813 | HTTP/1.1 200 OK 814 | Content-Type: application/json 815 | 816 | { 817 | ..., 818 | "value": [...], 819 | "@nextLink": "{opaqueUrl}" 820 | } 821 | ``` 822 | 823 | #### 9.8.2 Client-driven paging 824 | Clients MAY use _$top_ and _$skip_ query parameters to specify a number of results to return and an offset. The server SHOULD honor the values specified by the client; however, clients MUST be prepared to handle responses that contain a different page size or contain a continuation token. 825 | 826 | Note: If the server can't honor _$top_ and/or _$skip_, the server MUST return an error to the client informing about it instead of just ignoring the query options. This will avoid the risk of the client making assumptions about the data returned. 827 | 828 | Example: 829 | 830 | ```http 831 | GET http://api.contoso.com/v1.0/people?$top=5&$skip=2 HTTP/1.1 832 | Accept: application/json 833 | 834 | HTTP/1.1 200 OK 835 | Content-Type: application/json 836 | 837 | { 838 | ..., 839 | "value": [...] 840 | } 841 | ``` 842 | 843 | #### 9.8.3 Additional considerations 844 | **Stable order prerequisite:** Both forms of paging depend on the collection of items having a stable order. The server MUST supplement any specified order criteria with additional sorts (typically by key) to ensure that items are always ordered consistently. 845 | 846 | **Missing/repeated results:** Even if the server enforces a consistent sort order, results MAY be missing or repeated based on creation or deletion of other resources. Clients MUST be prepared to deal with these discrepancies. The server SHOULD always encode the record ID of the last read record, helping the client in the process of managing repeated/missing results. 847 | 848 | **Combining client- and server-driven paging:** Note that client-driven paging does not preclude server-driven paging. If the page size requested by the client is larger than the default page size supported by the server, the expected response would be the number of results specified by the client, paginated as specified by the server paging settings. 849 | 850 | **Page Size:** Clients MAY request server-driven paging with a specific page size by specifying a _$maxpagesize_ preference. The server SHOULD honor this preference if the specified page size is smaller than the server's default page size. 851 | 852 | **Paginating embedded collections:** It is possible for both client-driven paging and server-driven paging to be applied to embedded collections. If a server paginates an embedded collection, it MUST include additional continuation tokens as appropriate. 853 | 854 | **Recordset count:** Developers who want to know the full number of records across all pages, MAY include the query parameter _$count=true_ to tell the server to include the count of items in the response. 855 | 856 | ### 9.9 Compound collection operations 857 | Filtering, Sorting and Pagination operations MAY all be performed against a given collection. When these operations are performed together, the evaluation order MUST be: 858 | 859 | 1. **Filtering**. This includes all range expressions performed as an AND operation. 860 | 2. **Sorting**. The potentially filtered list is sorted according to the sort criteria. 861 | 3. **Pagination**. The materialized paginated view is presented over the filtered, sorted list. This applies to both server-driven pagination and client-driven pagination. 862 | 863 | ## 10 Delta queries 864 | Services MAY choose to support delta queries. 865 | 866 | ### 10.1 Delta links 867 | Delta links are opaque, service-generated links that the client uses to retrieve subsequent changes to a result. 868 | 869 | At a conceptual level delta links are based on a defining query that describes the set of results for which changes are being tracked. The delta link encodes the collection of entities for which changes are being tracked, along with a starting point from which to track changes. 870 | 871 | If the query contains a filter, the response MUST include only changes to entities matching the specified criteria. The key principles of the Delta Query are: 872 | - Every item in the set MUST have a persistent identifier. That identifier SHOULD be represented as "id". This identifier is a service defined opaque string that MAY be used by the client to track object across calls. 873 | - The delta MUST contain an entry for each entity that newly matches the specified criteria, and MUST contain a "@removed" entry for each entity that no longer matches the criteria. 874 | - Re-evaluate the query and compare it to original set of results; every entry uniquely in the current set MUST be returned as an Add operation, and every entry uniquely in the original set MUST be returned as a "remove" operation. 875 | - Each entity that previously did not match the criteria but matches it now MUST be returned as an "add"; conversely, each entity that previously matched the query but no longer does MUST be returned as a "@removed" entry. 876 | - Entities that have changed MUST be included in the set using their standard representation. 877 | - Services MAY add additional metadata to the "@removed" node, such as a reason for removal, or a "removed at" timestamp. We recommend teams coordinate with the Microsoft REST API Guidelines Working Group on extensions to help maintain consistency. 878 | 879 | The delta link MUST NOT encode any client top or skip value. 880 | 881 | ### 10.2 Entity representation 882 | Added and updated entities are represented in the entity set using their standard representation. From the perspective of the set, there is no difference between an added or updated entity. 883 | 884 | Removed entities are represented using only their "id" and an "@removed" node. The presence of an "@removed" node MUST represent the removal of the entry from the set. 885 | 886 | ### 10.3 Obtaining a delta link 887 | A delta link is obtained by querying a collection or entity and appending a $delta query string parameter. For example: 888 | 889 | ```http 890 | GET https://api.contoso.com/v1.0/people?$delta 891 | HTTP/1.1 892 | Accept: application/json 893 | 894 | HTTP/1.1 200 OK 895 | Content-Type: application/json 896 | 897 | { 898 | "value":[ 899 | { "id": "1", "name": "Matt"}, 900 | { "id": "2", "name": "Mark"}, 901 | { "id": "3", "name": "John"}, 902 | ], 903 | "@deltaLink": "{opaqueUrl}" 904 | } 905 | ``` 906 | 907 | Note: If the collection is paginated the deltaLink will only be present on the final page but MUST reflect any changes to the data returned across all pages. 908 | 909 | ### 10.4 Contents of a delta link response 910 | Added/Updated entries MUST appear as regular JSON objects, with regular item properties. Returning the added/modified items in their regular representation allows the client to merge them into their existing "cache" using standard merge concepts based on the "id" field. 911 | 912 | Entries removed from the defined collection MUST be included in the response. Items removed from the set MUST be represented using only their "id" and an "@removed" node. 913 | 914 | ### 10.5 Using a delta link 915 | The client requests changes by invoking the GET method on the delta link. The client MUST use the delta URL as is -- in other words the client MUST NOT modify the URL in any way (e.g., parsing it and adding additional query string parameters). In this example: 916 | 917 | ```http 918 | GET https://{opaqueUrl} HTTP/1.1 919 | Accept: application/json 920 | 921 | HTTP/1.1 200 OK 922 | Content-Type: application/json 923 | 924 | { 925 | "value":[ 926 | { "id": "1", "name": "Mat"}, 927 | { "id": "2", "name": "Marc"}, 928 | { "id": "3", "@removed": {} }, 929 | { "id": "4", "name": "Luc"} 930 | ], 931 | "@deltaLink": "{opaqueUrl}" 932 | } 933 | ``` 934 | 935 | The results of a request against the delta link may span multiple pages but MUST be ordered by the service across all pages in such a way as to ensure a deterministic result when applied in order to the response that contained the delta link. 936 | 937 | If no changes have occurred, the response is an empty collection that contains a delta link for subsequent changes if requested. This delta link MAY be identical to the delta link resulting in the empty collection of changes. 938 | 939 | If the delta link is no longer valid, the service MUST respond with _410 Gone_. The response SHOULD include a Location header that the client can use to retrieve a new baseline set of results. 940 | 941 | ## 11 JSON standardizations 942 | ### 11.1 JSON formatting standardization for primitive types 943 | Primitive values MUST be serialized to JSON following the rules of [RFC4627][rfc-4627]. 944 | 945 | ### 11.2 Guidelines for dates and times 946 | #### 11.2.1 Producing dates 947 | Services MUST produce dates using the `DateLiteral` format, and SHOULD use the `Iso8601Literal` format unless there are compelling reasons to do otherwise. Services that do use the `StructuredDateLiteral` format MUST NOT produce dates using the `T` kind unless BOTH the additional precision is REQUIRED and ECMAScript clients are explicitly unsupported. (Non-Normative statement: When deciding which particular `DateKind` to standardize on, the approximate order of preference is `E, C, U, W, O, X, I, T`. This optimizes for ECMAScript, .NET, and C++ programmers, in that order.) 948 | 949 | #### 11.2.2 Consuming dates 950 | Services MUST accept dates from clients that use the same `DateLiteral` format (including the `DateKind`, if applicable) that they produce, and SHOULD accept dates using any `DateLiteral` format. 951 | 952 | #### 11.2.3 Compatibility 953 | Services MUST use the same `DateLiteral` format (including the same `DateKind`, if applicable) for all resources of the same type, and SHOULD use the same `DateLiteral` format (and `DateKind`, if applicable) for all resources across the entire service. 954 | 955 | Any change to the `DateLiteral` format produced by the service (including the `DateKind`, if applicable) and any reductions in the `DateLiteral` formats (and `DateKind`, if applicable) accepted by the service MUST be treated as a breaking change. Any widening of the `DateLiteral` formats accepted by the service is NOT considered a breaking change. 956 | 957 | ### 11.3 JSON serialization of dates and times 958 | Round-tripping serialized dates with JSON is a hard problem. Although ECMAScript supports literals for most built-in types, it does not define a literal format for dates. The Web has coalesced around the [ECMAScript subset of ISO 8601 date formats (ISO 8601)][iso-8601], but there are situations where this format is not desirable. For those cases, this document defines a JSON serialization format that can be used to unambiguously represent dates in different formats. Other serialization formats (such as XML) could be derived from this format. 959 | 960 | #### 11.3.1 The `DateLiteral` format 961 | Dates represented in JSON are serialized using the following grammar. Informally, a `DateValue` is either an ISO 8601-formatted string or a JSON object containing two properties named `kind` and `value` that together define a point in time. The following is not a context-free grammar; in particular, the interpretation of `DateValue` depends on the value of `DateKind`, but this minimizes the number of productions required to describe the format. 962 | 963 | ``` 964 | DateLiteral: 965 | Iso8601Literal 966 | StructuredDateLiteral 967 | 968 | Iso8601Literal: 969 | A string literal as defined in http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15. Note that the full grammar for ISO 8601 (such as "basic format" without separators) is not supported. All dates default to UTC unless specified otherwise. 970 | 971 | StructuredDateLiteral: 972 | { DateKindProperty , DateValueProperty } 973 | { DateValueProperty , DateKindProperty } 974 | 975 | DateKindProperty 976 | "kind" : DateKind 977 | 978 | DateKind: 979 | "C" ; see below 980 | "E" ; see below 981 | "I" ; see below 982 | "O" ; see below 983 | "T" ; see below 984 | "U" ; see below 985 | "W" ; see below 986 | "X" ; see below 987 | 988 | DateValueProperty: 989 | "value" : DateValue 990 | 991 | DateValue: 992 | UnsignedInteger ; not defined here 993 | SignedInteger ; not defined here 994 | RealNumber ; not defined here 995 | Iso8601Literal ; as above 996 | ``` 997 | 998 | #### 11.3.2 Commentary on date formatting 999 | A `DateLiteral` using the `Iso8601Literal` production is relatively straightforward. Here is an example of an object with a property named `creationDate` that is set to February 13, 2015, at 1:15 p.m. UTC: 1000 | 1001 | ```json 1002 | { "creationDate" : "2015-02-13T13:15Z" } 1003 | ``` 1004 | 1005 | The `StructuredDateLiteral` consists of a `DateKind` and an accompanying `DateValue` whose valid values (and their interpretation) depend on the `DateKind`. The following table describes the valid combinations and their meaning: 1006 | 1007 | DateKind | DateValue | Colloquial Name & Interpretation | More Info 1008 | -------- | --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------- 1009 | C | UnsignedInteger | "CLR"; number of milliseconds since midnight January 1, 0001; negative values are not allowed. *See note below.* | [MSDN][clr-time] 1010 | E | SignedInteger | "ECMAScript"; number of milliseconds since midnight, January 1, 1970. | [ECMA International][ecmascript-time] 1011 | I | Iso8601Literal | "ISO 8601"; a string limited to the ECMAScript subset. | 1012 | O | RealNumber | "OLE Date"; integral part is the number of days since midnight, December 31, 1899, and fractional part is the time within the day (0.5 = midday). | [MSDN][ole-date] 1013 | T | SignedInteger | "Ticks"; number of ticks (100-nanosecond intervals) since midnight January 1, 1601. *See note below.* | [MSDN][ticks-time] 1014 | U | SignedInteger | "UNIX"; number of seconds since midnight, January 1, 1970. | [MSDN][unix-time] 1015 | W | SignedInteger | "Windows"; number of milliseconds since midnight January 1, 1601. *See note below.* | [MSDN][windows-time] 1016 | X | RealNumber | "Excel"; as for `O` but the year 1900 is incorrectly treated as a leap year, and day 0 is "January 0 (zero)." | [Microsoft Support][excel-time] 1017 | 1018 | **Important note for `C` and `W` kinds:** The native CLR and Windows times are represented by 100-nanosecond "tick" values. To interoperate with ECMAScript clients that have limited precision, _these values MUST be converted to and from milliseconds_ when (de)serialized as a `DateLiteral`. One millisecond is equivalent to 10,000 ticks. 1019 | 1020 | **Important note for `T` kind:** This kind preserves the full fidelity of the Windows native time formats (and is trivially convertible to and from the native CLR format) but is incompatible with ECMAScript clients. Therefore, its use SHOULD be limited to only those scenarios that both require the additional precision and do not need to interoperate with ECMAScript clients. 1021 | 1022 | Here is the same example of an object with a property named creationDate that is set to February 13, 2015, at 1:15 p.m. UTC, using several formats: 1023 | 1024 | ```json 1025 | [ 1026 | { "creationDate" : { "kind" : "O", "value" : 42048.55 } }, 1027 | { "creationDate" : { "kind" : "E", "value" : 1423862100000 } } 1028 | ] 1029 | ``` 1030 | 1031 | One of the benefits of separating the kind from the value is that once a client knows the kind used by a particular service, it can interpret the value without requiring any additional parsing. In the common case of the value being a number, this makes coding easier for developers: 1032 | 1033 | ```csharp 1034 | // We know this service always gives out ECMAScript-format dates 1035 | var date = new Date(serverResponse.someObject.creationDate.value); 1036 | ``` 1037 | 1038 | ### 11.4 Durations 1039 | [Durations][wikipedia-iso8601-durations] need to be serialized in conformance with [ISO 8601][wikipedia-iso8601-durations]. Durations are "represented by the format `P[n]Y[n]M[n]DT[n]H[n]M[n]S`." From the standard: 1040 | - P is the duration designator (historically called "period") placed at the start of the duration representation. 1041 | - Y is the year designator that follows the value for the number of years. 1042 | - M is the month designator that follows the value for the number of months. 1043 | - W is the week designator that follows the value for the number of weeks. 1044 | - D is the day designator that follows the value for the number of days. 1045 | - T is the time designator that precedes the time components of the representation. 1046 | - H is the hour designator that follows the value for the number of hours. 1047 | - M is the minute designator that follows the value for the number of minutes. 1048 | - S is the second designator that follows the value for the number of seconds. 1049 | 1050 | For example, "P3Y6M4DT12H30M5S" represents a duration of "three years, six months, four days, twelve hours, thirty minutes, and five seconds." 1051 | 1052 | ### 11.5 Intervals 1053 | [Intervals][wikipedia-iso8601-intervals] are defined as part of [ISO 8601][wikipedia-iso8601-intervals]. 1054 | - Start and end, such as "2007-03-01T13:00:00Z/2008-05-11T15:30:00Z" 1055 | - Start and duration, such as "2007-03-01T13:00:00Z/P1Y2M10DT2H30M" 1056 | - Duration and end, such as "P1Y2M10DT2H30M/2008-05-11T15:30:00Z" 1057 | - Duration only, such as "P1Y2M10DT2H30M," with additional context information 1058 | 1059 | ### 11.6 Repeating intervals 1060 | [Repeating Intervals][wikipedia-iso8601-repeatingintervals], as per [ISO 8601][wikipedia-iso8601-repeatingintervals], are: 1061 | 1062 | > Formed by adding "R[n]/" to the beginning of an interval expression, where R is used as the letter itself and [n] is replaced by the number of repetitions. Leaving out the value for [n] means an unbounded number of repetitions. 1063 | 1064 | For example, to repeat the interval of "P1Y2M10DT2H30M" five times starting at "2008-03-01T13:00:00Z," use "R5/2008-03-01T13:00:00Z/P1Y2M10DT2H30M." 1065 | 1066 | ## 12 Versioning 1067 | **All APIs compliant with the Microsoft REST API Guidelines MUST support explicit versioning.** It's critical that clients can count on services to be stable over time, and it's critical that services can add features and make changes. 1068 | 1069 | ### 12.1 Versioning formats 1070 | Services are versioned using a Major.Minor versioning scheme. Services MAY opt for a "Major" only version scheme in which case the ".0" is implied and all other rules in this section apply. Two options for specifying the version of a REST API request are supported: 1071 | - Embedded in the path of the request URL, at the end of the service root: `https://api.contoso.com/v1.0/products/users` 1072 | - As a query string parameter of the URL: `https://api.contoso.com/products/users?api-version=1.0` 1073 | 1074 | Guidance for choosing between the two options is as follows: 1075 | 1076 | 1. Services co-located behind a DNS endpoint MUST use the same versioning mechanism. 1077 | 2. In this scenario, a consistent user experience across the endpoint is paramount. The Microsoft REST API Guidelines Working Group recommends that new top-level DNS endpoints are not created without explicit conversations with your organization's leadership team. 1078 | 3. Services that guarantee the stability of their REST API's URL paths, even through future versions of the API, MAY adopt the query string parameter mechanism. This means the naming and structure of the relationships described in the API cannot evolve after the API ships, even across versions with breaking changes. 1079 | 4. Services that cannot ensure URL path stability across future versions MUST embed the version in the URL path. 1080 | 1081 | Certain bedrock services such as Microsoft's Azure Active Directory may be exposed behind multiple endpoints. Such services MUST support the versioning mechanisms of each endpoint, even if that means supporting multiple versioning mechanisms. 1082 | 1083 | #### 12.1.1 Group versioning 1084 | Group versioning is an OPTIONAL feature that MAY be offered on services using the query string parameter mechanism. Group versions allow for logical grouping of API endpoints under a common versioning moniker. This allows developers to look up a single version number and use it across multiple endpoints. Group version numbers are well known, and services SHOULD reject any unrecognized values. 1085 | 1086 | Internally, services will take a Group Version and map it to the appropriate Major.Minor version. 1087 | 1088 | The Group Version format is defined as YYYY-MM-DD, for example 2012-12-07 for December 7, 2012. This Date versioning format applies only to Group Versions and SHOULD NOT be used as an alternative to Major.Minor versioning. 1089 | 1090 | ##### 12.1.1.1 Examples of group versioning 1091 | 1092 | Group | Major.Minor 1093 | ---------- | ----------- 1094 | 2012-12-01 | 1.0 1095 | | 1.1 1096 | | 1.2 1097 | 2013-03-21 | 1.0 1098 | | 2.0 1099 | | 3.0 1100 | | 3.1 1101 | | 3.2 1102 | | 3.3 1103 | 1104 | Version Format | Example | Interpretation 1105 | ----------------------------- | ---------------------- | ------------------------------------------ 1106 | {groupVersion} | 2013-03-21, 2012-12-01 | 3.3, 1.2 1107 | {majorVersion} | 3 | 3.0 1108 | {majorVersion}.{minorVersion} | 1.2 | 1.2 1109 | 1110 | Clients can specify either the group version or the Major.Minor version: 1111 | 1112 | For example: 1113 | 1114 | ```http 1115 | GET http://api.contoso.com/acct1/c1/blob2?api-version=1.0 1116 | ``` 1117 | 1118 | ```http 1119 | PUT http://api.contoso.com/acct1/c1/b2?api-version=2011-12-07 1120 | ``` 1121 | 1122 | ### 12.2 When to version 1123 | Services MUST increment their version number in response to any breaking API change. See the following section for a detailed discussion of what constitutes a breaking change. Services MAY increment their version number for nonbreaking changes as well, if desired. 1124 | 1125 | Use a new major version number to signal that support for existing clients will be deprecated in the future. When introducing a new major version, services MUST provide a clear upgrade path for existing clients and develop a plan for deprecation that is consistent with their business group's policies. Services SHOULD use a new minor version number for all other changes. 1126 | 1127 | Online documentation of versioned services MUST indicate the current support status of each previous API version and provide a path to the latest version. 1128 | 1129 | ### 12.3 Definition of a breaking change 1130 | Changes to the contract of an API are considered a breaking change. Changes that impact the backwards compatibility of an API are a breaking change. 1131 | 1132 | Teams MAY define backwards compatibility as their business needs require. For example, Azure defines the addition of a new JSON field in a response to be not backwards compatible. Office 365 has a looser definition of backwards compatibility and allows JSON fields to be added to responses. 1133 | 1134 | Clear examples of breaking changes: 1135 | 1136 | 1. Removing or renaming APIs or API parameters 1137 | 2. Changes in behavior for an existing API 1138 | 3. Changes in Error Codes and Fault Contracts 1139 | 4. Anything that would violate the [Principle of Least Astonishment][principle-of-least-astonishment] 1140 | 1141 | Services MUST explicitly define their definition of a breaking change, especially with regard to adding new fields to JSON responses and adding new API arguments with default fields. Services that are co-located behind a DNS Endpoint with other services MUST be consistent in defining contract extensibility. 1142 | 1143 | The applicable changes described [in this section of the OData V4 spec][odata-breaking-changes] SHOULD be considered part of the minimum bar that all services MUST consider a breaking change. 1144 | 1145 | ## 13 Long running operations 1146 | Long running operations, sometimes called async operations, tend to mean different things to different people. This section sets forth guidance around different types of long running operations, and describes the wire protocols and best practices for these types of operations. 1147 | 1148 | 1. One or more clients MUST be able to monitor and operate on the same resource at the same time. 1149 | 2. The state of the system SHOULD be discoverable and testable at all times. Clients SHOULD be able to determine the system state even if the operation tracking resource is no longer active. The act of querying the state of a long running operation should itself leverage principles of the web. i.e. well defined resources with uniform interface semantics. Clients MAY issue a GET on some resource to determine the state of a long running operation 1150 | 3. Long running operations SHOULD work for clients looking to "Fire and Forget" and for clients looking to actively monitor and act upon results. 1151 | 4. Cancellation does not explicitly mean rollback. On a per-API defined case it may mean rollback, or compensation, or completion, or partial completion, etc. Following a cancelled operation, It SHOULD NOT be a client's responsibility to return the service to a consistent state which allows continued service. 1152 | 1153 | ### 13.1 Resource based long running operations (RELO) 1154 | Resource based modeling is where the status of an operation is encoded in the resource and the wire protocol used is the standard synchronous protocol. In this model state transitions are well defined and goal states are similarly defined. 1155 | 1156 | _This is the preferred model for long running operations and should be used wherever possible._ Avoiding the complexity and mechanics of the LRO Wire Protocol makes things simpler for our users and tooling chain. 1157 | 1158 | An example may be a machine reboot, where the operation itself completes synchronously but the GET operation on the virtual machine resource would have a "state: Rebooting", "state: Running" that could be queried at any time. 1159 | 1160 | This model MAY integrate Push Notifications. 1161 | 1162 | While most operations are likely to be POST semantics, In addition to POST semantics services MAY support PUT semantics via routing to simplify their APIs. For example, a user that wants to create a database named "db1" could call: 1163 | 1164 | ```http 1165 | PUT https://api.contoso.com/v1.0/databases/db1 1166 | ``` 1167 | 1168 | In this scenario the databases segment is processing the PUT operation. 1169 | 1170 | Services MAY also use the hybrid defined below. 1171 | 1172 | ### 13.2 Stepwise long running operations 1173 | A stepwise operation is one that takes a long, and often unpredictable, length of time to complete, and doesn't offer state transition modeled in the resource. This section outlines the approach that services should use to expose such long running operations. 1174 | 1175 | Service MAY expose stepwise operations. 1176 | 1177 | > Stepwise Long Running Operations are sometimes called "Async" operations. This causes confusion, as it mixes elements of platforms ("Async / await", "promises", "futures") with elements of API operation. This document uses the term "Stepwise Long Running Operation" or often just "Stepwise Operation" to avoid confusion over the word "Async". 1178 | 1179 | Services MUST perform as much synchronous validation as practical on stepwise requests. Services MUST prioritize returning errors in a synchronous way, with the goal of having only "Valid" operations processed using the long running operation wire protocol. 1180 | 1181 | For an API that's defined as a Stepwise Long Running Operation the service MUST go through the Stepwise Long Running Operation flow even if the operation can be completed immediately. In other words, APIs must adopt and stick with a LRO pattern and not change patterns based on circumstance. 1182 | 1183 | #### 13.2.1 PUT 1184 | Services MAY enable PUT requests for entity creation. 1185 | 1186 | ```http 1187 | PUT https://api.contoso.com/v1.0/databases/db1 1188 | ``` 1189 | 1190 | In this scenario the _databases_ segment is processing the PUT operation. 1191 | 1192 | ```http 1193 | HTTP/1.1 202 Accepted 1194 | Operation-Location: https://api.contoso.com/v1.0/operations/123 1195 | ``` 1196 | 1197 | For services that need to return a 201 Created here, use the hybrid flow described below. 1198 | 1199 | The 202 Accepted should return no body. The 201 Created case should return the body of the target resource. 1200 | 1201 | #### 13.2.2 POST 1202 | Services MAY enable POST requests for entity creation. 1203 | 1204 | ```http 1205 | POST https://api.contoso.com/v1.0/databases/ 1206 | 1207 | { 1208 | "fileName": "someFile.db", 1209 | "color": "red" 1210 | } 1211 | ``` 1212 | 1213 | ```http 1214 | HTTP/1.1 202 Accepted 1215 | Operation-Location: https://api.contoso.com/v1.0/operations/123 1216 | ``` 1217 | 1218 | #### 13.2.3 POST, hybrid model 1219 | Services MAY respond synchronously to POST requests to collections that create a resource even if the resources aren't fully created when the response is generated. In order to use this pattern, the response MUST include a representation of the incomplete resource and an indication that it is incomplete. 1220 | 1221 | For example: 1222 | 1223 | ```http 1224 | POST https://api.contoso.com/v1.0/databases/ HTTP/1.1 1225 | Host: api.contoso.com 1226 | Content-Type: application/json 1227 | Accept: application/json 1228 | 1229 | { 1230 | "fileName": "someFile.db", 1231 | "color": "red" 1232 | } 1233 | ``` 1234 | 1235 | Service response says the database has been created, but indicates the request is not completed by including the Operation-Location header. In this case the status property in the response payload also indicates the operation has not fully completed. 1236 | 1237 | ```http 1238 | HTTP/1.1 201 Created 1239 | Location: https://api.contoso.com/v1.0/databases/db1 1240 | Operation-Location: https://api.contoso.com/v1.0/operations/123 1241 | 1242 | { 1243 | "databaseName": "db1", 1244 | "color": "red", 1245 | "Status": "Provisioning", 1246 | [ … other fields for "database" …] 1247 | } 1248 | ``` 1249 | 1250 | #### 13.2.4 Operations resource 1251 | Services MAY provide a "/operations" resource at the tenant level. 1252 | 1253 | Services that provide the "/operations" resource MUST provide GET semantics. GET MUST enumerate the set of operations, following standard pagination, sorting, and filtering semantics. The default sort order for this operation MUST be: 1254 | 1255 | Primary Sort | Secondary Sort 1256 | ---------------------- | ----------------------- 1257 | Not Started Operations | Operation Creation Time 1258 | Running Operations | Operation Creation Time 1259 | Completed Operations | Operation Creation Time 1260 | 1261 | Note that "Completed Operations" is a goal state (see below), and may actually be any of several different states such as "successful", "cancelled", "failed" and so forth. 1262 | 1263 | #### 13.2.5 Operation resource 1264 | An operation is a user addressable resource that tracks a stepwise long running operation. Operations MUST support GET semantics. The GET operation against an operation MUST return: 1265 | 1266 | 1. The operation resource, it's state, and any extended state relevant to the particular API. 1267 | 2. 200 OK as the response code. 1268 | 1269 | Services MAY support operation cancellation by exposing DELETE on the operation. If supported DELETE operations MUST be idempotent. 1270 | 1271 | > Note: From an API design perspective, cancellation does not explicitly mean rollback. On a per-API defined case it may mean rollback, or compensation, or completion, or partial completion, etc. Following a cancelled operation It SHOULD NOT be a client's responsibility to return the service to a consistent state which allows continued service. 1272 | 1273 | Services that do not support operation cancellation MUST return a 405 Method Not Allowed in the event of a DELETE. 1274 | 1275 | Operations MUST support the following states: 1276 | 1277 | 1. NotStarted 1278 | 2. Running 1279 | 3. Succeeded. Terminal State. 1280 | 4. Failed. Terminal State. 1281 | 1282 | Services MAY add additional states, such as "Cancelled" or "Partially Completed". Services that support cancellation MUST sufficiently describe their cancellation such that the state of the system can be accurately determined and any compensating actions may be run. 1283 | 1284 | Services that support additional states should consider this list of canonical names and avoid creating new names if possible: Cancelling, Cancelled, Aborting, Aborted, Tombstone, Deleting, Deleted. 1285 | 1286 | An operation MUST contain, and provide in the GET response, the following information: 1287 | 1288 | 1. The timestamp when the operation was created. 1289 | 2. A timestamp for when the current state was entered. 1290 | 3. The operation state (notstarted / running / completed). 1291 | 1292 | Services MAY add additional, API specific, fields into the operation. The operation status JSON returned looks like: 1293 | 1294 | ```json 1295 | { 1296 | "createdDateTime": "2015-06-19T12-01-03.45Z", 1297 | "lastActionDateTime": "2015-06-19T12-01-03.45Z", 1298 | "status": "notstarted | running | succeeded | failed" 1299 | } 1300 | ``` 1301 | 1302 | ##### 13.2.5.1 Percent complete 1303 | Sometimes it is impossible for services to know with any accuracy when an operation will complete. Which makes using the Retry-After header problematic. In that case, services MAY include, in the operationStatus JSON, a percent complete field. 1304 | 1305 | ```json 1306 | { 1307 | "createdDateTime": "2015-06-19T12-01-03.45Z", 1308 | "percentComplete": "50", 1309 | "status": "running" 1310 | } 1311 | ``` 1312 | 1313 | In this example the server has indicated to the client that the long running operation is 50% complete. 1314 | 1315 | ##### 13.2.5.2 Target resource location 1316 | For operations that result in, or manipulate, a resource the service MUST include the target resource location in the status upon operation completion. 1317 | 1318 | ```json 1319 | { 1320 | "createdDateTime": "2015-06-19T12-01-03.45Z", 1321 | "lastActionDateTime": "2015-06-19T12-06-03.0024Z", 1322 | "status": "succeeded", 1323 | "resourceLocation": "https://api.contoso.com/v1.0/databases/db1" 1324 | } 1325 | ``` 1326 | 1327 | #### 13.2.6 Operation tombstones 1328 | Services MAY choose to support tombstoned operations. Services MAY choose to delete tombstones after a service defined period of time. 1329 | 1330 | #### 13.2.7 The typical flow, polling 1331 | - Client invokes a stepwise operation by invoking an action using POST 1332 | - The server MUST indicate the request has been started by responding with a 202 Accepted status code. The response SHOULD include the location header containing a URL that the client should poll for the results after waiting the number of seconds specified in the Retry-After header. 1333 | - Client polls the location until receiving a 200 OK response from the server. 1334 | 1335 | ##### 13.2.7.1 Example of the typical flow, polling 1336 | Client invokes the restart action: 1337 | 1338 | ```http 1339 | POST https://api.contoso.com/v1.0/databases HTTP/1.1 1340 | Accept: application/json 1341 | 1342 | { 1343 | "fromFile": "myFile.db", 1344 | "color": "red" 1345 | } 1346 | ``` 1347 | 1348 | The server response indicates the request has been created. 1349 | 1350 | ```http 1351 | HTTP/1.1 202 Accepted 1352 | Operation-Location: https://api.contoso.com/v1.0/operations/123 1353 | ``` 1354 | 1355 | Client waits for a period of time then invokes another request to try to get the operation status. 1356 | 1357 | ```http 1358 | GET https://api.contoso.com/v1.0/operations/123 1359 | Accept: application/json 1360 | ``` 1361 | 1362 | Server responds that results are still not ready and optionally provides a recommendation to wait 30 seconds. 1363 | 1364 | ```http 1365 | HTTP/1.1 200 OK 1366 | Retry-After: 30 1367 | 1368 | { 1369 | "createdDateTime": "2015-06-19T12-01-03.4Z", 1370 | "status": "running" 1371 | } 1372 | ``` 1373 | 1374 | Client waits the recommended 30 seconds and then invokes another request to get the results of the operation. 1375 | 1376 | ```http 1377 | GET https://api.contoso.com/v1.0/operations/123 1378 | Accept: application/json 1379 | ``` 1380 | 1381 | Server responds with a "status:succeeded" operation that includes the resource location. 1382 | 1383 | ```http 1384 | HTTP/1.1 200 OK 1385 | Content-Type: application/json 1386 | 1387 | { 1388 | "createdDateTime": "2015-06-19T12-01-03.45Z", 1389 | "lastActionDateTime": "2015-06-19T12-06-03.0024Z", 1390 | "status": "succeeded", 1391 | "resourceLocation": "https://api.contoso.com/v1.0/databases/db1" 1392 | } 1393 | ``` 1394 | 1395 | #### 13.2.8 The typical flow, push notifications 1396 | 1. Client invokes a long running operation by invoking an action using POST. The client has a push notification already setup on the parent resource. 1397 | 2. The service indicates the request has been started by responding with a 202 Accepted status code. The client ignores everything else. 1398 | 3. Upon completion of the overall operation the service pushes a notification via the subscription on the parent resource. 1399 | 4. The client retrieves the operation result via the resource URL. 1400 | 1401 | ##### 13.2.8.1 Example of the typical flow, push notifications existing subscription 1402 | Client invokes the backup action. The client already has a push notification subscription setup for db1. 1403 | 1404 | ```http 1405 | POST https://api.contoso.com/v1.0/databases/db1?backup HTTP/1.1 1406 | Accept: application/json 1407 | ``` 1408 | 1409 | The server response indicates the request has been accepted. 1410 | 1411 | ```http 1412 | HTTP/1.1 202 Accepted 1413 | Operation-Location: https://api.contoso.com/v1.0/operations/123 1414 | ``` 1415 | 1416 | The caller ignores all the headers in the return. 1417 | 1418 | The target URL receives a push notification when the operation is complete. 1419 | 1420 | ```http 1421 | HTTP/1.1 200 OK 1422 | Content-Type: application/json 1423 | 1424 | { 1425 | "value": [ 1426 | { 1427 | "subscriptionId": "1234-5678-1111-2222", 1428 | "context": "subscription context that was specified at setup", 1429 | "resourceUrl": "https://api.contoso.com/v1.0/databases/db1", 1430 | "userId" : "contoso.com/user@contoso.com", 1431 | "tenantId" : "contoso.com" 1432 | } 1433 | ] 1434 | } 1435 | ``` 1436 | 1437 | #### 13.2.9 Retry-After 1438 | In the examples above the Retry-After header indicates the number of seconds that the client should wait before trying to get the result from the URL identified by the location header. 1439 | 1440 | The HTTP specification allows the Retry-After header to alternatively specify a HTTP date, so clients should be prepared to handle this as well. 1441 | 1442 | ```http 1443 | HTTP/1.1 202 Accepted 1444 | Operation-Location: http://api.contoso.com/v1.0/operations/123 1445 | Retry-After: 60 1446 | ``` 1447 | 1448 | Note: The use of the HTTP Date is inconsistent with the use of ISO 8601 Date Format used throughout this document, but is explicitly defined by the HTTP standard in [RFC 7231][rfc-7231-7-1-1-1]. Services SHOULD prefer the integer number of seconds (in decimal) format over the HTTP date format. 1449 | 1450 | ### 13.3 Retention policy for operation results 1451 | In some situations, the result of a long running operation is not a resource that can be addressed. For example, if you invoke a long running Action that returns a Boolean (rather than a resource). In these situations, the Location header points to a place where the Boolean result can be retrieved. 1452 | 1453 | Which begs the question: "How long should operation results be retained?" 1454 | 1455 | A recommended minimum retention time is 24 hours. 1456 | 1457 | Operations SHOULD transition to "tombstone" for an additional period of time prior to being purged from the system. 1458 | 1459 | ## 14 Push notifications via webhooks 1460 | ### 14.1 Scope 1461 | Services MAY implement push notifications via web hooks. This section addresses the following key scenario: 1462 | 1463 | > Push notification via HTTP Callbacks, often called Web Hooks, to publicly-addressable servers. 1464 | 1465 | The approach set forth is chosen due to its simplicity, broad applicability, and low barrier to entry for service subscribers. It's intended as a minimal set of requirements and as a starting point for additional functionality. 1466 | 1467 | ### 14.2 Principles 1468 | The core principles for services that support web hooks are: 1469 | 1470 | 1. Services MUST implement at least a poke/pull model. In the poke/pull model, a notification is sent to a client, and clients then send a request to get the current state or the record of change since their last notification. This approach avoids complexities around message ordering, missed messages, and change sets. Services MAY add more data to provide rich notifications. 1471 | 2. Services MUST implement the challenge/response protocol for configuring callback URLs. 1472 | 3. Services SHOULD have a recommended age-out period, with flexibility for services to vary based on scenario. 1473 | 4. Services SHOULD allow subscriptions that are raising successful notifications to live forever and SHOULD be tolerant of reasonable outage periods. 1474 | 5. Firehose subscriptions MUST be delivered only over HTTPS. Services SHOULD require other subscription types to be HTTPS. See the "Security" section for more details. 1475 | 1476 | ### 14.3 Types of subscriptions 1477 | There are two subscription types, and services MAY implement either, both, or none. The supported subscription types are: 1478 | 1479 | 1. Firehose subscriptions – a subscription is manually created for the subscribing application, typically in an app registration portal. Notifications of activity that any users have consented to the app receiving are sent to this single subscription. 1480 | 2. Per-resource subscriptions – the subscribing application uses code to programmatically create a subscription at runtime for some user-specific entity(s). 1481 | 1482 | Services that support both subscription types SHOULD provide differentiated developer experiences for the two types: 1483 | 1484 | 1. Firehose – Services MUST NOT require developers to create code except to directly verify and respond to notifications. Services MUST provide administrative UI for subscription management. Services SHOULD NOT assume that end users are aware of the subscription, only the subscribing application's functionality. 1485 | 2. Per-user – Services MUST provide an API for developers to create and manage subscriptions as part of their app as well as verifying and responding to notifications. Services MAY expect end users to be aware of subscriptions and MUST allow end users to revoke subscriptions where they were created directly in response to user actions. 1486 | 1487 | ### 14.4 Call sequences 1488 | The call sequence for a firehose subscription MUST follow the diagram below. It shows manual registration of application and subscription, and then the end user making use of one of the service's APIs. At this part of the flow, two things MUST be stored: 1489 | 1490 | 1. The service MUST store the end user's act of consent to receiving notifications from this specific application (typically a background usage OAUTH scope.) 1491 | 2. The subscribing application MUST store the end user's tokens in order to call back for details once notified of changes. 1492 | 1493 | The final part of the sequence is the notification flow itself. 1494 | 1495 | Non-normative implementation guidance: A resource in the service changes and the service needs to run the following logic: 1496 | 1497 | 1. Determine the set of users who have access to the resource, and could thus expect apps to receive notifications about it on their behalf. 1498 | 2. See which of those users have consented to receiving notifications and from which apps. 1499 | 3. See which apps have registered a firehose subscription. 1500 | 4. Join 1, 2, 3 to produce the concrete set of notifications that must be sent to apps. 1501 | 1502 | It should be noted that the act of user consent and the act of setting up a firehose subscription could arrive in either order. Services SHOULD send notifications with setup processed in either order. 1503 | 1504 | ![Firehose subscription setup][websequencediagram-firehose-subscription-setup] 1505 | 1506 | For a per-user subscription, app registration is either manual or automated. The call flow for a per-user subscription MUST follow the diagram below. It shows the end user making use of one of the service's APIs, and again, the same two things MUST be stored: 1507 | 1508 | 1. The service MUST store the end user's act of consent to receiving notifications from this specific application (typically a background usage OAUTH scope). 1509 | 2. The subscribing application MUST store the end user's tokens in order to call back for details once notified of changes. 1510 | 1511 | In this case, the subscription is set up programmatically using the end-user's token from the subscribing application. The app MUST store the ID of the registered subscription alongside the user tokens. 1512 | 1513 | Non normative implementation guidance: In the final part of the sequence, when an item of data in the service changes and the service needs to run the following logic: 1514 | 1515 | 1. Find the set of subscriptions that correspond via resource to the data that changed. 1516 | 2. For subscriptions created under an app+user token, send a notification to the app per subscription with the subscription ID and user id of the subscription-creator. 1517 | - For subscriptions created with an app only token, check that the owner of the changed data or any user that has visibility of the changed data has consented to notifications to the application, and if so send a set of notifications per user id to the app per subscription with the subscription ID. 1518 | 1519 | ![User subscription setup][websequencediagram-user-subscription-setup] 1520 | 1521 | ### 14.5 Verifying subscriptions 1522 | When subscriptions change either programmatically or in response to change via administrative UI portals, the subscribing service needs to be protected from malicious or unexpected calls from services pushing potentially large volumes of notification traffic. 1523 | 1524 | For all subscriptions, whether firehose or per-user, services MUST send a verification request as part of creation or modification via portal UI or API request, before sending any other notifications. 1525 | 1526 | Verification requests MUST be of the following format as an HTTP/HTTPS POST to the subscription's _notificationUrl_. 1527 | 1528 | ```http 1529 | POST https://{notificationUrl}?validationToken={randomString} 1530 | ClientState: clientOriginatedOpaqueToken (if provided by client on subscription-creation) 1531 | Content-Length: 0 1532 | ``` 1533 | 1534 | For the subscription to be set up, the application MUST respond with 200 OK to this request, with the _validationToken_ value as the sole entity body. Note that if the _notificationUrl_ contains query parameters, the _validationToken_ parameter must be appended with an `&`. 1535 | 1536 | If any challenge request does not receive the prescribed response within 5 seconds of sending the request, the service MUST return an error, MUST NOT create the subscription, and MUST NOT send further requests or notifications to _notificationUrl_. 1537 | 1538 | Services MAY perform additional validations on URL ownership. 1539 | 1540 | ### 14.6 Receiving notifications 1541 | Services SHOULD send notifications in response to service data changes that do not include details of the changes themselves, but include enough information for the subscribing application to respond appropriately to the following process: 1542 | 1543 | 1. Applications MUST identify the correct cached OAuth token to use for a callback 1544 | 2. Applications MAY look up any previous delta token for the relevant scope of change 1545 | 3. Applications MUST determine the URL to call to perform the relevant query for the new state of the service, which MAY be a delta query. 1546 | 1547 | Services that are providing notifications that will be relayed to end users MAY choose to add more detail to notification packets in order to reduce incoming call load on their service. Such services MUST be clear that notifications are not guaranteed to be delivered and may be lossy or out of order. 1548 | 1549 | Notifications MAY be aggregated and sent in batches. Applications MUST be prepared to receive multiple events inside a single push notification. 1550 | 1551 | The service MUST send all Web Hook data notifications as POST requests. 1552 | 1553 | Services MUST allow for a 30-second timeout for notifications. If a timeout occurs or the application responds with a 5xx response, then the service SHOULD retry the notification with exponential back-off. All other responses will be ignored. 1554 | 1555 | The service MUST NOT follow 301/302 redirect requests. 1556 | 1557 | #### 14.6.1 Notification payload 1558 | The basic format for notification payloads is a list of events, each containing the id of the subscription whose referenced resources have changed, the type of change, the resource that should be consumed to identify the exact details of the change and sufficient identity information to look up the token required to call that resource. 1559 | 1560 | For a firehose subscription, a concrete example of this may look like: 1561 | 1562 | ```json 1563 | { 1564 | "value": [ 1565 | { 1566 | "subscriptionId": "32b8cbd6174ab18b", 1567 | "resource": "https://api.contoso.com/v1.0/users/user@contoso.com/files?$delta", 1568 | "userId" : "", 1569 | "tenantId" : "" 1570 | } 1571 | ] 1572 | } 1573 | ``` 1574 | 1575 | For a per-user subscription, a concrete example of this may look like: 1576 | 1577 | ```json 1578 | { 1579 | "value": [ 1580 | { 1581 | "subscriptionId": "32b8cbd6174ab183", 1582 | "clientState": "clientOriginatedOpaqueToken", 1583 | "expirationDateTime": "2016-02-04T11:23Z", 1584 | "resource": "https://api.contoso.com/v1.0/users/user@contoso.com/files/$delta", 1585 | "userId" : "", 1586 | "tenantId" : "" 1587 | }, 1588 | { 1589 | "subscriptionId": "97b391179fa22", 1590 | "clientState ": "clientOriginatedOpaqueToken", 1591 | "expirationDateTime": "2016-02-04T11:23Z", 1592 | "resource": "https://api.contoso.com/v1.0/users/user@contoso.com/files/$delta", 1593 | "userId" : "", 1594 | "tenantId" : "" 1595 | } 1596 | ] 1597 | } 1598 | ``` 1599 | 1600 | Following is a detailed description of the JSON payload. 1601 | 1602 | A notification item consists a top-level object that contains an array of events, each of which identified the subscription due to which this notification is being sent. 1603 | 1604 | Field | Description 1605 | ----- | -------------------------------------------------------------------------------------------------- 1606 | value | Array of events that have been raised within the subscription’s scope since the last notification. 1607 | 1608 | Each item of the events array contains the following properties: 1609 | 1610 | Field | Description 1611 | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 1612 | subscriptionId | The id of the subscription due to which this notification has been sent.
Services MUST provide the *subscriptionId* field. 1613 | clientState | Services MUST provide the *clientState* field if it was provided at subscription creation time. 1614 | expirationDateTime | Services MUST provide the *expirationDateTime* field if the subscription has one. 1615 | resource | Services MUST provide the resource field. This URL MUST be considered opaque by the subscribing application. In the case of a richer notification it MAY be subsumed by message content that implicitly contains the resource URL to avoid duplication.
If a service is providing this data as part of a more detailed data packet, then it need not be duplicated. 1616 | userId | Services MUST provide this field for user-scoped resources. In the case of user-scoped resources, the unique identifier for the user should be used.
In the case of resources shared between a specific set of users, multiple notifications must be sent, passing the unique identifier of each user.
For tenant-scoped resources, the user id of the subscription should be used. 1617 | tenantId | Services that wish to support cross-tenant requests SHOULD provide this field. Services that provide notifications on tenant-scoped data MUST send this field. 1618 | 1619 | ### 14.7 Managing subscriptions programmatically 1620 | For per-user subscriptions, an API MUST be provided to create and manage subscriptions. The API must support at least the operations described here. 1621 | 1622 | #### 14.7.1 Creating subscriptions 1623 | A client creates a subscription by issuing a POST request against the subscriptions resource. The subscription namespace is client-defined via the POST operation. 1624 | 1625 | ``` 1626 | https://api.contoso.com/apiVersion/$subscriptions 1627 | ``` 1628 | 1629 | The POST request contains a single subscription object to be created. That subscription object has the following properties: 1630 | 1631 | Property Name | Required | Notes 1632 | --------------- | -------- | --------------------------------------------------------------------------------------------------------------------------- 1633 | resource | Yes | Resource path to watch. 1634 | notificationUrl | Yes | The target web hook URL. 1635 | clientState | No | Opaque string passed back to the client on all notifications. Callers may choose to use this to provide tagging mechanisms. 1636 | 1637 | If the subscription was successfully created, the service MUST respond with the status code 201 CREATED and a body containing at least the following properties: 1638 | 1639 | Property Name | Required | Notes 1640 | ------------------ | -------- | ------------------------------------------------------------------------------------------- 1641 | id | Yes | Unique ID of the new subscription that can be used later to update/delete the subscription. 1642 | expirationDateTime | No | Uses existing Microsoft REST API Guidelines defined time formats. 1643 | 1644 | Creation of subscriptions SHOULD be idempotent. The combination of properties scoped to the auth token, provides a uniqueness constraint. 1645 | 1646 | Below is an example request using a User + Application principal to subscribe to notifications from a file: 1647 | 1648 | ```http 1649 | POST https://api.contoso.com/files/v1.0/$subscriptions HTTP 1.1 1650 | Authorization: Bearer {UserPrincipalBearerToken} 1651 | 1652 | { 1653 | "resource": "http://api.service.com/v1.0/files/file1.txt", 1654 | "notificationUrl": "https://contoso.com/myCallbacks", 1655 | "clientState": "clientOriginatedOpaqueToken" 1656 | } 1657 | ``` 1658 | 1659 | The service SHOULD respond to such a message with a response format minimally like this: 1660 | 1661 | ```json 1662 | { 1663 | "id": "32b8cbd6174ab18b", 1664 | "expirationDateTime": "2016-02-04T11:23Z" 1665 | } 1666 | ``` 1667 | 1668 | Below is an example using an Application-Only principal where the application is watching all files to which it's authorized: 1669 | 1670 | ```http 1671 | POST https://api.contoso.com/files/v1.0/$subscriptions HTTP 1.1 1672 | Authorization: Bearer {ApplicationPrincipalBearerToken} 1673 | 1674 | { 1675 | "resource": "All.Files", 1676 | "notificationUrl": "https://contoso.com/myCallbacks", 1677 | "clientState": "clientOriginatedOpaqueToken" 1678 | } 1679 | ``` 1680 | 1681 | The service SHOULD respond to such a message with a response format minimally like this: 1682 | 1683 | ```json 1684 | { 1685 | "id": "8cbd6174abb391179", 1686 | "expirationDateTime": "2016-02-04T11:23Z" 1687 | } 1688 | ``` 1689 | 1690 | #### 14.7.2 Updating subscriptions 1691 | Services MAY support amending subscriptions. To update the properties of an existing subscription, clients use PATCH requests providing the ID and the properties that need to change. Omitted properties will retain their values. To delete a property, assign a value of JSON null to it. 1692 | 1693 | As with creation, subscriptions are individually managed. 1694 | 1695 | The following request changes the notification URL of an existing subscription: 1696 | 1697 | ```http 1698 | PATCH https://api.contoso.com/files/v1.0/$subscriptions/{id} HTTP 1.1 1699 | Authorization: Bearer {UserPrincipalBearerToken} 1700 | 1701 | { 1702 | "notificationUrl": "https://contoso.com/myNewCallback" 1703 | } 1704 | ``` 1705 | 1706 | If the PATCH request contains a new _notificationUrl_, the server MUST perform validation on it as described above. If the new URL fails to validate, the service MUST fail the PATCH request and leave the subscription in its previous state. 1707 | 1708 | The service MUST return an empty body and `204 No Content` to indicate a successful patch. 1709 | 1710 | The service MUST return an error body and status code if the patch failed. 1711 | 1712 | The operation MUST succeed or fail atomically. 1713 | 1714 | #### 14.7.3 Deleting subscriptions 1715 | Services MUST support deleting subscriptions. Existing subscriptions can be deleted by making a DELETE request against the subscription resource: 1716 | 1717 | ```http 1718 | DELETE https://api.contoso.com/files/v1.0/$subscriptions/{id} HTTP 1.1 1719 | Authorization: Bearer {UserPrincipalBearerToken} 1720 | ``` 1721 | 1722 | As with update, the service MUST return `204 No Content` for a successful delete, or an error body and status code to indicate failure. 1723 | 1724 | #### 14.7.4 Enumerating subscriptions 1725 | To get a list of active subscriptions, clients issue a GET request against the subscriptions resource using a User + Application or Application-Only bearer token: 1726 | 1727 | ```http 1728 | GET https://api.contoso.com/files/v1.0/$subscriptions HTTP 1.1 1729 | Authorization: Bearer {UserPrincipalBearerToken} 1730 | ``` 1731 | 1732 | The service MUST return a format as below using a User + Application principal bearer token: 1733 | 1734 | ```json 1735 | { 1736 | "value": [ 1737 | { 1738 | "id": "32b8cbd6174ab18b", 1739 | "resource": " http://api.contoso.com/v1.0/files/file1.txt", 1740 | "notificationUrl": "https://contoso.com/myCallbacks", 1741 | "clientState": "clientOriginatedOpaqueToken", 1742 | "expirationDateTime": "2016-02-04T11:23Z" 1743 | } 1744 | ] 1745 | } 1746 | ``` 1747 | 1748 | An example that may be returned using Application-Only principal bearer token: 1749 | 1750 | ```json 1751 | { 1752 | "value": [ 1753 | { 1754 | "id": "6174ab18bfa22", 1755 | "resource": "All.Files ", 1756 | "notificationUrl": "https://contoso.com/myCallbacks", 1757 | "clientState": "clientOriginatedOpaqueToken", 1758 | "expirationDateTime": "2016-02-04T11:23Z" 1759 | } 1760 | ] 1761 | } 1762 | ``` 1763 | 1764 | ### 14.8 Security 1765 | All service URLs must be HTTPS (that is, all inbound calls MUST be HTTPS). Services that deal with Web Hooks MUST accept HTTPS. 1766 | 1767 | We recommend that services that allow client defined Web Hook Callback URLs SHOULD NOT transmit data over HTTP. This is because information can be inadvertently exposed via client, network, server logs and other mechanisms. 1768 | 1769 | However, there are scenarios where the above recommendations cannot be followed due to client endpoint or software limitations. Consequently, services MAY allow web hook URLs that are HTTP. 1770 | 1771 | Furthermore, services that allow client defined HTTP web hooks callback URLs SHOULD be compliant with privacy policy specified by engineering leadership. This will typically include recommending that clients prefer SSL connections and adhere to special precautions to ensure that logs and other service data collection are properly handled. 1772 | 1773 | For example, services may not want to require developers to generate certificates to onboard. Services might only enable this on test accounts. 1774 | 1775 | ## 15 Unsupported requests 1776 | RESTful API clients MAY request functionality that is currently unsupported. RESTful APIs MUST respond to valid but unsupported requests consistent with this section. 1777 | 1778 | ### 15.1 Essential guidance 1779 | RESTful APIs will often choose to limit functionality that can be performed by clients. For instance, auditing systems allow records to be created but not modified or deleted. Similarly, some APIs will expose collections but require or otherwise limit filtering and ordering criteria, or MAY not support client-driven pagination. 1780 | 1781 | ### 15.2 Feature allow list 1782 | If a service does not support any of the below API features, then an error response MUST be provided if the feature is requested by a caller. The features are: 1783 | - Key Addressing in a collection, such as: `https://api.contoso.com/v1.0/people/user1@contoso.com` 1784 | - Filtering a collection by a property value, such as: `https://api.contoso.com/v1.0/people?$filter=name eq 'david'` 1785 | - Filtering a collection by range, such as: `http://api.contoso.com/v1.0/people?$filter=hireDate ge 2014-01-01 and hireDate le 2014-12-31` 1786 | - Client-driven pagination via $top and $skip, such as: `http://api.contoso.com/v1.0/people?$top=5&$skip=2` 1787 | - Sorting by $orderBy, such as: `https://api.contoso.com/v1.0/people?$orderBy=name desc` 1788 | - Providing $delta tokens, such as: `https://api.contoso.com/v1.0/people?$delta` 1789 | 1790 | #### 15.2.1 Error response 1791 | Services MUST provide an error response if a caller requests an unsupported feature found in the feature allow list. The error response MUST be an HTTP status code from the 4xx series, indicating that the request cannot be fulfilled. Unless a more specific error status is appropriate for the given request, services SHOULD return "400 Bad Request" and an error payload conforming to the error response guidance provided in the Microsoft REST API Guidelines. Services SHOULD include enough detail in the response message for a developer to determine exactly what portion of the request is not supported. 1792 | 1793 | Example: 1794 | 1795 | ```http 1796 | GET https://api.contoso.com/v1.0/people?$orderBy=name HTTP/1.1 1797 | Accept: application/json 1798 | ``` 1799 | 1800 | ```http 1801 | HTTP/1.1 400 Bad Request 1802 | Content-Type: application/json 1803 | 1804 | { 1805 | "error": { 1806 | "code": "ErrorUnsupportedOrderBy", 1807 | "message": "Ordering by name is not supported." 1808 | } 1809 | } 1810 | ``` 1811 | 1812 | ## 16 Appendix 1813 | ### 16.1 Sequence diagram notes 1814 | All sequence diagrams in this document are generated using the WebSequenceDiagrams.com web site. To generate them, paste the text below into the web tool. 1815 | 1816 | #### 16.1.1 Push notifications, per user flow 1817 | 1818 | ``` 1819 | === Being Text === 1820 | note over Developer, Automation, App Server: 1821 | An App Developer like MovieMaker 1822 | Wants to integrate with primary service like Dropbox 1823 | end note 1824 | note over DB Portal, DB App Registration, DB Notifications, DB Auth, DB Service: The primary service like Dropbox 1825 | note over Client: The end users' browser or installed app 1826 | 1827 | note over Developer, Automation, App Server, DB Portal, DB App Registration, DB Notifications, Client : Manual App Registration 1828 | 1829 | 1830 | Developer <--> DB Portal : Login into Portal, App Registration UX 1831 | DB Portal -> +DB App Registration: App Name etc. 1832 | note over DB App Registration: Confirm Portal Access Token 1833 | 1834 | DB App Registration -> -DB Portal: App ID 1835 | DB Portal <--> App Server: Developer copies App ID 1836 | 1837 | note over Developer, Automation, App Server, DB Portal, DB App Registration, DB Notifications, Client : Manual Notification Registration 1838 | 1839 | Developer <--> DB Portal: webhook registration UX 1840 | DB Portal -> +DB Notifications: Register: App Server webhook URL, Scope, App ID 1841 | Note over DB Notifications : Confirm Portal Access Token 1842 | DB Notifications -> -DB Portal: notification ID 1843 | DB Portal --> App Server : Developer may copy notification ID 1844 | 1845 | 1846 | note over Developer, Automation, App Server, DB Portal, DB App Registration, DB Notifications, Client : Client Authorization 1847 | 1848 | Client -> +App Server : Request access to DB protected information 1849 | App Server -> -Client : Redirect to DB Authorization endpoint with authorization request 1850 | Client -> +DB Auth : Redirected authorization request 1851 | Client <--> DB Auth : Authorization UX 1852 | DB Auth -> -Client : Redirect back to App Server with code 1853 | Client -> +App Server : Redirect request back to access server with access code 1854 | App Server -> +DB Auth : Request tokens with access code 1855 | note right of DB Service: Cache that this User ID provided access to App ID 1856 | DB Auth -> -App Server : Response with access, refresh, and ID tokens 1857 | note right of App Server : Cache tokens by user ID 1858 | App Server -> -Client : Return information to client 1859 | 1860 | note over Developer, Automation, App Server, DB Portal, DB App Registration, DB Notifications, Client : Notification Flow 1861 | 1862 | Client <--> DB Service: Changes to user data - typical via interacting with App Server via Client 1863 | DB Service -> App Server : Notification with notification ID and user ID 1864 | App Server -> +DB Service : Request changed information with cached access tokens and "since" token 1865 | note over DB Service: Confirm User Access Token 1866 | DB Service -> -App Server : Response with data and new "since" token 1867 | note right of App Server: Update status and cache new "since" token 1868 | === End Text === 1869 | ``` 1870 | 1871 | #### 16.1.2 Push notifications, firehose flow 1872 | 1873 | ``` 1874 | === Being Text === 1875 | note over Developer, Automation, App Server: 1876 | An App Developer like MovieMaker 1877 | Wants to integrate with primary service like Dropbox 1878 | end note 1879 | note over DB Portal, DB App Registration, DB Notifications, DB Auth, DB Service: The primary service like Dropbox 1880 | note over Client: The end users' browser or installed app 1881 | 1882 | note over Developer, Automation, App Server, DB Portal, DB App Registration, DB Notifications, Client : App Registration 1883 | 1884 | alt Automated app registration 1885 | Developer <--> Automation: Configure 1886 | Automation -> +DB App Registration: App Name etc. 1887 | note over DB App Registration: Confirm App Access Token 1888 | DB App Registration -> -Automation: App ID, App Secret 1889 | Automation --> App Server : Embed App ID, App Secret 1890 | else Manual app registration 1891 | Developer <--> DB Portal : Login into Portal, App Registration UX 1892 | DB Portal -> +DB App Registration: App Name etc. 1893 | note over DB App Registration: Confirm Portal Access Token 1894 | 1895 | DB App Registration -> -DB Portal: App ID 1896 | DB Portal <--> App Server: Developer copies App ID 1897 | end 1898 | 1899 | note over Developer, Automation, App Server, DB Portal, DB App Registration, DB Notifications, Client : Client Authorization 1900 | 1901 | Client -> +App Server : Request access to DB protected information 1902 | App Server -> -Client : Redirect to DB Authorization endpoint with authorization request 1903 | Client -> +DB Auth : Redirected authorization request 1904 | Client <--> DB Auth : Authorization UX 1905 | DB Auth -> -Client : Redirect back to App Server with code 1906 | Client -> +App Server : Redirect request back to access server with access code 1907 | App Server -> +DB Auth : Request tokens with access code 1908 | note right of DB Service: Cache that this User ID provided access to App ID 1909 | DB Auth -> -App Server : Response with access, refresh, and ID tokens 1910 | note right of App Server : Cache tokens by user ID 1911 | App Server -> -Client : Return information to client 1912 | 1913 | 1914 | 1915 | note over Developer, Automation, App Server, DB Portal, DB App Registration, DB Notifications, Client : Notification Registration 1916 | 1917 | App Server->+DB Notifications: Register: App server webhook URL, Scope, App ID 1918 | note over DB Notifications : Confirm User Access Token 1919 | DB Notifications -> -App Server: notification ID 1920 | note right of App Server : Cache the Notification ID and User Access Token 1921 | 1922 | 1923 | 1924 | note over Developer, Automation, App Server, DB Portal, DB App Registration, DB Notifications, Client : Notification Flow 1925 | 1926 | Client <--> DB Service: Changes to user data - typical via interacting with App Server via Client 1927 | DB Service -> App Server : Notification with notification ID and user ID 1928 | App Server -> +DB Service : Request changed information with cached access tokens and "since" token 1929 | note over DB Service: Confirm User Access Token 1930 | DB Service -> -App Server : Response with data and new "since" token 1931 | note right of App Server: Update status and cache new "since" token 1932 | 1933 | 1934 | 1935 | === End Text === 1936 | ``` 1937 | [fielding]: https://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm 1938 | [IANA-headers]: http://www.iana.org/assignments/message-headers/message-headers.xhtml 1939 | [rfc7231-7-1-1-1]: https://tools.ietf.org/html/rfc7231#section-7.1.1.1 1940 | [rfc-7230-3-1-1]: https://tools.ietf.org/html/rfc7230#section-3.1.1 1941 | [rfc-7231]: https://tools.ietf.org/html/rfc7231 1942 | [rest-in-practice]: http://www.amazon.com/REST-Practice-Hypermedia-Systems-Architecture/dp/0596805829/ 1943 | [rest-on-wikipedia]: http://en.wikipedia.org/wiki/Representational_state_transfer 1944 | [rfc-5789]: http://tools.ietf.org/html/rfc5789 1945 | [rfc-5988]: http://tools.ietf.org/html/rfc5988 1946 | [rfc-3339]: https://tools.ietf.org/html/rfc3339 1947 | [cors-preflight]: http://www.w3.org/TR/cors/#resource-preflight-requests 1948 | [rfc-3864]: http://www.ietf.org/rfc/rfc3864.txt 1949 | [odata-json-annotations]: http://docs.oasis-open.org/odata/odata-json-format/v4.0/os/odata-json-format-v4.0-os.html#_Instance_Annotations 1950 | [cors]: http://www.w3.org/TR/access-control/ 1951 | [cors-user-credentials]: http://www.w3.org/TR/access-control/#user-credentials 1952 | [cors-simple-headers]: http://www.w3.org/TR/access-control/#simple-header 1953 | [rfc-4627]: https://tools.ietf.org/html/rfc4627 1954 | [iso-8601]: http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.15 1955 | [clr-time]: https://msdn.microsoft.com/en-us/library/System.DateTime(v=vs.110).aspx 1956 | [ecmascript-time]: http://www.ecma-international.org/ecma-262/5.1/#sec-15.9.1.1 1957 | [ole-date]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms221199(v=vs.85).aspx 1958 | [ticks-time]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724290(v=vs.85).aspx 1959 | [unix-time]: https://msdn.microsoft.com/en-us/library/1f4c8f33.aspx 1960 | [windows-time]: https://msdn.microsoft.com/en-us/library/windows/desktop/ms724290(v=vs.85).aspx 1961 | [excel-time]: http://support.microsoft.com/kb/214326?wa=wsignin1.0 1962 | [wikipedia-iso8601-durations]: http://en.wikipedia.org/wiki/ISO_8601#Durations 1963 | [wikipedia-iso8601-intervals]: http://en.wikipedia.org/wiki/ISO_8601#Time_intervals 1964 | [wikipedia-iso8601-repeatingintervals]: http://en.wikipedia.org/wiki/ISO_8601#Repeating_intervals 1965 | [principle-of-least-astonishment]: http://en.wikipedia.org/wiki/Principle_of_least_astonishment 1966 | [odata-breaking-changes]: http://docs.oasis-open.org/odata/odata/v4.0/errata02/os/complete/part1-protocol/odata-v4.0-errata02-os-part1-protocol-complete.html#_Toc406398209 1967 | [websequencediagram-firehose-subscription-setup]: http://www.websequencediagrams.com/cgi-bin/cdraw?lz=bm90ZSBvdmVyIERldmVsb3BlciwgQXV0b21hdGlvbiwgQXBwIFNlcnZlcjogCiAgICAgQW4AEAUAJwkgbGlrZSBNb3ZpZU1ha2VyACAGV2FudHMgdG8gaW50ZWdyYXRlIHdpdGggcHJpbWFyeSBzZXJ2aWNlADcGRHJvcGJveAplbmQgbm90ZQoAgQwLQiBQb3J0YWwsIERCAIEJBVJlZ2lzdHIAgRkHREIgTm90aWZpYwCBLAVzACEGdXRoACsFUwBgBjogVGhlAF0eAIF_CkNsaWVudAAtBmVuZCB1c2VycycgYnJvd3NlciBvciBpbnN0YWxsZWQgYXBwCgCBIQwAgiQgAIFABQCBIS8AgQoGIDogTWFudWFsAIFzEQoKCgCDAgo8LS0-AIIqCiA6IExvZ2luIGludG8Agj8JAII1ECBVWCAKACoKLT4gKwCCWBM6AIQGBU5hbWUgZXRjLgCDFQ4AGxJDb25maXJtAIEBCEFjY2VzcyBUb2tlbgoKAIM3EyAtPiAtAINkCQBnBklEAIEMCwCBVQUAhQIMAIR3CmNvcGllcwArCACCIHAAhHMMAIMKDwCDABg6IHdlYmhvb2sgcgCCeg4AgnUSAIVQDToAhXYHZXIAgwgGAIcTBgBECVVSTCwgU2NvcGUAhzIGSUQKTgCGPQwAhhwNIACDBh4AHhEAgxEPbgCBagwAgxwNAIMaDiAAgx0MbWF5IGNvcHkALREAhVtqAIZHB0F1dGhvcml6AIY7BwCGXQctPiArAIEuDVJlcXVlc3QgYQCFOQZ0byBEQiBwcm90ZWN0ZWQgaW5mb3IAiiQGCgCDBQstPiAtAIctCVJlZGlyZWN0ADYHAGwNIGVuZHBvaW50AIoWBmEADw1yAHYGAIEQDACJVAcASwtlZAAYHgCICAgAMAcAcA4AhGoGAE0FAIEdFmJhY2sgdG8AhF8NaXRoIGNvZGUAghoaaQCBagcAgToHAD0JAII-B3MAPgsAglEHAEsFAIIzDgCBXw0Agn8GdG9rZW5zACcSAI0_BXJpZ2h0IG9mAItpDUNhY2hlIHRoYXQgdGhpcyBVc2VyIElEIHByb3ZpZGVkAINNCwCIZgoAggcJAIN7D3Nwb25zAI0_BwCECgYsIHJlZnJlc2gsIGFuZCBJRACBHAcAgQMPAIYADQCBDAcAgUUGYnkAjFkFIElEAIQkG3R1cm4AhF4MIHRvIGMAjR8FAIwRagCJVw1GbG93AIYqCQCMaQgAgmoKaGFuZ2UAj3YFAIFXBWRhdGEgLSB0eXBpY2FsIHZpYQCQDgVyYWN0aW5nAJAPBgCJQQt2aWEAjnsHCgCPNgogAIhDEACKZw0AkFMFAIkBDwCDDAUAgkYWKwBNCwCHWApjAIEyBQCHRg0AhWUHYWNoAIQeDACEfwVhbmQgInNpbmNlIgCFEQYAkSQOAIR3CgCNfwcAhHQFAIpQEACBUgsAhFAcAII8BWFuZCBuZXcAYRQAhFUTOiBVcGRhdGUgc3RhdHUAgSkGAIFDBQAxEwoKCg&s=mscgen 1968 | [websequencediagram-user-subscription-setup]: http://www.websequencediagrams.com/cgi-bin/cdraw?lz=bm90ZSBvdmVyIERldmVsb3BlciwgQXV0b21hdGlvbiwgQXBwIFNlcnZlcjogCiAgICAgQW4AEAUAJwkgbGlrZSBNb3ZpZU1ha2VyACAGV2FudHMgdG8gaW50ZWdyYXRlIHdpdGggcHJpbWFyeSBzZXJ2aWNlADcGRHJvcGJveAplbmQgbm90ZQoAgQwLQiBQb3J0YWwsIERCAIEJBVJlZ2lzdHIAgRkHREIgTm90aWZpYwCBLAVzACEGdXRoACsFUwBgBjogVGhlAF0eAIF_CkNsaWVudAAtBmVuZCB1c2VycycgYnJvd3NlciBvciBpbnN0YWxsZWQgYXBwCgCBIQwAgiQgAIFABQCBIS8AgQoGIDoAgWwRCgphbHQAgyUIAIEHBiByABQMICAAgxsLPC0tPgCDTws6IENvbmZpZ3VyZQogIACDaAsgLT4gKwCCWBMAegZOYW1lIGV0Yy4AhAgFAIMaDQAfEgBdBXJtAIQ_BUFjY2VzcyBUb2tlAIETBgCDOxIgLT4gLQCBFgxBcHAgSUQAhHwIY3JldACBGxAtPgCFFgsgOiBFbWJlZAAkFGVsc2UgTWFudWFsAIIEJACEbQkgOiBMb2dpbiBpbnRvAIUBCQCBKRFVWACGGAUALQoAgh8mAIIZKwCBCAcAgjoNAIIsHACGLwkAgj8IAIESDgCECAYAh1ELAIdFCmNvcGllcwAuCGVuZACEeGoAhWQHQXV0aG9yaXoAhV8HAIV6By0-ICsAg2ANUmVxdWVzdCBhAIRVBnRvIERCIHByb3RlY3RlZCBpbmZvcgCJQQYKAIQaCy0-IC0AhkoJUmVkaXJlY3QANgcAbA0gZW5kcG9pbnQAiTMGYQAPDXIAdgYAgRAMAIhxBwBLC2VkABgeAIRjCAAwB0EAcQxVWAoASQgAgRwWYmFjayB0bwCFdAwAilwFY29kZQCCGRppAIFpBwCBOQcAPQkAgj0HcwA-CwCCUAcASwUAgjIOAIFeDQCCfgZ0b2tlbnMAJxIAjFsFcmlnaHQgb2YAiwUNQ2FjaGUgdGhhdCB0aGlzIFVzZXIgSUQgcHJvdmlkZWQAg0wLAIU6BwCCBAwAg3oPc3BvbnMAjFsHAIQJBiwgcmVmcmVzaCwgYW5kIElEAIEcBwCBAw8AiDENAIEMBwCBRQZieQCLdQUgSUQAhCMbdHVybgCEXQwgdG8gYwCMOwUKCgCLL2oAjXUMAIwTDwCPNQotPisAjhwQOgCORQdlcgCMVwYAg3YIZWJob29rIFVSTCwgU2NvcGUAkAEGSUQAjwoOAI5rDSAAi2UKAINFBQCLYw0AHBEAgzUOOiBuAIE2DABgCACDCB1oZQCBaQ5JRACDYwUAahIAghB4RmxvdwCJMwkAjE0IAIV0CmhhbmdlAJIcBQCEYQVkYXRhIC0gdHlwaWNhbCB2aWEAkjQFcmFjdGluZwCSNQYAjV8LdmlhAJEhBwoAkVwKIACNfhAAhAsNAJJ5BQCCWQ8AhhYFAIVQFisATQsAimEKYwCBMgUAik8NAIhvB2FjaACHKAwAiAkFYW5kICJzaW5jZSIAiBsGAJNKDgCIAQoAhB0cAIFSCwCHWhwAgjwFYW5kIG5ldwBhFACHXxM6IFVwZGF0ZSBzdGF0dQCBKQYAgUMFADETCgoK&s=mscgen 1969 | -------------------------------------------------------------------------------- /lang/ko/README.md: -------------------------------------------------------------------------------- 1 | # Microsoft REST API Guidelines 2 | The [Microsoft REST API Guidelines](Guidelines.md), as a design principle, encourages application developers to have resources accessible to them via a RESTful HTTP interface. To provide the smoothest possible experience for developers on platforms following the Microsoft REST API Guidelines, REST APIs SHOULD follow consistent design guidelines to make using them easy and intuitive. 3 | 4 | ## Code of Conduct 5 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. 6 | 7 | ## This repository 8 | This repository contains a collection of documents and related materials supporting the overall Microsoft REST API Guidelines initiative. To contribute to this repository, please see the [contribution guidance][contribution-guidance]. 9 | 10 | [contribution-guidance]: CONTRIBUTING.md 11 | --------------------------------------------------------------------------------