Skip to content

Instantly share code, notes, and snippets.

@khornberg
Created August 7, 2020 13:50
Show Gist options
  • Save khornberg/acaa6e1c9041fc8762764fb3b4b8efd8 to your computer and use it in GitHub Desktop.
Save khornberg/acaa6e1c9041fc8762764fb3b4b8efd8 to your computer and use it in GitHub Desktop.
JSON:API general OpenSpec
{"openapi": "3.0.2", "info": {"version": "1.0.0", "title": "{json:api} Specification", "description": "An include file to define the [{json:api} 1.0 specification](http://jsonapi.org/format). N.B. I've got some confusion going on between a validating a jsonapi schema and defining one!\n\nThis file also provides a limited demonstration of jsonapi with path items for collections, items and their methods. You should be able to open in a modern version of [swagger-editor](https://github.com/swagger-api/swagger-editor) or [swagger-ui-watcher](https://github.com/moon0326/swagger-ui-watcher).\n\nThis file was created by downloading the [schema definition](http://jsonapi.org/schema) and then editing as needed to make it useful with the Open API Specification. It is subject to the `CC0 1.0 Universal` license as it is derived from the {json:api} specification.\n\nSeveral changes had to be made to that schema since it is non-normative and primarily only documented the results of GET operations. See especially definitions of `post_datum`, `post_resource`, `datum`, and `metaonly` that were added.\n\n**USAGE**\n\nYou can reference definitions in this schema with `$ref` as defined in the OAS specification, but be aware that the \"[[Reference Object](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.2.md#reference-object)] cannot be extended with additional properties and any properties added SHALL be ignored.\" So $refs are pretty useless if you are trying to keep things DRY.\nSpecifically, you'll need to copy and the path items into your own schema doc and \"extend\" them by adding what you need (e.g. security, additional parameters, referneces to your app's request/response schemas, etc.). For example:\n```\npaths:\n /courses/:\n get:\n description: Returns a collection of courses\n operationId: find courses\n security:\n - basicAuth: []\n - oauth: [auth-columbia, read]\n parameters:\n # I wish I could pull all these in at once...\n - $ref: './jsonapi.yaml#/components/parameters/include'\n - $ref: './jsonapi.yaml#/components/parameters/sort'\n - $ref: './jsonapi.yaml#/components/parameters/pageSize'\n - $ref: './jsonapi.yaml#/components/parameters/pageNumber'\n - name: 'filter[id]'\n in: query\n description: exact id\n required: false\n style: form\n schema:\n $ref: './jsonapi.yaml#/components/schemas/id'\n responses:\n '200':\n description: course response\n content:\n application/vnd.api+json:\n schema:\n $ref: '#/components/schemas/CourseCollection'\n '401':\n description: not authorized\n content:\n application/vnd.api+json:\n schema:\n $ref: './jsonapi.yaml#/components/schemas/error'\n\n```\nYou can locate this file on a web server or in a local directory and `$ref` it appropriately; `swagger-ui-watcher` will follow the `$ref`s and can be used to \"bundle\" your schema into a single JSON document as follows:\n```\nswagger-ui-watcher -b myapp.json --path myapp.yaml\n```\n", "contact": {"name": "Alan Crosswell", "email": "alan@columbia.edu", "url": "http://www.columbia.edu/~alan"}, "license": {"name": "CC0 1.0 Universal", "url": "https://creativecommons.org/publicdomain/zero/1.0/"}}, "externalDocs": {"description": "Read more about {json:api} here", "url": "https://jsonapi.org/"}, "servers": [{"url": "{serverURL}", "description": "provide your server URL", "variables": {"serverURL": {"default": "http://localhost:8000/v1", "description": "path for server"}}}, {"url": "{serverURL}", "description": "provide your server URL", "variables": {"serverURL": {"default": "http://localhost:8000/v1", "description": "path for server"}}}], "paths": {"/{collection}/": {"parameters": [{"name": "collection", "in": "path", "required": true, "schema": {"type": "string"}}], "get": {"description": "get a collection", "operationId": "get collection", "parameters": [{"$ref": "#/components/parameters/include"}, {"$ref": "#/components/parameters/sort"}, {"$ref": "#/components/parameters/pageSize"}, {"$ref": "#/components/parameters/pageNumber"}], "responses": {"200": {"description": "[OK](https://jsonapi.org/format/#fetching-resources-responses-200)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/success"}}}}, "404": {"description": "[Not found](https://jsonapi.org/format/#fetching-resources-responses-404)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}, "default": {"description": "collection response", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/JSONAPIresponse"}}}}}}, "post": {"description": "[add](https://jsonapi.org/format/#crud-creating) item to a collection", "operationId": "post item", "requestBody": {"description": "item to post", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/post_datum"}}}}, "responses": {"201": {"description": "[Created](https://jsonapi.org/format/#crud-creating-responses-201). Assigned `id` and/or any other changes are in this response.", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/datum"}}}}, "202": {"description": "Accepted for [asynchronous processing](https://jsonapi.org/recommendations/#asynchronous-processing).", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/datum"}}}, "headers": {"Content-Location": {"description": "URL for status of processing", "schema": {"type": "string", "format": "uri-reference"}}}}, "204": {"description": "[Created](https://jsonapi.org/format/#crud-creating-responses-204) with the supplied `id`. No other changes from what was POSTed."}, "403": {"description": "[Forbidden](https://jsonapi.org/format/#crud-creating-responses-403)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}, "404": {"description": "[Related resource does not exist](https://jsonapi.org/format/#crud-creating-responses-404).", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}, "409": {"description": "[Conflict](https://jsonapi.org/format/#crud-creating-responses-409)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}, "default": {"description": "other post response", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/JSONAPIresponse"}}}}}}}, "/{collection}/{id}/": {"parameters": [{"name": "collection", "in": "path", "required": true, "schema": {"type": "string"}}, {"name": "id", "in": "path", "required": true, "schema": {"$ref": "#/components/schemas/id"}}], "get": {"description": "get an item", "operationId": "get item", "responses": {"200": {"description": "[OK](https://jsonapi.org/format/#fetching-resources-responses-200)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/datum"}}}}, "404": {"description": "[Not found](https://jsonapi.org/format/#fetching-resources-responses-404)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}, "default": {"description": "get item response", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/JSONAPIresponse"}}}}}}, "patch": {"description": "[update](https://jsonapi.org/format/#crud-updating) an item", "operationId": "patch item", "requestBody": {"description": "item to patch", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/datum"}}}}, "responses": {"200": {"description": "[OK](https://jsonapi.org/format/#crud-updating-responses-200)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/datum"}}}}, "202": {"description": "Accepted for [asynchronous processing](https://jsonapi.org/recommendations/#asynchronous-processing).", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/datum"}}}, "headers": {"Content-Location": {"description": "URL for status of processing", "schema": {"type": "string", "format": "uri-reference"}}}}, "204": {"description": "[Patched](https://jsonapi.org/format/#crud-updating-responses-204). No other changes from what was PATCHed."}, "403": {"description": "[Forbidden](https://jsonapi.org/format/#crud-updating-responses-403)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}, "404": {"description": "[Resource does not exist](https://jsonapi.org/format/#crud-updating-responses-404).", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}, "409": {"description": "[Conflict](https://jsonapi.org/format/#crud-updating-responses-409)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}, "default": {"description": "get item response", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/JSONAPIresponse"}}}}}}, "delete": {"description": "[delete](https://jsonapi.org/format/#crud-deleting) an item", "operationId": "delete item", "responses": {"200": {"description": "[OK](https://jsonapi.org/format/#crud-deleting-responses-200)", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/onlymeta"}}}}, "202": {"description": "Accepted for [asynchronous processing](https://jsonapi.org/recommendations/#asynchronous-processing).", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/datum"}}}}, "204": {"description": "[Deleted](https://jsonapi.org/format/#crud-deleting-responses-204)."}, "404": {"description": "[Resource does not exist](https://jsonapi.org/format/#crud-deleting-responses-404).", "content": {"application/vnd.api+json": {"schema": {"$ref": "#/components/schemas/failure"}}}}}}}}, "components": {"schemas": {"JSONAPIresponse": {"oneOf": [{"$ref": "#/components/schemas/success"}, {"$ref": "#/components/schemas/failure"}, {"$ref": "#/components/schemas/info"}]}, "success": {"type": "object", "required": ["data"], "properties": {"data": {"$ref": "#/components/schemas/data"}, "included": {"description": "To reduce the number of HTTP requests, servers **MAY** allow responses that include related resources along with the requested primary resources. Such responses are called `compound documents`.", "type": "array", "items": {"$ref": "#/components/schemas/resource"}, "uniqueItems": true}, "meta": {"$ref": "#/components/schemas/meta"}, "links": {"description": "Link members related to the primary data.", "allOf": [{"$ref": "#/components/schemas/links"}, {"$ref": "#/components/schemas/pagination"}]}, "jsonapi": {"$ref": "#/components/schemas/jsonapi"}}, "additionalProperties": false}, "failure": {"type": "object", "required": ["errors"], "properties": {"errors": {"type": "array", "items": {"$ref": "#/components/schemas/error"}, "uniqueItems": true}, "meta": {"$ref": "#/components/schemas/meta"}, "jsonapi": {"$ref": "#/components/schemas/jsonapi"}, "links": {"$ref": "#/components/schemas/links"}}, "additionalProperties": false}, "info": {"type": "object", "required": ["meta"], "properties": {"meta": {"$ref": "#/components/schemas/meta"}, "links": {"$ref": "#/components/schemas/links"}, "jsonapi": {"$ref": "#/components/schemas/jsonapi"}}, "additionalProperties": false}, "onlymeta": {"properties": {"meta": {"$ref": "#/components/schemas/meta"}}, "additionalProperties": false}, "meta": {"description": "Non-standard meta-information that can not be represented as an attribute or relationship.", "type": "object", "additionalProperties": true}, "data": {"description": "The document's `primary data` is a representation of the resource or collection of resources targeted by a request.", "oneOf": [{"$ref": "#/components/schemas/resource"}, {"description": "An array of resource objects, an array of resource identifier objects, or an empty array ([]), for requests that target resource collections.", "type": "array", "items": {"$ref": "#/components/schemas/resource"}, "uniqueItems": true}, {"$ref": "#/components/schemas/nulltype"}]}, "post_datum": {"description": "singular item being [created](https://jsonapi.org/format/#crud-creating). `id` is optional and may be ignored if supplied and created by the system.", "properties": {"data": {"$ref": "#/components/schemas/post_resource"}}}, "datum": {"description": "singular item", "properties": {"data": {"$ref": "#/components/schemas/resource"}}}, "resource": {"description": "Resource objects appear in a JSON API document to represent resources.", "type": "object", "required": ["type", "id"], "properties": {"type": {"$ref": "#/components/schemas/type"}, "id": {"$ref": "#/components/schemas/id"}, "attributes": {"$ref": "#/components/schemas/attributes"}, "relationships": {"$ref": "#/components/schemas/relationships"}, "links": {"$ref": "#/components/schemas/links"}, "meta": {"$ref": "#/components/schemas/meta"}}, "additionalProperties": false}, "post_resource": {"description": "A POSTable resource object has an optional id.", "type": "object", "required": ["type"], "properties": {"type": {"$ref": "#/components/schemas/type"}, "id": {"$ref": "#/components/schemas/id"}, "attributes": {"$ref": "#/components/schemas/attributes"}, "relationships": {"$ref": "#/components/schemas/relationships"}, "links": {"$ref": "#/components/schemas/links"}, "meta": {"$ref": "#/components/schemas/meta"}}, "additionalProperties": false}, "relationshipLinks": {"description": "A resource object **MAY** contain references to other resource objects (`relationships`). Relationships may be to-one or to-many. Relationships can be specified by including a member in a resource's links object.", "type": "object", "properties": {"self": {"description": "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.", "$ref": "#/components/schemas/link"}, "related": {"$ref": "#/components/schemas/link"}}, "additionalProperties": true}, "links": {"type": "object", "additionalProperties": {"$ref": "#/components/schemas/link"}}, "link": {"description": "A link **MUST** be represented as either: a string containing the link's URL or a link object.", "oneOf": [{"description": "A string containing the link's URL.", "type": "string", "format": "uri-reference"}, {"type": "object", "required": ["href"], "properties": {"href": {"description": "A string containing the link's URL.", "type": "string", "format": "uri-reference"}, "meta": {"$ref": "#/components/schemas/meta"}}}]}, "attributes": {"description": "Members of the attributes object (`attributes`) represent information about the resource object in which it's defined.", "type": "object", "additionalProperties": false}, "relationships": {"description": "Members of the relationships object represent references from the resource object in which it's defined to other resource objects. N.B. this is validation, not useful for inclusion.", "type": "object", "additionalProperties": {"$ref": "#/components/schemas/relationship"}}, "relationship": {"description": "A single relationship description", "type": "object", "properties": {"links": {"$ref": "#/components/schemas/relationshipLinks"}, "data": {"description": "Member, whose value represents `resource linkage`.", "oneOf": [{"$ref": "#/components/schemas/relationshipToOne"}, {"$ref": "#/components/schemas/relationshipToMany"}]}, "meta": {"$ref": "#/components/schemas/meta"}}, "anyOf": [{"required": ["data"]}, {"required": ["meta"]}, {"required": ["links"]}], "additionalProperties": false}, "relationshipToOne": {"description": "References to other resource objects in a to-one (`relationship`). Relationships can be specified by including a member in a resource's links object.", "anyOf": [{"$ref": "#/components/schemas/empty"}, {"$ref": "#/components/schemas/linkage"}]}, "reltoone": {"description": "A singular relationship", "type": "object", "properties": {"links": {"$ref": "#/components/schemas/relationshipLinks"}, "data": {"$ref": "#/components/schemas/relationshipToOne"}, "meta": {"$ref": "#/components/schemas/meta"}}}, "reltomany": {"description": "A multiple relationship", "type": "object", "properties": {"links": {"$ref": "#/components/schemas/relationshipLinks"}, "data": {"$ref": "#/components/schemas/relationshipToMany"}, "meta": {"$ref": "#/components/schemas/meta"}}}, "reltoonedata": {"description": "A singular relationship, data only.", "type": "object", "properties": {"data": {"$ref": "#/components/schemas/relationshipToOne"}}}, "reltomanydata": {"description": "A multiple relationship, data only.", "type": "object", "properties": {"data": {"$ref": "#/components/schemas/relationshipToMany"}}}, "relationshipToMany": {"description": "An array of objects each containing `type` and `id` members for to-many relationships.", "type": "array", "items": {"$ref": "#/components/schemas/linkage"}, "uniqueItems": true}, "empty": {"$ref": "#/components/schemas/nulltype"}, "linkage": {"description": "The `type` and `id` to non-empty members.", "type": "object", "required": ["type", "id"], "properties": {"type": {"type": "string"}, "id": {"type": "string"}, "meta": {"$ref": "#/components/schemas/meta"}}, "additionalProperties": false}, "pagination": {"type": "object", "properties": {"first": {"description": "The first page of data", "oneOf": [{"type": "string", "format": "uri-reference"}, {"$ref": "#/components/schemas/nulltype"}]}, "last": {"description": "The last page of data", "oneOf": [{"type": "string", "format": "uri-reference"}, {"$ref": "#/components/schemas/nulltype"}]}, "prev": {"description": "The previous page of data", "oneOf": [{"type": "string", "format": "uri-reference"}, {"$ref": "#/components/schemas/nulltype"}]}, "next": {"description": "The next page of data", "oneOf": [{"type": "string", "format": "uri-reference"}, {"$ref": "#/components/schemas/nulltype"}]}}}, "jsonapi": {"description": "An object describing the server's implementation", "type": "object", "properties": {"version": {"type": "string"}, "meta": {"$ref": "#/components/schemas/meta"}}, "additionalProperties": false}, "error": {"type": "object", "properties": {"id": {"description": "A unique identifier for this particular occurrence of the problem.", "type": "string"}, "links": {"$ref": "#/components/schemas/links"}, "status": {"description": "The HTTP status code applicable to this problem, expressed as a string value.", "type": "string"}, "code": {"description": "An application-specific error code, expressed as a string value.", "type": "string"}, "title": {"description": "A short, human-readable summary of the problem. It **SHOULD NOT** change from occurrence to occurrence of the problem, except for purposes of localization.", "type": "string"}, "detail": {"description": "A human-readable explanation specific to this occurrence of the problem.", "type": "string"}, "source": {"type": "object", "properties": {"pointer": {"description": "A JSON Pointer [RFC6901] to the associated entity in the request document [e.g. `/data` for a primary data object, or `/data/attributes/title` for a specific attribute].", "type": "string"}, "parameter": {"description": "A string indicating which query parameter caused the error.", "type": "string"}}}, "meta": {"$ref": "#/components/schemas/meta"}}, "additionalProperties": false}, "nulltype": {"description": "OAS doesn't allow the null type so use this.", "type": "object", "nullable": true, "default": null}, "id": {"type": "string", "description": "[resource object identifier](https://jsonapi.org/format/#document-resource-object-identification)"}, "type": {"type": "string", "description": "[resource object type](https://jsonapi.org/format/#document-resource-object-identification)"}}, "parameters": {"include": {"name": "include", "in": "query", "description": "[list of included related resources](https://jsonapi.org/format/#fetching-includes)", "required": false, "style": "form", "schema": {"type": "string"}}, "sort": {"name": "sort", "in": "query", "description": "[fields to sort by](https://jsonapi.org/format/#fetching-sorting)", "required": false, "style": "form", "schema": {"type": "string"}}, "pageSize": {"name": "page[size]", "in": "query", "description": "size of page for paginated results", "required": false, "schema": {"type": "integer", "format": "int32"}}, "pageNumber": {"name": "page[number]", "in": "query", "description": "page number of results", "required": false, "schema": {"type": "integer", "format": "int32"}}, "pageLimit": {"name": "page[limit]", "in": "query", "description": "limit for this page of paginated results", "required": false, "schema": {"type": "integer", "format": "int32"}}, "pageOffset": {"name": "page[offset]", "in": "query", "description": "collection items offset for paginated results", "required": false, "schema": {"type": "integer", "format": "int32"}}, "fields": {"name": "fields", "in": "query", "description": "sparse fieldsets: `fields[TYPE]=field1,field2,...`", "required": false, "style": "deepObject", "schema": {"type": "string"}}, "filter": {"name": "filter", "in": "query", "description": "filter[NAME]=value(s)", "required": false, "style": "deepObject", "schema": {"type": "string"}}}}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment