Skip to content

Instantly share code, notes, and snippets.

@bobholt
Created March 17, 2015 13:55
Show Gist options
  • Save bobholt/1a5e9103be5fa85a53da to your computer and use it in GitHub Desktop.
Save bobholt/1a5e9103be5fa85a53da to your computer and use it in GitHub Desktop.
json-api diff
diff --git a/about/index.md b/about/index.md
index 5e61dd8..f371287 100644
--- a/about/index.md
+++ b/about/index.md
@@ -14,20 +14,12 @@ JSON API is:
## Editors <a href="#editors" id="editors" class="headerlink"></a>
-There are two primary editors of this specification:
+There are four primary editors of this specification:
- [Steve Klabnik](http://twitter.com/steveklabnik)
- [Yehuda Katz](http://twitter.com/wycats)
-
-> Perhaps most significant to the Web, however, is that the separation [between
-> clients and servers] allows the components to evolve independently, thus
-> supporting the Internet-scale requirement of multiple organizational domains.
->
-> - Roy Fielding, "Architectural Styles and the Design of Network-based
-> Software Architectures", Chapter 5.
-
-Steve primarily represents the server side, Yehuda the client side. Both of us
-care about both, but we want to make sure to have a champion on either side.
+- [Dan Gebhardt](http://twitter.com/dgeb)
+- [Tyler Kellen](http://twitter.com/tkellen)
## History <a href="#history" id="history" class="headerlink"></a>
diff --git a/examples/index.md b/examples/index.md
index 14837d2..b2ecc4b 100644
--- a/examples/index.md
+++ b/examples/index.md
@@ -33,6 +33,8 @@ implementations. There is a [custom adapter](https://github.com/daliwali/ember-j
* [jsonapi-consumer](https://github.com/jsmestad/jsonapi-consumer) a ruby library for consuming JSONAPI payloads.
+* [JsonApiClient](https://github.com/chingor13/json_api_client) attempts to give you a query building framework that is easy to understand (similar to ActiveRecord scopes)
+
## Server <a href="#server" id="server" class="headerlink"></a>
### PHP <a href="#server-php" id="server-php" class="headerlink"></a>
@@ -50,8 +52,6 @@ implementations. There is a [custom adapter](https://github.com/daliwali/ember-j
is one of the original exemplar implementations, but is slightly out of date at
the moment.
-* [JsonApiClient](https://github.com/chingor13/json_api_client) attempts to give you a query building framework that is easy to understand (similar to ActiveRecord scopes)
-
* [The rabl wiki](https://github.com/nesquena/rabl/wiki/Conforming-to-jsonapi.org-format)
has a page describing how to emit conformant JSON.
@@ -77,7 +77,7 @@ has a page describing how to emit conformant JSON.
### .NET <a href="#server-net" id="server-net" class="headerlink"></a>
-* [JSONAPI.NET](http://jsonapi.codeplex.com) is a .NET library that integrates with ASP.NET WebAPI, Json.NET, and (optionally) Entity Framework to help you quickly create JSON API compliant web services.
+* [JSONAPI.NET](https://github.com/SphtKr/JSONAPI.NET) is a .NET library that integrates with ASP.NET WebAPI, Json.NET, and (optionally) Entity Framework to help you quickly create JSON API compliant web services.
## Messages <a href="#messages" id="messages" class="headerlink"></a>
diff --git a/extensions/bulk/index.md b/extensions/bulk/index.md
index c0e1538..d591d08 100644
--- a/extensions/bulk/index.md
+++ b/extensions/bulk/index.md
@@ -10,14 +10,9 @@ extension](/extensions/#official-extensions) of the JSON API specification.
It provides support for performing multiple operations in a request,
including adding and removing multiple resources.
-Servers **SHOULD** indicate support for the JSON API media type's Bulk
-extension by including the header `Content-Type: application/vnd.api+json;
-ext=bulk` in every response.
-
-Clients **MAY** request the JSON API media type's Bulk extension by
-specifying the header `Accept: application/vnd.api+json; ext=bulk`. Servers
-that do not support the Bulk extension **MUST** return a `415 Unsupported
-Media Type` status code.
+Servers and clients **MUST** negotiate support for and use of the Bulk extension
+[as described in the base specification](/format/#extending) using `bulk` as the
+name of the extension.
## Bulk Operations <a href="#bulk-operations" id="bulk-operations" class="headerlink"></a>
@@ -58,7 +53,7 @@ Accept: application/vnd.api+json; ext=bulk
## Updating Multiple Resources <a href="#updating-multiple-resources" id="updating-multiple-resources" class="headerlink"></a>
-Multiple resources can be updated by sending a `PUT` request to a URL that
+Multiple resources can be updated by sending a `PATCH` request to a URL that
represents a collection of resources to which they all belong. The request
**MUST** include an array of resource objects as primary data. Each resource
object **MUST** contain at least `type` and `id` members.
@@ -66,7 +61,7 @@ object **MUST** contain at least `type` and `id` members.
For example:
```text
-PUT /articles
+PATCH /articles
Content-Type: application/vnd.api+json; ext=bulk
Accept: application/vnd.api+json; ext=bulk
@@ -89,8 +84,7 @@ Multiple resources can be deleted by sending a `DELETE` request to a URL that
represents a collection of resources to which they all belong.
The body of the request **MUST** contain a `data` member whose value is an
-object that contains `type` and `ids`, or an array of objects that each
-contain a `type` and `id`.
+an array of objects that each contain a `type` and `id`.
For example:
@@ -100,6 +94,9 @@ Content-Type: application/vnd.api+json; ext=bulk
Accept: application/vnd.api+json; ext=bulk
{
- "data": { "type": "articles", "ids": ["1", "2"] }
+ "data": [
+ { "type": "articles", "id": "1" },
+ { "type": "articles", "id": "2" }
+ ]
}
```
diff --git a/extensions/index.md b/extensions/index.md
index bee1864..c7256d9 100644
--- a/extensions/index.md
+++ b/extensions/index.md
@@ -5,8 +5,9 @@ title: Extensions
JSON API can be extended in several ways:
-* The `ext` media type parameter can be used to declare and request support for
- extensions, [as discussed in the base specification](/format#extending).
+* The `supported-ext` and `ext` media type parameters can be used to negotiate
+ support for extensions,
+ [as discussed in the base specification](/format#extending).
Official and custom extensions to the specification are discussed below.
* Meta information can be included in several places in a document,
@@ -20,18 +21,19 @@ JSON API currently supports the following official extensions:
* [Bulk extension](/extensions/bulk/) - provides support for performing multiple
operations in a request, including adding and removing multiple resources.
- The Bulk extension is referenced with the media type parameter `ext=bulk`.
+ The Bulk extension is referenced with the extension name `bulk`.
-* [Patch extension](/extensions/patch/) - provides support for modification of resources
- with the HTTP PATCH method [[RFC5789](http://tools.ietf.org/html/rfc5789)]
- and the JSON Patch format [[RFC6902](http://tools.ietf.org/html/rfc6902)].
- The Patch extension is referenced with the media type parameter `ext=patch`.
+* [JSON Patch extension](/extensions/jsonpatch/) - provides support for
+ modification of resources with the HTTP PATCH method
+ [[RFC5789](http://tools.ietf.org/html/rfc5789)] and the JSON Patch format
+ [[RFC6902](http://tools.ietf.org/html/rfc6902)]. The JSON Patch extension is
+ referenced with the extension name `jsonpatch`.
## Custom Extensions <a href="#custom-extensions" id="custom-extensions" class="headerlink"></a>
The JSON API media type can be extended for your organization by writing your
own custom extension. This extension should also be specified using the `ext`
-media type parameter.
+and `supported-ext` media type parameters.
It is strongly recommended that custom extensions be prefixed with a unique
identifier for your organization to avoid namespace collision. For example,
diff --git a/extensions/jsonpatch/index.md b/extensions/jsonpatch/index.md
new file mode 100644
index 0000000..c052167
--- /dev/null
+++ b/extensions/jsonpatch/index.md
@@ -0,0 +1,324 @@
+---
+layout: page
+title: "JSON Patch Extension"
+---
+
+## Introduction <a href="#introduction" id="introduction" class="headerlink"></a>
+
+The "JSON Patch extension" is an [official
+extension](/extensions/#official-extensions) of the JSON API specification.
+It provides support for modification of resources with the HTTP PATCH method
+[[RFC5789](http://tools.ietf.org/html/rfc5789)] and the JSON Patch format
+[[RFC6902](http://tools.ietf.org/html/rfc6902)].
+
+For the sake of brevity, operatons requested with `PATCH` and conforming
+with JSON Patch will be called "Patch operations".
+
+Servers and clients **MUST** negotiate support for and use of the JSON Patch
+extension [as described in the base specification](/format/#extending) using
+`jsonpatch` as the name of the extension.
+
+## Patch Operations <a href="#patch-operations" id="patch-operations" class="headerlink"></a>
+
+Patch operations **MUST** be sent as an array to conform with the JSON
+Patch format. A server **MAY** limit the type, order, and count of
+operations allowed in this top level array.
+
+### Request URLs and Patch Paths <a href="#patch-urls" id="patch-urls" class="headerlink"></a>
+
+The request URL and each Patch operation's `"path"` are complementary and
+**MUST** combine to target a particular resource, collection, attribute, or
+relationship.
+
+If a server supports the Patch extension, it **MUST** allow Patch operations at
+any resource or relationship URLs that accept POST, PATCH, or DELETE requests.
+
+Patch operations **MAY** also be allowed at the root URL of an API. In this
+case, every `"path"` within a Patch operation **MUST** include the full
+resource path relative to the root URL. This allows for general "fire hose"
+updates to any resource or relationship represented by an API. As stated
+above, a server **MAY** limit the type, order, and count of bulk operations.
+
+### Creating Resources <a href="#patch-creating" id="patch-creating" class="headerlink"></a>
+
+To create a resource, request an `"add"` operation with a `"path"` that points
+to the end of its corresponding resource collection (`"/-"`). The `"value"`
+should contain a resource object.
+
+For example, a new photo could be created with the following request:
+
+```text
+PATCH /photos
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ {
+ "op": "add",
+ "path": "/-",
+ "value": {
+ "type": "photos",
+ "title": "Ember Hamster",
+ "src": "http://example.com/images/productivity.png"
+ }
+ }
+]
+```
+
+### Updating Attributes <a href="#patch-updating-attributes" id="patch-updating-attributes" class="headerlink"></a>
+
+To update an attribute, perform a `"replace"` operation with the attribute's
+name specified by the `"path"`.
+
+For instance, the following request should update just the `src` property of the
+photo at `/photos/1`:
+
+```text
+PATCH /photos/1
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ { "op": "replace", "path": "/src", "value": "http://example.com/hamster.png" }
+]
+```
+
+### Updating Relationships <a href="#patch-updating-relationships" id="patch-updating-relationships" class="headerlink"></a>
+
+To update a relationship, send an appropriate Patch operation to the
+relationship's URL.
+
+A server **MAY** also support relationship updates at a higher level, such
+as the resource's URL or the API's root URL. As discussed above, the request
+URL and each Patch operation's `"path"` must be complementary and combine to
+target a particular relationship's URL.
+
+#### Updating To-One Relationships <a href="#patch-updating-to-one-relationships" id="patch-updating-to-one-relationships" class="headerlink"></a>
+
+To update a to-one relationship, perform a `"replace"` operation with a URL and
+`"path"` that targets the relationship. The `"value"` should be a link object
+that contains `"type"` and `"id"` members.
+
+For instance, the following request should update the `author` of an article:
+
+```text
+PATCH /article/1/links/author
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ { "op": "replace", "path": "", "value": {"type": "people", "id": "1"} }
+]
+```
+
+To remove a to-one relationship, perform a `replace` operation on the
+relationship to change its value to `null`. For example:
+
+```text
+PATCH /article/1/links/author
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ { "op": "replace", "path": "", "value": null }
+]
+```
+
+#### Updating To-Many Relationships <a href="#patch-updating-to-many-relationships" id="patch-updating-to-many-relationships" class="headerlink"></a>
+
+A server **MUST** respond to Patch operations that target a *to-many
+relationship URL* as described below.
+
+For all operations, the `"value"` **MUST** contain an object that contains
+`type` and `id` members, or an array of objects that each contain `type`
+and `id` members.
+
+If a client requests a `"replace"` operation to a *to-many relationship URL*, the
+server **MUST** either completely replace every member of the relationship,
+return an appropriate error response if some resources can not be found or
+accessed, or return a `403 Forbidden` response if complete replacement is
+not allowed by the server.
+
+For example, the following request replaces every tag for an article:
+
+```text
+PATCH /photos/1/links/tags
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ {
+ "op": "replace",
+ "path": "",
+ "value": [
+ { "type": "tags", "id": "2" },
+ { "type": "tags", "id": "3" }
+ ]
+ }
+]
+```
+
+To add an element to a to-many relationship, request an `"add"` operation that
+targets the relationship's URL. Because the operation is targeting the end of a
+collection, the `"path"` must end with `"/-"`.
+
+In the following example, the comment with ID `123` is added to the list of
+comments for the article with ID `1`:
+
+```text
+PATCH /articles/1/links/comments
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ {
+ "op": "add",
+ "path": "/-",
+ "value": [
+ { "type": "comments", "id": "123" }
+ ]
+ }
+]
+```
+
+To remove a to-many relationship, perform a `"remove"` operation that targets
+the relationship's URL.
+
+In the following example, comments with IDs of `5` and `13` are removed
+from the list of comments for the article with ID `1`:
+
+```text
+PATCH /articles/1/links/comments
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ {
+ "op": "remove",
+ "path": "",
+ "value": [
+ { "type": "comments", "id": "5" },
+ { "type": "comments", "id": "13" }
+ ]
+ }
+]
+```
+
+### Deleting a Resource <a href="#patch-deleting" id="patch-deleting" class="headerlink"></a>
+
+To delete a resource, perform a `"remove"` operation with a URL and `"path"`
+that targets the resource.
+
+For instance, photo `1` might be deleted with the following request:
+
+```text
+PATCH /photos/1
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ { "op": "remove", "path": "" }
+]
+```
+
+### Responses <a href="#patch-responses" id="patch-responses" class="headerlink"></a>
+
+#### 204 No Content <a href="#patch-responses-204" id="patch-responses-204" class="headerlink"></a>
+
+A server **MUST** return a `204 No Content` status code in response to a
+successful Patch operation in which the client's current attributes remain up to
+date.
+
+#### 200 OK <a href="#patch-responses-200" id="patch-responses-200" class="headerlink"></a>
+
+If a server accepts an update but also changes the resource(s) in other ways
+than those specified by the request (for example, updating the `updatedAt`
+attribute or a computed `sha`), it **MUST** return a `200 OK` response as well
+as a representation of the updated resources.
+
+The server **MUST** specify a `Content-Type` header of `application/vnd.api+json;
+ext=jsonpatch`. The body of the response **MUST** contain an array of JSON objects,
+each of which **MUST** conform to the JSON API media type
+(`application/vnd.api+json`). Response objects in this array **MUST** be in
+sequential order and correspond to the operations in the request document.
+
+For instance, a request may create two photos in separate operations:
+
+```text
+PATCH /photos
+Content-Type: application/vnd.api+json; ext=jsonpatch
+Accept: application/vnd.api+json; ext=jsonpatch
+
+[
+ {
+ "op": "add",
+ "path": "/-",
+ "value": {
+ "type": "photos",
+ "title": "Ember Hamster",
+ "src": "http://example.com/images/productivity.png"
+ }
+ },
+ {
+ "op": "add",
+ "path": "/-",
+ "value": {
+ "type": "photos",
+ "title": "Mustaches on a Stick",
+ "src": "http://example.com/images/mustaches.png"
+ }
+ }
+]
+```
+
+The response would then include corresponding JSON API documents contained
+within an array:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json; ext=jsonpatch
+
+[
+ {
+ "data": [{
+ "type": "photos",
+ "id": "123",
+ "title": "Ember Hamster",
+ "src": "http://example.com/images/productivity.png"
+ }]
+ }, {
+ "data": [{
+ "type": "photos",
+ "id": "124",
+ "title": "Mustaches on a Stick",
+ "src": "http://example.com/images/mustaches.png"
+ }]
+ }
+]
+```
+
+#### Other Responses <a href="#patch-responses-other" id="patch-responses-other" class="headerlink"></a>
+
+When a server encounters one or more problems while processing a Patch
+operation, it **SHOULD** specify the most appropriate HTTP error code in the
+response. Clients **MUST** interpret those errors in accordance with HTTP
+semantics.
+
+A server **MAY** choose to stop processing Patch operations as soon as the
+first problem is encountered, or it **MAY** continue processing operations and
+encounter multiple problems. For instance, a server might process multiple
+attribute updates and then return multiple validation problems in a single
+response.
+
+When a server encounters multiple problems from a single request, the most
+generally applicable HTTP error code should be specified in the response. For
+instance, `400 Bad Request` might be appropriate for multiple 4xx errors or `500
+Internal Server Error` might be appropriate for multiple 5xx errors.
+
+A server **MAY** return error objects that correspond to each operation. The
+body of the response **MUST** contain an array of JSON objects, which
+**MUST** be in sequential order and correspond to the operations in the
+request document. Each response object **SHOULD** contain only error objects
+keyed by `"errors"`, since no operations can be completed successfully when
+any errors occur. Error codes for each specific operation **SHOULD** be
+returned in the `"status"` member of each error object.
diff --git a/extensions/patch/index.md b/extensions/patch/index.md
deleted file mode 100644
index 4dcb61f..0000000
--- a/extensions/patch/index.md
+++ /dev/null
@@ -1,309 +0,0 @@
----
-layout: page
-title: "Patch Extension"
----
-
-## Introduction <a href="#introduction" id="introduction" class="headerlink"></a>
-
-The "Patch extension" is an [official
-extension](/extensions/#official-extensions) of the JSON API specification.
-It provides support for modification of resources with the HTTP PATCH method
-[[RFC5789](http://tools.ietf.org/html/rfc5789)] and the JSON Patch format
-[[RFC6902](http://tools.ietf.org/html/rfc6902)].
-
-For the sake of brevity, operatons requested with `PATCH` and conforming
-with JSON Patch will be called "Patch operations".
-
-Servers **SHOULD** indicate support for the JSON API media type's Patch
-extension by including the header `Content-Type: application/vnd.api+json;
-ext=patch` in every response.
-
-Clients **MAY** request the JSON API media type's Patch extension by
-specifying the header `Accept: application/vnd.api+json; ext=patch`. Servers
-that do not support the Patch extension **MUST** return a `415 Unsupported
-Media Type` status code.
-
-## Patch Operations <a href="#patch-operations" id="patch-operations" class="headerlink"></a>
-
-Patch operations **MUST** be sent as an array to conform with the JSON
-Patch format. A server **MAY** limit the type, order, and count of
-operations allowed in this top level array.
-
-### Request URLs and Patch Paths <a href="#patch-urls" id="patch-urls" class="headerlink"></a>
-
-The request URL and each Patch operation's `"path"` are complementary and
-MUST combine to target a particular resource, collection, attribute, or
-relationship.
-
-If a server supports the Patch extension, it **MUST** allow PATCH requests at
-any resource or relationship URLs that accept POST, PUT, or DELETE requests.
-
-PATCH requests **MAY** also be allowed at the root URL of an API. In this
-case, every `"path"` within a Patch operation **MUST** include the full
-resource path relative to the root URL. This allows for general "fire hose"
-updates to any resource or relationship represented by an API. As stated
-above, a server **MAY** limit the type, order, and count of bulk operations.
-
-### Creating Resources <a href="#patch-creating" id="patch-creating" class="headerlink"></a>
-
-To create a resource, request an `"add"` operation with a `"path"` that points
-to the end of its corresponding resource collection (`"/-"`). The `"value"`
-should contain a resource object.
-
-For example, a new photo could be created with the following request:
-
-```text
-PATCH /photos
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- {
- "op": "add",
- "path": "/-",
- "value": {
- "type": "photos",
- "title": "Ember Hamster",
- "src": "http://example.com/images/productivity.png"
- }
- }
-]
-```
-
-### Updating Attributes <a href="#patch-updating-attributes" id="patch-updating-attributes" class="headerlink"></a>
-
-To update an attribute, perform a `"replace"` operation with the attribute's
-name specified by the `"path"`.
-
-For instance, the following request should update just the `src` property of the
-photo at `/photos/1`:
-
-```text
-PATCH /photos/1
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- { "op": "replace", "path": "/src", "value": "http://example.com/hamster.png" }
-]
-```
-
-### Updating Relationships <a href="#patch-updating-relationships" id="patch-updating-relationships" class="headerlink"></a>
-
-To update a relationship, send an appropriate Patch operation to the
-relationship's URL.
-
-A server **MAY** also support relationship updates at a higher level, such
-as the resource's URL or the API's root URL. As discussed above, the request
-URL and each Patch operation's `"path"` must be complementary and combine to
-target a particular relationship's URL.
-
-#### Updating To-One Relationships <a href="#patch-updating-to-one-relationships" id="patch-updating-to-one-relationships" class="headerlink"></a>
-
-To update a to-one relationship, perform a `"replace"` operation with a URL and
-`"path"` that targets the relationship. The `"value"` should be a link object
-that contains `"type"` and `"id"` members.
-
-For instance, the following request should update the `author` of an article:
-
-```text
-PATCH /article/1/links/author
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- { "op": "replace", "path": "", "value": {"type": "people", "id": "1"} }
-]
-```
-
-To remove a to-one relationship, perform a `replace` operation on the
-relationship to change its value to `null`. For example:
-
-```text
-PATCH /article/1/links/author
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- { "op": "replace", "path": "", "value": null }
-]
-```
-
-#### Updating To-Many Relationships <a href="#patch-updating-to-many-relationships" id="patch-updating-to-many-relationships" class="headerlink"></a>
-
-A server **MUST** respond to Patch operations that target a *to-many
-relationship URL* as described below.
-
-For all operations, the `"value"` **MUST** contain an object that contains
-`type` and `ids` members, or an array of objects that each contain `type`
-and `id` members.
-
-If a client requests a `"replace"` operation to a *to-many relationship URL*, the
-server **MUST** either completely replace every member of the relationship,
-return an appropriate error response if some resources can not be found or
-accessed, or return a `403 Forbidden` response if complete replacement is
-not allowed by the server.
-
-For example, the following request replaces every tag for an article:
-
-```text
-PATCH /photos/1/links/tags
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- { "op": "replace", "path": "", "value": {"type": "tags", "ids": ["2", "3"]} }
-]
-```
-
-To add an element to a to-many relationship, request an `"add"` operation that
-targets the relationship's URL. Because the operation is targeting the end of a
-collection, the `"path"` must end with `"/-"`.
-
-In the following example, the comment with ID `123` is added to the list of
-comments for the article with ID `1`:
-
-```text
-PATCH /articles/1/links/comments
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- { "op": "add", "path": "/-", "value": { "type": "comments", "ids": ["123"] } }
-]
-```
-
-To remove a to-many relationship, perform a `"remove"` operation that targets
-the relationship's URL.
-
-In the following example, comments with IDs of `12` and `13` are removed
-from the list of comments for the article with ID `1`:
-
-```text
-PATCH /articles/1/links/comments
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- { "op": "remove", "path": "", "value": {"type": "comments", "ids": ["5", "13"]} }
-]
-```
-
-### Deleting a Resource <a href="#patch-deleting" id="patch-deleting" class="headerlink"></a>
-
-To delete a resource, perform a `"remove"` operation with a URL and `"path"`
-that targets the resource.
-
-For instance, photo `1` might be deleted with the following request:
-
-```text
-PATCH /photos/1
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- { "op": "remove", "path": "" }
-]
-```
-
-### Responses <a href="#patch-responses" id="patch-responses" class="headerlink"></a>
-
-#### 204 No Content <a href="#patch-responses-204" id="patch-responses-204" class="headerlink"></a>
-
-A server **MUST** return a `204 No Content` status code in response to a
-successful `PATCH` request in which the client's current attributes remain up to
-date.
-
-#### 200 OK <a href="#patch-responses-200" id="patch-responses-200" class="headerlink"></a>
-
-If a server accepts an update but also changes the resource(s) in other ways
-than those specified by the request (for example, updating the `updatedAt`
-attribute or a computed `sha`), it **MUST** return a `200 OK` response as well
-as a representation of the updated resources.
-
-The server **MUST** specify a `Content-Type` header of `application/json`. The
-body of the response **MUST** contain an array of JSON objects, each of which
-**MUST** conform to the JSON API media type (`application/vnd.api+json`).
-Response objects in this array **MUST** be in sequential order and correspond to
-the operations in the request document.
-
-For instance, a request may create two photos in separate operations:
-
-```text
-PATCH /photos
-Content-Type: application/vnd.api+json; ext=patch
-Accept: application/vnd.api+json; ext=patch
-
-[
- {
- "op": "add",
- "path": "/-",
- "value": {
- "type": "photos",
- "title": "Ember Hamster",
- "src": "http://example.com/images/productivity.png"
- }
- },
- {
- "op": "add",
- "path": "/-",
- "value": {
- "type": "photos",
- "title": "Mustaches on a Stick",
- "src": "http://example.com/images/mustaches.png"
- }
- }
-]
-```
-
-The response would then include corresponding JSON API documents contained
-within an array:
-
-```text
-HTTP/1.1 200 OK
-Content-Type: application/vnd.api+json; ext=patch
-
-[
- {
- "data": [{
- "type": "photos",
- "id": "123",
- "title": "Ember Hamster",
- "src": "http://example.com/images/productivity.png"
- }]
- }, {
- "data": [{
- "type": "photos",
- "id": "124",
- "title": "Mustaches on a Stick",
- "src": "http://example.com/images/mustaches.png"
- }]
- }
-]
-```
-
-#### Other Responses <a href="#patch-responses-other" id="patch-responses-other" class="headerlink"></a>
-
-When a server encounters one or more problems while processing a `PATCH`
-request, it **SHOULD** specify the most appropriate HTTP error code in the
-response. Clients **MUST** interpret those errors in accordance with HTTP
-semantics.
-
-A server **MAY** choose to stop processing Patch operations as soon as the
-first problem is encountered, or it **MAY** continue processing operations and
-encounter multiple problems. For instance, a server might process multiple
-attribute updates and then return multiple validation problems in a single
-response.
-
-When a server encounters multiple problems from a single request, the most
-generally applicable HTTP error code should be specified in the response. For
-instance, `400 Bad Request` might be appropriate for multiple 4xx errors or `500
-Internal Server Error` might be appropriate for multiple 5xx errors.
-
-A server **MAY** return error objects that correspond to each operation. The
-body of the response **MUST** contain an array of JSON objects, which
-**MUST** be in sequential order and correspond to the operations in the
-request document. Each response object **SHOULD** contain only error objects
-keyed by `"errors"`, since no operations can be completed successfully when
-any errors occur. Error codes for each specific operation **SHOULD** be
-returned in the `"status"` member of each error object.
diff --git a/faq/index.md b/faq/index.md
index 73f1027..7680bcb 100644
--- a/faq/index.md
+++ b/faq/index.md
@@ -54,14 +54,7 @@ is still pending to be included in the standard since is still in
### Is there a JSON Schema describing JSON API? <a href="#is-there-a-json-schema-describing-json-api" id="is-there-a-json-schema-describing-json-api" class="headerlink"></a>
-Yes, you can find the JSON Schema definition at
-[http://jsonapi.org/schema](http://jsonapi.org/schema). Please note that this
-schema is not a perfect document. Just because a JSON document may validate
-against this schema, that does not necessarily mean it is a valid JSON API
-document. The schema is provided for a base level sanity check.
-
-You can find more information about the JSON Schema format at
-[http://json-schema.org](http://json-schema.org).
+Not currently, no. JSON Schema cannot fully represent the semantics of JSON API, and so any such schema would be partial anyway.
### Why are resource collections returned as arrays instead of sets keyed by ID?
@@ -72,10 +65,10 @@ specified criteria.
In addition, JSON API allows read-only resources to be returned without IDs,
which would of course be incompatible with a set keyed by IDs.
-### Why are related resources nested in a `linked` object in a compound document?
+### Why are related resources nested in an `included` object in a compound document?
Primary resources should be isolated because their order and number is often
significant. It's necessary to separate primary and related resources by more
than type because it's possible that a primary resource may have related
resources of the same type (e.g. the "parents" of a "person"). Nesting related
-resources in `linked` prevents this possible conflict.
+resources in `included` prevents this possible conflict.
diff --git a/format/index.md b/format/index.md
index f931543..9f1a0f9 100644
--- a/format/index.md
+++ b/format/index.md
@@ -30,19 +30,54 @@ interpreted as described in RFC 2119
The base JSON API specification **MAY** be extended to support additional
capabilities.
-Servers that support one or more extensions to JSON API **SHOULD** return
-those extensions in every response in the `ext` media type parameter of the
-`Content-Type` header. The value of the `ext` parameter **MUST** be a
-comma-separated (U+002C COMMA, ",") list of extension names.
+An extension **MAY** make changes to and deviate from the requirements of the
+base specification apart from this section, which remains binding.
+
+Servers that support one or more extensions to JSON API **MUST** return
+those extensions in every response in the `supported-ext` media type
+parameter of the `Content-Type` header. The value of the `supported-ext`
+parameter **MUST** be a comma-separated (U+002C COMMA, ",") list of
+extension names.
+
+For example: a response that includes the header `Content-Type:
+application/vnd.api+json; supported-ext=bulk,jsonpatch` indicates that the
+server supports both the "bulk" and "jsonpatch" extensions.
+
+If an extension is used to form a particular request or response document,
+then it **MUST** be specified by including its name in the `ext` media type
+parameter with the `Content-Type` header. The value of the `ext` media type
+parameter **MUST** be formatted as a comma-separated (U+002C COMMA, ",")
+list of extension names and **MUST** be limited to a subset of the
+extensions supported by the server, which are listed in `supported-ext`
+of every response.
For example: a response that includes the header `Content-Type:
-application/vnd.api+json; ext=bulk,patch` indicates that the server supports
-both the "bulk" and "patch" extensions.
+application/vnd.api+json; ext=ext1,ext2; supported-ext=ext1,ext2,ext3`
+indicates that the response document is formatted according to the
+extensions "ext1" and "ext2". Another example: a request that includes
+the header `Content-Type: application/vnd.api+json; ext=ext1,ext2`
+indicates that the request document is formatted according to the
+extensions "ext1" and "ext2".
Clients **MAY** request a particular media type extension by including its
name in the `ext` media type parameter with the `Accept` header. Servers
-that do not support a requested extension **MUST** return a `415 Unsupported
-Media Type` status code.
+that do not support a requested extension or combination of extensions
+**MUST** return a `406 Not Acceptable` status code.
+
+If the media type in the `Accept` header is supported by a server but the
+media type in the `Content-Type` header is unsupported, the server
+**MUST** return a `415 Unsupported Media Type` status code.
+
+Servers **MUST NOT** provide extended functionality that is incompatible
+with the base specification to clients that do not request the extension in
+the `ext` parameter of the `Content-Type` or the `Accept` header.
+
+> Note: Since extensions can contradict one another or have interactions
+that can be resolved in many equally plausible ways, it is the
+responsibility of the server to decide which extensions are compatible, and
+it is the responsibility of the designer of each implementation of this
+specification to describe extension interoperability rules which are
+applicable to that implementation.
## Document Structure <a href="#document-structure" id="document-structure" class="headerlink"></a>
@@ -56,16 +91,22 @@ Although the same media type is used for both request and response documents,
certain aspects are only applicable to one or the other. These differences are
called out below.
+Unless otherwise noted, objects defined by this specification **MUST NOT**
+contain any additional members. Client and server implementations **MUST**
+ignore object members not recognized by this specification.
+
+> Note: These conditions for object members allow this specification to
+evolve through additive changes.
+
### Top Level <a href="#document-structure-top-level" id="document-structure-top-level" class="headerlink"></a>
-A JSON object **MUST** be at the root of every JSON API response. This object
-defines a document's "top level".
+A JSON object **MUST** be at the root of every JSON API response containing
+data. This object defines a document's "top level".
The document's "primary data" is a representation of the resource, collection
of resources, or resource relationship primarily targeted by a request.
-A document **MUST** contain either primary data or a collection of error
-objects.
+A document **MUST** contain either primary data or an array of [error objects](#errors).
Primary data **MUST** appear under a top-level key named `"data"`. Primary
data **MUST** be either a single resource object, an array of resource
@@ -81,24 +122,41 @@ objects, or a value representing a resource relationship.
}
```
+A logical collection of resources (e.g., the target of a to-many relationship)
+**MUST** be represented as an array, even if it only contains one item.
+A logically singular resource (e.g., the target of a to-one relationship)
+**MUST** be represented as a single resource object.
+
Error objects **MUST** appear under a top-level key named `"errors"`.
A document's top level **MAY** also have the following members:
* `"meta"`: non-standard meta-information about the primary data.
* `"links"`: URLs related to the primary data.
-* `"linked"`: a list of resource objects that are linked to the primary data
- and/or each other ("linked resources").
+* `"included"`: a list of resource objects that are related to the primary data
+ and/or each other ("included resources").
If any of these members appears in the top-level of a response, their values
**MUST** comply with this specification.
-The top level of a document **MUST NOT** contain any additional members.
-
### Resource Objects <a href="#document-structure-resource-objects" id="document-structure-resource-objects" class="headerlink"></a>
-"Resource objects" appear in a JSON API document to represent primary data
-and linked resources.
+"Resource objects" appear in a JSON API document to represent resources.
+
+A resource object **MUST** contain at least the following top-level members:
+
+* `"id"`
+* `"type"`
+
+Exception: The `id` member is not required when the resource object originates at
+the client and represents a new resource to be created on the server.
+
+In addition, a resource object **MAY** contain any of these top-level members:
+
+* `"links"`: a "links object", providing information about a resource's
+ relationships (described below).
+* `"meta"`: non-standard meta-information about a resource that can not be
+ represented as an attribute or relationship.
Here's how an article (i.e. a resource of type "articles") might appear in a document:
@@ -107,32 +165,39 @@ Here's how an article (i.e. a resource of type "articles") might appear in a doc
{
"type": "articles",
"id": "1",
- "title": "Rails is Omakase"
+ "title": "Rails is Omakase",
+ "links": {
+ "author": {
+ "self": "/articles/1/links/author",
+ "related": "/articles/1/author",
+ "linkage": { "type": "people", "id": "9" }
+ }
+ }
}
// ...
```
-#### Resource Attributes <a href="#document-structure-resource-object-attributes" id="document-structure-resource-object-attributes" class="headerlink"></a>
+#### Attributes <a href="#document-structure-resource-object-attributes" id="document-structure-resource-object-attributes"></a>
-A resource object **MUST** contain at least the following top-level members:
+A resource object **MAY** contain additional top-level members. These members
+represent "[attributes]" and may contain any valid JSON value.
-* `"id"`
-* `"type"`
+Although has-one foreign keys (e.g. `author_id`) are often stored internally
+alongside other information to be represented in a resource object, these keys
+**SHOULD NOT** appear as attributes. If relations are provided, they **MUST**
+be represented under the "links object".
-In addition, a resource object **MAY** contain any of these top-level members:
+#### Complex Attributes <a href="#document-structure-resource-object-complex-attributes" id="document-structure-resource-object-complex-attributes"></a>
-* `"links"`: information about a resource's relationships (described
- below).
-* `"meta"`: non-standard meta-information about a resource that can not be
- represented as an attribute or relationship.
+"[Complex attributes]" are [attributes] whose value is an object or array with
+any level of nesting. An object that constitutes or is contained in a complex
+attribute must reserve the `id`, `type`, `links`, and `meta` members for future
+use.
-Any other member in a resource object represents an "attribute", which may
-contain any valid JSON value.
+#### Fields <a href="#document-structure-resource-object-fields" id="document-structure-resource-object-fields" class="headerlink"></a>
-> Note: Although has-one foreign keys are often stored as columns in a
-database alongside other fields, foreign keys **MUST NOT** be included in a
-resource's attributes. All relations **MUST** be represented under a
-resource's links object, as described below.
+A resource object's [attributes] and relationships are collectively called its
+"[fields]". <a href="#document-structure-resource-object-fields" id="document-structure-resource-object-fields"></a>
#### Resource Identification <a href="#document-structure-resource-identification" id="document-structure-resource-identification" class="headerlink"></a>
@@ -159,10 +224,10 @@ consistently throughout an implementation.
Each resource object **MUST** contain an `id` member, whose value **MUST**
be a string.
-#### Links
+#### Links <a href="#document-structure-links" id="document-structure-links" class="headerlink"></a>
The value of the `"links"` key is a JSON object (a "links object") that
-represents linked resources, keyed by the name of each association.
+represents related resources, keyed by the name of each association.
The key `"self"` is reserved within the links object for the resource URL,
as described below.
@@ -198,33 +263,26 @@ The name of the relationship declared in the key **SHALL NOT** be `"self"`.
The value of a relationship **MUST** be one of the following:
-* A string, which represents a URL for the related resource(s) (a "related
- resource URL"). When fetched, it returns the related resource object(s) as the
- response's primary data. For example, an `article`'s `comments` could specify a
- URL that returns a list of comment resource objects when retrieved through a
- `GET` request. A related resource URL **SHOULD** remain constant even when the
- resource(s) it represents mutate.
+* A URL for the related resource(s) (a "related resource URL"). When fetched, it
+ returns the related resource object(s) as the response's primary data. For
+ example, an `article`'s `comments` relationship could specify a URL that
+ returns a list of comment resource objects when retrieved through a `GET`
+ request. A related resource URL **MUST** remain constant even when the
+ relationship (the set of referenced resources) mutates. That is, the response
+ from a related resource URL always reflects the current state of the
+ relationship.
* An object (a "link object").
If a relationship is provided as a link object, it **MUST** contain at least
one of the following:
-* A `self` member, whose value is a URL for the relationship itself (a
+* A `"self"` member, whose value is a URL for the relationship itself (a
"relationship URL"). This URL allows the client to directly manipulate the
relationship. For example, it would allow a client to remove an `author` from
an `article` without deleting the `people` resource itself.
-* A `resource` member, whose value is a related resource URL (as defined above).
-* Linkage to other resource objects ("object linkage") included in a compound
- document. This allows a client to link together all of the resource objects
- included in a compound document without having to `GET` one of the
- relationship URLs. Linkage **MUST** be expressed as:
- * `type` and `id` members for to-one relationships. `type` is not required
- if the value of `id` is `null`.
- * `type` and `ids` members for homogenous to-many relationships. `type` is
- not required if the value of `ids` is an empty array (`[]`).
- * A `data` member whose value is an array of objects each containing `type`
- and `id` members for heterogenous to-many relationships.
+* A `"related"` member, whose value is a related resource URL (as defined above).
+* A `"linkage"` member, whose value represents "resource linkage".
* A `"meta"` member that contains non-standard meta-information about the
relationship.
@@ -232,40 +290,25 @@ A link object that represents a to-many relationship **MAY** also contain
pagination links, as described below.
If a link object refers to resource objects included in the same compound
-document, it **MUST** include object linkage to those resource objects.
+document, it **MUST** include resource linkage to those resource objects.
-For example, the following article is associated with an `author` and `comments`:
+Resource linkage **MUST** be represented as one of the following:
-```javascript
-// ...
-{
- "type": "articles",
- "id": "1",
- "title": "Rails is Omakase",
- "links": {
- "self": "http://example.com/articles/1",
- "author": {
- "self": "http://example.com/articles/1/links/author"
- "resource": "http://example.com/articles/1/author",
- "type": "people",
- "id": "9"
- },
- "comments": {
- "resource": "http://example.com/articles/1/comments"
- }
- }
-}
-// ...
-```
+* `null` for empty to-one relationships.
+* an object containing `"type"` and `"id"` members for non-empty to-one
+ relationships.
+* an empty array (`[]`) for empty to-many relationships.
+* an array of objects each containing `"type"` and `"id"` members for non-empty
+ to-many relationships.
-The `author` relationship includes a URL for the relationship itself (which
-allows the client to change the related author without deleting the `people`
-object), a URL to fetch the resource objects, and linkage information for
-the current compound document.
+> Note: Resource linkage in a compound document allows a client to link
+together all of the included resource objects without having to `GET` any
+relationship URLs.
+
+> Note: If present, a *related resource URL* must be a valid URL, even if the
+relationship isn't currently associated with any target resources.
-The `comments` relationship is simpler: it just provides a URL to fetch the
-comments. The following resource object, which provides the `comments`
-relationship as a string value rather than an object, is equivalent:
+For example, the following article is associated with an `author` and `comments`:
```javascript
// ...
@@ -276,10 +319,9 @@ relationship as a string value rather than an object, is equivalent:
"links": {
"self": "http://example.com/articles/1",
"author": {
- "self": "http://example.com/articles/1/links/author"
- "resource": "http://example.com/articles/1/author",
- "type": "people",
- "id": "9"
+ "self": "http://example.com/articles/1/links/author",
+ "related": "http://example.com/articles/1/author",
+ "linkage": { "type": "people", "id": "9" }
},
"comments": "http://example.com/articles/1/comments"
}
@@ -287,14 +329,22 @@ relationship as a string value rather than an object, is equivalent:
// ...
```
+The `author` relationship includes a URL for the relationship itself (which
+allows the client to change the related author directly), a related resource URL
+to fetch the resource objects, and linkage information.
+
+The `comments` relationship is simpler: it just provides a related resource URL
+to fetch the comments. The URL can therefore be specified directly as the
+attribute value.
+
### Compound Documents <a href="#document-structure-compound-documents" id="document-structure-compound-documents" class="headerlink"></a>
To reduce the number of HTTP requests, servers **MAY** allow responses that
-include linked resources along with the requested primary resources. Such
+include related resources along with the requested primary resources. Such
responses are called "compound documents".
-In a compound document, linked resources **MUST** be included as an array of
-resource objects in a top level `"linked"` member.
+In a compound document, all included resources **MUST** be represented as an
+array of resource objects in a top-level `"included"` member.
A complete example document with multiple included relationships:
@@ -308,19 +358,20 @@ A complete example document with multiple included relationships:
"self": "http://example.com/articles/1",
"author": {
"self": "http://example.com/articles/1/links/author",
- "resource": "http://example.com/articles/1/author",
- "type": "people",
- "id": "9"
+ "related": "http://example.com/articles/1/author",
+ "linkage": { "type": "people", "id": "9" }
},
"comments": {
"self": "http://example.com/articles/1/links/comments",
- "resource": "http://example.com/articles/1/comments",
- "type": "comments",
- "ids": ["5", "12"]
+ "related": "http://example.com/articles/1/comments",
+ "linkage": [
+ { "type": "comments", "id": "5" },
+ { "type": "comments", "id": "12" }
+ ]
}
}
}],
- "linked": [{
+ "included": [{
"type": "people",
"id": "9",
"first-name": "Dan",
@@ -385,36 +436,292 @@ For example:
}
```
+Any members **MAY** be specified within `meta` objects.
+
### Top-level Links <a href="#document-structure-top-level-links" id="document-structure-top-level-links" class="headerlink"></a>
The top-level links object **MAY** contain the following members:
* `"self"` - a link for fetching the data in the response document.
-* Pagination links for the primary data, as described below.
+* `"related"` - a related resource URL (as defined above) when the primary
+ data represents a resource relationship.
+* Pagination links for the primary data (as described below).
-## Fetching Resources <a href="#fetching" id="fetching" class="headerlink"></a>
+## Fetching Data <a href="#fetching" id="fetching" class="headerlink"></a>
-A resource, or collection of resources, can be fetched by sending a `GET`
-request to an endpoint.
+Data, including resources and relationships, can be fetched by sending a
+`GET` request to an endpoint.
JSON API requests **MUST** include an `Accept` header specifying the JSON
-API media type.
+API media type. This header value **MUST** also include media type
+extensions relevant to the request. Servers **MUST** return a `406 Not
+Acceptable` status code if this header is missing or specifies an
+unsupported media type.
+
+> Note: Servers may support multiple media types at any endpoint. For example,
+a server may choose to support `text/html` in order to simplify viewing content
+via a web browser.
Responses can be further refined with the optional features described below.
-### Inclusion of Linked Resources <a href="#fetching-includes" id="fetching-includes" class="headerlink"></a>
+### Fetching Resources <a href="#fetching-resources" id="fetching-resources" class="headerlink"></a>
-An endpoint **MAY** return resources linked to the primary data by default.
+A server **MUST** support fetching resource data for every URL provided as:
-An endpoint **MAY** also support custom inclusion of linked resources based
+* a `self` link as part of the top-level *links object*
+* a `self` link as part of a *resource object*
+* a `related` link as part of a *link object*
+
+For example, the following request fetches a collection of articles:
+
+```text
+GET /articles
+```
+
+The following request fetches an article:
+
+```text
+GET /articles/1
+```
+
+And the following request fetches an article's author:
+
+```text
+GET /articles/1/author
+```
+
+#### Responses <a href="#fetching-resources-responses" id="fetching-resources-responses" class="headerlink"></a>
+
+##### 200 OK <a href="#fetching-resources-responses-200" id="fetching-resources-responses-200" class="headerlink"></a>
+
+A server **MUST** respond to a successful request to fetch an individual
+resource or resource collection with a `200 OK` response.
+
+A server **MUST** respond to a successful request to fetch a resource
+collection with an array of *resource objects* or an empty array (`[]`) as
+the response document's primary data.
+
+For example, a `GET` request to a collection of articles could return:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json
+
+{
+ "links": {
+ "self": "http://example.com/articles"
+ },
+ "data": [{
+ "type": "articles",
+ "id": "1",
+ "title": "JSON API paints my bikeshed!"
+ }, {
+ "type": "articles",
+ "id": "2",
+ "title": "Rails is Omakase"
+ }]
+}
+```
+
+A similar response representing an empty collection would be:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json
+
+{
+ "links": {
+ "self": "http://example.com/articles"
+ },
+ "data": []
+}
+```
+
+A server **MUST** respond to a successful request to fetch an individual
+resource with a *resource object* or `null` provided as the response
+document's primary data.
+
+> Note: `null` is only an appropriate response for fetching a to-one
+related resource URL to indicate the absence of a resource in the relationship.
+
+For example, a `GET` request to an individual article could return:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json
+
+{
+ "links": {
+ "self": "http://example.com/articles/1"
+ },
+ "data": {
+ "type": "articles",
+ "id": "1",
+ "title": "JSON API paints my bikeshed!",
+ "links": {
+ "author": {
+ "related": "http://example.com/articles/1/author"
+ }
+ }
+ }
+}
+```
+
+If the above article's author is missing, then a `GET` request to that related
+resource would return:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json
+
+{
+ "links": {
+ "self": "http://example.com/articles/1/author"
+ },
+ "data": null
+}
+```
+
+##### 404 Not Found <a href="#fetching-resources-responses-404" id="fetching-resources-responses-404" class="headerlink"></a>
+
+A server **MUST** return `404 Not Found` when processing a request to fetch
+a resource that does not exist.
+
+> Note: When requesting a related resource that is not present, a server
+**MUST** respond with `200 OK` and `null` or an empty array (`[]`) as the
+response document's primary data, as described above.
+
+##### Other Responses <a href="#fetching-resources-responses-other" id="fetching-resources-responses-other" class="headerlink"></a>
+
+Servers **MAY** use other HTTP error codes to represent errors. Clients
+**MUST** interpret those errors in accordance with HTTP semantics. Error
+details **MAY** also be returned, as discussed below.
+
+### Fetching Relationships <a href="#fetching-relationships" id="fetching-relationships" class="headerlink"></a>
+
+A server **MUST** support fetching relationship data for every relationship URL
+provided as a `self` link as part of a *link object*.
+
+For example, the following request fetches data about an article's comments:
+
+```text
+GET /articles/1/links/comments
+```
+
+And the following request fetches data about an article's author:
+
+```text
+GET /articles/1/links/author
+```
+
+#### Responses <a href="#fetching-relationships-responses" id="fetching-relationships-responses" class="headerlink"></a>
+
+##### 200 OK <a href="#fetching-relationships-responses-200" id="fetching-relationships-responses-200" class="headerlink"></a>
+
+A server **MUST** respond to a successful request to fetch a relationship
+with a `200 OK` response.
+
+The primary data in the response document **MUST** match the appropriate
+value for resource linkage, as described above for link objects.
+
+The top-level *links object* **MAY** contain `self` and `related` links,
+as described above for link objects.
+
+For example, a `GET` request a to-one relationship URL could return:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json
+
+{
+ "links": {
+ "self": "/articles/1/links/author",
+ "related": "/articles/1/author"
+ },
+ "data": {
+ "type": "people",
+ "id": "12"
+ }
+}
+```
+
+If the above relationship is empty, then a `GET` request to the same URL would
+return:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json
+
+{
+ "links": {
+ "self": "/articles/1/links/author",
+ "related": "/articles/1/author"
+ },
+ "data": null
+}
+```
+
+A `GET` request to a to-many relationship URL could return:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json
+
+{
+ "links": {
+ "self": "/articles/1/links/tags",
+ "related": "/articles/1/tags"
+ },
+ "data": [
+ { "type": "tags", "id": "2" },
+ { "type": "tags", "id": "3" }
+ ]
+}
+```
+
+If the above relationship is empty, then a `GET` request to the same URL would
+return:
+
+```text
+HTTP/1.1 200 OK
+Content-Type: application/vnd.api+json
+
+{
+ "links": {
+ "self": "/articles/1/links/tags",
+ "related": "/articles/1/tags"
+ },
+ "data": []
+}
+```
+
+##### 404 Not Found <a href="#fetching-relationships-responses-404" id="fetching-relationships-responses-404" class="headerlink"></a>
+
+A server **MUST** return `404 Not Found` when processing a request to fetch
+a relationship URL that does not exist.
+
+> Note: If a relationship URL exists but the relationship is empty, then
+`200 OK` **MUST** be returned, as described above.
+
+##### Other Responses <a href="#fetching-relationships-responses-other" id="fetching-relationships-responses-other" class="headerlink"></a>
+
+Servers **MAY** use other HTTP error codes to represent errors. Clients
+**MUST** interpret those errors in accordance with HTTP semantics. Error
+details **MAY** also be returned, as discussed below.
+
+### Inclusion of Related Resources <a href="#fetching-includes" id="fetching-includes" class="headerlink"></a>
+
+An endpoint **MAY** return resources related to the primary data by default.
+
+An endpoint **MAY** also support custom inclusion of related resources based
upon an `include` request parameter. This parameter **MUST** specify the
relationship using the name used in the `links` section of the primary data.
If a client supplies an `include` parameter, the server **MUST NOT** include
-other resource objects in the `linked` section of the compound document.
+other resource objects in the `included` section of the compound document.
-The value of the `include` parameter is a comma-separated (U+002C COMMA,
-",") list of relationship paths. A relationship path is a dot-separated
+The value of the `include` parameter **MUST** be a comma-separated (U+002C
+COMMA, ",") list of relationship paths. A relationship path is a dot-separated
(U+002E FULL-STOP, ".") list of relationship names. Each relationship name
**MUST** be identical to the key in the `links` section of its parent
resource object.
@@ -429,7 +736,7 @@ For instance, comments could be requested with an article:
GET /articles/1?include=comments
```
-In order to request resources linked to other resources, a dot-separated path
+In order to request resources related to other resources, a dot-separated path
for each relationship name can be specified:
```text
@@ -441,7 +748,7 @@ include `comments` in the response. This can happen if the client already
has the `comments` locally, and now wants to fetch the associated authors
without fetching the comments again.
-Multiple linked resources can be requested in a comma-separated list:
+Multiple related resources can be requested in a comma-separated list:
```text
GET /articles/1?include=author,comments,comments.author
@@ -449,17 +756,22 @@ GET /articles/1?include=author,comments,comments.author
### Sparse Fieldsets <a href="#fetching-sparse-fieldsets" id="fetching-sparse-fieldsets" class="headerlink"></a>
-A client **MAY** request that an endpoint return only specific fields in the
-response on a per-type basis by including a `fields[TYPE]` parameter. The
-value of the parameter refers to an attribute name or a relationship name.
+A client **MAY** request that an endpoint return only specific [fields] in the
+response on a per-type basis by including a `fields[TYPE]` parameter.
+
+> Note: Only [fields] are affected; `type`, `id`, and (optionally) `self` are
+included as normal.
+
+The value of the `fields` parameter **MUST** be a comma-separated (U+002C
+COMMA, ",") list that refers to the name(s) of the fields to be returned.
+
+If a client requests a restricted set of [fields], an endpoint **MUST NOT**
+include additional [fields] in the response.
```text
-GET /articles?include=author&fields[articles]=id,title&fields[people]=id,name
+GET /articles?include=author&fields[articles]=title,body&fields[people]=name
```
-If a client requests a restricted set of fields, an endpoint **MUST NOT** include other
-fields in the response.
-
### Sorting <a href="#fetching-sorting" id="fetching-sorting" class="headerlink"></a>
A server **MAY** choose to support requests to sort resource collections
@@ -516,9 +828,9 @@ A server **MAY** provide links to traverse a paginated data set ("pagination
links").
Pagination links **MUST** appear in the link object that corresponds to a
-collection. To paginate the primary data, include pagination links in the
-top-level `links` object. To paginate a linked collection returned in a
-compound document, include pagination links in the corresponding link
+collection. To paginate the primary data, supply pagination links in the
+top-level `links` object. To paginate an included collection returned in
+a compound document, supply pagination links in the corresponding link
object.
The following keys **MUST** be used for pagination links:
@@ -534,7 +846,8 @@ particular link is unavailable.
Concepts of order, as expressed in the naming of pagination links, **MUST**
remain consistent with JSON API's [sorting rules](#fetching-sorting).
-The `page` query parameter is reserved for servers to use to specify pagination.
+The `page` query parameter is reserved for pagination. Servers and clients
+**SHOULD** use this key for pagination operations.
> Note: JSON API is agnostic about the pagination strategy used by a server.
Effective pagination strategies include (but are not limited to):
@@ -546,11 +859,12 @@ cursor-based strategy might use `page[cursor]`.
### Filtering <a href="#fetching-filtering" id="fetching-filtering" class="headerlink"></a>
-The `filter` query parameter is reserved for servers to use for filtering data.
+The `filter` query parameter is reserved for filtering data. Servers and clients
+**SHOULD** use this key for filtering operations.
-> Note: JSON API is agnostic about the filtering strategies supported by a
-server. The `filter` query parameter can be used as the basis for any number of
-filtering strategies.
+> Note: JSON API is agnostic about the strategies supported by a server. The
+`filter` query parameter can be used as the basis for any number of filtering
+strategies.
## Creating, Updating and Deleting Resources <a href="#crud" id="crud" class="headerlink"></a>
@@ -564,20 +878,20 @@ include media type extensions relevant to the request.
A request **MUST** completely succeed or fail (in a single "transaction"). No
partial updates are allowed.
+> Note: The `type` member is required in every resource object throughout requests and
+responses in JSON API. There are some cases, such as when `POST`ing to an
+endpoint representing heterogenous data, when the `type` could not be inferred
+from the endpoint. However, picking and choosing when it is required would be
+confusing; it would be hard to remember when it was required and when it was
+not. Therefore, to improve consistency and minimize confusion, `type` is
+always required.
+
### Creating Resources <a href="#crud-creating" id="crud-creating" class="headerlink"></a>
A resource can be created by sending a `POST` request to a URL that represents
a collection of resources. The request **MUST** include a single resource object
as primary data. The resource object **MUST** contain at least a `type` member.
-> Note: The `type` member is required throughout requests and responses in
-JSON API. There are some cases, such as when `POST`ing to an endpoint
-representing heterogenous data, when the `type` could not be inferred from
-the endpoint. However, picking and choosing when it is required would be
-confusing; it would be hard to remember when it was required and when it was
-not. Therefore, to improve consistency and minimize confusion, `type` is
-always required.
-
For instance, a new photo might be created with the following request:
```text
@@ -632,8 +946,7 @@ to create a resource with a client-generated ID.
##### 201 Created <a href="#crud-creating-responses-201" id="crud-creating-responses-201" class="headerlink"></a>
A server **MUST** respond to a successful resource creation request according to
-[`HTTP semantics`]
-(http://tools.ietf.org/html/draft-ietf-httpbis-p2-semantics-22#section-6.3).
+[`HTTP semantics`](http://tools.ietf.org/html/rfc7231#section-6.3).
The response **MUST** include a `Location` header identifying the location
of the newly created resource.
@@ -645,7 +958,7 @@ ID](#crud-creating-client-ids), and a resource has been created, the server
The response **MUST** also include a document that contains the primary
resource created.
-If the data object returned by the response contains a `self` key in its
+If the resource object returned by the response contains a `self` key in its
`links` member, the value of the `self` member **MUST** match the value of
the `Location` header.
@@ -674,7 +987,7 @@ ID](#crud-creating-client-ids), the server **MUST** return either a `201
Created` status code and response document (as described above) or a `204 No
Content` status code with no response document.
-> Note: If a `204` response is received the client should consider the data
+> Note: If a `204` response is received the client should consider the resource
object sent in the request to be accepted by the server, as if the server
had returned it back in a `201` response.
@@ -699,20 +1012,20 @@ details **MAY** also be returned, as discussed below.
### Updating Resources <a href="#crud-updating" id="crud-updating" class="headerlink"></a>
-A resource's attributes and relationships can be updated by sending a `PUT`
+A resource's attributes and relationships can be updated by sending a `PATCH`
request to the URL that represents the resource.
-The URL for a resource can be obtained:
-
-* from the `self` link in the resource object
-* for a *data object*, the original URL that was used to `GET` the document
+The URL for a resource can be obtained in the `self` link of the resource
+object. Alternatively, when a `GET` request returns a single resource object as
+primary data, the same request URL can be used for updates.
-The `PUT` request **MUST** include a single resource object as primary data.
+The `PATCH` request **MUST** include a single resource object as primary data.
+The resource object **MUST** contain `type` and `id` members.
For example:
```text
-PUT /articles/1
+PATCH /articles/1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
@@ -728,24 +1041,17 @@ Accept: application/vnd.api+json
#### Updating a Resource's Attributes <a href="#crud-updating-resource-attributes" id="crud-updating-resource-attributes" class="headerlink"></a>
Any or all of a resource's attributes **MAY** be included in the resource
-object included in a `PUT` request.
+object included in a `PATCH` request.
If a request does not include all of the fields for a resource, the server
**MUST** interpret the missing fields as if they were included together with
their current values. It **MUST NOT** interpret them as `null` values.
-> Note: Because the resources represented by JSON API have a list of known
-fields, the server *must* interpret the missing attributes in some way.
-Choosing to interpret them as `null` values would be just as arbitrary as
-choosing to interpret them as containing their current values, and the
-dominant real-world practice is to interpret such a request as a request for
-a partial update.
-
-For example, the following `PUT` request is interpreted as a request to
+For example, the following `PATCH` request is interpreted as a request to
update only the `title` and `text` attributes of an article:
```text
-PUT /articles/1
+PATCH /articles/1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
@@ -762,16 +1068,16 @@ Accept: application/vnd.api+json
#### Updating a Resource's To-One Relationships <a href="#crud-updating-resource-to-one-relationships" id="crud-updating-resource-to-one-relationships" class="headerlink"></a>
If a to-one relationship is provided in the `links` section of a resource
-object in a `PUT` request, it **MUST** be one of:
+object in a `PATCH` request, its value **MUST** be either:
* an object with `type` and `id` members corresponding to the related resource
* `null`, to remove the relationship
-For instance, the following `PUT` request will update the `title` attribute
+For instance, the following `PATCH` request will update the `title` attribute
and `author` relationship of an article:
```text
-PUT /articles/1
+PATCH /articles/1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
@@ -790,19 +1096,17 @@ Accept: application/vnd.api+json
#### Updating a Resource's To-Many Relationships <a href="#crud-updating-resource-to-many-relationships" id="crud-updating-resource-to-many-relationships" class="headerlink"></a>
If a to-many relationship is included in the `links` section of a resource
-object, it **MUST** be an object containing:
+object, it **MUST** be either:
-* `type` and `ids` members for homogenous to-many relationships; to clear the
- relationship, set the `ids` member to `[]`
-* a `data` member whose value is an array of objects each containing `type` and
- `id` members for heterogenous to-many relationships; to clear the
- relationship, set the `data` member to `[]`
+* an array of objects each containing `type` and `id` members to replace all
+ members of the relationship.
+* an empty array (`[]`) to clear the relationship.
-For instance, the following `PUT` request performs a complete replacement of
+For instance, the following `PATCH` request performs a complete replacement of
the `tags` for an article:
```text
-PUT /articles/1
+PATCH /articles/1
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
@@ -812,7 +1116,10 @@ Accept: application/vnd.api+json
"id": "1",
"title": "Rails is a Melting Pot",
"links": {
- "tags": { "type": "tags", "ids": ["2", "3"] }
+ "tags": [
+ { "type": "tags", "id": "2" },
+ { "type": "tags", "id": "3" }
+ ]
}
}
}
@@ -837,7 +1144,7 @@ successful and the client's current attributes remain up to date.
##### 200 OK <a href="#crud-updating-responses-200" id="crud-updating-responses-200" class="headerlink"></a>
If a server accepts an update but also changes the resource(s) in other ways
-than those specified by the request (for example, updating the `updatedAt`
+than those specified by the request (for example, updating the `updated-at`
attribute or a computed `sha`), it **MUST** return a `200 OK` response.
The response document for a `200 OK` **MUST** include a representation of
@@ -858,11 +1165,11 @@ references a related resource that does not exist.
##### 409 Conflict <a href="#crud-updating-responses-409" id="crud-updating-responses-409" class="headerlink"></a>
-A server **MAY** return `409 Conflict` when processing a `PUT` request to
+A server **MAY** return `409 Conflict` when processing a `PATCH` request to
update a resource if that update would violate other server-enforced
-constraints (such as a uniqueness constraint on a field other than `id`).
+constraints (such as a uniqueness constraint on a property other than `id`).
-A server **MUST** return `409 Conflict` when processing a `PUT` request in
+A server **MUST** return `409 Conflict` when processing a `PATCH` request in
which the resource's `type` and `id` do not match the server's endpoint.
##### Other Responses <a href="#crud-updating-responses-other" id="crud-updating-responses-other" class="headerlink"></a>
@@ -895,19 +1202,19 @@ relationship is deleted (as a garbage collection measure).
#### Updating To-One Relationships <a href="#crud-updating-to-one-relationships" id="crud-updating-to-one-relationships" class="headerlink"></a>
-A server **MUST** respond to `PUT` requests to a *to-one relationship URL* as
+A server **MUST** respond to `PATCH` requests to a *to-one relationship URL* as
described below.
-The `PUT` request **MUST** include a top-level member named `data` containing
+The `PATCH` request **MUST** include a top-level member named `data` containing
one of:
-* an object with `type` and `id` members corresponding to the related resource
-* `null`, to remove the relationship
+* an object with `type` and `id` members corresponding to the related resource.
+* `null`, to remove the relationship.
For example, the following request updates the author of an article:
```text
-PUT /articles/1/links/author
+PATCH /articles/1/links/author
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
@@ -919,7 +1226,7 @@ Accept: application/vnd.api+json
And the following request clears the author of the same article:
```text
-PUT /articles/1/links/author
+PATCH /articles/1/links/author
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
@@ -933,14 +1240,14 @@ a `204 No Content` response.
#### Updating To-Many Relationships <a href="#crud-updating-to-many-relationships" id="crud-updating-to-many-relationships" class="headerlink"></a>
-A server **MUST** respond to `PUT`, `POST`, and `DELETE` requests to a *to-many
-relationship URL* as described below.
+A server **MUST** respond to `PATCH`, `POST`, and `DELETE` requests to a
+*to-many relationship URL* as described below.
For all request types, the body **MUST** contain a `data` member whose value
-is an object that contains `type` and `ids` members, or an array of objects
+is an object that contains `type` and `id` members, or an array of objects
that each contain `type` and `id` members.
-If a client makes a `PUT` request to a *to-many relationship URL*, the
+If a client makes a `PATCH` request to a *to-many relationship URL*, the
server **MUST** either completely replace every member of the relationship,
return an appropriate error response if some resources can not be found or
accessed, or return a `403 Forbidden` response if complete replacement is
@@ -949,12 +1256,27 @@ not allowed by the server.
For example, the following request replaces every tag for an article:
```text
-PUT /articles/1/links/tags
+PATCH /articles/1/links/tags
Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
- "data": { "type": "tags", "ids": ["2", "3"] }
+ "data": [
+ { "type": "tags", "id": "2" },
+ { "type": "tags", "id": "3" }
+ ]
+}
+```
+
+And the following request clears every tag for an article:
+
+```text
+PATCH /articles/1/links/tags
+Content-Type: application/vnd.api+json
+Accept: application/vnd.api+json
+
+{
+ "data": []
}
```
@@ -984,7 +1306,9 @@ Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
- "data": { "type": "comments", "ids": ["123"] }
+ "data": [
+ { "type": "comments", "id": "123" }
+ ]
}
```
@@ -1008,7 +1332,10 @@ Content-Type: application/vnd.api+json
Accept: application/vnd.api+json
{
- "data": { "type": "comments", "ids": ["12", "13"] }
+ "data": [
+ { "type": "comments", "id": "12" },
+ { "type": "comments", "id": "13" }
+ ]
}
```
@@ -1055,11 +1382,6 @@ DELETE /photos/1
A server **MUST** return a `204 No Content` status code if a delete request is
successful.
-##### 404 Not Found <a href="#crud-deleting-responses-404" id="crud-deleting-responses-404" class="headerlink"></a>
-
-A server **MUST** return `404 Not Found` when processing a request to delete
-a resource that does not exist.
-
##### Other Responses <a href="#crud-deleting-responses-other" id="crud-deleting-responses-other" class="headerlink"></a>
Servers **MAY** use other HTTP error codes to represent errors. Clients
@@ -1068,9 +1390,8 @@ details **MAY** also be returned, as discussed below.
## Errors <a href="#errors" id="errors" class="headerlink"></a>
-Error objects are specialized resource objects that **MAY** be returned in a
-response to provide additional information about problems encountered while
-performing an operation. Error objects **MUST** be returned as a collection
+Error objects provide additional information about problems encountered while
+performing an operation. Error objects **MUST** be returned as an array
keyed by `"errors"` in the top level of a JSON API document, and **SHOULD
NOT** be returned with any primary data.
@@ -1096,3 +1417,7 @@ An error object **MAY** have the following members:
[e.g. `["/first-name", "/last-name"]` to reference a couple attributes].
Additional members **MAY** be specified within error objects.
+
+[attributes]: #document-structure-resource-object-attributes
+[complex attributes]: #document-structure-resource-object-complex-attributes
+[fields]: #document-structure-resource-object-fields
diff --git a/index.md b/index.md
index a9cf6af..88f64e2 100644
--- a/index.md
+++ b/index.md
@@ -32,19 +32,20 @@ Here's an example response from a blog that implements JSON API:
"self": "http://example.com/posts/1",
"author": {
"self": "http://example.com/posts/1/links/author",
- "resource": "http://example.com/posts/1/author",
- "type": "people",
- "id": "9"
+ "related": "http://example.com/posts/1/author",
+ "linkage": { "type": "people", "id": "9" }
},
"comments": {
"self": "http://example.com/posts/1/links/comments",
- "resource": "http://example.com/posts/1/comments",
- "type": "comments",
- "ids": ["5", "12"]
+ "related": "http://example.com/posts/1/comments",
+ "linkage": [
+ { "type": "comments", "id": "5" },
+ { "type": "comments", "id": "12" }
+ ]
}
}
}],
- "linked": [{
+ "included": [{
"type": "people",
"id": "9",
"first-name": "Dan",
@@ -95,11 +96,12 @@ specification](/format).
JSON API can be [extended in several ways](/extensions).
-Official extensions are available for [bulk](/extensions/bulk/) and
-[patch](/extensions/patch/) operations.
+Official extensions are available for [Bulk](/extensions/bulk/) and
+[JSON Patch](/extensions/jsonpatch/) operations.
## Update history <a href="#update-history" id="update-history" class="headerlink"></a>
+- 2015-03-16: Release candiate 3 released.
- 2013-05-03: Initial release of the draft.
- 2013-07-22: Media type registration completed with the IANA.
diff --git a/recommendations/index.md b/recommendations/index.md
index dfa50c5..bc524f7 100644
--- a/recommendations/index.md
+++ b/recommendations/index.md
@@ -71,7 +71,7 @@ a client to remove an `author` from a `post` without deleting the `people`
resource itself.
* the "related resource URL" - a URL for the related resource(s), which is
-identified with the `"resource"` key within a link object. When fetched, it
+identified with the `"related"` key within a link object. When fetched, it
returns the related resource object(s) as the response's primary data.
It is recommended that a relationship URL be formed by appending `/links/` and
@@ -108,7 +108,7 @@ Because these URLs represent resources in relationships, they should not be
used as `self` links for the resources themselves. Instead the recommendations
for individual resource URLs should still apply when forming `self` links.
-## Recommendations for Filtering <a href="filtering" id="filtering" class="headerlink"></a>
+## Recommendations for Filtering <a href="#filtering" id="filtering" class="headerlink"></a>
The base specification is agnostic about filtering strategies supported by a
server. The `filter` query parameter is reserved to be used as the basis for
diff --git a/schema b/schema
deleted file mode 100644
index 028102c..0000000
--- a/schema
+++ /dev/null
@@ -1,40 +0,0 @@
-{
- "id": "http://jsonapi.org/schema#",
- "$schema": "http://json-schema.org/draft-04/schema#",
- "title": "JSON API Schema",
- "description": "This is a schema for responses in the JSON API format. For more, see http://jsonapi.org",
- "type": "object",
- "resources":{
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "id": { "type":["string"] },
- "href": { "type":"string" },
- "links": { "type": "object" }
- },
- "required": ["id"]
- }
- },
- "patternProperties": {
- "^(?!href$)(?!links$)(?!id$)(?!meta)(?!linked)": {
- "$ref":"#/resources"
- }
- },
- "properties": {
- "meta": {
- "type": "object"
- },
- "links":{
- "type": "object"
- },
- "linked": {
- "type": "object",
- "patternProperties": {
- ".*": {
- "$ref":"#/resources"
- }
- }
- }
- }
-}
diff --git a/status/index.md b/status/index.md
index 38c3cbf..b602caa 100644
--- a/status/index.md
+++ b/status/index.md
@@ -3,10 +3,10 @@ layout: page
title: "JSON API: Specification Status"
---
-**This document is a work in progress** and will change as implementation work
-progresses. Implementors should be aware that this specification is not stable.
-It is currently missing some details about the `meta` attribute and could be
-more precise about details of working with relationships.
+JSON API is at a third release candidate state. This means that it is not yet
+stable, however, libraries intended to work with 1.0 should implement this
+version of the specification. We may make very small tweaks, but everything is
+basically in place.
Work on this specification is being done at its [GitHub
repository](https://github.com/json-api/json-api). Please feel free to help
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment