├── .circleci
└── config.yml
├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── Makefile
├── Pipfile
├── Pipfile.lock
├── README.md
├── conftest.py
├── docs
├── _static
│ └── css
│ │ └── table.css
├── _templates
│ └── sidebar_intro.html
├── additional-information.md
├── conf.py
├── element-definitions.md
├── examples.md
├── extensions
│ ├── index.rst
│ └── oas
│ │ ├── extensions.rst
│ │ └── index.rst
├── index.md
├── migration.md
├── overview.md
└── tools.md
├── element-schema.json
├── requirements.txt
└── test
└── test_markdown.py
/.circleci/config.yml:
--------------------------------------------------------------------------------
1 | version: 2
2 |
3 | jobs:
4 | test:
5 | working_directory: ~/repo
6 | docker:
7 | - image: circleci/python:3.6
8 | steps:
9 | - checkout
10 | - run: pipenv install --dev
11 | - run: pipenv run pytest
12 |
13 | workflows:
14 | version: 2
15 | test:
16 | jobs:
17 | - test
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | _build/
2 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # API Elements Changelog
2 |
3 | All notable changes to the Refract project will be documented in this file.
4 |
5 | ## Master
6 |
7 | - Added cookie option to `Token Authentication Scheme`
8 | - Added `refresh` relation context to `Oauth2 Scheme`
9 |
10 | ## 1.0.0-rc1
11 |
12 | - Initial production-ready version of API Elements
13 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to API Elements Documentation
2 |
3 | The documentation is built using Sphinx, a Python tool. Assuming you have
4 | Python 3 and
5 | [pipenv](https://pipenv.readthedocs.io/en/latest/install/#installing-pipenv)
6 | installed, the following steps can be used to build the site.
7 |
8 | ```shell
9 | $ pipenv install --dev
10 | ```
11 |
12 | ## Running the Development Server
13 |
14 | You can run a local development server to preview changes using the following:
15 |
16 | ```shell
17 | $ pipenv run serve
18 | ```
19 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Apiary Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | # Minimal makefile for Sphinx documentation
2 | #
3 |
4 | # You can set these variables from the command line.
5 | SPHINXOPTS =
6 | SPHINXBUILD = sphinx-build
7 | SPHINXPROJ = APIElements
8 | SOURCEDIR = docs
9 | BUILDDIR = _build
10 |
11 | # Put it first so that "make" without argument is like "make help".
12 | help:
13 | @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
14 |
15 | .PHONY: help Makefile
16 |
17 | # Catch-all target: route all unknown targets to Sphinx using the new
18 | # "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
19 | %: Makefile
20 | @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
21 |
22 | watch:
23 | sphinx-autobuild docs _build/html
24 |
--------------------------------------------------------------------------------
/Pipfile:
--------------------------------------------------------------------------------
1 | [[source]]
2 | name = "pypi"
3 | url = "https://pypi.org/simple"
4 | verify_ssl = true
5 |
6 | [scripts]
7 | serve = "sphinx-autobuild docs _build/html"
8 |
9 | [packages]
10 | sphinx = "*"
11 | recommonmark = "*"
12 | sphinx-rtd-theme = "*"
13 | pygments-apiblueprint = "*"
14 | pygments = "*"
15 |
16 | [dev-packages]
17 | sphinx-autobuild = "*"
18 | pytest = "*"
19 | jsonschema = "*"
20 |
21 | [requires]
22 | python_version = "3.6"
23 |
--------------------------------------------------------------------------------
/Pipfile.lock:
--------------------------------------------------------------------------------
1 | {
2 | "_meta": {
3 | "hash": {
4 | "sha256": "c65fded42a5502136c301c4837427467cc7df7eade5eef70af462544035f5f7f"
5 | },
6 | "pipfile-spec": 6,
7 | "requires": {
8 | "python_version": "3.6"
9 | },
10 | "sources": [
11 | {
12 | "name": "pypi",
13 | "url": "https://pypi.org/simple",
14 | "verify_ssl": true
15 | }
16 | ]
17 | },
18 | "default": {
19 | "alabaster": {
20 | "hashes": [
21 | "sha256:446438bdcca0e05bd45ea2de1668c1d9b032e1a9154c2c259092d77031ddd359",
22 | "sha256:a661d72d58e6ea8a57f7a86e37d86716863ee5e92788398526d58b26a4e4dc02"
23 | ],
24 | "version": "==0.7.12"
25 | },
26 | "babel": {
27 | "hashes": [
28 | "sha256:af92e6106cb7c55286b25b38ad7695f8b4efb36a90ba483d7f7a6628c46158ab",
29 | "sha256:e86135ae101e31e2c8ec20a4e0c5220f4eed12487d5cf3f78be7e98d3a57fc28"
30 | ],
31 | "version": "==2.7.0"
32 | },
33 | "certifi": {
34 | "hashes": [
35 | "sha256:59b7658e26ca9c7339e00f8f4636cdfe59d34fa37b9b04f6f9e9926b3cece1a5",
36 | "sha256:b26104d6835d1f5e49452a26eb2ff87fe7090b89dfcaee5ea2212697e1e1d7ae"
37 | ],
38 | "version": "==2019.3.9"
39 | },
40 | "chardet": {
41 | "hashes": [
42 | "sha256:84ab92ed1c4d4f16916e05906b6b75a6c0fb5db821cc65e70cbd64a3e2a5eaae",
43 | "sha256:fc323ffcaeaed0e0a02bf4d117757b98aed530d9ed4531e3e15460124c106691"
44 | ],
45 | "version": "==3.0.4"
46 | },
47 | "commonmark": {
48 | "hashes": [
49 | "sha256:14c3df31e8c9c463377e287b2a1eefaa6019ab97b22dad36e2f32be59d61d68d",
50 | "sha256:867fc5db078ede373ab811e16b6789e9d033b15ccd7296f370ca52d1ee792ce0"
51 | ],
52 | "version": "==0.9.0"
53 | },
54 | "docutils": {
55 | "hashes": [
56 | "sha256:02aec4bd92ab067f6ff27a38a38a41173bf01bed8f89157768c1573f53e474a6",
57 | "sha256:51e64ef2ebfb29cae1faa133b3710143496eca21c530f3f71424d77687764274",
58 | "sha256:7a4bd47eaf6596e1295ecb11361139febe29b084a87bf005bf899f9a42edc3c6"
59 | ],
60 | "version": "==0.14"
61 | },
62 | "future": {
63 | "hashes": [
64 | "sha256:67045236dcfd6816dc439556d009594abf643e5eb48992e36beac09c2ca659b8"
65 | ],
66 | "version": "==0.17.1"
67 | },
68 | "idna": {
69 | "hashes": [
70 | "sha256:c357b3f628cf53ae2c4c05627ecc484553142ca23264e593d327bcde5e9c3407",
71 | "sha256:ea8b7f6188e6fa117537c3df7da9fc686d485087abf6ac197f9c46432f7e4a3c"
72 | ],
73 | "version": "==2.8"
74 | },
75 | "imagesize": {
76 | "hashes": [
77 | "sha256:3f349de3eb99145973fefb7dbe38554414e5c30abd0c8e4b970a7c9d09f3a1d8",
78 | "sha256:f3832918bc3c66617f92e35f5d70729187676313caa60c187eb0f28b8fe5e3b5"
79 | ],
80 | "version": "==1.1.0"
81 | },
82 | "jinja2": {
83 | "hashes": [
84 | "sha256:065c4f02ebe7f7cf559e49ee5a95fb800a9e4528727aec6f24402a5374c65013",
85 | "sha256:14dd6caf1527abb21f08f86c784eac40853ba93edb79552aa1e4b8aef1b61c7b"
86 | ],
87 | "version": "==2.10.1"
88 | },
89 | "markupsafe": {
90 | "hashes": [
91 | "sha256:00bc623926325b26bb9605ae9eae8a215691f33cae5df11ca5424f06f2d1f473",
92 | "sha256:09027a7803a62ca78792ad89403b1b7a73a01c8cb65909cd876f7fcebd79b161",
93 | "sha256:09c4b7f37d6c648cb13f9230d847adf22f8171b1ccc4d5682398e77f40309235",
94 | "sha256:1027c282dad077d0bae18be6794e6b6b8c91d58ed8a8d89a89d59693b9131db5",
95 | "sha256:24982cc2533820871eba85ba648cd53d8623687ff11cbb805be4ff7b4c971aff",
96 | "sha256:29872e92839765e546828bb7754a68c418d927cd064fd4708fab9fe9c8bb116b",
97 | "sha256:43a55c2930bbc139570ac2452adf3d70cdbb3cfe5912c71cdce1c2c6bbd9c5d1",
98 | "sha256:46c99d2de99945ec5cb54f23c8cd5689f6d7177305ebff350a58ce5f8de1669e",
99 | "sha256:500d4957e52ddc3351cabf489e79c91c17f6e0899158447047588650b5e69183",
100 | "sha256:535f6fc4d397c1563d08b88e485c3496cf5784e927af890fb3c3aac7f933ec66",
101 | "sha256:62fe6c95e3ec8a7fad637b7f3d372c15ec1caa01ab47926cfdf7a75b40e0eac1",
102 | "sha256:6dd73240d2af64df90aa7c4e7481e23825ea70af4b4922f8ede5b9e35f78a3b1",
103 | "sha256:717ba8fe3ae9cc0006d7c451f0bb265ee07739daf76355d06366154ee68d221e",
104 | "sha256:79855e1c5b8da654cf486b830bd42c06e8780cea587384cf6545b7d9ac013a0b",
105 | "sha256:7c1699dfe0cf8ff607dbdcc1e9b9af1755371f92a68f706051cc8c37d447c905",
106 | "sha256:88e5fcfb52ee7b911e8bb6d6aa2fd21fbecc674eadd44118a9cc3863f938e735",
107 | "sha256:8defac2f2ccd6805ebf65f5eeb132adcf2ab57aa11fdf4c0dd5169a004710e7d",
108 | "sha256:98c7086708b163d425c67c7a91bad6e466bb99d797aa64f965e9d25c12111a5e",
109 | "sha256:9add70b36c5666a2ed02b43b335fe19002ee5235efd4b8a89bfcf9005bebac0d",
110 | "sha256:9bf40443012702a1d2070043cb6291650a0841ece432556f784f004937f0f32c",
111 | "sha256:ade5e387d2ad0d7ebf59146cc00c8044acbd863725f887353a10df825fc8ae21",
112 | "sha256:b00c1de48212e4cc9603895652c5c410df699856a2853135b3967591e4beebc2",
113 | "sha256:b1282f8c00509d99fef04d8ba936b156d419be841854fe901d8ae224c59f0be5",
114 | "sha256:b2051432115498d3562c084a49bba65d97cf251f5a331c64a12ee7e04dacc51b",
115 | "sha256:ba59edeaa2fc6114428f1637ffff42da1e311e29382d81b339c1817d37ec93c6",
116 | "sha256:c8716a48d94b06bb3b2524c2b77e055fb313aeb4ea620c8dd03a105574ba704f",
117 | "sha256:cd5df75523866410809ca100dc9681e301e3c27567cf498077e8551b6d20e42f",
118 | "sha256:e249096428b3ae81b08327a63a485ad0878de3fb939049038579ac0ef61e17e7"
119 | ],
120 | "version": "==1.1.1"
121 | },
122 | "packaging": {
123 | "hashes": [
124 | "sha256:0c98a5d0be38ed775798ece1b9727178c4469d9c3b4ada66e8e6b7849f8732af",
125 | "sha256:9e1cbf8c12b1f1ce0bb5344b8d7ecf66a6f8a6e91bcb0c84593ed6d3ab5c4ab3"
126 | ],
127 | "version": "==19.0"
128 | },
129 | "pygments": {
130 | "hashes": [
131 | "sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127",
132 | "sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"
133 | ],
134 | "index": "pypi",
135 | "version": "==2.4.2"
136 | },
137 | "pygments-apiblueprint": {
138 | "hashes": [
139 | "sha256:18f4b4794936cf3ebfe33b6bedb07e70672a1aa030adb279196e28d54105d5da",
140 | "sha256:ef6347951044b93a1e3b4ee83da43203910d9d7d3724a32edcc6b12d655d7838"
141 | ],
142 | "index": "pypi",
143 | "version": "==0.1.0"
144 | },
145 | "pygments-markdown-lexer": {
146 | "hashes": [
147 | "sha256:4c128c26450b5886521c674d759f95fc3768b8955a7d9c81866ee0213c2febdf"
148 | ],
149 | "version": "==0.1.0.dev39"
150 | },
151 | "pyparsing": {
152 | "hashes": [
153 | "sha256:1873c03321fc118f4e9746baf201ff990ceb915f433f23b395f5580d1840cb2a",
154 | "sha256:9b6323ef4ab914af344ba97510e966d64ba91055d6b9afa6b30799340e89cc03"
155 | ],
156 | "version": "==2.4.0"
157 | },
158 | "pytz": {
159 | "hashes": [
160 | "sha256:303879e36b721603cc54604edcac9d20401bdbe31e1e4fdee5b9f98d5d31dfda",
161 | "sha256:d747dd3d23d77ef44c6a3526e274af6efeb0a6f1afd5a69ba4d5be4098c8e141"
162 | ],
163 | "version": "==2019.1"
164 | },
165 | "recommonmark": {
166 | "hashes": [
167 | "sha256:a520b8d25071a51ae23a27cf6252f2fe387f51bdc913390d83b2b50617f5bb48",
168 | "sha256:c85228b9b7aea7157662520e74b4e8791c5eacd375332ec68381b52bf10165be"
169 | ],
170 | "index": "pypi",
171 | "version": "==0.5.0"
172 | },
173 | "requests": {
174 | "hashes": [
175 | "sha256:11e007a8a2aa0323f5a921e9e6a2d7e4e67d9877e85773fba9ba6419025cbeb4",
176 | "sha256:9cf5292fcd0f598c671cfc1e0d7d1a7f13bb8085e9a590f48c010551dc6c4b31"
177 | ],
178 | "version": "==2.22.0"
179 | },
180 | "six": {
181 | "hashes": [
182 | "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
183 | "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
184 | ],
185 | "version": "==1.12.0"
186 | },
187 | "snowballstemmer": {
188 | "hashes": [
189 | "sha256:919f26a68b2c17a7634da993d91339e288964f93c274f1343e3bbbe2096e1128",
190 | "sha256:9f3bcd3c401c3e862ec0ebe6d2c069ebc012ce142cce209c098ccb5b09136e89"
191 | ],
192 | "version": "==1.2.1"
193 | },
194 | "sphinx": {
195 | "hashes": [
196 | "sha256:423280646fb37944dd3c85c58fb92a20d745793a9f6c511f59da82fa97cd404b",
197 | "sha256:de930f42600a4fef993587633984cc5027dedba2464bcf00ddace26b40f8d9ce"
198 | ],
199 | "index": "pypi",
200 | "version": "==2.0.1"
201 | },
202 | "sphinx-rtd-theme": {
203 | "hashes": [
204 | "sha256:00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4",
205 | "sha256:728607e34d60456d736cc7991fd236afb828b21b82f956c5ea75f94c8414040a"
206 | ],
207 | "index": "pypi",
208 | "version": "==0.4.3"
209 | },
210 | "sphinxcontrib-applehelp": {
211 | "hashes": [
212 | "sha256:edaa0ab2b2bc74403149cb0209d6775c96de797dfd5b5e2a71981309efab3897",
213 | "sha256:fb8dee85af95e5c30c91f10e7eb3c8967308518e0f7488a2828ef7bc191d0d5d"
214 | ],
215 | "version": "==1.0.1"
216 | },
217 | "sphinxcontrib-devhelp": {
218 | "hashes": [
219 | "sha256:6c64b077937330a9128a4da74586e8c2130262f014689b4b89e2d08ee7294a34",
220 | "sha256:9512ecb00a2b0821a146736b39f7aeb90759834b07e81e8cc23a9c70bacb9981"
221 | ],
222 | "version": "==1.0.1"
223 | },
224 | "sphinxcontrib-htmlhelp": {
225 | "hashes": [
226 | "sha256:4670f99f8951bd78cd4ad2ab962f798f5618b17675c35c5ac3b2132a14ea8422",
227 | "sha256:d4fd39a65a625c9df86d7fa8a2d9f3cd8299a3a4b15db63b50aac9e161d8eff7"
228 | ],
229 | "version": "==1.0.2"
230 | },
231 | "sphinxcontrib-jsmath": {
232 | "hashes": [
233 | "sha256:2ec2eaebfb78f3f2078e73666b1415417a116cc848b72e5172e596c871103178",
234 | "sha256:a9925e4a4587247ed2191a22df5f6970656cb8ca2bd6284309578f2153e0c4b8"
235 | ],
236 | "version": "==1.0.1"
237 | },
238 | "sphinxcontrib-qthelp": {
239 | "hashes": [
240 | "sha256:513049b93031beb1f57d4daea74068a4feb77aa5630f856fcff2e50de14e9a20",
241 | "sha256:79465ce11ae5694ff165becda529a600c754f4bc459778778c7017374d4d406f"
242 | ],
243 | "version": "==1.0.2"
244 | },
245 | "sphinxcontrib-serializinghtml": {
246 | "hashes": [
247 | "sha256:c0efb33f8052c04fd7a26c0a07f1678e8512e0faec19f4aa8f2473a8b81d5227",
248 | "sha256:db6615af393650bf1151a6cd39120c29abaf93cc60db8c48eb2dddbfdc3a9768"
249 | ],
250 | "version": "==1.1.3"
251 | },
252 | "urllib3": {
253 | "hashes": [
254 | "sha256:b246607a25ac80bedac05c6f282e3cdaf3afb65420fd024ac94435cabe6e18d1",
255 | "sha256:dbe59173209418ae49d485b87d1681aefa36252ee85884c31346debd19463232"
256 | ],
257 | "version": "==1.25.3"
258 | }
259 | },
260 | "develop": {
261 | "argh": {
262 | "hashes": [
263 | "sha256:a9b3aaa1904eeb78e32394cd46c6f37ac0fb4af6dc488daa58971bdc7d7fcaf3",
264 | "sha256:e9535b8c84dc9571a48999094fda7f33e63c3f1b74f3e5f3ac0105a58405bb65"
265 | ],
266 | "version": "==0.26.2"
267 | },
268 | "atomicwrites": {
269 | "hashes": [
270 | "sha256:03472c30eb2c5d1ba9227e4c2ca66ab8287fbfbbda3888aa93dc2e28fc6811b4",
271 | "sha256:75a9445bac02d8d058d5e1fe689654ba5a6556a1dfd8ce6ec55a0ed79866cfa6"
272 | ],
273 | "version": "==1.3.0"
274 | },
275 | "attrs": {
276 | "hashes": [
277 | "sha256:69c0dbf2ed392de1cb5ec704444b08a5ef81680a61cb899dc08127123af36a79",
278 | "sha256:f0b870f674851ecbfbbbd364d6b5cbdff9dcedbc7f3f5e18a6891057f21fe399"
279 | ],
280 | "version": "==19.1.0"
281 | },
282 | "importlib-metadata": {
283 | "hashes": [
284 | "sha256:027cfc6524613de726789072f95d2e4cc64dd1dee8096d42d13f2ead5bd302f5",
285 | "sha256:0d05199e1f0b1a8707a1b9c46476d4a49807fb56cb1b0737db1d37feb42fe31d"
286 | ],
287 | "version": "==0.15"
288 | },
289 | "jsonschema": {
290 | "hashes": [
291 | "sha256:0c0a81564f181de3212efa2d17de1910f8732fa1b71c42266d983cd74304e20d",
292 | "sha256:a5f6559964a3851f59040d3b961de5e68e70971afb88ba519d27e6a039efff1a"
293 | ],
294 | "index": "pypi",
295 | "version": "==3.0.1"
296 | },
297 | "livereload": {
298 | "hashes": [
299 | "sha256:78d55f2c268a8823ba499305dcac64e28ddeb9a92571e12d543cd304faf5817b",
300 | "sha256:89254f78d7529d7ea0a3417d224c34287ebfe266b05e67e51facaf82c27f0f66"
301 | ],
302 | "version": "==2.6.1"
303 | },
304 | "more-itertools": {
305 | "hashes": [
306 | "sha256:2112d2ca570bb7c3e53ea1a35cd5df42bb0fd10c45f0fb97178679c3c03d64c7",
307 | "sha256:c3e4748ba1aad8dba30a4886b0b1a2004f9a863837b8654e7059eebf727afa5a"
308 | ],
309 | "markers": "python_version > '2.7'",
310 | "version": "==7.0.0"
311 | },
312 | "pathtools": {
313 | "hashes": [
314 | "sha256:7c35c5421a39bb82e58018febd90e3b6e5db34c5443aaaf742b3f33d4655f1c0"
315 | ],
316 | "version": "==0.1.2"
317 | },
318 | "pluggy": {
319 | "hashes": [
320 | "sha256:0825a152ac059776623854c1543d65a4ad408eb3d33ee114dff91e57ec6ae6fc",
321 | "sha256:b9817417e95936bf75d85d3f8767f7df6cdde751fc40aed3bb3074cbcb77757c"
322 | ],
323 | "version": "==0.12.0"
324 | },
325 | "port-for": {
326 | "hashes": [
327 | "sha256:b16a84bb29c2954db44c29be38b17c659c9c27e33918dec16b90d375cc596f1c"
328 | ],
329 | "version": "==0.3.1"
330 | },
331 | "py": {
332 | "hashes": [
333 | "sha256:64f65755aee5b381cea27766a3a147c3f15b9b6b9ac88676de66ba2ae36793fa",
334 | "sha256:dc639b046a6e2cff5bbe40194ad65936d6ba360b52b3c3fe1d08a82dd50b5e53"
335 | ],
336 | "version": "==1.8.0"
337 | },
338 | "pyrsistent": {
339 | "hashes": [
340 | "sha256:16692ee739d42cf5e39cef8d27649a8c1fdb7aa99887098f1460057c5eb75c3a"
341 | ],
342 | "version": "==0.15.2"
343 | },
344 | "pytest": {
345 | "hashes": [
346 | "sha256:1a8aa4fa958f8f451ac5441f3ac130d9fc86ea38780dd2715e6d5c5882700b24",
347 | "sha256:b8bf138592384bd4e87338cb0f256bf5f615398a649d4bd83915f0e4047a5ca6"
348 | ],
349 | "index": "pypi",
350 | "version": "==4.5.0"
351 | },
352 | "pyyaml": {
353 | "hashes": [
354 | "sha256:1adecc22f88d38052fb787d959f003811ca858b799590a5eaa70e63dca50308c",
355 | "sha256:436bc774ecf7c103814098159fbb84c2715d25980175292c648f2da143909f95",
356 | "sha256:460a5a4248763f6f37ea225d19d5c205677d8d525f6a83357ca622ed541830c2",
357 | "sha256:5a22a9c84653debfbf198d02fe592c176ea548cccce47553f35f466e15cf2fd4",
358 | "sha256:7a5d3f26b89d688db27822343dfa25c599627bc92093e788956372285c6298ad",
359 | "sha256:9372b04a02080752d9e6f990179a4ab840227c6e2ce15b95e1278456664cf2ba",
360 | "sha256:a5dcbebee834eaddf3fa7366316b880ff4062e4bcc9787b78c7fbb4a26ff2dd1",
361 | "sha256:aee5bab92a176e7cd034e57f46e9df9a9862a71f8f37cad167c6fc74c65f5b4e",
362 | "sha256:c51f642898c0bacd335fc119da60baae0824f2cde95b0330b56c0553439f0673",
363 | "sha256:c68ea4d3ba1705da1e0d85da6684ac657912679a649e8868bd850d2c299cce13",
364 | "sha256:e23d0cc5299223dcc37885dae624f382297717e459ea24053709675a976a3e19"
365 | ],
366 | "version": "==5.1"
367 | },
368 | "six": {
369 | "hashes": [
370 | "sha256:3350809f0555b11f552448330d0b52d5f24c91a322ea4a15ef22629740f3761c",
371 | "sha256:d16a0141ec1a18405cd4ce8b4613101da75da0e9a7aec5bdd4fa804d0e0eba73"
372 | ],
373 | "version": "==1.12.0"
374 | },
375 | "sphinx-autobuild": {
376 | "hashes": [
377 | "sha256:66388f81884666e3821edbe05dd53a0cfb68093873d17320d0610de8db28c74e",
378 | "sha256:e60aea0789cab02fa32ee63c7acae5ef41c06f1434d9fd0a74250a61f5994692"
379 | ],
380 | "index": "pypi",
381 | "version": "==0.7.1"
382 | },
383 | "tornado": {
384 | "hashes": [
385 | "sha256:1174dcb84d08887b55defb2cda1986faeeea715fff189ef3dc44cce99f5fca6b",
386 | "sha256:2613fab506bd2aedb3722c8c64c17f8f74f4070afed6eea17f20b2115e445aec",
387 | "sha256:44b82bc1146a24e5b9853d04c142576b4e8fa7a92f2e30bc364a85d1f75c4de2",
388 | "sha256:457fcbee4df737d2defc181b9073758d73f54a6cfc1f280533ff48831b39f4a8",
389 | "sha256:49603e1a6e24104961497ad0c07c799aec1caac7400a6762b687e74c8206677d",
390 | "sha256:8c2f40b99a8153893793559919a355d7b74649a11e59f411b0b0a1793e160bc0",
391 | "sha256:e1d897889c3b5a829426b7d52828fb37b28bc181cd598624e65c8be40ee3f7fa"
392 | ],
393 | "version": "==6.0.2"
394 | },
395 | "watchdog": {
396 | "hashes": [
397 | "sha256:965f658d0732de3188211932aeb0bb457587f04f63ab4c1e33eab878e9de961d"
398 | ],
399 | "version": "==0.9.0"
400 | },
401 | "wcwidth": {
402 | "hashes": [
403 | "sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
404 | "sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
405 | ],
406 | "version": "==0.1.7"
407 | },
408 | "zipp": {
409 | "hashes": [
410 | "sha256:8c1019c6aad13642199fbe458275ad6a84907634cc9f0989877ccc4a2840139d",
411 | "sha256:ca943a7e809cc12257001ccfb99e3563da9af99d52f261725e96dfe0f9275bc3"
412 | ],
413 | "version": "==0.5.1"
414 | }
415 | }
416 | }
417 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # API Elements
2 | API Elements is a structure for describing APIs and the complex data structures used within them. It also provides structures for defining parsing results for parsing API definitions from formats like API Blueprint and Swagger/OpenAPI Format.
3 |
4 | ## Documentation and Reference
5 |
6 | Please refer to the [documentation and reference](http://api-elements.readthedocs.org/en/latest/) for more information.
7 |
--------------------------------------------------------------------------------
/conftest.py:
--------------------------------------------------------------------------------
1 | from pathlib import Path
2 |
3 |
4 | def pytest_generate_tests(metafunc):
5 | if 'markdown_file' in metafunc.fixturenames:
6 | paths = Path('docs').glob('*.md')
7 | metafunc.parametrize('markdown_file', paths)
8 |
--------------------------------------------------------------------------------
/docs/_static/css/table.css:
--------------------------------------------------------------------------------
1 | table.markdown th, table.markdown td {
2 | padding: 6px 13px;
3 | border: 1px solid #dfe2e5;
4 | }
5 |
6 | table.markdown th {
7 | font-weight: 600;
8 | }
9 |
10 | table.markdown tr:nth-child(2n) {
11 | background-color: #f6f8fa;
12 | }
13 |
14 | table {
15 | border-spacing: 0;
16 | border-collapse: collapse;
17 | }
18 |
--------------------------------------------------------------------------------
/docs/_templates/sidebar_intro.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
8 |
9 |
10 | API Elements is a structure for describing APIs and the complex data structures used within them.
11 |
12 |
20 |
21 |
--------------------------------------------------------------------------------
/docs/additional-information.md:
--------------------------------------------------------------------------------
1 | # Additional Information
2 |
3 | This page lists links and references for additional reading.
4 |
5 | - [API Blueprint](https://apiblueprint.org/) - API description format that utilizes API Elements as its parsing results
6 | - [MSON](https://github.com/apiaryio/mson) - Data structure format that utilizes API Elements as its parsing results (see the Data Structure Elements)
7 |
--------------------------------------------------------------------------------
/docs/conf.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python3
2 | # -*- coding: utf-8 -*-
3 | #
4 | # a documentation build configuration file, created by
5 | # sphinx-quickstart on Mon Jan 15 14:21:21 2018.
6 | #
7 | # This file is execfile()d with the current directory set to its
8 | # containing dir.
9 | #
10 | # Note that not all possible configuration values are present in this
11 | # autogenerated file.
12 | #
13 | # All configuration values have a default; values that are commented out
14 | # serve to show the default.
15 |
16 | # If extensions (or modules to document with autodoc) are in another directory,
17 | # add these directories to sys.path here. If the directory is relative to the
18 | # documentation root, use os.path.abspath to make it absolute, like shown here.
19 | #
20 | # import os
21 | # import sys
22 | # sys.path.insert(0, os.path.abspath('.'))
23 |
24 | import recommonmark
25 | from recommonmark.transform import AutoStructify
26 | from recommonmark.parser import CommonMarkParser
27 |
28 |
29 | # -- General configuration ------------------------------------------------
30 |
31 | # If your documentation needs a minimal Sphinx version, state it here.
32 | #
33 | # needs_sphinx = '1.0'
34 |
35 | # Add any Sphinx extension module names here, as strings. They can be
36 | # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
37 | # ones.
38 | extensions = []
39 |
40 | # Add any paths that contain templates here, relative to this directory.
41 | templates_path = ['_templates']
42 |
43 | # The suffix(es) of source filenames.
44 | # You can specify multiple suffix as a list of string:
45 | #
46 | source_suffix = ['.rst', '.md']
47 |
48 | source_parsers = {
49 | '.md': CommonMarkParser,
50 | }
51 |
52 | # The master toctree document.
53 | master_doc = 'index'
54 |
55 | # General information about the project.
56 | project = 'API Elements'
57 | copyright = '2018, Apiary'
58 | author = 'Apiary'
59 |
60 | # The version info for the project you're documenting, acts as replacement for
61 | # |version| and |release|, also used in various other places throughout the
62 | # built documents.
63 | #
64 | # The short X.Y version.
65 | version = '1.0'
66 | # The full version, including alpha/beta/rc tags.
67 | release = '1.0'
68 |
69 | # The language for content autogenerated by Sphinx. Refer to documentation
70 | # for a list of supported languages.
71 | #
72 | # This is also used if you do content translation via gettext catalogs.
73 | # Usually you set "language" from the command line for these cases.
74 | language = None
75 |
76 | # List of patterns, relative to source directory, that match files and
77 | # directories to ignore when looking for source files.
78 | # This patterns also effect to html_static_path and html_extra_path
79 | exclude_patterns = []
80 |
81 | # The name of the Pygments (syntax highlighting) style to use.
82 | pygments_style = 'sphinx'
83 |
84 | # If true, `todo` and `todoList` produce output, else they produce nothing.
85 | todo_include_todos = False
86 |
87 |
88 | # -- Options for HTML output ----------------------------------------------
89 |
90 | # The theme to use for HTML and HTML Help pages. See the documentation for
91 | # a list of builtin themes.
92 | #
93 | html_theme = 'sphinx_rtd_theme'
94 |
95 | # Theme options are theme-specific and customize the look and feel of a theme
96 | # further. For a list of options available for each theme, see the
97 | # documentation.
98 | #
99 | # html_theme_options = {}
100 |
101 | # Add any paths that contain custom static files (such as style sheets) here,
102 | # relative to this directory. They are copied after the builtin static files,
103 | # so a file named "default.css" will overwrite the builtin "default.css".
104 | html_static_path = ['_static']
105 |
106 | # Custom sidebar templates, must be a dictionary that maps document names
107 | # to template names.
108 | #
109 | # This is required for the alabaster theme
110 | # refs: http://alabaster.readthedocs.io/en/latest/installation.html#sidebars
111 |
112 | # Custom sidebar templates, maps document names to template names.
113 | html_sidebars = {
114 | 'index': ['sidebar_intro.html', 'globaltoc.html', 'searchbox.html'],
115 | '**': ['sidebar_intro.html', 'localtoc.html', 'relations.html', 'searchbox.html'],
116 | }
117 |
118 | html_show_sourcelink = False
119 | html_show_sphinx = False
120 |
121 |
122 | # -- Options for HTMLHelp output ------------------------------------------
123 |
124 | # Output file base name for HTML help builder.
125 | htmlhelp_basename = 'adoc'
126 |
127 |
128 | # -- Options for LaTeX output ---------------------------------------------
129 |
130 | latex_elements = {
131 | # The paper size ('letterpaper' or 'a4paper').
132 | #
133 | # 'papersize': 'letterpaper',
134 |
135 | # The font size ('10pt', '11pt' or '12pt').
136 | #
137 | # 'pointsize': '10pt',
138 |
139 | # Additional stuff for the LaTeX preamble.
140 | #
141 | # 'preamble': '',
142 |
143 | # Latex figure (float) alignment
144 | #
145 | # 'figure_align': 'htbp',
146 | }
147 |
148 | # Grouping the document tree into LaTeX files. List of tuples
149 | # (source start file, target name, title,
150 | # author, documentclass [howto, manual, or own class]).
151 | latex_documents = [
152 | (master_doc, 'a.tex', 'a Documentation',
153 | 'a', 'manual'),
154 | ]
155 |
156 |
157 | # -- Options for manual page output ---------------------------------------
158 |
159 | # One entry per manual page. List of tuples
160 | # (source start file, name, description, authors, manual section).
161 | man_pages = [
162 | (master_doc, 'a', 'a Documentation',
163 | [author], 1)
164 | ]
165 |
166 |
167 | # -- Options for Texinfo output -------------------------------------------
168 |
169 | # Grouping the document tree into Texinfo files. List of tuples
170 | # (source start file, target name, title, author,
171 | # dir menu entry, description, category)
172 | texinfo_documents = [
173 | (master_doc, 'a', 'a Documentation',
174 | author, 'a', 'One line description of project.',
175 | 'Miscellaneous'),
176 | ]
177 |
178 |
179 | github_doc_root = 'https://github.com/apiaryio/api-elements/tree/master/doc/'
180 |
181 |
182 | def setup_recommonmark(app):
183 | app.add_config_value('recommonmark_config', {
184 | 'url_resolver': lambda url: github_doc_root + url,
185 | 'enable_eval_rst': True,
186 | 'auto_toc_tree_section': 'Contents',
187 | 'enable_auto_doc_ref': False,
188 | }, True)
189 | app.add_transform(AutoStructify)
190 |
191 |
192 | def setup(app):
193 | app.add_stylesheet('css/table.css')
194 | setup_recommonmark(app)
195 |
--------------------------------------------------------------------------------
/docs/element-definitions.md:
--------------------------------------------------------------------------------
1 | # Element Reference
2 |
3 | ## Element
4 |
5 | An _Element_ SHALL be a tuple (`element`, `meta`, `attributes`, `content`) where
6 | - `element` SHALL be a non-empty, finite character string identifying the _type_ of this Element
7 | - `meta` SHALL be a set of _properties_, some of which have [reserved semantics](#reserved-meta-properties)
8 | - `attributes` SHALL be a set of _properties_ defined by the _type_ of this Element
9 | - `content` SHALL be defined by the _type_ of this Element
10 |
11 | Entries in `meta` SHOULD be independent of Element.
12 | Entries in `attributes` MAY be Element specific.
13 |
14 | ### Property
15 |
16 | A _property_ SHALL be a tuple (`key`, `value`) where
17 | - `key` SHALL be a non-empty, finite character string
18 | - `value` SHALL be an _Element_
19 | - Two properties SHALL be equal if their keys are.
20 |
21 | > The last statement defining equality on properties through their keys allows definition of _objects_ as _sets_ of properties.
22 |
23 | ### Values
24 | Following values can be described in API Elements:
25 | - _null_ value
26 | - boolean values _true_ and _false_
27 | - rational numbers, i.e. floating point numbers with finite precision
28 | - finite character strings
29 | - finite sets of properties
30 | - finite lists of values
31 |
32 | ### Types
33 | Types specify value categories. Every Element SHALL describe a type.
34 |
35 | Note that because types may be restricted to exactly one value, an Element MAY match only a single value; such an Element still represents a type, not the value itself.
36 |
37 | An Element can therefore be thought of as a predicate that holds if, and only if, given value is in its value category. Given `Number` is the predicate classifying rational numbers, `Number(42.0)` SHALL hold, whereas `Number("foobar")` SHALL NOT.
38 |
39 | #### Subtypes
40 | We say the type _S_ is a _subtype_ of type _T_ if, and only if, all values of _S_ are also values of _T_.
41 |
42 | ---
43 |
44 | API Elements predefines three broad categories of Element types:
45 | 1. [Data Structure Element types](#data-structure-element-types) - Tools to define types, e.g. [string][], [array][], [object][]
46 | 2. [API Element types](#api-element-types) - Types specific to API description
47 | 3. [Parse Result Element types](#parse-result-element-types) - Types specific to document parsing, e.g. source map, parse result
48 |
49 |
50 | ### Reserved meta properties
51 |
52 | Any of the following properties MAY be an entry of any Element's `meta`:
53 |
54 | - `id` ([String][]) - Unique name of this Element; defines a named type; MUST be unique with respect to other `id`s in a document
55 | - `ref` ([Ref](#ref-element)) - Pointer to referenced element or type
56 | - `classes` ([Array][][[String][]]) - Classifications for given element
57 | - `title` ([String][]) - Human-readable title of element
58 | - `description` ([String][]) - Human-readable description of element
59 | - `links` ([Array][][[Link Element](#link-element)]) - Meta links for a given element
60 |
61 | ### Examples
62 |
63 | A primitive Element representing finite character strings is [String][], of type id `string`. Serialized into JSON, an Element representing `Hello world!` interpreted as a [String][] value:
64 |
65 | ```json
66 | {
67 | "element": "string",
68 | "content": "Hello world!"
69 | }
70 | ```
71 |
72 |
73 | A less trivial example is the following `asset` Element. The specific semantic interpretation of an `asset` Element is well defined in the API Elements Reference section. What we essentially describe here is a JSON snippet `{"foo": "bar"}` defined in the message body of documentation.
74 | ```json
75 | {
76 | "element": "asset",
77 | "meta": {
78 | "classes": {
79 | "element": "array",
80 | "content": [
81 | {
82 | "element": "string",
83 | "content": "messageBody"
84 | }
85 | ]
86 | }
87 | },
88 | "attributes": {
89 | "contentType": {
90 | "element": "string",
91 | "content": "application/json"
92 | }
93 | },
94 | "content": "{\"foo\": \"bar\"}"
95 | }
96 | ```
97 |
98 | ---
99 |
100 | ## Data Structure Element types
101 |
102 | ### Overview
103 |
104 | [API Elements](#api-element-types) and [Parse Result Elements](#parse-result-element-types) are all defined via Data Structure Elements.
105 | The following table summarizes them very broadly.
106 |
107 |
108 |
109 |
110 | Name |
111 | Type (JSON serialized) |
112 | Value (JSON serialized) |
113 |
114 |
115 |
116 |
117 | null |
118 |
119 | {
120 | "element": "null"
121 | }
122 | |
123 | null |
124 |
125 |
126 | boolean |
127 |
128 | {
129 | "element": "boolean"
130 | }
131 | |
132 |
133 | true
134 | false
135 | |
136 |
137 |
138 | number |
139 |
140 | {
141 | "element": "number"
142 | }
143 | |
144 |
145 | 0
146 | -1.5
147 | 6.53e-3
148 | |
149 |
150 |
151 | string |
152 |
153 | {
154 | "element": "string"
155 | }
156 | |
157 |
158 | "Hello world"
159 | ""
160 | |
161 |
162 |
163 |
164 |
165 | array |
166 |
167 | {
168 | "element": "array"
169 | }
170 | |
171 |
172 | []
173 | [42, "Hello world!"]
174 | |
175 |
176 |
177 | member |
178 |
179 | {
180 | "element": "member",
181 | "content": {
182 | "key": {
183 | "element": "string",
184 | "content": "foo"
185 | },
186 | "value": {
187 | "element": "string"
188 | }
189 | }
190 | }
191 | |
192 |
193 | Properties in JSON cannot be represented as standalone values. However, they exist as fragments of a JSON objects:
194 | "foo": ""
195 | "foo": "Hey!"
196 | |
197 |
198 |
199 | object |
200 |
201 | {
202 | "element": "object"
203 | }
204 | |
205 |
206 | {}
207 | {
208 | "foo": "Hey!"
209 | }
210 | {
211 | "bar": true
212 | }
213 | |
214 |
215 |
216 | enum |
217 |
218 | {
219 | "element": "enum",
220 | "attributes": {
221 | "enumerations": {
222 | "element": "array",
223 | "content": [
224 | {
225 | "element": "string"
226 | },
227 | {
228 | "element": "number"
229 | }
230 | ]
231 | }
232 | }
233 | }
234 | |
235 |
236 | -45.9
237 | "Hello world!"
238 | ""
239 | 0
240 | |
241 |
242 |
243 | select & option |
244 |
245 | {
246 | "element": "select",
247 | "content": [
248 | {
249 | "element": "option",
250 | "content": {
251 | "element": "string"
252 | }
253 | },
254 | {
255 | "element": "option",
256 | "content": {
257 | "element": "number"
258 | }
259 | }
260 | ]
261 | }
262 | |
263 |
264 | -45.9
265 | "Hello world!"
266 | ""
267 | 0
268 | |
269 |
270 |
271 | extend |
272 |
273 | {
274 | "element": "extend",
275 | "content": [
276 | {
277 | "element": "object",
278 | "content": [
279 | {
280 | "element": "member",
281 | "content": {
282 | "key": {
283 | "element": "string",
284 | "content": "foo"
285 | },
286 | "value": {
287 | "element": "string"
288 | }
289 | }
290 | },
291 | {
292 | "element": "member"
293 | "content": {
294 | "key": {
295 | "element": "string",
296 | "content": "bar"
297 | },
298 | "value": {
299 | "element": "number"
300 | }
301 | }
302 | }
303 | ]
304 | },
305 | {
306 | "element": "object",
307 | "content": [
308 | {
309 | "element": "member"
310 | "content": {
311 | "key": {
312 | "element": "string",
313 | "content": "baz"
314 | },
315 | "value": {
316 | "element": "boolean"
317 | }
318 | }
319 | }
320 | ]
321 | }
322 | ]
323 | }
324 | |
325 |
326 | {}
327 | {
328 | "foo": "Hey!"
329 | }
330 | {
331 | "bar": 42.3
332 | }
333 | {
334 | "foo": "Hello",
335 | "bar": 3.14,
336 | "baz": true
337 | }
338 | |
339 |
340 |
341 |
342 |
343 | ref |
344 |
345 | Given an named type such as
346 | {
347 | "element": "string",
348 | "meta": {
349 | "id": {
350 | "element": "string",
351 | "content": "SpecialString"
352 | }
353 | }
354 | }
355 | }
356 | A reference:
357 | {
358 | "element": "ref"
359 | "content": "MyString"
360 | }
361 | |
362 |
363 | ""
364 | "abc"
365 | "Hello world!"
366 | |
367 |
368 |
369 |
370 |
371 | ---
372 |
373 | ### Fail Element
374 | Type with empty domain. Attempts at instantiation of this Element SHALL fail.
375 |
376 | #### Template
377 | - `element` - `"fail"`
378 |
379 | > Reserved for future use.
380 |
381 | ---
382 |
383 | ### Null Element
384 | Type with domain of a single value.
385 |
386 | #### Template
387 | - `element` - `"null"`
388 |
389 | #### Example
390 |
391 | The example below defines an Element representing only the null value.
392 | ```json
393 | {
394 | "element": "null"
395 | }
396 | ```
397 |
398 | ---
399 |
400 | ### Boolean Element
401 |
402 | Type with domain of two values: _true_ and _false_.
403 |
404 | #### Template
405 | - `element` - `"boolean"`
406 | - `attributes`
407 | - `typeAttributes` ([Array][][[String][]])
408 | - `fixed` ([String][]) - The type this Element describes is restricted to the value given in `content`
409 | - `validation` - _reserved for future use_
410 | - `samples` ([Array][][[Boolean][]]) - Alternative sample values for this Element; type of items in `samples` MUST match the type this Element describes
411 | - `default` ([Boolean][]) - Default value for this Element; type of `default` MUST match the type this Element describes
412 | - `content` - _false_ or _true_
413 |
414 | #### Example
415 |
416 | Type Element representing only boolean values (JSON `true`, `false`):
417 |
418 | ```json
419 |
420 | {
421 | "element": "boolean"
422 | }
423 |
424 | ```
425 |
426 | Type Element representing only boolean "true" (JSON `true`):
427 |
428 | ```json
429 |
430 | {
431 | "element": "boolean",
432 | "attributes": {
433 | "typeAttributes": {
434 | "element": "array",
435 | "content": [
436 | {
437 | "element": "string",
438 | "content": "fixed"
439 | }
440 | ]
441 | }
442 | },
443 | "content": true
444 | }
445 |
446 | ```
447 |
448 | ---
449 |
450 | ### Number Element
451 |
452 | Type with domain of all rational numbers, i.e. floating-point numbers with finite precision.
453 |
454 |
455 | #### Template
456 | - `element` - `"number"`
457 | - `attributes`
458 | - `typeAttributes` ([Array][][[String][]])
459 | - `fixed` ([String][]) - The type this Element describes is restricted to the value given in `content`
460 | - `validation` - _reserved for future use_
461 | - `samples` ([Array][][[Number][]]) - Alternative sample values for this Element; type of items in `samples` MUST match the type this Element describes
462 | - `default` ([Number][]) - Default value for this Element; type of `default` MUST match the type this Element describes
463 | - `content` - Rational number
464 |
465 | #### Example
466 |
467 | Type Element representing only rationals. Matches JSON number values.
468 |
469 | ```json
470 |
471 | {
472 | "element": "number"
473 | }
474 |
475 | ```
476 |
477 | Type Element representing only the number `42`:
478 |
479 | ```json
480 |
481 | {
482 | "element": "number",
483 | "attributes": {
484 | "typeAttributes": {
485 | "element": "array",
486 | "content": [
487 | {
488 | "element": "string",
489 | "content": "fixed"
490 | }
491 | ]
492 | }
493 | },
494 | "content": 42
495 | }
496 |
497 | ```
498 |
499 | ---
500 |
501 | ### String Element
502 |
503 | Type with domain of all finite character strings.
504 |
505 |
506 | #### Template
507 | - `element` - `"string"`
508 | - `attributes`
509 | - `typeAttributes` ([Array][][[String][]])
510 | - `fixed` ([String][]) - The type this Element describes is restricted to the value given in `content`.
511 | - `validation` - _reserved for future use_
512 | - `samples` ([Array][][[String][]]) - Alternative sample values for this Element; type of items in `samples` MUST match the type this Element describes
513 | - `default` ([String][]) - Default value for this Element; type of `default` MUST match the type this Element describes
514 | - `content` - Finite character string
515 |
516 | #### Example
517 |
518 | Type Element representing only finite character strings. Matches JSON string values.
519 |
520 | ```json
521 |
522 | {
523 | "element": "string"
524 | }
525 |
526 | ```
527 |
528 | Type Element representing only the character string `"rocket science"`.
529 |
530 | ```json
531 |
532 | {
533 | "element": "string",
534 | "attributes": {
535 | "typeAttributes": {
536 | "element": "array",
537 | "content": [
538 | {
539 | "element": "string",
540 | "content": "fixed"
541 | }
542 | ]
543 | }
544 | },
545 | "content": "rocket science"
546 | }
547 |
548 | ```
549 |
550 | ---
551 |
552 | ### Array Element
553 |
554 | Type with domain of all finite lists of values.
555 |
556 |
557 | #### Template
558 | - `element` - `"array"`
559 | - `attributes`
560 | - `typeAttributes` ([Array][][[String][]])
561 | - `fixed` ([String][]) - Restricts domain to a positionally typed fixed-length list over types in content. Further applies the `fixed` type attribute to nested [Array][]s, [Object][]s and any other type defining content or default.
562 | - `fixedType` ([String][]) - Restricts domain to a list of types given in `content`.
563 | - `validation` - _reserved for future use_
564 | - `samples` ([Array][][[Array][]]) - Alternative sample values for this Element; type of items in `samples` MUST match the type this Element describes
565 | - `default` ([Array][]) - Default value for this Element; type of `default` MUST match the type this Element describes
566 | - `content` - Finite list of Elements
567 |
568 | #### Examples
569 |
570 | Type Element representing only lists (JSON `array`).
571 |
572 | ```json
573 |
574 | {
575 | "element": "array"
576 | }
577 |
578 | ```
579 |
580 | Type Element representing only pairs of (`string`, `number`).
581 |
582 | ```json
583 |
584 | {
585 | "element": "array",
586 | "attributes": {
587 | "typeAttributes": {
588 | "element": "array",
589 | "content": [
590 | {
591 | "element": "string",
592 | "content": "fixed"
593 | }
594 | ]
595 | }
596 | },
597 | "content": [
598 | {
599 | "element": "string"
600 | },
601 | {
602 | "element": "number"
603 | }
604 | ]
605 | }
606 |
607 | ```
608 |
609 | Type Element representing only lists where items are either a JSON `string` or a JSON `number`.
610 |
611 | ```json
612 |
613 | {
614 | "element": "array",
615 | "attributes": {
616 | "typeAttributes": {
617 | "element": "array",
618 | "content": [
619 | {
620 | "element": "string",
621 | "content": "fixedType"
622 | }
623 | ]
624 | }
625 | },
626 | "content": [
627 | {
628 | "element": "string"
629 | },
630 | {
631 | "element": "number"
632 | }
633 | ]
634 | }
635 |
636 | ```
637 |
638 | ---
639 |
640 | ### Member Element
641 | Type with domain of all [_properties_](#property).
642 |
643 | #### Template
644 | - `element` - `"member"`
645 | - `attributes`
646 | - `typeAttributes` ([Array][][[String][]])
647 | - `required` ([String][]) - Property MUST be present in value represented by the containing [Object][]. I.e. restricts the domain of the containing Object Element type to one containing this property.
648 | - `optional` ([String][]) - Property MAY NOT be present in value represented by the containing [Object][]. I.e. expands the domain of the containing Object Element type to one not containing this property.
649 | - `variable` - ([Boolean][]) - Property key SHALL be interpreted as a variable name instead of a literal name
650 | - `validation` - _reserved for future use_
651 | - `content`
652 | - `key` - An Element representing a key; MUST be set; SHOULD be a [String][]
653 | - `value` - An Element representing the value
654 |
655 | #### Examples
656 | See [Object][] for examples.
657 |
658 | ---
659 |
660 | ### Object Element
661 |
662 | Type with domain of all finite sets of [_properties_](#property).
663 |
664 |
665 | #### Template
666 | - `element` - `"object"`
667 | - `attributes`
668 | - `typeAttributes` ([Array][][[String][]])
669 | - `fixed` ([String][]) - Restricts domain to a fixed sized set of properties, making them implicitly required. Further applies the `fixed` type attribute to nested [Array][]s, [Object][]s and any other type defining content or default.
670 | - `fixedType` ([String][]) - Restricts domain to a fixed sized set of properties, making them implicitly required.
671 | - `validation` - _reserved for future use_
672 | - `samples` ([Array][][[Object][]]) - Alternative sample values for this Element; type of items in `samples` MUST match the type this Element describes
673 | - `default` ([Object][]) - Default value for this Element; type of `default` MUST match the type this Element describes
674 | - `content` - List of any of
675 | - [Member][] - Object property
676 | - [Extend](#extend-element) - MUST type a property
677 | - [Select](#select-element) - Contained [Option Element](#option-element)s MUST type properties
678 | - [Ref](#ref-element) - MUST reference an Object Element
679 |
680 | [References](#ref-element) in the `content` of an Object Element SHALL be semantically equivalent to their substitution by items held in the content of the referenced Object Element. Less formally, Ref Elements in the content of Object Element represent in-place mixins.
681 |
682 | #### Examples
683 |
684 | Type Element representing only property lists (JSON `object`).
685 |
686 | ```json
687 |
688 | {
689 | "element": "object"
690 | }
691 |
692 | ```
693 |
694 | Type Element representing only a specific property list instance (JSON `{"foo": false, "bar": "fun"}`).
695 |
696 | ```json
697 |
698 | {
699 | "element": "object",
700 | "attributes": {
701 | "typeAttributes": {
702 | "element": "array",
703 | "content": [
704 | {
705 | "element": "string",
706 | "content": "fixed"
707 | }
708 | ]
709 | }
710 | },
711 | "content": [
712 | {
713 | "element": "member",
714 | "content": {
715 | "key": {
716 | "element": "string",
717 | "content": "foo"
718 | },
719 | "value": {
720 | "element": "boolean",
721 | "content": false
722 | }
723 | }
724 | },
725 | {
726 | "element": "member",
727 | "content": {
728 | "key": {
729 | "element": "string",
730 | "content": "foo"
731 | },
732 | "value": {
733 | "element": "string",
734 | "content": "fun"
735 | }
736 | }
737 | }
738 | ]
739 | }
740 |
741 | ```
742 |
743 | Type Element representing only a property list with key "foo" of value type `boolean` and with the key "bar" of value type `string` (JSON `{"foo": false, "bar": "fun"}`, `{"foo": true, "bar": ""}` etc.).
744 |
745 | ```json
746 |
747 | {
748 | "element": "object",
749 | "attributes": {
750 | "typeAttributes": {
751 | "element": "array",
752 | "content": [
753 | {
754 | "element": "string",
755 | "content": "fixedType"
756 | }
757 | ]
758 | }
759 | },
760 | "content": [
761 | {
762 | "element": "member",
763 | "content": {
764 | "key": {
765 | "element": "string",
766 | "content": "foo"
767 | },
768 | "value": {
769 | "element": "boolean",
770 | "content": false
771 | }
772 | }
773 | },
774 | {
775 | "element": "member",
776 | "content": {
777 | "key": {
778 | "element": "string",
779 | "content": "bar"
780 | },
781 | "value": {
782 | "element": "string",
783 | "content": "fun"
784 | }
785 | }
786 | }
787 | ]
788 | }
789 |
790 | ```
791 |
792 | ---
793 |
794 | ### Enum Element
795 |
796 | Type with domain of the union of values typed by Elements in the `enumerations` attribute. Also called tagged union or Σ-type.
797 |
798 | #### Template
799 | - `element` - `"enum"`
800 | - `attributes`
801 | - `enumerations` ([Array][]) - List of Elements
802 | - `typeAttributes` ([Array][][[String][]])
803 | - `fixed` ([String][]) - Elements in `enumerations` SHALL be interpreted `fixed`.
804 | - `validation` - _reserved for future use_
805 | - `samples` ([Array][][[Element](#types)]]) - Alternative sample values for this Element; type of items in `samples` MUST match the type this Element describes
806 | - `default` ([Element](#types)) - Default value for this Element; type of `default` MUST match the type this Element describes
807 | - `content` - An Element matching one of the Elements in the `enumerations` attribute
808 |
809 | #### Examples
810 |
811 | Type Element representing strings and numbers.
812 |
813 | ```json
814 | {
815 | "element": "enum",
816 | "attributes": {
817 | "enumerations": {
818 | "element": "array",
819 | "content": [
820 | {
821 | "element": "string"
822 | },
823 | {
824 | "element": "number"
825 | }
826 | ]
827 | }
828 | }
829 | }
830 | ```
831 |
832 | Type Element representing a specific string and all numbers.
833 |
834 | ```json
835 | {
836 | "element": "enum",
837 | "attributes": {
838 | "enumerations": {
839 | "element": "array",
840 | "content": [
841 | {
842 | "element": "string",
843 | "attributes": {
844 | "typeAttributes": {
845 | "element": "array",
846 | "content": [
847 | {
848 | "element": "string",
849 | "content": "fixed"
850 | }
851 | ]
852 | }
853 | },
854 | "content": "Hello world!"
855 | },
856 | {
857 | "element": "number"
858 | }
859 | ]
860 | }
861 | }
862 | }
863 | ```
864 |
865 | ---
866 |
867 | ### Select Element
868 |
869 | Type with domain of the union of values typed by [Option Elements](#option-element) in `content`. Select Element SHOULD only be used to denote alternative sets of properties in an [Object Element][].
870 |
871 | #### Template
872 | - `element` - `"select"`
873 | - `attributes`
874 | - `content` - Finite list of [Option Elements](#option-element)
875 |
876 | ---
877 |
878 | ### Option Element
879 |
880 | Type with the domain of non-empty finite sets of [properties](#property). An Option Element MUST be contained in a [Select Element](#select-element) and its items MUST type [properties](#property).
881 |
882 | #### Template
883 | - `element` - `"option"`
884 | - `attributes`
885 | - `content` - Non-empty list of [Elements](#types) typing properties
886 |
887 | ---
888 |
889 | ### Extend Element
890 |
891 | Type with domain of _merged_ Elements specified in `content`. All entries in `content` MUST type the same data structure type. [Ref Elements](#ref-element) encountered in `content` are dereferenced before merging.
892 |
893 | Merging SHALL be defined based on the type of entries in `content` as follows:
894 | - [Array][] - List concatenation
895 | - [Object][] - Set union; if duplicit property keys are encountered during merging, all but the last SHALL be discarded; tooling SHOULD emit a warning in such a case.
896 | - [Select Element](#select-element) - Option concatenation
897 | - [String][] - Last entry in Extend Element SHALL be used, previous are ignored
898 | - [Boolean][] - Last entry in Extend Element SHALL be used, previous are ignored
899 | - [Number][] - Last entry in Extend Element SHALL be used, previous are ignored
900 | - [Ref Element](#ref-element) - Substitute by referenced Element and apply one of the rules above
901 |
902 | Extend Element SHOULD NOT be used to encode semantic inheritance; use the `id` meta property to define a named type and reference it through the child's `element` entry.
903 |
904 | #### Template
905 | - `element` - `"extend"`
906 | - `content` - List of [Data Structure Elements](#data-structure-element-types) to be merged
907 |
908 | ---
909 |
910 | ### Ref Element
911 |
912 | Ref Element MAY be used to reference elements in remote documents or elements in the local document.
913 | The `ref` element _transcludes_ the contents of the element into the document in which it is referenced.
914 |
915 | The following rules apply:
916 |
917 | 1. When referencing an element in the local document, the `id` of the element MAY be used
918 | 2. When referencing remote elements, an absolute URL or relative URL MAY be used
919 | 3. When a URL fragment exists in the URL given, it references the element with the matching `id` in the given document. The URL fragment MAY need to be URL decoded before making a match.
920 | 4. When a URL fragment does not exist, the URL references the root element
921 | 5. When `path` is used, it references the given property of the referenced element
922 | 6. When `path` is used in an element that includes the data of the pointer (such as with `ref`), the referenced path MAY need to be converted to a refract structure in order to be valid
923 |
924 | Transclusion of a Ref Element SHALL be defined as follows:
925 | 1. If the Ref Element is held by an [Array][] Element and references an Array Element, its content entries SHALL be inserted in place of the Ref Element.
926 | 2. Else, if the Ref Element is held by an [Object][] Element and references an Object Element, its content entries SHALL be inserted in place of the Ref Element.
927 | 3. Otherwise, the Ref Element is substituted by the Element it references.
928 |
929 | #### Template
930 |
931 | - `element` - `"ref"`
932 | - `attributes`
933 | - `path` (enum[[String][]]) - Path of referenced element to transclude instead of element itself
934 | - element (default) - The complete referenced element
935 | - meta - The meta data of the referenced element
936 | - attributes - The attributes of the referenced element
937 | - content - The content of the referenced element
938 | - `validation` - _reserved for future use_
939 | - `content` - URL to an Element in this document as a string
940 |
941 | #### Examples
942 |
943 | Elements MAY be referenced in remote or local documents.
944 |
945 | ##### Referencing Remote Element
946 |
947 | ```json
948 | {
949 | "element": "ref",
950 | "content": "http://example.com/document#foo"
951 | }
952 | ```
953 |
954 | ##### Referencing Local Elements
955 |
956 | ```json
957 | {
958 | "element": "ref",
959 | "content": "foo"
960 | }
961 | ```
962 |
963 | ##### Reference Parts of Elements
964 |
965 | Given an element instance of:
966 |
967 | ```json
968 | {
969 | "element": "array",
970 | "meta": {
971 | "id": {
972 | "element": "string",
973 | "content": "colors"
974 | }
975 | },
976 | "content": [
977 | {
978 | "element": "string",
979 | "content": "red"
980 | },
981 | {
982 | "element": "string",
983 | "content": "green"
984 | }
985 | ]
986 | }
987 | ```
988 |
989 | And given an array where a reference is used as:
990 |
991 | ```json
992 | {
993 | "element": "array",
994 | "content": [
995 | {
996 | "element": "string",
997 | "content": "blue"
998 | },
999 | {
1000 | "element": "ref",
1001 | "attributes": {
1002 | "path": {
1003 | "element": "string",
1004 | "content": "content"
1005 | }
1006 | },
1007 | "content": "colors"
1008 | }
1009 | ]
1010 | }
1011 | ```
1012 |
1013 | The resulting dereferenced array is:
1014 |
1015 | ```json
1016 | {
1017 | "element": "array",
1018 | "content": [
1019 | {
1020 | "element": "string",
1021 | "content": "blue"
1022 | },
1023 | {
1024 | "element": "string",
1025 | "content": "red"
1026 | },
1027 | {
1028 | "element": "string",
1029 | "content": "green"
1030 | }
1031 | ]
1032 | }
1033 | ```
1034 |
1035 | ### Link Element
1036 |
1037 | Hyperlinking MAY be used to link to other resources, provide links to instructions on how to process a given element (by way of a [profile](#profiles) or other means), and may be used to provide meta data about the element in which it's found. The meaning and purpose of the hyperlink is defined by the link relation according to [RFC 5988](https://tools.ietf.org/html/rfc5988).
1038 |
1039 | #### Template
1040 |
1041 | - `element`: `"link"`
1042 | - `attributes`
1043 | - `relation` ([String][]) - Link relation type as specified in [RFC 5988](https://tools.ietf.org/html/rfc5988).
1044 | - `href` ([String][]) - The URI for the given link
1045 | - `validation` - _reserved for future use_
1046 |
1047 | #### Example
1048 |
1049 | The following shows a link with the relation of `foo` and the URL of `/bar`.
1050 |
1051 | ```json
1052 | {
1053 | "element": "link",
1054 | "attributes": {
1055 | "relation": {
1056 | "element": "string",
1057 | "content": "foo"
1058 | },
1059 | "href": {
1060 | "element": "string",
1061 | "content": "/bar"
1062 | }
1063 | }
1064 | }
1065 | ```
1066 |
1067 | ---
1068 |
1069 | ## API Element Types
1070 |
1071 | ### Href ([String][])
1072 |
1073 | [Subtype][] of [String][] with domain of all URI-References per [RFC 3986][].
1074 |
1075 | #### Template
1076 |
1077 | - `element` - `"href"`
1078 |
1079 | ### Templated Href ([String][])
1080 |
1081 | [Subtype][] of [String][] with domain of all URI-Templates per [RFC 6570][].
1082 |
1083 | #### Template
1084 |
1085 | - `element` - `"templatedHref"`
1086 |
1087 | ### Href Variables ([Object][])
1088 |
1089 | Subtype of [Object][] representing an object where each property's key is a `varname` (Commonly described as URI Template variable) per [RFC 6570][].
1090 |
1091 | #### Template
1092 |
1093 | - `element` - `"hrefVariables"`
1094 |
1095 | ### Data Structure
1096 |
1097 | Data structure definition using Data Structure elements.
1098 |
1099 | #### Template
1100 |
1101 | - `element` - `"dataStructure"`
1102 | - `content` - [Data Structure Element](#data-structure-element-types)
1103 |
1104 | ### Asset ([String][])
1105 |
1106 | [Subtype][] of [String][] with domain of all `message-body` as per [RFC 2616][].
1107 |
1108 | #### Template
1109 |
1110 | - `element` - `"asset"`
1111 | - `attributes`
1112 | - `contentType` ([String][]) - Optional media type of the asset. When this is unset, the content type SHOULD be inherited from the `Content-Type` header of a parent HTTP Message Payload
1113 | - `href` ([Href][]) - Link to the asset
1114 | - `content` - A textual representation of the asset
1115 |
1116 | #### Classifications
1117 |
1118 | - `"messageBody"` - Asset is an example of message-body
1119 | - `"messageBodySchema"` - Asset is a schema for message-body
1120 |
1121 | ### Resource
1122 |
1123 | The Resource representation with its available transitions and its data.
1124 |
1125 | #### Template
1126 |
1127 | - `element` - `"resource"`
1128 | - `attributes`
1129 | - `hosts` ([Array][][[Resource][]]).
1130 |
1131 | Optional list of host resources. Every entry SHALL be interpreted as if classified as `host`.
1132 | _See `host` classification in [Resource][] for further semantics._
1133 |
1134 | Overrides any otherwise relevant `hosts` definitions.
1135 |
1136 | - `href` ([Templated Href][]) - URI Template for this resource.
1137 | - `hrefVariables` ([Href Variables][]) - URI Template variables.
1138 | - `content` (array)
1139 | - ([Copy][]) - Textual information of this resource in API Description.
1140 | - ([Category][]) - A group of Transition elements.
1141 | - ([Transition][]) - State transitions available for this resource.
1142 |
1143 | The `content` MAY include multiple `Transition` elements.
1144 |
1145 | - ([Data Structure][]) - Data structure representing the resource.
1146 |
1147 | The `content` MUST NOT include more than one `Data Structure`.
1148 |
1149 | #### Classifications
1150 |
1151 | - `"host"` - A host resource represents the "root" of the API resource.
1152 | The resource href MAY be append to the host href to create a absolute URI.
1153 | A resource that has a `host` classification MUST be a root component of a URI.
1154 |
1155 | #### Example
1156 |
1157 | ```json
1158 | {
1159 | "element": "resource",
1160 | "meta": {
1161 | "title": {
1162 | "element": "string",
1163 | "content": "Question"
1164 | },
1165 | "description": {
1166 | "element": "string",
1167 | "content": "A Question object has the following attributes."
1168 | }
1169 | },
1170 | "attributes": {
1171 | "href": {
1172 | "element": "string",
1173 | "content": "/questions/{question_id}"
1174 | },
1175 | "hrefVariables": {
1176 | "element": "hrefVariables",
1177 | "content": [
1178 | {
1179 | "element": "member",
1180 | "content": {
1181 | "key": {
1182 | "element": "string",
1183 | "content": "question_id"
1184 | }
1185 | }
1186 | }
1187 | ]
1188 | }
1189 | },
1190 | "content": [
1191 | {
1192 | "element": "dataStructure"
1193 | }
1194 | ]
1195 | }
1196 | ```
1197 |
1198 | ### Transition
1199 |
1200 | A transition is an available progression from one state to another state.
1201 | Exercising a transition initiates a transaction.
1202 |
1203 | The content of this element is array of protocol-specific transactions.
1204 |
1205 | Note: At the moment only the HTTP protocol is supported.
1206 |
1207 | #### Template
1208 |
1209 | - `element` - `"transition"`
1210 | - `attributes`
1211 | - `contentTypes` ([Array][][[String][]]) - A collection of content types that MAY be used for the transition.
1212 |
1213 | - `data` ([Data Structure][]) - Data structure describing the transition's `Request` `message-body` unless overridden.
1214 |
1215 | Definition of any input message-body attribute for this transition.
1216 |
1217 | - `hosts` ([Array][][[Resource][]]).
1218 |
1219 | Optional list of host resources. Every entry SHALL be interpreted as if classified as `host`.
1220 |
1221 | _See `host` classification in [Resource][] for further semantics._
1222 |
1223 | All [Resource][]s nested under the [Transition][]'s `content` SHALL interpret this `hosts` definition as their own, unless it is overridden by another `hosts` definition on the path to the [Resource][] element.
1224 |
1225 | - `href` ([Templated Href][]) - URI template for this transition.
1226 |
1227 | If present, the value of the `href` attribute SHOULD be used to resolve
1228 | the target URI of the transition.
1229 |
1230 | If not set, the parent `resource` element `href` attribute SHOULD be
1231 | used to resolve the target URI of the transition.
1232 |
1233 | - `hrefVariables` ([Href Variables][]) - URI Template variables.
1234 |
1235 | Definition of any input URI path segments or URI query parameters for this transition.
1236 |
1237 | If `href` and `hrefVariables` attributes aren't set, the parent `resource`
1238 | element `hrefVariables` SHOULD be used to resolve the transition input
1239 | parameters.
1240 |
1241 | - `relation` - ([String][]) - Link relation type as specified in [RFC 5988][].
1242 |
1243 | The value of `relation` attribute SHOULD be interpreted as a link relation
1244 | between transition's parent resource and the transition's target resource
1245 | as specified in the `href` attribute.
1246 | - `content` (array)
1247 | - ([Copy][]) - Textual information of this transition in API Description.
1248 | - ([HTTP Transaction](#http-transaction-array))
1249 |
1250 | Transaction examples are protocol-specific examples of a REST transaction
1251 | that was initialized by exercising a transition.
1252 |
1253 | For the time being this reference document defines only HTTP-specific transaction
1254 | data structures.
1255 |
1256 | #### Example
1257 |
1258 | ```json
1259 | {
1260 | "element": "transition",
1261 | "attributes": {
1262 | "relation": {
1263 | "element": "string",
1264 | "content": "update"
1265 | },
1266 | "href": {
1267 | "element": "string",
1268 | "content": "https://polls.apiblueprint.org/questions/{question_id}"
1269 | }
1270 | },
1271 | "content": []
1272 | }
1273 | ```
1274 |
1275 | ### API Metadata ([Member][])
1276 |
1277 | [Subtype][] of [Member][] representing a property whose key and value are strings.
1278 |
1279 | #### Classifications
1280 |
1281 | - `"user"` - User-specific metadata. Metadata written in the source.
1282 | - `"adapter"` - Serialization-specific metadata. Metadata provided by adapter.
1283 |
1284 | ### Category
1285 |
1286 | Grouping element – a set of elements forming a logical unit of an API such as
1287 | group of related resources or data structures.
1288 |
1289 | A category element MAY include additional classification of the category.
1290 | The classification MAY hint what is the content or semantics of the category.
1291 | The classification MAY be extended and MAY contain more than one classes.
1292 |
1293 | For example a `category` element may be classified both as `resourceGroup` and
1294 | `dataStructures` to denote it includes both resource and data structures. It
1295 | may also include the `transitions` classification to denote it includes
1296 | transitions.
1297 |
1298 | #### Template
1299 |
1300 | - `element` - `"category"`
1301 | - `attributes` - is intended for place element specific info
1302 | - `metadata` ([Array][][[API Metadata](#api-metadata-member)]) - Arbitrary metadata
1303 | - `version` ([String][]) - reserved for API documentation version info, if presented MUST be placed on API Category (top-level group)
1304 | - `content` (array)
1305 |
1306 | #### Classifications
1307 |
1308 | - `"api"` - Category is a API top-level group.
1309 | - `"authSchemes"` - Category is a group of authentication and authorization scheme definitions.
1310 | - `"dataStructures"` - Category is a set of data structures.
1311 | - `"hosts"` - Category of [Resource][]s interpreted as a list of host resources of an API. Every entry SHALL be interpreted as if classified as `host`.
1312 |
1313 | _See `host` classification in [Resource][] for further semantics._
1314 |
1315 | - `"resourceGroup"` - Category is a set of resources.
1316 | - `"scenario"` - Category is set of steps.
1317 | - `"transitions"` - Category is a group of transitions.
1318 |
1319 | #### Example
1320 |
1321 | ```json
1322 | {
1323 | "element": "category",
1324 | "meta": {
1325 | "classes": {
1326 | "element": "array",
1327 | "content": [
1328 | {
1329 | "element": "string",
1330 | "content": "api"
1331 | }
1332 | ]
1333 | },
1334 | "title": {
1335 | "element": "string",
1336 | "content": "Polls API"
1337 | }
1338 | },
1339 | "attributes": {
1340 | "metadata": {
1341 | "element": "array",
1342 | "content": [
1343 | {
1344 | "element": "member",
1345 | "meta": {
1346 | "classes": {
1347 | "element": "array",
1348 | "content": [
1349 | {
1350 | "element": "string",
1351 | "content": "user"
1352 | }
1353 | ]
1354 | }
1355 | },
1356 | "content": {
1357 | "key": {
1358 | "element": "string",
1359 | "content": "HOST"
1360 | },
1361 | "value": {
1362 | "element": "string",
1363 | "content": "http://polls.apiblueprint.org/"
1364 | }
1365 | }
1366 | }
1367 | ]
1368 | }
1369 | },
1370 | "content": [
1371 | {
1372 | "element": "category",
1373 | "meta": {
1374 | "classes": {
1375 | "element": "array",
1376 | "content": [
1377 | {
1378 | "element": "string",
1379 | "content": "resourceGroup"
1380 | }
1381 | ]
1382 | },
1383 | "title": {
1384 | "element": "string",
1385 | "content": "Question"
1386 | }
1387 | },
1388 | "content": [
1389 | {
1390 | "element": "copy",
1391 | "content": "Resources related to questions in the API."
1392 | }
1393 | ]
1394 | }
1395 | ]
1396 | }
1397 | ```
1398 |
1399 | ### Copy ([String][])
1400 |
1401 | [Subtype][] of [String][] which represents a textual information in API description.
1402 |
1403 | Its content is a string and it MAY include information about the media type
1404 | of the copy's content.
1405 |
1406 | Unless specified otherwise, a copy element's content represents the
1407 | description of its parent element and SHOULD be used instead of parent
1408 | element's description metadata.
1409 |
1410 | #### Template
1411 |
1412 | - `element` - `"copy"`
1413 | - `attributes`
1414 | - `contentType` ([String][]) - Optional media type of the content.
1415 | - `content` - Text
1416 |
1417 | #### Example
1418 |
1419 | Given an API description with following layout:
1420 |
1421 | - Group
1422 | - Copy "Lorem Ipsum"
1423 | - Resource "A"
1424 | - Resource "B"
1425 | - Copy "Dolor Sit Amet"
1426 |
1427 | ```json
1428 | {
1429 | "element": "category",
1430 | "content": [
1431 | {
1432 | "element": "copy",
1433 | "content": "Lorem Ipsum"
1434 | },
1435 | {
1436 | "element": "resource"
1437 | },
1438 | {
1439 | "element": "resource"
1440 | },
1441 | {
1442 | "element": "copy",
1443 | "content": "Dolor Sit Amet"
1444 | }
1445 | ]
1446 | }
1447 | ```
1448 |
1449 | ### Protocol-specific Elements
1450 |
1451 | #### HTTP Transaction ([Array][])
1452 |
1453 | Example of an HTTP Transaction.
1454 |
1455 | ##### Template
1456 |
1457 | - `element` - `"httpTransaction"`
1458 | - `attributes`
1459 | - `authSchemes` ([Array][]) - An array of authentication and authorization schemes that apply to the transaction
1460 | - `content` (array) - Request and response message pair (tuple).
1461 | - ([Copy][]) - Textual information of this transaction in API Description.
1462 | - ([HTTP Request Message](#http-request-message-http-message-payload))
1463 |
1464 | The `content` MUST include exactly one `HTTP Request Message` element.
1465 |
1466 | - ([HTTP Response Message](#http-response-message-http-message-payload))
1467 |
1468 | The `content` MUST include exactly one `HTTP Response Message` element.
1469 |
1470 | ##### Example
1471 |
1472 | ```json
1473 | {
1474 | "element": "httpTransaction",
1475 | "content": [
1476 | {
1477 | "element": "httpRequest",
1478 | "attributes": {
1479 | "method": {
1480 | "element": "string",
1481 | "content": "GET"
1482 | },
1483 | "href": {
1484 | "element": "string",
1485 | "content": "/questions/{question_id}"
1486 | },
1487 | "hrefVariables": {
1488 | "element": "hrefVariables",
1489 | "content": [
1490 | {
1491 | "element": "member",
1492 | "content": {
1493 | "key": {
1494 | "element": "string",
1495 | "content": "question_id"
1496 | }
1497 | }
1498 | }
1499 | ]
1500 | }
1501 | },
1502 | "content": []
1503 | },
1504 | {
1505 | "element": "httpResponse",
1506 | "attributes": {
1507 | "statusCode": {
1508 | "element": "number",
1509 | "content": 200
1510 | }
1511 | },
1512 | "content": [
1513 | {
1514 | "element": "asset",
1515 | "meta": {
1516 | "classes": {
1517 | "element": "array",
1518 | "content": [
1519 | {
1520 | "element": "string",
1521 | "content": "messageBody"
1522 | }
1523 | ]
1524 | }
1525 | },
1526 | "attributes": {
1527 | "contentType": {
1528 | "element": "string",
1529 | "content": "application/json"
1530 | }
1531 | },
1532 | "content": "{\"name\": \"John\"}"
1533 | }
1534 | ]
1535 | }
1536 | ]
1537 | }
1538 | ```
1539 |
1540 | #### HTTP Headers ([Object][])
1541 |
1542 | [Subtype][] of [Object][] representing an object where each property's key is a `field-name` (Commonly known as HTTP Header name) per [RFC 822][] and the property's key is a `field-value` (Commonly known as HTTP Header value) per [RFC 2616][].
1543 |
1544 | ##### Template
1545 |
1546 | - `element` - `"httpHeaders"`
1547 |
1548 | ##### Example
1549 |
1550 | ```json
1551 | {
1552 | "element": "httpHeaders",
1553 | "content": [
1554 | {
1555 | "element": "member",
1556 | "content": {
1557 | "key": {
1558 | "element": "string",
1559 | "content": "Content-Type"
1560 | },
1561 | "value": {
1562 | "element": "string",
1563 | "content": "application/json"
1564 | }
1565 | }
1566 | }
1567 | ]
1568 | }
1569 | ```
1570 |
1571 | #### HTTP Message Payload ([Array][])
1572 |
1573 | [Subtype][] of [Array][] representing a `HTTP-message` (Commonly known as Payload) per [RFC 2616][].
1574 |
1575 | ##### Template
1576 |
1577 | - `attributes`
1578 | - `headers` ([HTTP Headers][])
1579 | - `content` (array)
1580 | - ([Copy][]) - Textual information of this payload in API Description.
1581 | - ([Data Structure][]) - Data structure describing the payload's `message-body`.
1582 |
1583 | The `content` MUST NOT contain more than one `Data Structure`.
1584 |
1585 | - ([Asset][]) - An asset associated with the payload's `message-body`.
1586 |
1587 | This asset MAY represent payload body or body's schema.
1588 |
1589 | The `content` SHOULD NOT contain more than one asset of its respective type.
1590 |
1591 | #### HTTP Request Message ([HTTP Message Payload][])
1592 |
1593 | [Subtype][] of [HTTP Message Payload][] representing a `Request` (Commonly known as HTTP Request) per [RFC 2616][].
1594 |
1595 | ##### Template
1596 |
1597 | - `element` - `"httpRequest"`
1598 | - `attributes`
1599 | - `method` ([String][]) - `Method` part of HTTP Request per [RFC 2616][].
1600 |
1601 | The method value SHOULD be inherited from a parent transition if it is unset.
1602 |
1603 | - `href` ([Templated Href][]) - URI Template for this HTTP request. Combined with `hrefVariables` forms the `Request-URI` part of HTTP Request per [RFC 2616][].
1604 |
1605 | If present, the value of the `href` attribute SHOULD be used to resolve
1606 | the target URI of the http request.
1607 |
1608 | If not set, the `href` attribute which was used to resolve the target
1609 | URI of the parent transition SHOULD be used to resolve the URI of
1610 | the http request.
1611 |
1612 | - `hrefVariables` ([Href Variables][]) - URI Template variables.
1613 |
1614 | Definition of any input URI path segments or URI query parameters for this transition.
1615 |
1616 | If `href` and `hrefVariables` attributes aren't set, the `hrefVariables` attribute
1617 | which was used to resolve the input parameters of the parent transition SHOULD
1618 | be used to resolve the http request input parameters.
1619 |
1620 |
1621 | #### HTTP Response Message ([HTTP Message Payload][])
1622 |
1623 | [Subtype][] of [HTTP Message Payload][] representing a `Response` (Commonly known as HTTP Response) per [RFC 2616][].
1624 |
1625 | ##### Template
1626 |
1627 | - `element` - `"httpResponse"`
1628 | - `attributes`
1629 | - `statusCode` ([Number][]) - `Status-Code` part of HTTP Response per [RFC 2616][].
1630 |
1631 |
1632 | ## Parse Result Element types
1633 |
1634 |
1635 | ### Parse Result ([Array][])
1636 |
1637 | A result of parsing of an API description document.
1638 |
1639 | #### Template
1640 |
1641 | - `element` - `"parseResult"`
1642 | - `content` (array)
1643 | - ([Category][])
1644 | - ([Annotation](#annotation-string))
1645 |
1646 | #### Example
1647 |
1648 | Given following API Blueprint document:
1649 |
1650 | ```apib
1651 | # GET /1
1652 | ```
1653 |
1654 | The parse result is (using null in `category` content for simplicity):
1655 |
1656 | ```json
1657 | {
1658 | "element": "parseResult",
1659 | "content": [
1660 | {
1661 | "element": "category",
1662 | "meta": {
1663 | "classes": {
1664 | "element": "array",
1665 | "content": [
1666 | {
1667 | "element": "string",
1668 | "content": "api"
1669 | }
1670 | ]
1671 | }
1672 | }
1673 | },
1674 | {
1675 | "element": "annotation",
1676 | "meta": {
1677 | "classes": {
1678 | "element": "array",
1679 | "content": [
1680 | {
1681 | "element": "string",
1682 | "content": "warning"
1683 | }
1684 | ]
1685 | }
1686 | },
1687 | "attributes": {
1688 | "code": {
1689 | "element": "number",
1690 | "content": 6
1691 | },
1692 | "sourceMap": {
1693 | "element": "array",
1694 | "content": [
1695 | {
1696 | "element": "sourceMap",
1697 | "content": [
1698 | {
1699 | "element": "array",
1700 | "content": [
1701 | {
1702 | "element": "number",
1703 | "content": 0
1704 | },
1705 | {
1706 | "element": "number",
1707 | "content": 9
1708 | }
1709 | ]
1710 | }
1711 | ]
1712 | }
1713 | ]
1714 | }
1715 | },
1716 | "content": "action"
1717 | }
1718 | ]
1719 | }
1720 | ```
1721 |
1722 | ### Annotation ([String][])
1723 |
1724 | Annotation for a source file. Usually generated by a parser or adapter.
1725 |
1726 | #### Template
1727 |
1728 | - `element` - `"annotation"`
1729 | - `attributes`
1730 | - `code` ([Number][]) - Parser-specific code of the annotation. Refer to parser documentation for explanation of the codes.
1731 | - `sourceMap` ([Array][][[Source Map][]]) - Locations of the annotation in the source file.
1732 | - `content` - Textual annotation.
1733 |
1734 | This is – in most cases – a human-readable message to be displayed to user.
1735 |
1736 | #### Classifications
1737 |
1738 | - `"error"` - Annotation is an error
1739 | - `"warning"` - Annotation is a warning
1740 |
1741 | #### Example
1742 |
1743 | ```json
1744 | {
1745 | "element": "annotation",
1746 | "meta": {
1747 | "classes": {
1748 | "element": "array",
1749 | "content": [
1750 | {
1751 | "element": "string",
1752 | "content": "warning"
1753 | }
1754 | ]
1755 | }
1756 | },
1757 | "attributes": {
1758 | "code": {
1759 | "element": "number",
1760 | "content": 6
1761 | },
1762 | "sourceMap": {
1763 | "element": "array",
1764 | "content": [
1765 | {
1766 | "element": "sourceMap",
1767 | "content": [
1768 | {
1769 | "element": "array",
1770 | "content": [
1771 | {
1772 | "element": "number",
1773 | "content": 4
1774 | },
1775 | {
1776 | "element": "number",
1777 | "content": 12
1778 | }
1779 | ]
1780 | },
1781 | {
1782 | "element": "array",
1783 | "content": [
1784 | {
1785 | "element": "number",
1786 | "content": 20
1787 | },
1788 | {
1789 | "element": "number",
1790 | "content": 12
1791 | }
1792 | ]
1793 | }
1794 | ]
1795 | }
1796 | ]
1797 | }
1798 | },
1799 | "content": "action is missing a response"
1800 | }
1801 | ```
1802 |
1803 | ### Source Map
1804 |
1805 | Source map of an Element.
1806 |
1807 | Every Element MAY include a `sourceMap` attribute. Its content MUST
1808 | be an array of `Source Map` elements. The Source Map elements represent the
1809 | location(s) in source file(s) from which the element was composed.
1810 |
1811 | If used, it represents the location of bytes in the source file.
1812 | This location SHOULD include the bytes used to build the parent element.
1813 |
1814 | The Source Map element MUST NOT be used in its normal form
1815 | unless the particular application clearly implies what is the source file the
1816 | source map is pointing in.
1817 |
1818 | A source map is a series of byte-blocks. These
1819 | blocks may be non-continuous. For example, a block in the series may not start
1820 | immediately after the previous block. Each block, however, is a continuous
1821 | series of bytes.
1822 |
1823 | #### Template
1824 |
1825 | - `element` - `"sourceMap"`
1826 | - `content` (array) - Array of byte blocks.
1827 | - ([Array][]) - Continuous bytes block. A pair of byte index and byte count.
1828 | - `content` (array)
1829 | - ([Number][]) - Zero-based index of a byte in the source document.
1830 | - attributes
1831 | - line ([Number][]) - The line number the source map starts on.
1832 | - column ([Number][]) - The column number of the line that the source map starts on.
1833 | - ([Number][]) - Count of bytes starting from the byte index.
1834 | - attributes
1835 | - line ([Number][]) - The line number the source map ends on.
1836 | - column ([Number][]) - The column number of the line that the source map ends on.
1837 |
1838 | #### Example
1839 |
1840 | ```json
1841 | {
1842 | "element": "sourceMap",
1843 | "content": [
1844 | {
1845 | "element": "array",
1846 | "content": [
1847 | {
1848 | "element": "number",
1849 | "content": 4
1850 | },
1851 | {
1852 | "element": "number",
1853 | "content": 12
1854 | }
1855 | ]
1856 | },
1857 | {
1858 | "element": "array",
1859 | "content": [
1860 | {
1861 | "element": "number",
1862 | "content": 4
1863 | },
1864 | {
1865 | "element": "number",
1866 | "content": 12
1867 | }
1868 | ]
1869 | }
1870 | ]
1871 | }
1872 | ```
1873 |
1874 | This reads, "The location starts at the 5th byte of the source file. It
1875 | includes the 12 subsequent bytes including the starting one. Then it
1876 | continues at the 21st byte for another 12 bytes."
1877 |
1878 | #### Example
1879 |
1880 | ```json
1881 | {
1882 | "element": "sourceMap",
1883 | "content": [
1884 | {
1885 | "element": "array",
1886 | "content": [
1887 | {
1888 | "element": "number",
1889 | "attributes": {
1890 | "line": {
1891 | "element": "number",
1892 | "content": 3
1893 | },
1894 | "column": {
1895 | "element": "number",
1896 | "content": 2
1897 | }
1898 | },
1899 | "content": 4
1900 | },
1901 | {
1902 | "element": "number",
1903 | "attributes": {
1904 | "line": {
1905 | "element": "number",
1906 | "content": 3
1907 | },
1908 | "column": {
1909 | "element": "number",
1910 | "content": 10
1911 | }
1912 | },
1913 | "content": 12
1914 | }
1915 | ]
1916 | }
1917 | ]
1918 | }
1919 | ```
1920 |
1921 | This reads, "The location starts at the 5th byte (the 2nd byte of line 3) of the source file. It includes 12 bytes, until column 10 on line 3".
1922 |
1923 | **NOTE** *`line` and `column` are optional and may not always be available*.
1924 |
1925 | ### Link Relations
1926 |
1927 | In addition to conforming to [RFC 5988][] for link relations, there are also additional link relations
1928 | available for parse results.
1929 |
1930 | #### Origin Link Relation
1931 |
1932 | The `origin` link relation defines the origin of a given element. This link can
1933 | point to specific tooling that was used to parse or generate a given element.
1934 |
1935 | #### Inferred Link Relation
1936 |
1937 | The `inferred` link relation gives a hint to whether or not an element was
1938 | inferred or whether it was found in the originating document. The presence of
1939 | the `inferred` link tells the user that the element was created based on some
1940 | varying assumptions, and the URL to which the link points MAY provide an
1941 | explanation on how and why it was inferred.
1942 |
1943 | ## Authentication and Authorization Schemes
1944 |
1945 | Authentication and authorization schemes MAY be defined within an API Elements document. These schemes are then used within the context of a resource to define which schemes to apply when making a transaction.
1946 |
1947 | ### Basic Authentication Scheme ([Object][])
1948 |
1949 | This element may be used to define a basic authentication scheme implementation for an API as described in [RFC 2617](https://tools.ietf.org/html/rfc2617).
1950 |
1951 | The element MAY have a username and password defined as member elements within the scheme, but these are not required.
1952 |
1953 | - `username` (string, optional)
1954 | - `password` (string, optional)
1955 |
1956 | #### Template
1957 |
1958 | - `element` - `"Basic Authentication Scheme"`
1959 |
1960 | #### Example
1961 |
1962 | This example shows a custom basic authentication scheme being defined as `Custom Basic Auth`. This scheme is then used on an HTTP transaction within a resource. Please note this example is incomplete for the sake of keeping it short.
1963 |
1964 | ```json
1965 | {
1966 | "element": "category",
1967 | "meta": {
1968 | "classes": {
1969 | "element": "array",
1970 | "content": [
1971 | {
1972 | "element": "string",
1973 | "content": "api"
1974 | }
1975 | ]
1976 | }
1977 | },
1978 | "content": [
1979 | {
1980 | "element": "category",
1981 | "meta": {
1982 | "classes": {
1983 | "element": "array",
1984 | "content": [
1985 | {
1986 | "element": "string",
1987 | "content": "authSchemes"
1988 | }
1989 | ]
1990 | }
1991 | },
1992 | "content": [
1993 | {
1994 | "element": "Basic Authentication Scheme",
1995 | "meta": {
1996 | "id": {
1997 | "element": "string",
1998 | "content": "Custom Basic Auth"
1999 | }
2000 | },
2001 | "content": [
2002 | {
2003 | "element": "member",
2004 | "content": {
2005 | "key": {
2006 | "element": "string",
2007 | "content": "username"
2008 | },
2009 | "value": {
2010 | "element": "string",
2011 | "content": "john.doe"
2012 | }
2013 | }
2014 | },
2015 | {
2016 | "element": "member",
2017 | "content": {
2018 | "key": {
2019 | "element": "string",
2020 | "content": "password"
2021 | },
2022 | "value": {
2023 | "element": "string",
2024 | "content": "1234password"
2025 | }
2026 | }
2027 | }
2028 | ]
2029 | }
2030 | ]
2031 | },
2032 | {
2033 | "element": "resource",
2034 | "attributes": {
2035 | "href": {
2036 | "element": "string",
2037 | "content": "/users"
2038 | }
2039 | },
2040 | "content": [
2041 | {
2042 | "element": "transition",
2043 | "content": [
2044 | {
2045 | "element": "httpTransaction",
2046 | "attributes": {
2047 | "authSchemes": {
2048 | "element": "array",
2049 | "content": [
2050 | {
2051 | "element": "Custom Basic Auth"
2052 | }
2053 | ]
2054 | }
2055 | }
2056 | }
2057 | ]
2058 | }
2059 | ]
2060 | }
2061 | ]
2062 | }
2063 | ```
2064 |
2065 | ### Token Authentication Scheme ([Object][])
2066 |
2067 | This describes an authentication scheme that uses a token as a way to authenticate and authorize. The token MAY exist as an HTTP header field, query parameter or as a cookie.
2068 |
2069 | - One of
2070 | - `httpHeaderName` (string)
2071 | - `queryParameterName` (string)
2072 | - `cookieName` (string)
2073 |
2074 | When used as a query parameter, an HREF Variable is not required to be defined within the scope of the resource or transition, but is rather infered from the used token authentications scheme.
2075 |
2076 | #### Template
2077 |
2078 | - `element` - `"Token Authentication Scheme"`
2079 |
2080 | #### Example
2081 |
2082 | This example shows a custom token authentication scheme being defined as `Custom Token Auth` that uses a query parameter for the token. This scheme is then used on an HTTP transaction within a resource. Please note this example is incomplete for the sake of keeping it short.
2083 |
2084 | ```json
2085 | {
2086 | "element": "category",
2087 | "meta": {
2088 | "classes": {
2089 | "element": "array",
2090 | "content": [
2091 | {
2092 | "element": "string",
2093 | "content": "api"
2094 | }
2095 | ]
2096 | }
2097 | },
2098 | "content": [
2099 | {
2100 | "element": "category",
2101 | "meta": {
2102 | "classes": {
2103 | "element": "array",
2104 | "content": [
2105 | {
2106 | "element": "string",
2107 | "content": "authSchemes"
2108 | }
2109 | ]
2110 | }
2111 | },
2112 | "content": [
2113 | {
2114 | "element": "Token Authentication Scheme",
2115 | "meta": {
2116 | "id": {
2117 | "element": "string",
2118 | "content": "Custom Token Auth"
2119 | }
2120 | },
2121 | "content": [
2122 | {
2123 | "element": "member",
2124 | "content": {
2125 | "key": {
2126 | "element": "string",
2127 | "content": "queryParameterName"
2128 | },
2129 | "value": {
2130 | "element": "string",
2131 | "content": "api_key"
2132 | }
2133 | }
2134 | }
2135 | ]
2136 | }
2137 | ]
2138 | },
2139 | {
2140 | "element": "resource",
2141 | "attributes": {
2142 | "href": {
2143 | "element": "string",
2144 | "content": "/users"
2145 | }
2146 | },
2147 | "content": [
2148 | {
2149 | "element": "transition",
2150 | "content": [
2151 | {
2152 | "element": "httpTransaction",
2153 | "attributes": {
2154 | "authSchemes": {
2155 | "element": "array",
2156 | "content": [
2157 | {
2158 | "element": "Custom Token Auth"
2159 | }
2160 | ]
2161 | }
2162 | }
2163 | }
2164 | ]
2165 | }
2166 | ]
2167 | }
2168 | ]
2169 | }
2170 | ```
2171 |
2172 | ### OAuth2 Scheme
2173 |
2174 | This describes an authentication scheme that uses OAuth2 as defined in [RFC 6749](https://tools.ietf.org/html/rfc6749).
2175 |
2176 | The element MAY have the following members to define additional information about the OAuth2 implementation.
2177 |
2178 | - `scopes` ([Array][][[String][]])
2179 | - `grantType` (enum[[String][]])
2180 | - `authorization code`
2181 | - `implicit`
2182 | - `resource owner password credentials`
2183 | - `client credentials`
2184 |
2185 | Transition elements are used to define the URLs for the authorize, token and refresh endpoints for the OAuth2 schemes. When including these endpoints, the following link relations SHOULD be used.
2186 |
2187 | - `authorize` - URL for the authorization endpoint
2188 | - `token` - URL for the token endpoint
2189 | - `refresh` - URL for the refresh endpoint
2190 |
2191 | The HREF values for these transitions MAY be either relative or absolute URLs.
2192 |
2193 | #### Template
2194 |
2195 | - `element` - `"OAuth2 Scheme"`
2196 | - `content` (array)
2197 | - ([Member][])
2198 | - ([Transition][])
2199 |
2200 | #### Example
2201 |
2202 | This example shows a custom OAuth2 scheme being defined as `Custom OAuth2`. This scheme is then used on an HTTP transaction within a resource. There are a couple of things to note about this example:
2203 |
2204 | 1. There are two scopes defined within the scheme, but only one is used within the context of the transaction.
2205 | 1. Transitions are used to define the authorize and token endpoints.
2206 |
2207 | Also, please note this example is incomplete for the sake of keeping it short.
2208 |
2209 | ```json
2210 | {
2211 | "element": "category",
2212 | "meta": {
2213 | "classes": {
2214 | "element": "array",
2215 | "content": [
2216 | {
2217 | "element": "string",
2218 | "content": "api"
2219 | }
2220 | ]
2221 | }
2222 | },
2223 | "content": [
2224 | {
2225 | "element": "category",
2226 | "meta": {
2227 | "classes": {
2228 | "element": "array",
2229 | "content": [
2230 | {
2231 | "element": "string",
2232 | "content": "authSchemes"
2233 | }
2234 | ]
2235 | }
2236 | },
2237 | "content": [
2238 | {
2239 | "element": "OAuth2 Scheme",
2240 | "meta": {
2241 | "id": {
2242 | "element": "string",
2243 | "content": "Custom OAuth2"
2244 | }
2245 | },
2246 | "content": [
2247 | {
2248 | "element": "member",
2249 | "content": {
2250 | "key": {
2251 | "element": "string",
2252 | "content": "scopes"
2253 | },
2254 | "value": {
2255 | "element": "array",
2256 | "content": [
2257 | {
2258 | "element": "string",
2259 | "content": "scope1"
2260 | },
2261 | {
2262 | "element": "string",
2263 | "content": "scope2"
2264 | }
2265 | ]
2266 | }
2267 | }
2268 | },
2269 | {
2270 | "element": "member",
2271 | "content": {
2272 | "key": {
2273 | "element": "string",
2274 | "content": "grantType"
2275 | },
2276 | "value": {
2277 | "element": "string",
2278 | "content": "implicit"
2279 | }
2280 | }
2281 | },
2282 | {
2283 | "element": "transition",
2284 | "attributes": {
2285 | "relation": {
2286 | "element": "string",
2287 | "content": "authorize"
2288 | },
2289 | "href": {
2290 | "element": "string",
2291 | "content": "/authorize"
2292 | }
2293 | }
2294 | },
2295 | {
2296 | "element": "transition",
2297 | "attributes": {
2298 | "relation": {
2299 | "element": "string",
2300 | "content": "token"
2301 | },
2302 | "href": {
2303 | "element": "string",
2304 | "content": "/token"
2305 | }
2306 | }
2307 | }
2308 | ]
2309 | }
2310 | ]
2311 | },
2312 | {
2313 | "element": "resource",
2314 | "attributes": {
2315 | "href": {
2316 | "element": "string",
2317 | "content": "/users"
2318 | }
2319 | },
2320 | "content": [
2321 | {
2322 | "element": "transition",
2323 | "content": [
2324 | {
2325 | "element": "httpTransaction",
2326 | "attributes": {
2327 | "authSchemes": {
2328 | "element": "array",
2329 | "content": [
2330 | {
2331 | "element": "Custom OAuth2",
2332 | "content": [
2333 | {
2334 | "element": "member",
2335 | "content": {
2336 | "key": {
2337 | "element": "string",
2338 | "content": "scopes"
2339 | },
2340 | "value": {
2341 | "element": "array",
2342 | "content": [
2343 | {
2344 | "element": "string",
2345 | "content": "scope1"
2346 | }
2347 | ]
2348 | }
2349 | }
2350 | }
2351 | ]
2352 | }
2353 | ]
2354 | }
2355 | }
2356 | }
2357 | ]
2358 | }
2359 | ]
2360 | }
2361 | ]
2362 | }
2363 | ```
2364 |
2365 | ---
2366 |
2367 | ## Profiles
2368 |
2369 | The primary means by which users can provide semantic definitions and other meta information is through a profile. A profile MAY provide semantic information about an element and its data, it MAY provide specific instructions about elements such as how inheritance should work or how elements should be processed, and it MAY be used to modify understanding of existing elements in other profiles. The usage of a profile is not limited to these uses here, and SHOULD be left up to the profile author to define its use.
2370 |
2371 | To point to a profile, you MAY use the [profile link relation](https://www.ietf.org/rfc/rfc6906.txt) as a meta link in your root element or in any other element. Profile links may also be found outside of the document itself in places like the [HTTP Link Header](http://www.w3.org/wiki/LinkHeader). Additionally, a profile link is not required in order to use the functionality a profile provides, as a media type MAY define the same things a profile.
2372 |
2373 | Below is an example of how a profile link is used as a meta link.
2374 |
2375 | ```json
2376 | {
2377 | "element": "foo",
2378 | "meta": {
2379 | "links": {
2380 | "element": "array",
2381 | "content": [
2382 | {
2383 | "element": "link",
2384 | "attributes": {
2385 | "relation": {
2386 | "element": "string",
2387 | "content": "profile"
2388 | },
2389 | "href": {
2390 | "element": "string",
2391 | "content": "http://example.com/profiles/foo"
2392 | }
2393 | }
2394 | }
2395 | ]
2396 | }
2397 | },
2398 | "content": "bar"
2399 | }
2400 | ```
2401 |
2402 | The example shows a `foo` element with a `profile` link. This profile link informs the parser this particular element is defined as part of the linked profile.
2403 |
2404 | ---
2405 |
2406 |
2407 | ## Extending API Elements
2408 |
2409 | An API Elements document MAY be extended by providing a [profile link](https://www.ietf.org/rfc/rfc6906.txt) that describes how non-specification elements should be handled.
2410 |
2411 | Additionally, an `extension` element is provided as a way to extend API Elements documents to include additional data not expressed by the elements in this specification.
2412 |
2413 | When the `extension` element is used, it SHOULD include a profile link that provides information on how the content and attributes SHOULD be handled. Additionally, the presence of an `extension` element MUST NOT change the meaning of the rest of the API Elements document in which it is found. In other words, a tool SHOULD be able to safely ignore an `extension` element.
2414 |
2415 | For changes that need to make unsafe changes, a custom media type or profile SHOULD be used.
2416 |
2417 | ### Extension
2418 |
2419 | - `element` - `"extension"`
2420 | - `content` (enum) - Custom content of extension element
2421 | - ([String][])
2422 | - ([Number][])
2423 | - ([Boolean][])
2424 | - ([Array][])
2425 | - ([Object][])
2426 |
2427 | ### Example
2428 |
2429 | This `extension` element has a custom content, and the meaning and handling instructions for this content.
2430 |
2431 | ```json
2432 | {
2433 | "element": "extension",
2434 | "meta": {
2435 | "links": {
2436 | "element": "array",
2437 | "content": [
2438 | {
2439 | "element": "link",
2440 | "attributes": {
2441 | "relation": {
2442 | "element": "string",
2443 | "content": "profile"
2444 | },
2445 | "href": {
2446 | "element": "string",
2447 | "content": "http://example.com/extensions/info/"
2448 | }
2449 | }
2450 | }
2451 | ]
2452 | }
2453 | },
2454 | "content": {
2455 | "element": "object",
2456 | "content": [
2457 | {
2458 | "element": "member",
2459 | "content": {
2460 | "key": {
2461 | "element": "string",
2462 | "content": "version"
2463 | },
2464 | "value": {
2465 | "element": "string",
2466 | "content": "1.0"
2467 | }
2468 | }
2469 | }
2470 | ]
2471 | }
2472 | }
2473 | ```
2474 |
2475 | This specific extension adds an object for including information about an API that may be specific to an implementation—in this case, a version number of the API. The URL `http://example.com/extensions/info/` would then provide instructions on the meaning and structure of the `content`.
2476 |
2477 | As a tool comes across this extension element, it would look at the profile URL to see if it understands this particular element. If not, it can ignore it safely, but if so, it can use it as it sees fit.
2478 |
2479 | ---
2480 |
2481 |
2482 | [MSON]: https://github.com/apiaryio/mson
2483 | [MSON Reference]: https://github.com/apiaryio/mson/blob/master/MSON%20Reference.md
2484 |
2485 |
2486 | [RFC 822]: https://datatracker.ietf.org/doc/rfc822/
2487 | [RFC 2119]: https://datatracker.ietf.org/doc/rfc2119/
2488 | [RFC 2616]: https://datatracker.ietf.org/doc/rfc2616/
2489 | [RFC 3986]: https://datatracker.ietf.org/doc/rfc3986/
2490 | [RFC 5988]: http://datatracker.ietf.org/doc/rfc5988/
2491 | [RFC 6570]: https://datatracker.ietf.org/doc/rfc6570/
2492 | [RFC 7230]: http://datatracker.ietf.org/doc/rfc7230/
2493 |
2494 | [Subtype]: #subtypes
2495 | [String]: #string-element
2496 | [Number]: #number-element
2497 | [Boolean]: #boolean-element
2498 | [Array]: #array-element
2499 | [Object]: #object-element
2500 | [Member]: #member-element
2501 | [Href]: #href-string
2502 | [Templated Href]: #templated-href-string
2503 | [Href Variables]: #href-variables-object
2504 | [Data Structure]: #data-structure
2505 | [Copy]: #copy-string
2506 | [Asset]: #asset-string
2507 | [Resource]: #resource
2508 | [Transition]: #transition
2509 | [Category]: #category
2510 | [HTTP Headers]: #http-headers-array-member
2511 | [HTTP Message Payload]: #http-message-payload-array
2512 | [Source Map]: #source-map
2513 |
--------------------------------------------------------------------------------
/docs/examples.md:
--------------------------------------------------------------------------------
1 | # Examples
2 |
3 | ## API Description Formats
4 |
5 | ### API Blueprint Example
6 |
7 | This shows an example of the parse results of an API Blueprint. Here is a very minimal example API Blueprint.
8 |
9 | ```markdown
10 | # My API
11 | ## Foo [/foo]
12 | ```
13 |
14 | When this document is parsed, it returns a serialization of API Elements that looks like the following.
15 |
16 | ```json
17 | {
18 | "element": "parseResult",
19 | "content": [
20 | {
21 | "element": "category",
22 | "meta": {
23 | "classes": {
24 | "element": "array",
25 | "content": [
26 | {
27 | "element": "string",
28 | "content": "api"
29 | }
30 | ]
31 | },
32 | "title": {
33 | "element": "string",
34 | "content": "My API"
35 | }
36 | },
37 | "content": [
38 | {
39 | "element": "category",
40 | "meta": {
41 | "classes": {
42 | "element": "array",
43 | "content": [
44 | {
45 | "element": "string",
46 | "content": "resourceGroup"
47 | }
48 | ]
49 | },
50 | "title": {
51 | "element": "string",
52 | "content": ""
53 | }
54 | },
55 | "content": [
56 | {
57 | "element": "resource",
58 | "meta": {
59 | "title": {
60 | "element": "string",
61 | "content": "Foo"
62 | }
63 | },
64 | "attributes": {
65 | "href": {
66 | "element": "string",
67 | "content": "/foo"
68 | }
69 | },
70 | "content": []
71 | }
72 | ]
73 | }
74 | ]
75 | }
76 | ]
77 | }
78 | ```
79 |
80 | ### Swagger / OpenAPI Format Example
81 |
82 | This shows an example of the parse results of a Swagger document.
83 |
84 | ```json
85 | {
86 | "swagger": "2.0",
87 | "info": {
88 | "title": "My API",
89 | "version": "1.0.0"
90 | },
91 | "paths": {
92 | "/foo": {}
93 | }
94 | }
95 | ```
96 |
97 | When this document is parsed, it returns a serialization of API Elements that looks like:
98 |
99 | ```json
100 | {
101 | "element": "parseResult",
102 | "content": [
103 | {
104 | "element": "category",
105 | "meta": {
106 | "classes": {
107 | "element": "array",
108 | "content": [
109 | {
110 | "element": "string",
111 | "content": "api"
112 | }
113 | ]
114 | },
115 | "title": {
116 | "element": "string",
117 | "content": "My API"
118 | }
119 | },
120 | "content": [
121 | {
122 | "element": "resource",
123 | "attributes": {
124 | "href": {
125 | "element": "string",
126 | "content": "/foo"
127 | }
128 | },
129 | "content": []
130 | }
131 | ]
132 | }
133 | ]
134 | }
135 | ```
136 |
137 | As you can see, Swagger and API Blueprint both convey the same information resulting in almost the same parse results. This shows the importance of querying the results rather than looking for specific paths in the document.
138 |
139 | ## Data Structure
140 |
141 | This section shows what individual and specific data structures look like when converted to API Elements. In the context of an API description or parse results, these structures will be nested within the document.
142 |
143 | If you have an [MSON][] definition like the one below.
144 |
145 | ```markdown
146 | # My List (array)
147 | - 1 (number)
148 | - 2 (number)
149 | - 3 (number)
150 | ```
151 |
152 | When the structure is parsed, it returns a serialization of API Elements that looks like:
153 |
154 | ```json
155 | {
156 | "element": "array",
157 | "meta": {
158 | "id": {
159 | "element": "string",
160 | "content": "My List"
161 | }
162 | },
163 | "content": [
164 | {
165 | "element": "number",
166 | "content": 1
167 | },
168 | {
169 | "element": "number",
170 | "content": 2
171 | },
172 | {
173 | "element": "number",
174 | "content": 3
175 | }
176 | ]
177 | }
178 | ```
179 |
180 | And when it is converted to JSON, it looks like:
181 |
182 | ```json
183 | [1, 2, 3]
184 | ```
185 |
186 | [MSON]: https://github.com/apiaryio/mson
187 |
--------------------------------------------------------------------------------
/docs/extensions/index.rst:
--------------------------------------------------------------------------------
1 | Extensions Registry
2 | ===================
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | oas/index
8 |
--------------------------------------------------------------------------------
/docs/extensions/oas/extensions.rst:
--------------------------------------------------------------------------------
1 | OpenAPI Specification Extensions
2 | ================================
3 |
4 | This document is a profile for storing OpenAPI Specification Extensions within
5 | an API Element extension.
6 |
7 | The contents of an extension element with this profile will contain the
8 | contents of the extensions is an object containing any vendor extensions found in
9 | the underlying Swagger Description document.
10 |
11 | For example, if a vendor extension with the key ``x-sts`` with a value true was
12 | found in an OpenAPI document, it may be represented using the following
13 | extension element::
14 |
15 | {
16 | "element": "extension",
17 | "meta": {
18 | "links": [
19 | {
20 | "element": "link",
21 | "attributes": {
22 | "relation": "profile",
23 | "href": "https://apielements.org/extensions/oas/extensions/"
24 | }
25 | }
26 | ]
27 | },
28 | "content": {
29 | "element": "object",
30 | "content": [
31 | {
32 | "element": "member",
33 | "content": {
34 | "key": {
35 | "element": "string",
36 | "content": "sts"
37 | },
38 | "value": {
39 | "element": "boolean",
40 | "content": true
41 | }
42 | }
43 | }
44 | ]
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/docs/extensions/oas/index.rst:
--------------------------------------------------------------------------------
1 | OpenAPI Specification Extensions
2 | ================================
3 |
4 | .. toctree::
5 | :maxdepth: 1
6 |
7 | extensions
8 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # API Elements
2 |
3 | API Elements is a structure for describing APIs and the complex data structures used within them. It also provides structures for defining parsing results for parsing API definitions from formats like API Blueprint and Swagger/OpenAPI Format.
4 |
5 | ## Getting Started
6 |
7 | To start learning about and using API Elements, please check out the [overview](overview.html), which includes explanations and examples. If you are interested in finding libraries and tools for building and consuming API Elements, you will find this information on the [tools](tools.html) page.
8 |
9 | ## Contributing
10 |
11 | Feel free report problems or propose new ideas using the API Elements GitHub
12 | [issues][]. We are always interested in Pull Requests as well for changes.
13 |
14 | ## About this Documentation
15 |
16 | This documentation conforms to [RFC 2119][], which says:
17 |
18 | > The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”, “RECOMMENDED”, “MAY”, and “OPTIONAL” in this document are to be interpreted as described in RFC 2119.
19 |
20 | [MSON][] is used throughout this document to define elements and structures.
21 |
22 | ## Contents
23 |
24 | ```eval_rst
25 | .. toctree::
26 | :maxdepth: 1
27 |
28 | overview
29 | element-definitions
30 | examples
31 | tools
32 | additional-information
33 | extensions/index
34 | migration
35 | ```
36 |
37 | ## License
38 |
39 | MIT License. See the [LICENSE][] file.
40 |
41 | [RFC 2119]: https://datatracker.ietf.org/doc/rfc2119/
42 | [issues]: https://github.com/apiaryio/api-elements/issues
43 | [MSON]: https://github.com/apiaryio/mson
44 | [LICENSE]: https://github.com/apiaryio/api-elements/blob/master/LICENSE
45 |
--------------------------------------------------------------------------------
/docs/migration.md:
--------------------------------------------------------------------------------
1 | # Migration Guide
2 |
3 | This guide documents all of the changes between API Elements 0.6 and API
4 | Elements 1.0.
5 |
6 | ## JSON Serialisation
7 |
8 | In prior versions of API Elements, an Element (i.e. a type) could be
9 | occasionally serialized as a [value](/element-definitions.html#values). This
10 | behaviour has since been dropped, so that Elements are always serialized in
11 | full form (i.e. as a type, not as a value). For example:
12 |
13 | ```json
14 | {
15 | "element": "null",
16 | "meta": {
17 | "title": "empty"
18 | }
19 | }
20 | ```
21 |
22 | Elements must always be serialised as an element, for example the following
23 | would be valid in API Elements 1.0:
24 |
25 | ```json
26 | {
27 | "element": "null",
28 | "meta": {
29 | "title": {
30 | "element": "string",
31 | "content": "empty"
32 | }
33 | }
34 | }
35 | ```
36 |
37 | In previous versions of API Elements, both forms were valid so this is not a
38 | breaking change. However, we found multiple implementations that were fragile
39 | and could break when different forms were used.
40 |
41 | ## Changes to Elements
42 |
43 | ### Category Element
44 |
45 | The `meta` attribute has been renamed to `metadata` in a [Category
46 | Element](/element-definitions.html#category) for
47 | clarity.
48 |
49 | Before
50 |
51 | ```json
52 | {
53 | "element": "category",
54 | "attributes": {
55 | "meta": {
56 | "element": "array",
57 | "content": [
58 | {
59 | "element": "member",
60 | "content": {
61 | "key": {
62 | "element": "string",
63 | "content": "HOST"
64 | },
65 | "value": {
66 | "element": "string",
67 | "content": "http://polls.apiblueprint.org/"
68 | }
69 | }
70 | }
71 | ]
72 | }
73 | }
74 | }
75 | ```
76 |
77 | After
78 |
79 | ```json
80 | {
81 | "element": "category",
82 | "attributes": {
83 | "metadata": {
84 | "element": "array",
85 | "content": [
86 | {
87 | "element": "member",
88 | "content": {
89 | "key": {
90 | "element": "string",
91 | "content": "HOST"
92 | },
93 | "value": {
94 | "element": "string",
95 | "content": "http://polls.apiblueprint.org/"
96 | }
97 | }
98 | }
99 | ]
100 | }
101 | }
102 | }
103 | ```
104 |
105 | ### Source Map Element
106 |
107 | A [Source Map Element](/element-definitions.html#source-map) may contain an
108 | optional line and column number to make it easier to handle source map
109 | information. Computing the line and column number can often be expensive so it
110 | may be provided by a parser. Note however that it is optional and it is down
111 | the each individual tooling on whether it is present, some tools only provide
112 | line and column number for source maps contained within Annotation Elements.
113 |
114 | ```json
115 | {
116 | "element": "sourceMap",
117 | "content": [
118 | {
119 | "element": "array",
120 | "content": [
121 | {
122 | "element": "number",
123 | "attributes": {
124 | "line": {
125 | "element": "number",
126 | "content": 3
127 | },
128 | "column": {
129 | "element": "number",
130 | "content": 2
131 | }
132 | },
133 | "content": 4
134 | },
135 | {
136 | "element": "number",
137 | "attributes": {
138 | "line": {
139 | "element": "number",
140 | "content": 3
141 | },
142 | "column": {
143 | "element": "number",
144 | "content": 10
145 | }
146 | },
147 | "content": 12
148 | }
149 | ]
150 | }
151 | ]
152 | }
153 | ```
154 |
155 | ### Data Structure Elements
156 |
157 | #### Enumeration Element
158 |
159 | The layout of the [Enum Element](/element-definitions.html#enum-element) has
160 | been altered. The enumerations have been moved to an enumerations attribute of
161 | the element and the content now represents the given value.
162 |
163 | Enumerations themselves are an array of the possible enumerations.
164 |
165 | Before
166 |
167 | ```json
168 | {
169 | "element": "enum",
170 | "content": [
171 | {
172 | "element": "string",
173 | "content": "north"
174 | },
175 | {
176 | "element": "string",
177 | "content": "east"
178 | },
179 | {
180 | "element": "string",
181 | "content": "south"
182 | },
183 | {
184 | "element": "string",
185 | "content": "west"
186 | }
187 | ]
188 | }
189 | ```
190 |
191 | After
192 |
193 | ```json
194 | {
195 | "element": "enum",
196 | "attributes": {
197 | "enumerations": {
198 | "element": "array",
199 | "content": [
200 | {
201 | "element": "string",
202 | "content": "north"
203 | },
204 | {
205 | "element": "string",
206 | "content": "east"
207 | },
208 | {
209 | "element": "string",
210 | "content": "south"
211 | },
212 | {
213 | "element": "string",
214 | "content": "west"
215 | }
216 | ]
217 | }
218 | }
219 | }
220 | ```
221 |
222 | The intent of the structure was that it represents an enumeration of `north`,
223 | `east`, `south` and `west`. As the enumerations do not include a `fixed` type
224 | attribute it represents an enumeration where any string is valid and not just
225 | the fixed values. This created a limitation that tooling cannot determine the
226 | difference between one of the fixed element enumerations, or a type with a
227 | value. Thus, when the values are fixed they will now include a `fixed` type
228 | attribute as follows:
229 |
230 | ```json
231 | {
232 | "element": "enum",
233 | "attributes": {
234 | "enumerations": {
235 | "element": "array",
236 | "content": [
237 | {
238 | "element": "string",
239 | "attributes": {
240 | "typeAttributes": {
241 | "element": "array",
242 | "content": [
243 | {
244 | "element": "string",
245 | "content": "fixed"
246 | }
247 | ]
248 | }
249 | },
250 | "content": "north"
251 | },
252 | {
253 | "element": "string",
254 | "attributes": {
255 | "typeAttributes": {
256 | "element": "array",
257 | "content": [
258 | {
259 | "element": "string",
260 | "content": "fixed"
261 | }
262 | ]
263 | }
264 | },
265 | "content": "east"
266 | },
267 | {
268 | "element": "string",
269 | "attributes": {
270 | "typeAttributes": {
271 | "element": "array",
272 | "content": [
273 | {
274 | "element": "string",
275 | "content": "fixed"
276 | }
277 | ]
278 | }
279 | },
280 | "content": "south"
281 | },
282 | {
283 | "element": "string",
284 | "attributes": {
285 | "typeAttributes": {
286 | "element": "array",
287 | "content": [
288 | {
289 | "element": "string",
290 | "content": "fixed"
291 | }
292 | ]
293 | }
294 | },
295 | "content": "west"
296 | }
297 | ]
298 | }
299 | }
300 | }
301 | ```
302 |
--------------------------------------------------------------------------------
/docs/overview.md:
--------------------------------------------------------------------------------
1 | # API Elements Overview
2 |
3 | **Version**: 1.0.0-rc1
4 |
5 | **Mime Type**: TBD
6 |
7 | ## About API Elements
8 |
9 | The purpose of API Elements is to provide a single, unifying structure for describing APIs across all API description formats and serialization formats. There currently exists several formats one can choose when defining an API, from API Blueprint to Swagger—which is now known as the OpenAPI Format. There are also many serialization formats such as XML or JSON. Without a way to parse these formats to the same structure, developers are required to handle each format one-by-one, each in a different way and each translating to their internal domain model. This is tedious, time-consuming, and requires each maintainer to stay in step with every format they support.
10 |
11 | API Elements solves this complex problem in a simple way. It allows parsers to parse to a single structure and allows tool builders to consume one structure for all formats.
12 |
13 | If there is one thing API description formats have taught us, it is that a single contract provides the best and fastest way to design and iterate on an API. Developers building the API can move independently as they progress towards the defined contract found in the API Blueprint or Swagger document. Conversely, API consumers can build tools for consuming the API based on the API definition document.
14 |
15 | This same pattern has proven to be just as valuable for building API description formats and tooling. API Elements is the contract for producing and consuming the many description and serialization formats and allows everyone to move quickly and independently.
16 |
17 | ## What is an Element?
18 |
19 | API Elements is made up of many small elements that have a rich semantic meaning given their value and context. An element is an individual piece that makes up an API, and can range from defining a resource to providing an example of an HTTP request.
20 |
21 | The API Elements project defines elements used for:
22 |
23 | 1. Describing an API
24 | 1. Describing data structures used within that API
25 | 1. Describing parse results when parsing API-related documents
26 |
27 | These elements also seek to provide a way to decouple APIs and their semantics from the implementation details.
28 |
29 | ## Relationship of Elements
30 |
31 | One purpose of the API Elements reference is to allow consumers to decouple their implementations from the structure of the document. Because of this, when consuming documents of API Elements, it is recommended to write code that queries the tree rather than looking for defined paths.
32 |
33 | It is also helpful to know the relationship between elements. The list below shows the relationship between the elements in this reference, but does not specify how the structure must be built.
34 |
35 | - Category (API)
36 | - Copy
37 | - Data Structure
38 | - Category (Group of Resource Elements)
39 | - Category (Group of Authentication and Authorization Scheme Definitions)
40 | - Category (Group of Resource Elements representing hosts)
41 | - Resource
42 | - Copy
43 | - Data Structure
44 | - Category (Group of Transition Elements)
45 | - Transition
46 | - Copy
47 | - HTTP Transaction
48 | - Copy
49 | - HTTP Request
50 | - Copy
51 | - Data Structure
52 | - Asset
53 | - HTTP Response
54 | - Copy
55 | - Data Structure
56 | - Asset
57 |
58 | This main API Category element MAY also be wrapped in a Parse Result element for conveying parsing information, such as source maps, warnings, and errors.
59 |
60 | ## Basic Element
61 |
62 | Every element defined with API Elements has four primary pieces of data.
63 |
64 | - `element` (string) - defines the type of element used
65 | - `meta` (object) - an object that includes metadata about the element
66 | - `attributes` (object) - user-specified attributes for a given element
67 | - `content` - value of the element based on its type
68 |
69 | This structure defined in detail in the [Element Definitions](./element-definitions.html) document.
70 |
71 | Here is an example of what an Element MAY look like serialized into JSON.
72 |
73 | ```json
74 | {
75 | "element": "string",
76 | "meta": {
77 | "id": {
78 | "element": "string",
79 | "content": "foo"
80 | },
81 | "title": {
82 | "element": "string",
83 | "content": "Foo"
84 | },
85 | "description": {
86 | "element": "string",
87 | "content": "My foo element"
88 | }
89 | },
90 | "content": "bar"
91 | }
92 | ```
93 |
94 | Additional examples are provided throughout this documentation for specific API Elements. As this shows, though, it allows for API Elements to not only define data, but also metadata as well. This is especially important when providing source maps and adding human readable titles to values.
95 |
96 | ## Consuming Documents
97 |
98 | As mentioned, for consumers, it is important to not couple code to the specific structure of an API Elements document. The common pitfall is to reference elements by specifying a specific and strict path to those elements, but it is recommended to try to avoid this for sake of evolvability and safety.
99 |
100 | For example, to get the first HTTP Transaction element from an API Elements tree.
101 |
102 | Relying on a fixed tree structure:
103 |
104 | ```js
105 | const transaction = apielements.content[0].content[0].content[0].content[0].content[0]
106 | ```
107 |
108 | Querying the tree in a way that does not use a strict path:
109 |
110 | ```js
111 | import query from 'refract-query';
112 | const transaction = query(apielements, {element: 'httpTransaction'})[0];
113 | ```
114 |
115 | The structure of an API Elements document is recursive by nature. When looking for specific elements, it is best to walk the API Elements tree to look for a match. Querying the API Elements tree will decouple your code from specific API description syntax. Also, it decouples your code from the specific structure of these documents as long as they are semantically equivalent.
116 |
117 | [MSON]: https://github.com/apiaryio/mson
118 | [RFC 2119]: https://datatracker.ietf.org/doc/rfc2119/
119 |
--------------------------------------------------------------------------------
/docs/tools.md:
--------------------------------------------------------------------------------
1 | # Tooling
2 |
3 | There are various API Elements tools available to interact and parse API
4 | Description Documents.
5 |
6 | ## [API Description Parsing Service](http://docs.apiblueprintapi.apiary.io/#reference)
7 |
8 | API Description Parsing Serice (formerly API Bluerpint API) is a hosted service
9 | that takes API Description documents such as API Blueprint or Swagger 2.0 as
10 | input and returns API Elements.
11 |
12 | ## JavaScript
13 |
14 | ### [Fury](https://github.com/apiaryio/fury.js)
15 |
16 | Fury is a library for validating and parsing API description documents, Furys
17 | API provides [API Element JS](https://api-elements-js.readthedocs.io/) objects.
18 |
19 | ### [API Element JS](https://api-elements-js.readthedocs.io/)
20 |
21 | The API Elements JS Package provides an interface for querying and interacting
22 | with API Elements. This library can be used in conjunction with Fury to handle
23 | parsing of API Description documents into API Elements.
24 |
25 | ## Python
26 |
27 | ### [refract.py](https://github.com/kylef/refract.py)
28 |
29 | A Python library for interacting with Refract and API Elements in Python.
30 |
31 | ---
32 |
33 | ## API Blueprint
34 |
35 | The API Blueprint ecosystem heavily uses API Elements under the hood. Although
36 | we would recommend interacting with API Elements using the JavaScript tooling
37 | above as it is generic and not API Blueprint specific.
38 |
39 | ### [Drafter](https://github.com/apiaryio/drafter)
40 |
41 | Drafter is a library for parsing API Blueprint documents and return parse results in API Elements.
42 |
43 | ### [Drafter JS](https://github.com/apiaryio/drafter-npm)
44 |
45 | Drafter JS is a JavaScript interface to Drafter and can be used in Node.JS or natively in a browser.
46 |
--------------------------------------------------------------------------------
/element-schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "oneOf": [
3 | { "$ref": "#/definitions/element" }
4 | ],
5 | "definitions": {
6 | "element": {
7 | "title": "Element",
8 | "type": "object",
9 | "properties": {
10 | "element": {
11 | "type": "string"
12 | },
13 | "meta": {
14 | "type": "object",
15 | "properties": {
16 | "id": { "$ref": "#/definitions/element" },
17 | "title": { "$ref": "#/definitions/string-element" },
18 | "description": { "$ref": "#/definitions/string-element" },
19 | "ref": { "$ref": "#/definitions/ref-element" },
20 | "classes": { "$ref": "#/definitions/array-string-element" },
21 | "links": { "$ref": "#/definitions/array-link-element" }
22 | },
23 | "additionalProperties": false
24 | },
25 | "attributes": {
26 | "type": "object",
27 | "patternProperties": {
28 | "": {
29 | "$ref": "#/definitions/element"
30 | }
31 | }
32 | },
33 | "content": {
34 | "oneOf": [
35 | {
36 | "type": [
37 | "string",
38 | "number",
39 | "boolean",
40 | "null",
41 | "array"
42 | ],
43 | "items": {
44 | "$ref": "#/definitions/element"
45 | }
46 | },
47 | {
48 | "$ref": "#/definitions/element"
49 | },
50 | {
51 | "$ref": "#/definitions/key-value-pair"
52 | }
53 | ]
54 | }
55 | },
56 | "required": [
57 | "element"
58 | ],
59 | "additionalProperties": false
60 | },
61 | "key-value-pair": {
62 | "title": "Key Value Pair",
63 | "type": "object",
64 | "properties": {
65 | "key": {
66 | "$ref": "#/definitions/element"
67 | },
68 | "value": {
69 | "$ref": "#/definitions/element"
70 | }
71 | },
72 | "required": ["key"],
73 | "additionalProperties": false
74 | },
75 | "string-element": {
76 | "title": "String Element",
77 | "allOf": [
78 | { "$ref": "#/definitions/element" },
79 | {
80 | "properties": {
81 | "element": {
82 | "enum": ["string"]
83 | },
84 | "content": {
85 | "type": ["string"]
86 | }
87 | }
88 | }
89 | ]
90 | },
91 | "array-element": {
92 | "title": "Array Element",
93 | "allOf": [
94 | { "$ref": "#/definitions/element" },
95 | {
96 | "properties": {
97 | "element": {
98 | "enum": ["array"]
99 | },
100 | "content": {
101 | "type": ["array"]
102 | }
103 | }
104 | }
105 | ]
106 | },
107 | "array-string-element": {
108 | "title": "Array Element of String Element",
109 | "allOf": [
110 | { "$ref": "#/definitions/array-element" },
111 | {
112 | "properties": {
113 | "content": {
114 | "items": { "$ref": "#/definitions/string-element" }
115 | }
116 | }
117 | }
118 | ]
119 | },
120 | "link-element": {
121 | "title": "Link Element",
122 | "allOf": [
123 | { "$ref": "#/definitions/element" },
124 | {
125 | "properties": {
126 | "element": {
127 | "enum": ["link"]
128 | }
129 | }
130 | }
131 | ]
132 | },
133 | "array-link-element": {
134 | "title": "Array Element of Link Element",
135 | "allOf": [
136 | { "$ref": "#/definitions/array-element" },
137 | {
138 | "properties": {
139 | "content": {
140 | "items": { "$ref": "#/definitions/link-element" }
141 | }
142 | }
143 | }
144 | ]
145 | },
146 | "ref-element": {
147 | "title": "Reference Element",
148 | "allOf": [
149 | { "$ref": "#/definitions/element" },
150 | {
151 | "properties": {
152 | "element": {
153 | "enum": ["ref"]
154 | },
155 | "content": {
156 | "type": ["string"]
157 | },
158 | "attributes": {
159 | "properties": {
160 | "path": {
161 | "allOf": [
162 | { "$ref": "#/definitions/string-element" },
163 | {
164 | "properties": {
165 | "content": {
166 | "enum": ["element", "meta", "attributes", "content"]
167 | }
168 | }
169 | }
170 | ]
171 | }
172 | }
173 | }
174 | },
175 | "required": ["content"]
176 | }
177 | ]
178 | }
179 | }
180 | }
181 |
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | -i https://pypi.org/simple
2 | alabaster==0.7.12
3 | argh==0.26.2
4 | babel==2.6.0
5 | certifi==2018.11.29
6 | chardet==3.0.4
7 | commonmark==0.8.1
8 | docutils==0.14
9 | future==0.17.1
10 | idna==2.8
11 | imagesize==1.1.0
12 | jinja2==2.10
13 | livereload==2.6.0
14 | markupsafe==1.1.0
15 | packaging==19.0
16 | pathtools==0.1.2
17 | port-for==0.3.1
18 | pygments-apiblueprint==0.1.0
19 | pygments-markdown-lexer==0.1.0.dev39
20 | pygments==2.3.1
21 | pyparsing==2.3.1
22 | pytz==2018.9
23 | pyyaml==4.2b4
24 | recommonmark==0.5.0
25 | requests==2.21.0
26 | six==1.12.0
27 | snowballstemmer==1.2.1
28 | sphinx-autobuild==0.7.1
29 | sphinx-rtd-theme==0.4.2
30 | sphinx==1.8.3
31 | sphinxcontrib-websupport==1.1.0
32 | tornado==6.0a1
33 | urllib3==1.24.1
34 | watchdog==0.9.0
35 |
--------------------------------------------------------------------------------
/test/test_markdown.py:
--------------------------------------------------------------------------------
1 | import sys
2 | import warnings
3 | import json
4 |
5 | import pytest
6 | from jsonschema import validate
7 | import commonmark
8 |
9 |
10 | parser = commonmark.Parser()
11 |
12 |
13 | with open('element-schema.json') as fp:
14 | SCHEMA = json.load(fp)
15 |
16 |
17 | def test_markdown(markdown_file):
18 | if markdown_file.samefile('docs/migration.md'):
19 | pytest.skip('migration.md intentionally contains invalid API Elements')
20 |
21 | with open(markdown_file) as fp:
22 | ast = parser.parse(fp.read())
23 |
24 | for node, _ in ast.walker():
25 | try:
26 | if node.t == 'code_block' and node.info == 'json':
27 | element = json.loads(node.literal)
28 |
29 | if isinstance(element, dict) and 'element' in element:
30 | validate(instance=element, schema=SCHEMA)
31 | except:
32 | warnings.warn('line {}, column: {}'.format(*node.sourcepos[0]))
33 | raise
34 |
--------------------------------------------------------------------------------