├── .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 |

API Elements

2 | 3 |

4 | 8 |

9 | 10 |

API Elements is a structure for describing APIs and the complex data structures used within them.

11 | 12 |
13 |

14 | 18 |

19 |
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 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 123 | 124 | 125 | 126 | 127 | 132 | 136 | 137 | 138 | 139 | 144 | 149 | 150 | 151 | 152 | 157 | 161 | 162 | 163 | 164 | 165 | 166 | 171 | 175 | 176 | 177 | 178 | 192 | 197 | 198 | 199 | 200 | 205 | 214 | 215 | 216 | 217 | 235 | 241 | 242 | 243 | 244 | 263 | 269 | 270 | 271 | 272 | 325 | 339 | 340 | 341 | 342 | 343 | 344 | 362 | 367 | 368 | 369 |
NameType (JSON serialized)Value (JSON serialized)
null 119 |
{
 120 |   "element": "null"
 121 | }
122 |
null
boolean 128 |
{
 129 |   "element": "boolean"
 130 | }
131 |
133 |
true
134 |
false
135 |
number 140 |
{
 141 |   "element": "number"
 142 | }
143 |
145 |
0
146 |
-1.5
147 |
6.53e-3
148 |
string 153 |
{
 154 |   "element": "string"
 155 | }
156 |
158 |
"Hello world"
159 |
""
160 |
array 167 |
{
 168 |   "element": "array"
 169 | }
170 |
172 |
[]
173 |
[42, "Hello world!"]
174 |
member 179 |
{
 180 |   "element": "member",
 181 |   "content": {
 182 |     "key": {
 183 |       "element": "string",
 184 |       "content": "foo"
 185 |     },
 186 |     "value": {
 187 |       "element": "string"
 188 |     }
 189 |   }
 190 | }
191 |
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 |
object 201 |
{
 202 |   "element": "object"
 203 | }
204 |
206 |
{}
207 |
{
 208 |   "foo": "Hey!"
 209 | }
210 |
{
 211 |   "bar": true
 212 | }
213 |
enum 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 |
236 |
-45.9
237 |
"Hello world!"
238 |
""
239 |
0
240 |
select & option 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 |
264 |
-45.9
265 |
"Hello world!"
266 |
""
267 |
0
268 |
extend 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 |
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 |
ref 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 |
363 |
""
364 |
"abc"
365 |
"Hello world!"
366 |
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 | --------------------------------------------------------------------------------