Created
June 2, 2021 20:48
-
-
Save jgornick/950118e222f155be4e052d78f46454d0 to your computer and use it in GitHub Desktop.
JSON:API - OpenAPI
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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! | |
This 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). | |
This 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. | |
Several 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. | |
**USAGE** | |
You 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. | |
Specifically, 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: | |
``` | |
paths: | |
/courses/: | |
get: | |
description: Returns a collection of courses | |
operationId: find courses | |
security: | |
- basicAuth: [] | |
- oauth: [auth-columbia, read] | |
parameters: | |
# I wish I could pull all these in at once... | |
- $ref: './jsonapi.yaml#/components/parameters/include' | |
- $ref: './jsonapi.yaml#/components/parameters/sort' | |
- $ref: './jsonapi.yaml#/components/parameters/pageSize' | |
- $ref: './jsonapi.yaml#/components/parameters/pageNumber' | |
- name: 'filter[id]' | |
in: query | |
description: exact id | |
required: false | |
style: form | |
schema: | |
$ref: './jsonapi.yaml#/components/schemas/id' | |
responses: | |
'200': | |
description: course response | |
content: | |
application/vnd.api+json: | |
schema: | |
$ref: '#/components/schemas/CourseCollection' | |
'401': | |
description: not authorized | |
content: | |
application/vnd.api+json: | |
schema: | |
$ref: './jsonapi.yaml#/components/schemas/error' | |
``` | |
You 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: | |
``` | |
swagger-ui-watcher -b myapp.json --path myapp.yaml | |
``` | |
contact: | |
name: Alan Crosswell | |
email: [email protected] | |
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 | |
# not sure why but swagger-editor only prompts for the variable if there's more than one server listed. | |
- url: "{serverURL}" | |
description: provide your server URL | |
variables: | |
serverURL: | |
default: http://localhost:8000/v1 | |
description: path for server | |
# Example generic paths and their methods: path parameters are {collection} and {id} | |
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' | |
# Following is {json:api} schema definition in a form suitable for $ref usage | |
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 | |
# unfortunately $ref resource and tring to change required doesn't work. | |
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" | |
# not clear what it means to try to POST links but the spec says POST a Resource Object... | |
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 | |
# properties: | |
# ^(?!relationships$|links$|id$|type$)\w[-\w_]*$: | |
# type: object | |
# description: Attributes may contain any valid JSON value. | |
additionalProperties: false | |
# TODO: This validates rather than defines: | |
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 | |
# properties: | |
# ^(?!id$|type$)\w[-\w_]*$: | |
# $ref: "#/components/schemas/relationship" | |
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 | |
# unable to properly represent fields and filters? swagger-edit appears to not implement this correctly. | |
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