├── .editorconfig ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .prettier.rc.js ├── .travis.yml ├── CHANGELOG.md ├── CODE_OF_CONDUCT.md ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── Vagrantfile ├── config.rb ├── deploy.sh ├── font-selection.json ├── lib ├── multilang.rb ├── nesting_unique_head.rb ├── toc_data.rb └── unique_head.rb ├── package-lock.json ├── package.json ├── patches └── widdershins+4.0.1.patch ├── source ├── fonts │ ├── AvenirNextLTPro-Bold.otf │ ├── AvenirNextLTPro-Bold.ttf │ ├── AvenirNextLTPro-Demi-Bold.otf │ ├── AvenirNextLTPro-Demi-Bold.ttf │ ├── AvenirNextLTPro-Heavy.otf │ ├── AvenirNextLTPro-Heavy.ttf │ ├── AvenirNextLTPro-Medium.otf │ ├── AvenirNextLTPro-Medium.ttf │ ├── AvenirNextLTPro-Regular.otf │ ├── AvenirNextLTPro-Regular.ttf │ ├── AvenirNextLTPro-UltLt.otf │ ├── AvenirNextLTPro-UltLt.ttf │ ├── slate.eot │ ├── slate.svg │ ├── slate.ttf │ ├── slate.woff │ └── slate.woff2 ├── images │ ├── logo.png │ ├── navbar.png │ └── og.jpg ├── includes │ ├── _docs.md │ └── _errors.md ├── index.html.md ├── javascripts │ ├── all.js │ ├── all_nosearch.js │ ├── app │ │ ├── _lang.js │ │ ├── _search.js │ │ └── _toc.js │ └── lib │ │ ├── _energize.js │ │ ├── _imagesloaded.min.js │ │ ├── _jquery.highlight.js │ │ ├── _jquery.js │ │ └── _lunr.js ├── layouts │ └── layout.erb └── stylesheets │ ├── _icon-font.scss │ ├── _normalize.scss │ ├── _rtl.scss │ ├── _variables.scss │ ├── print.css.scss │ └── screen.css.scss └── swagger ├── examples ├── playlists.search.json ├── playlists.trending.json ├── playlists.{playlist_id}.json ├── playlists.{playlist_id}.tracks.json ├── resolve.json ├── tips.json ├── tracks.json ├── tracks.search.json ├── tracks.trending.json ├── tracks.trending.underground.json ├── tracks.{track_id}.json ├── users.handle.{handle}.json ├── users.handle.{handle}.tracks.ai_attributed.json ├── users.id.json ├── users.search.json ├── users.verify_token.json ├── users.{id}.connected_wallets.json ├── users.{id}.favorites.json ├── users.{id}.followers.json ├── users.{id}.following.json ├── users.{id}.json ├── users.{id}.related.json ├── users.{id}.reposts.json ├── users.{id}.subscribers.json ├── users.{id}.supporters.json ├── users.{id}.supporting.json ├── users.{id}.tags.json └── users.{id}.tracks.json ├── generateExamples.js ├── helpers.js ├── index.js ├── swagger.json ├── swaggerModifiers.js └── templates ├── README.md ├── authentication.def ├── authentication_none.def ├── callbacks.def ├── code_csharp.dot ├── code_go.dot ├── code_http.dot ├── code_java.dot ├── code_javascript.dot ├── code_jquery.dot ├── code_nodejs.dot ├── code_php.dot ├── code_python.dot ├── code_ruby.dot ├── code_shell.dot ├── debug.def ├── discovery.def ├── footer.def ├── links.def ├── main.dot ├── operation.dot ├── parameters.def ├── responses.def ├── security.def └── translations.dot /.editorconfig: -------------------------------------------------------------------------------- 1 | # EditorConfig is awesome: http://EditorConfig.org 2 | 3 | # Top-most EditorConfig file 4 | root = true 5 | 6 | # Unix-style newlines with a newline ending every file 7 | [*] 8 | end_of_line = lf 9 | insert_final_newline = true 10 | indent_style = space 11 | indent_size = 2 12 | trim_trailing_whitespace = true 13 | 14 | [*.rb] 15 | charset = utf-8 16 | 17 | [*.md] 18 | trim_trailing_whitespace = false 19 | 20 | [*.js] 21 | indent_size = 2 -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | env: { 3 | node: true 4 | }, 5 | extends: ['prettier-standard', 'standard', 'prettier'], 6 | parserOptions: { 7 | ecmaVersion: 2018 8 | }, 9 | plugins: ['prettier'], 10 | rules: { 11 | semi: ['error', 'never'], 12 | 'no-undef': 'off', 13 | 'no-empty': 'off', 14 | 'arrow-parens': 'off', 15 | 'padded-blocks': 'off', 16 | 'space-before-function-paren': 'off', 17 | 18 | 'prettier/prettier': 'error' 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | Operating system: ✍️ TODO 12 | Last upstream commit (run `git log --author="Robert Lord" | head -n 1`): ✍️ TODO 13 | Browser version(s): ✍️ TODO 14 | Ruby version (run `ruby -v`): ✍️ TODO 15 | 16 | --- 17 | 18 | ✍️ TODO write your issue here 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.gem 2 | *.rbc 3 | .bundle 4 | .config 5 | coverage 6 | InstalledFiles 7 | lib/bundler/man 8 | pkg 9 | rdoc 10 | spec/reports 11 | test/tmp 12 | test/version_tmp 13 | tmp 14 | *.DS_STORE 15 | build/ 16 | .cache 17 | .vagrant 18 | .sass-cache 19 | 20 | # YARD artifacts 21 | .yardoc 22 | _yardoc 23 | doc/ 24 | .idea/ 25 | 26 | 27 | # NODE 28 | node_modules/ -------------------------------------------------------------------------------- /.prettier.rc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | ...require("prettier-config-standard"), 3 | jsxBracketSameLine: false, 4 | jsxSingleQuote: true, 5 | }; 6 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: ruby 4 | 5 | rvm: 6 | - 2.3.3 7 | - 2.4.0 8 | 9 | cache: bundler 10 | script: bundle exec middleman build 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | ## Version 2.3.1 4 | 5 | *July 5, 2018* 6 | 7 | - Update `sprockets` in `Gemfile.lock` to fix security warnings 8 | 9 | ## Version 2.3 10 | 11 | *July 5, 2018* 12 | 13 | - Allows strikethrough in markdown by default. 14 | - Upgrades jQuery to 3.2.1, thanks to [Tomi Takussaari](https://github.com/TomiTakussaari) 15 | - Fixes invalid HTML in `layout.erb`, thanks to [Eric Scouten](https://github.com/scouten) for pointing out 16 | - Hopefully fixes Vagrant memory issues, thanks to [Petter Blomberg](https://github.com/p-blomberg) for the suggestion 17 | - Cleans HTML in headers before setting `document.title`, thanks to [Dan Levy](https://github.com/justsml) 18 | - Allows trailing whitespace in markdown files, thanks to [Samuel Cousin](https://github.com/kuzyn) 19 | - Fixes pushState/replaceState problems with scrolling not changing the document hash, thanks to [Andrey Fedorov](https://github.com/anfedorov) 20 | - Removes some outdated examples, thanks [@al-tr](https://github.com/al-tr), [Jerome Dahdah](https://github.com/jdahdah), and [Ricardo Castro](https://github.com/mccricardo) 21 | - Fixes `nav-padding` bug, thanks [Jerome Dahdah](https://github.com/jdahdah) 22 | - Code style fixes thanks to [Sebastian Zaremba](https://github.com/vassyz) 23 | - Nokogiri version bump thanks to [Grey Baker](https://github.com/greysteil) 24 | - Fix to default `index.md` text thanks to [Nick Busey](https://github.com/NickBusey) 25 | 26 | Thanks to everyone who contributed to this release! 27 | 28 | ## Version 2.2 29 | 30 | *January 19, 2018* 31 | 32 | - Fixes bugs with some non-roman languages not generating unique headers 33 | - Adds editorconfig, thanks to [Jay Thomas](https://github.com/jaythomas) 34 | - Adds optional `NestingUniqueHeadCounter`, thanks to [Vladimir Morozov](https://github.com/greenhost87) 35 | - Small fixes to typos and language, thx [Emir Ribić](https://github.com/ribice), [Gregor Martynus](https://github.com/gr2m), and [Martius](https://github.com/martiuslim)! 36 | - Adds links to Spectrum chat for questions in README and ISSUE_TEMPLATE 37 | 38 | ## Version 2.1 39 | 40 | *October 30, 2017* 41 | 42 | - Right-to-left text stylesheet option, thanks to [Mohammad Hossein Rabiee](https://github.com/mhrabiee) 43 | - Fix for HTML5 history state bug, thanks to [Zach Toolson](https://github.com/ztoolson) 44 | - Small styling changes, typo fixes, small bug fixes from [Marian Friedmann](https://github.com/rnarian), [Ben Wilhelm](https://github.com/benwilhelm), [Fouad Matin](https://github.com/fouad), [Nicolas Bonduel](https://github.com/NicolasBonduel), [Christian Oliff](https://github.com/coliff) 45 | 46 | Thanks to everyone who submitted PRs for this version! 47 | 48 | ## Version 2.0 49 | 50 | *July 17, 2017* 51 | 52 | - All-new statically generated table of contents 53 | - Should be much faster loading and scrolling for large pages 54 | - Smaller Javascript file sizes 55 | - Avoids the problem with the last link in the ToC not ever highlighting if the section was shorter than the page 56 | - Fixes control-click not opening in a new page 57 | - Automatically updates the HTML title as you scroll 58 | - Updated design 59 | - New default colors! 60 | - New spacings and sizes! 61 | - System-default typefaces, just like GitHub 62 | - Added search input delay on large corpuses to reduce lag 63 | - We even bumped the major version cause hey, why not? 64 | - Various small bug fixes 65 | 66 | Thanks to everyone who helped debug or wrote code for this version! It was a serious community effort, and I couldn't have done it alone. 67 | 68 | ## Version 1.5 69 | 70 | *February 23, 2017* 71 | 72 | - Add [multiple tabs per programming language](https://github.com/lord/slate/wiki/Multiple-language-tabs-per-programming-language) feature 73 | - Upgrade Middleman to add Ruby 1.4.0 compatibility 74 | - Switch default code highlighting color scheme to better highlight JSON 75 | - Various small typo and bug fixes 76 | 77 | ## Version 1.4 78 | 79 | *November 24, 2016* 80 | 81 | - Upgrade Middleman and Rouge gems, should hopefully solve a number of bugs 82 | - Update some links in README 83 | - Fix broken Vagrant startup script 84 | - Fix some problems with deploy.sh help message 85 | - Fix bug with language tabs not hiding properly if no error 86 | - Add `!default` to SASS variables 87 | - Fix bug with logo margin 88 | - Bump tested Ruby versions in .travis.yml 89 | 90 | ## Version 1.3.3 91 | 92 | *June 11, 2016* 93 | 94 | Documentation and example changes. 95 | 96 | ## Version 1.3.2 97 | 98 | *February 3, 2016* 99 | 100 | A small bugfix for slightly incorrect background colors on code samples in some cases. 101 | 102 | ## Version 1.3.1 103 | 104 | *January 31, 2016* 105 | 106 | A small bugfix for incorrect whitespace in code blocks. 107 | 108 | ## Version 1.3 109 | 110 | *January 27, 2016* 111 | 112 | We've upgraded Middleman and a number of other dependencies, which should fix quite a few bugs. 113 | 114 | Instead of `rake build` and `rake deploy`, you should now run `bundle exec middleman build --clean` to build your server, and `./deploy.sh` to deploy it to Github Pages. 115 | 116 | ## Version 1.2 117 | 118 | *June 20, 2015* 119 | 120 | **Fixes:** 121 | 122 | - Remove crash on invalid languages 123 | - Update Tocify to scroll to the highlighted header in the Table of Contents 124 | - Fix variable leak and update search algorithms 125 | - Update Python examples to be valid Python 126 | - Update gems 127 | - More misc. bugfixes of Javascript errors 128 | - Add Dockerfile 129 | - Remove unused gems 130 | - Optimize images, fonts, and generated asset files 131 | - Add chinese font support 132 | - Remove RedCarpet header ID patch 133 | - Update language tabs to not disturb existing query strings 134 | 135 | ## Version 1.1 136 | 137 | *July 27, 2014* 138 | 139 | **Fixes:** 140 | 141 | - Finally, a fix for the redcarpet upgrade bug 142 | 143 | ## Version 1.0 144 | 145 | *July 2, 2014* 146 | 147 | [View Issues](https://github.com/tripit/slate/issues?milestone=1&state=closed) 148 | 149 | **Features:** 150 | 151 | - Responsive designs for phones and tablets 152 | - Started tagging versions 153 | 154 | **Fixes:** 155 | 156 | - Fixed 'unrecognized expression' error 157 | - Fixed #undefined hash bug 158 | - Fixed bug where the current language tab would be unselected 159 | - Fixed bug where tocify wouldn't highlight the current section while searching 160 | - Fixed bug where ids of header tags would have special characters that caused problems 161 | - Updated layout so that pages with disabled search wouldn't load search.js 162 | - Cleaned up Javascript 163 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation. 6 | 7 | ## Our Standards 8 | 9 | Examples of behavior that contributes to creating a positive environment include: 10 | 11 | * Using welcoming and inclusive language 12 | * Being respectful of differing viewpoints and experiences 13 | * Gracefully accepting constructive criticism 14 | * Focusing on what is best for the community 15 | * Showing empathy towards other community members 16 | 17 | Examples of unacceptable behavior by participants include: 18 | 19 | * The use of sexualized language or imagery and unwelcome sexual attention or advances 20 | * Trolling, insulting/derogatory comments, and personal or political attacks 21 | * Public or private harassment 22 | * Publishing others' private information, such as a physical or electronic address, without explicit permission 23 | * Other conduct which could reasonably be considered inappropriate in a professional setting 24 | 25 | ## Our Responsibilities 26 | 27 | Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior. 28 | 29 | Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful. 30 | 31 | ## Scope 32 | 33 | This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers. 34 | 35 | ## Enforcement 36 | 37 | Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at hello@lord.io. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately. 38 | 39 | Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership. 40 | 41 | ## Attribution 42 | 43 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version] 44 | 45 | [homepage]: http://contributor-covenant.org 46 | [version]: http://contributor-covenant.org/version/1/4/ 47 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | ruby '>=2.3.1' 2 | source 'https://rubygems.org' 3 | 4 | # Middleman 5 | gem 'middleman', '~>4.2.1' 6 | gem 'middleman-syntax', '~> 3.0.0' 7 | gem 'middleman-autoprefixer', '~> 2.7.0' 8 | gem 'middleman-sprockets', '~> 4.1.0' 9 | gem 'rouge', '~> 2.0.5' 10 | gem 'redcarpet', '~> 3.4.0' 11 | gem 'nokogiri', '~> 1.8.2' 12 | -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (5.0.1) 5 | concurrent-ruby (~> 1.0, >= 1.0.2) 6 | i18n (~> 0.7) 7 | minitest (~> 5.1) 8 | tzinfo (~> 1.1) 9 | addressable (2.5.0) 10 | public_suffix (~> 2.0, >= 2.0.2) 11 | autoprefixer-rails (6.6.1) 12 | execjs 13 | backports (3.6.8) 14 | coffee-script (2.4.1) 15 | coffee-script-source 16 | execjs 17 | coffee-script-source (1.12.2) 18 | compass-import-once (1.0.5) 19 | sass (>= 3.2, < 3.5) 20 | concurrent-ruby (1.0.5) 21 | contracts (0.13.0) 22 | dotenv (2.2.0) 23 | erubis (2.7.0) 24 | execjs (2.7.0) 25 | fast_blank (1.0.0) 26 | fastimage (2.0.1) 27 | addressable (~> 2) 28 | ffi (1.15.5) 29 | haml (4.0.7) 30 | tilt 31 | hamster (3.0.0) 32 | concurrent-ruby (~> 1.0) 33 | hashie (3.5.1) 34 | i18n (0.7.0) 35 | kramdown (1.13.2) 36 | listen (3.0.8) 37 | rb-fsevent (~> 0.9, >= 0.9.4) 38 | rb-inotify (~> 0.9, >= 0.9.7) 39 | memoist (0.15.0) 40 | middleman (4.2.1) 41 | coffee-script (~> 2.2) 42 | compass-import-once (= 1.0.5) 43 | haml (>= 4.0.5) 44 | kramdown (~> 1.2) 45 | middleman-cli (= 4.2.1) 46 | middleman-core (= 4.2.1) 47 | sass (>= 3.4.0, < 4.0) 48 | middleman-autoprefixer (2.7.1) 49 | autoprefixer-rails (>= 6.5.2, < 7.0.0) 50 | middleman-core (>= 3.3.3) 51 | middleman-cli (4.2.1) 52 | thor (>= 0.17.0, < 2.0) 53 | middleman-core (4.2.1) 54 | activesupport (>= 4.2, < 5.1) 55 | addressable (~> 2.3) 56 | backports (~> 3.6) 57 | bundler (~> 1.1) 58 | contracts (~> 0.13.0) 59 | dotenv 60 | erubis 61 | execjs (~> 2.0) 62 | fast_blank 63 | fastimage (~> 2.0) 64 | hamster (~> 3.0) 65 | hashie (~> 3.4) 66 | i18n (~> 0.7.0) 67 | listen (~> 3.0.0) 68 | memoist (~> 0.14) 69 | padrino-helpers (~> 0.13.0) 70 | parallel 71 | rack (>= 1.4.5, < 3) 72 | sass (>= 3.4) 73 | servolux 74 | tilt (~> 2.0) 75 | uglifier (~> 3.0) 76 | middleman-sprockets (4.1.0) 77 | middleman-core (~> 4.0) 78 | sprockets (>= 3.0) 79 | middleman-syntax (3.0.0) 80 | middleman-core (>= 3.2) 81 | rouge (~> 2.0) 82 | mini_portile2 (2.3.0) 83 | minitest (5.10.1) 84 | nokogiri (1.8.2) 85 | mini_portile2 (~> 2.3.0) 86 | padrino-helpers (0.13.3.3) 87 | i18n (~> 0.6, >= 0.6.7) 88 | padrino-support (= 0.13.3.3) 89 | tilt (>= 1.4.1, < 3) 90 | padrino-support (0.13.3.3) 91 | activesupport (>= 3.1) 92 | parallel (1.10.0) 93 | public_suffix (2.0.5) 94 | rack (2.0.5) 95 | rb-fsevent (0.9.8) 96 | rb-inotify (0.9.8) 97 | ffi (>= 0.5.0) 98 | redcarpet (3.4.0) 99 | rouge (2.0.7) 100 | sass (3.4.23) 101 | servolux (0.12.0) 102 | sprockets (3.7.2) 103 | concurrent-ruby (~> 1.0) 104 | rack (> 1, < 3) 105 | thor (0.19.4) 106 | thread_safe (0.3.5) 107 | tilt (2.0.6) 108 | tzinfo (1.2.2) 109 | thread_safe (~> 0.1) 110 | uglifier (3.0.4) 111 | execjs (>= 0.3.0, < 3) 112 | 113 | PLATFORMS 114 | ruby 115 | 116 | DEPENDENCIES 117 | middleman (~> 4.2.1) 118 | middleman-autoprefixer (~> 2.7.0) 119 | middleman-sprockets (~> 4.1.0) 120 | middleman-syntax (~> 3.0.0) 121 | nokogiri (~> 1.8.2) 122 | redcarpet (~> 3.4.0) 123 | rouge (~> 2.0.5) 124 | 125 | RUBY VERSION 126 | ruby 2.3.3p222 127 | 128 | BUNDLED WITH 129 | 1.15.4 130 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright 2008-2013 Concur Technologies, Inc. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may 4 | not use this file except in compliance with the License. You may obtain 5 | a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 11 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 12 | License for the specific language governing permissions and limitations 13 | under the License. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Audius API Documentation 2 | 3 | [https://audiusproject.github.io/api-docs](https://audiusproject.github.io/api-docs) 4 | 5 | 6 | ## Getting started: 7 | 8 | ### 1. Install deps: 9 | ```bash 10 | gem install bundler 11 | bundle install 12 | npm install 13 | ``` 14 | 15 | If you see issues with bundler/ffi, you can try running `bundle update ffi` as per `https://stackoverflow.com/questions/31100347/bundle-install-is-not-successful-cannot-install-ffi-1-9-9-osx-10-9` 16 | 17 | ### 2. Start server 18 | ```bash 19 | # Runs the server on localhost:4567 and watches for changes 20 | npm run start 21 | ``` 22 | 23 | ### 3. Generate docs 24 | ```bash 25 | # Runs with all options, including updating the example responses from prod 26 | # Uses http://dn1_web-server_1:5000/v1/swagger.json to pull the swagger.json 27 | # and https://discoveryprovider.audius.co to generate the example responses by default 28 | node ./swagger/index.js -f -e -rpo 29 | 30 | # Shortcut of the above 31 | npm run gen 32 | 33 | # Don't refresh the example responses, but refresh the swagger.json from prod 34 | node ./swagger/index.js -f https://discoveryprovider.audius.co/v1/swagger.json -rpo 35 | 36 | # Don't refresh the swagger, but refresh the example responses using a specific DN 37 | # (assumes example parameters are already inserted - if they aren't, use -p) 38 | node ./swagger/index.js -e http://discoveryprovider2.audius.co 39 | ``` 40 | 41 | Note: To build and inspect the output of the actual website (eg to put on .audius.co), run `npm run build` 42 | 43 | 44 | ## Doc generation script options 45 | 46 | The `./swagger/index.js` script has customizable options that inform how it runs 47 | ``` 48 | node ./swagger/index.js -h 49 | ``` 50 | ``` 51 | Usage: index [options] 52 | 53 | Options: 54 | -e, --generate-examples Generate example documentation from the given discovery node (default: false) 55 | -f, --fetch-swagger Fetch the swagger.json from a DN (default: false) 56 | -r, --insert-responses Whether to pre-process the schema to insert example responses (default: false) 57 | -p, --insert-parameters Whether to pre-process the schema to insert example parameters (default: false) 58 | -o, --rename-operations Whether to pre-process the schema to rename select operation IDs to more human-friendly titles (default: false) 59 | -v, --verbose Whether to run widdershins with vebose option set to true (default: false) 60 | -h, --help display help for command 61 | ``` 62 | 63 | ## Deploy (github pages): 64 | 65 | IMPORTANT: Make sure you have generated the docs first! 66 | 67 | ```bash 68 | > ./deploy.sh 69 | ``` 70 | -------------------------------------------------------------------------------- /Vagrantfile: -------------------------------------------------------------------------------- 1 | Vagrant.configure(2) do |config| 2 | config.vm.box = "ubuntu/trusty64" 3 | config.vm.network :forwarded_port, guest: 4567, host: 4567 4 | config.vm.provider "virtualbox" do |vb| 5 | vb.memory = "2048" 6 | end 7 | 8 | config.vm.provision "bootstrap", 9 | type: "shell", 10 | inline: <<-SHELL 11 | sudo apt-add-repository ppa:brightbox/ruby-ng 12 | sudo apt-get update 13 | sudo apt-get install -yq ruby2.4 ruby2.4-dev 14 | sudo apt-get install -yq pkg-config build-essential nodejs git libxml2-dev libxslt-dev 15 | sudo apt-get autoremove -yq 16 | gem2.4 install --no-ri --no-rdoc bundler 17 | SHELL 18 | 19 | # add the local user git config to the vm 20 | config.vm.provision "file", source: "~/.gitconfig", destination: ".gitconfig" 21 | 22 | config.vm.provision "install", 23 | type: "shell", 24 | privileged: false, 25 | inline: <<-SHELL 26 | echo "==============================================" 27 | echo "Installing app dependencies" 28 | cd /vagrant 29 | bundle config build.nokogiri --use-system-libraries 30 | bundle install 31 | SHELL 32 | 33 | config.vm.provision "run", 34 | type: "shell", 35 | privileged: false, 36 | run: "always", 37 | inline: <<-SHELL 38 | echo "==============================================" 39 | echo "Starting up middleman at http://localhost:4567" 40 | echo "If it does not come up, check the ~/middleman.log file for any error messages" 41 | cd /vagrant 42 | bundle exec middleman server --watcher-force-polling --watcher-latency=1 &> ~/middleman.log & 43 | SHELL 44 | end 45 | -------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | # Unique header generation 2 | require './lib/unique_head.rb' 3 | 4 | # Markdown 5 | set :markdown_engine, :redcarpet 6 | set :markdown, 7 | fenced_code_blocks: true, 8 | smartypants: true, 9 | disable_indented_code_blocks: true, 10 | prettify: true, 11 | strikethrough: true, 12 | tables: true, 13 | with_toc_data: true, 14 | no_intra_emphasis: true, 15 | renderer: UniqueHeadCounter 16 | 17 | # Assets 18 | set :css_dir, 'stylesheets' 19 | set :js_dir, 'javascripts' 20 | set :images_dir, 'images' 21 | set :fonts_dir, 'fonts' 22 | 23 | # Activate the syntax highlighter 24 | activate :syntax 25 | ready do 26 | require './lib/multilang.rb' 27 | end 28 | 29 | activate :sprockets 30 | 31 | activate :autoprefixer do |config| 32 | config.browsers = ['last 2 version', 'Firefox ESR'] 33 | config.cascade = false 34 | config.inline = true 35 | end 36 | 37 | # Github pages require relative links 38 | activate :relative_assets 39 | set :relative_links, true 40 | 41 | # Build Configuration 42 | configure :build do 43 | # If you're having trouble with Middleman hanging, commenting 44 | # out the following two lines has been known to help 45 | activate :minify_css 46 | activate :minify_javascript 47 | # activate :relative_assets 48 | # activate :asset_hash 49 | # activate :gzip 50 | end 51 | 52 | # Deploy Configuration 53 | # If you want Middleman to listen on a different port, you can set that below 54 | set :port, 4567 55 | 56 | helpers do 57 | require './lib/toc_data.rb' 58 | end 59 | -------------------------------------------------------------------------------- /deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | set -o errexit #abort if any command fails 3 | me=$(basename "$0") 4 | 5 | help_message="\ 6 | Usage: $me [-c FILE] [] 7 | Deploy generated files to a git branch. 8 | 9 | Options: 10 | 11 | -h, --help Show this help information. 12 | -v, --verbose Increase verbosity. Useful for debugging. 13 | -e, --allow-empty Allow deployment of an empty directory. 14 | -m, --message MESSAGE Specify the message used when committing on the 15 | deploy branch. 16 | -n, --no-hash Don't append the source commit's hash to the deploy 17 | commit's message. 18 | --source-only Only build but not push 19 | --push-only Only push but not build 20 | " 21 | 22 | 23 | run_build() { 24 | bundle exec middleman build --clean 25 | } 26 | 27 | parse_args() { 28 | # Set args from a local environment file. 29 | if [ -e ".env" ]; then 30 | source .env 31 | fi 32 | 33 | # Parse arg flags 34 | # If something is exposed as an environment variable, set/overwrite it 35 | # here. Otherwise, set/overwrite the internal variable instead. 36 | while : ; do 37 | if [[ $1 = "-h" || $1 = "--help" ]]; then 38 | echo "$help_message" 39 | return 0 40 | elif [[ $1 = "-v" || $1 = "--verbose" ]]; then 41 | verbose=true 42 | shift 43 | elif [[ $1 = "-e" || $1 = "--allow-empty" ]]; then 44 | allow_empty=true 45 | shift 46 | elif [[ ( $1 = "-m" || $1 = "--message" ) && -n $2 ]]; then 47 | commit_message=$2 48 | shift 2 49 | elif [[ $1 = "-n" || $1 = "--no-hash" ]]; then 50 | GIT_DEPLOY_APPEND_HASH=false 51 | shift 52 | else 53 | break 54 | fi 55 | done 56 | 57 | # Set internal option vars from the environment and arg flags. All internal 58 | # vars should be declared here, with sane defaults if applicable. 59 | 60 | # Source directory & target branch. 61 | deploy_directory=build 62 | deploy_branch=gh-pages 63 | 64 | #if no user identity is already set in the current git environment, use this: 65 | default_username=${GIT_DEPLOY_USERNAME:-deploy.sh} 66 | default_email=${GIT_DEPLOY_EMAIL:-} 67 | 68 | #repository to deploy to. must be readable and writable. 69 | repo=origin 70 | 71 | #append commit hash to the end of message by default 72 | append_hash=${GIT_DEPLOY_APPEND_HASH:-true} 73 | } 74 | 75 | main() { 76 | parse_args "$@" 77 | 78 | enable_expanded_output 79 | 80 | if ! git diff --exit-code --quiet --cached; then 81 | echo Aborting due to uncommitted changes in the index >&2 82 | return 1 83 | fi 84 | 85 | commit_title=`git log -n 1 --format="%s" HEAD` 86 | commit_hash=` git log -n 1 --format="%H" HEAD` 87 | 88 | #default commit message uses last title if a custom one is not supplied 89 | if [[ -z $commit_message ]]; then 90 | commit_message="publish: $commit_title" 91 | fi 92 | 93 | #append hash to commit message unless no hash flag was found 94 | if [ $append_hash = true ]; then 95 | commit_message="$commit_message"$'\n\n'"generated from commit $commit_hash" 96 | fi 97 | 98 | previous_branch=`git rev-parse --abbrev-ref HEAD` 99 | 100 | if [ ! -d "$deploy_directory" ]; then 101 | echo "Deploy directory '$deploy_directory' does not exist. Aborting." >&2 102 | return 1 103 | fi 104 | 105 | # must use short form of flag in ls for compatibility with macOS and BSD 106 | if [[ -z `ls -A "$deploy_directory" 2> /dev/null` && -z $allow_empty ]]; then 107 | echo "Deploy directory '$deploy_directory' is empty. Aborting. If you're sure you want to deploy an empty tree, use the --allow-empty / -e flag." >&2 108 | return 1 109 | fi 110 | 111 | if git ls-remote --exit-code $repo "refs/heads/$deploy_branch" ; then 112 | # deploy_branch exists in $repo; make sure we have the latest version 113 | 114 | disable_expanded_output 115 | git fetch --force $repo $deploy_branch:$deploy_branch 116 | enable_expanded_output 117 | fi 118 | 119 | # check if deploy_branch exists locally 120 | if git show-ref --verify --quiet "refs/heads/$deploy_branch" 121 | then incremental_deploy 122 | else initial_deploy 123 | fi 124 | 125 | restore_head 126 | } 127 | 128 | initial_deploy() { 129 | git --work-tree "$deploy_directory" checkout --orphan $deploy_branch 130 | git --work-tree "$deploy_directory" add --all 131 | commit+push 132 | } 133 | 134 | incremental_deploy() { 135 | #make deploy_branch the current branch 136 | git symbolic-ref HEAD refs/heads/$deploy_branch 137 | #put the previously committed contents of deploy_branch into the index 138 | git --work-tree "$deploy_directory" reset --mixed --quiet 139 | git --work-tree "$deploy_directory" add --all 140 | 141 | set +o errexit 142 | diff=$(git --work-tree "$deploy_directory" diff --exit-code --quiet HEAD --)$? 143 | set -o errexit 144 | case $diff in 145 | 0) echo No changes to files in $deploy_directory. Skipping commit.;; 146 | 1) commit+push;; 147 | *) 148 | echo git diff exited with code $diff. Aborting. Staying on branch $deploy_branch so you can debug. To switch back to master, use: git symbolic-ref HEAD refs/heads/master && git reset --mixed >&2 149 | return $diff 150 | ;; 151 | esac 152 | } 153 | 154 | commit+push() { 155 | set_user_id 156 | git --work-tree "$deploy_directory" commit -m "$commit_message" 157 | 158 | disable_expanded_output 159 | #--quiet is important here to avoid outputting the repo URL, which may contain a secret token 160 | git push --quiet $repo $deploy_branch 161 | enable_expanded_output 162 | } 163 | 164 | #echo expanded commands as they are executed (for debugging) 165 | enable_expanded_output() { 166 | if [ $verbose ]; then 167 | set -o xtrace 168 | set +o verbose 169 | fi 170 | } 171 | 172 | #this is used to avoid outputting the repo URL, which may contain a secret token 173 | disable_expanded_output() { 174 | if [ $verbose ]; then 175 | set +o xtrace 176 | set -o verbose 177 | fi 178 | } 179 | 180 | set_user_id() { 181 | if [[ -z `git config user.name` ]]; then 182 | git config user.name "$default_username" 183 | fi 184 | if [[ -z `git config user.email` ]]; then 185 | git config user.email "$default_email" 186 | fi 187 | } 188 | 189 | restore_head() { 190 | if [[ $previous_branch = "HEAD" ]]; then 191 | #we weren't on any branch before, so just set HEAD back to the commit it was on 192 | git update-ref --no-deref HEAD $commit_hash $deploy_branch 193 | else 194 | git symbolic-ref HEAD refs/heads/$previous_branch 195 | fi 196 | 197 | git reset --mixed 198 | } 199 | 200 | filter() { 201 | sed -e "s|$repo|\$repo|g" 202 | } 203 | 204 | sanitize() { 205 | "$@" 2> >(filter 1>&2) | filter 206 | } 207 | 208 | if [[ $1 = --source-only ]]; then 209 | run_build 210 | elif [[ $1 = --push-only ]]; then 211 | main "$@" 212 | else 213 | run_build 214 | main "$@" 215 | fi 216 | -------------------------------------------------------------------------------- /font-selection.json: -------------------------------------------------------------------------------- 1 | { 2 | "IcoMoonType": "selection", 3 | "icons": [ 4 | { 5 | "icon": { 6 | "paths": [ 7 | "M438.857 73.143q119.429 0 220.286 58.857t159.714 159.714 58.857 220.286-58.857 220.286-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857zM512 785.714v-108.571q0-8-5.143-13.429t-12.571-5.429h-109.714q-7.429 0-13.143 5.714t-5.714 13.143v108.571q0 7.429 5.714 13.143t13.143 5.714h109.714q7.429 0 12.571-5.429t5.143-13.429zM510.857 589.143l10.286-354.857q0-6.857-5.714-10.286-5.714-4.571-13.714-4.571h-125.714q-8 0-13.714 4.571-5.714 3.429-5.714 10.286l9.714 354.857q0 5.714 5.714 10t13.714 4.286h105.714q8 0 13.429-4.286t6-10z" 8 | ], 9 | "attrs": [], 10 | "isMulticolor": false, 11 | "tags": [ 12 | "exclamation-circle" 13 | ], 14 | "defaultCode": 61546, 15 | "grid": 14 16 | }, 17 | "attrs": [], 18 | "properties": { 19 | "id": 100, 20 | "order": 4, 21 | "prevSize": 28, 22 | "code": 58880, 23 | "name": "exclamation-sign", 24 | "ligatures": "" 25 | }, 26 | "setIdx": 0, 27 | "iconIdx": 0 28 | }, 29 | { 30 | "icon": { 31 | "paths": [ 32 | "M585.143 786.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-54.857v-292.571q0-8-5.143-13.143t-13.143-5.143h-182.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h54.857v182.857h-54.857q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h256q8 0 13.143-5.143t5.143-13.143zM512 274.286v-91.429q0-8-5.143-13.143t-13.143-5.143h-109.714q-8 0-13.143 5.143t-5.143 13.143v91.429q0 8 5.143 13.143t13.143 5.143h109.714q8 0 13.143-5.143t5.143-13.143zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z" 33 | ], 34 | "attrs": [], 35 | "isMulticolor": false, 36 | "tags": [ 37 | "info-circle" 38 | ], 39 | "defaultCode": 61530, 40 | "grid": 14 41 | }, 42 | "attrs": [], 43 | "properties": { 44 | "id": 85, 45 | "order": 3, 46 | "name": "info-sign", 47 | "prevSize": 28, 48 | "code": 58882 49 | }, 50 | "setIdx": 0, 51 | "iconIdx": 2 52 | }, 53 | { 54 | "icon": { 55 | "paths": [ 56 | "M733.714 419.429q0-16-10.286-26.286l-52-51.429q-10.857-10.857-25.714-10.857t-25.714 10.857l-233.143 232.571-129.143-129.143q-10.857-10.857-25.714-10.857t-25.714 10.857l-52 51.429q-10.286 10.286-10.286 26.286 0 15.429 10.286 25.714l206.857 206.857q10.857 10.857 25.714 10.857 15.429 0 26.286-10.857l310.286-310.286q10.286-10.286 10.286-25.714zM877.714 512q0 119.429-58.857 220.286t-159.714 159.714-220.286 58.857-220.286-58.857-159.714-159.714-58.857-220.286 58.857-220.286 159.714-159.714 220.286-58.857 220.286 58.857 159.714 159.714 58.857 220.286z" 57 | ], 58 | "attrs": [], 59 | "isMulticolor": false, 60 | "tags": [ 61 | "check-circle" 62 | ], 63 | "defaultCode": 61528, 64 | "grid": 14 65 | }, 66 | "attrs": [], 67 | "properties": { 68 | "id": 83, 69 | "order": 9, 70 | "prevSize": 28, 71 | "code": 58886, 72 | "name": "ok-sign" 73 | }, 74 | "setIdx": 0, 75 | "iconIdx": 6 76 | }, 77 | { 78 | "icon": { 79 | "paths": [ 80 | "M658.286 475.429q0-105.714-75.143-180.857t-180.857-75.143-180.857 75.143-75.143 180.857 75.143 180.857 180.857 75.143 180.857-75.143 75.143-180.857zM950.857 950.857q0 29.714-21.714 51.429t-51.429 21.714q-30.857 0-51.429-21.714l-196-195.429q-102.286 70.857-228 70.857-81.714 0-156.286-31.714t-128.571-85.714-85.714-128.571-31.714-156.286 31.714-156.286 85.714-128.571 128.571-85.714 156.286-31.714 156.286 31.714 128.571 85.714 85.714 128.571 31.714 156.286q0 125.714-70.857 228l196 196q21.143 21.143 21.143 51.429z" 81 | ], 82 | "width": 951, 83 | "attrs": [], 84 | "isMulticolor": false, 85 | "tags": [ 86 | "search" 87 | ], 88 | "defaultCode": 61442, 89 | "grid": 14 90 | }, 91 | "attrs": [], 92 | "properties": { 93 | "id": 2, 94 | "order": 1, 95 | "prevSize": 28, 96 | "code": 58887, 97 | "name": "icon-search" 98 | }, 99 | "setIdx": 0, 100 | "iconIdx": 7 101 | } 102 | ], 103 | "height": 1024, 104 | "metadata": { 105 | "name": "slate", 106 | "license": "SIL OFL 1.1" 107 | }, 108 | "preferences": { 109 | "showGlyphs": true, 110 | "showQuickUse": true, 111 | "showQuickUse2": true, 112 | "showSVGs": true, 113 | "fontPref": { 114 | "prefix": "icon-", 115 | "metadata": { 116 | "fontFamily": "slate", 117 | "majorVersion": 1, 118 | "minorVersion": 0, 119 | "description": "Based on FontAwesome", 120 | "license": "SIL OFL 1.1" 121 | }, 122 | "metrics": { 123 | "emSize": 1024, 124 | "baseline": 6.25, 125 | "whitespace": 50 126 | }, 127 | "resetPoint": 58880, 128 | "showSelector": false, 129 | "selector": "class", 130 | "classSelector": ".icon", 131 | "showMetrics": false, 132 | "showMetadata": true, 133 | "showVersion": true, 134 | "ie7": false 135 | }, 136 | "imagePref": { 137 | "prefix": "icon-", 138 | "png": true, 139 | "useClassSelector": true, 140 | "color": 4473924, 141 | "bgColor": 16777215 142 | }, 143 | "historySize": 100, 144 | "showCodes": true, 145 | "gridSize": 16, 146 | "showLiga": false 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /lib/multilang.rb: -------------------------------------------------------------------------------- 1 | module Multilang 2 | def block_code(code, full_lang_name) 3 | if full_lang_name 4 | parts = full_lang_name.split('--') 5 | rouge_lang_name = (parts) ? parts[0] : "" # just parts[0] here causes null ref exception when no language specified 6 | super(code, rouge_lang_name).sub("highlight #{rouge_lang_name}") do |match| 7 | match + " tab-" + full_lang_name 8 | end 9 | else 10 | super(code, full_lang_name) 11 | end 12 | end 13 | end 14 | 15 | require 'middleman-core/renderers/redcarpet' 16 | Middleman::Renderers::MiddlemanRedcarpetHTML.send :include, Multilang 17 | -------------------------------------------------------------------------------- /lib/nesting_unique_head.rb: -------------------------------------------------------------------------------- 1 | # Nested unique header generation 2 | require 'middleman-core/renderers/redcarpet' 3 | 4 | class NestingUniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML 5 | def initialize 6 | super 7 | @@headers_history = {} if !defined?(@@headers_history) 8 | end 9 | 10 | def header(text, header_level) 11 | friendly_text = text.gsub(/<[^>]*>/,"").parameterize 12 | @@headers_history[header_level] = text.parameterize 13 | 14 | if header_level > 1 15 | for i in (header_level - 1).downto(1) 16 | friendly_text.prepend("#{@@headers_history[i]}-") if @@headers_history.key?(i) 17 | end 18 | end 19 | 20 | return "#{text}" 21 | end 22 | end 23 | -------------------------------------------------------------------------------- /lib/toc_data.rb: -------------------------------------------------------------------------------- 1 | require 'nokogiri' 2 | 3 | def toc_data(page_content) 4 | html_doc = Nokogiri::HTML::DocumentFragment.parse(page_content) 5 | 6 | # get a flat list of headers 7 | headers = [] 8 | html_doc.css('h1, h2, h3').each do |header| 9 | headers.push({ 10 | id: header.attribute('id').to_s, 11 | content: header.children, 12 | title: header.children.to_s.gsub(/<[^>]*>/, ''), 13 | level: header.name[1].to_i, 14 | children: [] 15 | }) 16 | end 17 | 18 | [3,2].each do |header_level| 19 | header_to_nest = nil 20 | headers = headers.reject do |header| 21 | if header[:level] == header_level 22 | header_to_nest[:children].push header if header_to_nest 23 | true 24 | else 25 | header_to_nest = header if header[:level] < header_level 26 | false 27 | end 28 | end 29 | end 30 | headers 31 | end 32 | -------------------------------------------------------------------------------- /lib/unique_head.rb: -------------------------------------------------------------------------------- 1 | # Unique header generation 2 | require 'middleman-core/renderers/redcarpet' 3 | require 'digest' 4 | class UniqueHeadCounter < Middleman::Renderers::MiddlemanRedcarpetHTML 5 | def initialize 6 | super 7 | @head_count = {} 8 | end 9 | def header(text, header_level) 10 | friendly_text = text.gsub(/<[^>]*>/,"").parameterize 11 | if friendly_text.strip.length == 0 12 | # Looks like parameterize removed the whole thing! It removes many unicode 13 | # characters like Chinese and Russian. To get a unique URL, let's just 14 | # URI escape the whole header 15 | friendly_text = Digest::SHA1.hexdigest(text)[0,10] 16 | end 17 | @head_count[friendly_text] ||= 0 18 | @head_count[friendly_text] += 1 19 | if @head_count[friendly_text] > 1 20 | friendly_text += "-#{@head_count[friendly_text]}" 21 | end 22 | return "#{text}" 23 | end 24 | end 25 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "audius-api-docs", 3 | "private": "true", 4 | "version": "1.0.0", 5 | "description": "Documentation generator for the Audius read-only API", 6 | "main": "index.js", 7 | "directories": { 8 | "lib": "lib" 9 | }, 10 | "dependencies": {}, 11 | "devDependencies": { 12 | "commander": "9.1.0", 13 | "eslint": "8.12.0", 14 | "eslint-config-prettier": "8.5.0", 15 | "eslint-config-prettier-standard": "4.0.1", 16 | "eslint-config-standard": "16.0.3", 17 | "eslint-plugin-import": "2.26.0", 18 | "eslint-plugin-node": "11.1.0", 19 | "eslint-plugin-prettier": "4.0.0", 20 | "eslint-plugin-promise": "6.0.0", 21 | "eslint-plugin-standard": "5.0.0", 22 | "isomorphic-fetch": "3.0.0", 23 | "patch-package": "6.4.7", 24 | "prettier": "2.6.2", 25 | "prettier-config-standard": "5.0.0", 26 | "standard": "16.0.4", 27 | "widdershins": "4.0.1" 28 | }, 29 | "scripts": { 30 | "postinstall": "patch-package", 31 | "start": "bundle exec middleman server", 32 | "build": "bundle exec middleman build --clean", 33 | "gen": "node ./swagger/index.js -f -e -rpo", 34 | "gen:prod": "node ./swagger/index.js -f https://discoveryprovider.audius.co/v1/swagger.json -e http://discoveryprovider3.audius.co -rpo", 35 | "test": "echo \"Error: no test specified\" && exit 1" 36 | }, 37 | "repository": { 38 | "type": "git", 39 | "url": "git+https://github.com/AudiusProject/api-docs.git" 40 | }, 41 | "author": "", 42 | "license": "ISC", 43 | "bugs": { 44 | "url": "https://github.com/AudiusProject/api-docs/issues" 45 | }, 46 | "homepage": "https://github.com/AudiusProject/api-docs#readme" 47 | } 48 | -------------------------------------------------------------------------------- /patches/widdershins+4.0.1.patch: -------------------------------------------------------------------------------- 1 | diff --git a/node_modules/widdershins/lib/openapi3.js b/node_modules/widdershins/lib/openapi3.js 2 | index d673b05..74887c7 100644 3 | --- a/node_modules/widdershins/lib/openapi3.js 4 | +++ b/node_modules/widdershins/lib/openapi3.js 5 | @@ -238,7 +238,7 @@ function getParameters(data) { 6 | requiredUriTemplateStr = requiredUriTemplateStr.split('{' + param.name + '}').join(template); 7 | } 8 | if (param.in === 'query') { 9 | - let isFirst = uriTemplateStr.indexOf('{&') < 0; 10 | + let isFirst = uriTemplateStr.indexOf('{?') < 0; 11 | // Since RFC6570 doesn't support multiple operators we cannot use (?+ and (&+ for reserved parameters 12 | let prefix = isFirst ? '{?' : '{&'; 13 | var template = ''; 14 | @@ -248,7 +248,7 @@ function getParameters(data) { 15 | template += param.explode ? '*}' : '}'; 16 | uriTemplateStr += (prefix + template); 17 | 18 | - if (param.required) { 19 | + if (param.required || param.example) { 20 | let isFirstRequired = requiredUriTemplateStr.indexOf('{?') < 0; 21 | let reqPrefix = isFirstRequired ? '{?' : '{&'; 22 | requiredUriTemplateStr += (reqPrefix + template); 23 | -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Bold.otf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Bold.ttf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Demi-Bold.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Demi-Bold.otf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Demi-Bold.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Demi-Bold.ttf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Heavy.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Heavy.otf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Heavy.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Heavy.ttf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Medium.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Medium.otf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Medium.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Medium.ttf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Regular.otf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-Regular.ttf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-UltLt.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-UltLt.otf -------------------------------------------------------------------------------- /source/fonts/AvenirNextLTPro-UltLt.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/AvenirNextLTPro-UltLt.ttf -------------------------------------------------------------------------------- /source/fonts/slate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/slate.eot -------------------------------------------------------------------------------- /source/fonts/slate.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Generated by IcoMoon 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /source/fonts/slate.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/slate.ttf -------------------------------------------------------------------------------- /source/fonts/slate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/slate.woff -------------------------------------------------------------------------------- /source/fonts/slate.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/fonts/slate.woff2 -------------------------------------------------------------------------------- /source/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/images/logo.png -------------------------------------------------------------------------------- /source/images/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/images/navbar.png -------------------------------------------------------------------------------- /source/images/og.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/source/images/og.jpg -------------------------------------------------------------------------------- /source/includes/_errors.md: -------------------------------------------------------------------------------- 1 | # Errors 2 | 3 | 6 | 7 | The Kittn API uses the following error codes: 8 | 9 | 10 | Error Code | Meaning 11 | ---------- | ------- 12 | 400 | Bad Request -- Your request is invalid. 13 | 401 | Unauthorized -- Your API key is wrong. 14 | 403 | Forbidden -- The kitten requested is hidden for administrators only. 15 | 404 | Not Found -- The specified kitten could not be found. 16 | 405 | Method Not Allowed -- You tried to access a kitten with an invalid method. 17 | 406 | Not Acceptable -- You requested a format that isn't json. 18 | 410 | Gone -- The kitten requested has been removed from our servers. 19 | 418 | I'm a teapot. 20 | 429 | Too Many Requests -- You're requesting too many kittens! Slow down! 21 | 500 | Internal Server Error -- We had a problem with our server. Try again later. 22 | 503 | Service Unavailable -- We're temporarily offline for maintenance. Please try again later. 23 | -------------------------------------------------------------------------------- /source/index.html.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Audius API Docs 3 | 4 | toc_footers: 5 | - Audius App 6 | - github.com/AudiusProject 7 | - audius.org 8 | 9 | search: true 10 | 11 | language_tabs: 12 | - shell: Shell 13 | - http: HTTP 14 | - javascript: JavaScript 15 | - python: Python 16 | - php: PHP 17 | - java: Java 18 | - ruby: Ruby 19 | - go: Go 20 | 21 | includes: 22 | - docs 23 | --- 24 | 25 | 26 | 49 | 50 |
51 |
52 | 53 | # Audius API Docs 54 | 55 | The Audius API is entirely free to use. We ask that you adhere to the guidelines in this doc and always credit artists. 56 | 57 | 58 | ## Selecting a Host 59 | 60 | > Code Sample 61 | 62 | ```shell 63 | curl https://api.audius.co 64 | ``` 65 | 66 | ```http 67 | GET https://api.audius.co HTTP/1.1 68 | ``` 69 | 70 | ```javascript 71 | 72 | const sample = (arr) => arr[Math.floor(Math.random() * arr.length)] 73 | const host = await fetch('https://api.audius.co') 74 | .then(r => r.json()) 75 | .then(j => j.data) 76 | .then(d => sample(d)) 77 | 78 | ``` 79 | 80 | ```python 81 | import random 82 | import requests 83 | 84 | host = random.choice((requests.get('https://api.audius.co')).json()['data']) 85 | ``` 86 | 87 | Audius is a decentralized music streaming service. To use the API, you first select an API endpoint from the list of endpoints returned by: 88 | 89 | [https://api.audius.co](https://api.audius.co) 90 | 91 | Once you've selected a host, all API requests can be sent directly to it. We recommend selecting a host each time your application starts up as availability may change over time. 92 | 93 | For the following documention, we've selected one for you: 94 | 95 | ` AUDIUS_API_HOST ` 96 | 97 | ## Specifying App Name 98 | 99 | If you're integrating the Audius API into an app in production, we ask that you include an `&app_name=` param with each query. Your unique app name is entirely up to you! 100 | 101 |
102 |
-------------------------------------------------------------------------------- /source/javascripts/all.js: -------------------------------------------------------------------------------- 1 | //= require ./all_nosearch 2 | //= require ./app/_search 3 | -------------------------------------------------------------------------------- /source/javascripts/all_nosearch.js: -------------------------------------------------------------------------------- 1 | //= require ./lib/_energize 2 | //= require ./app/_toc 3 | //= require ./app/_lang 4 | 5 | $(function() { 6 | loadToc($('#toc'), '.toc-link', '.toc-list-h2', 10); 7 | setupLanguages($('body').data('languages')); 8 | $('.content').imagesLoaded( function() { 9 | window.recacheHeights(); 10 | window.refreshToc(); 11 | }); 12 | }); 13 | 14 | window.onpopstate = function() { 15 | activateLanguage(getLanguageFromQueryString()); 16 | }; 17 | -------------------------------------------------------------------------------- /source/javascripts/app/_lang.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery 2 | 3 | /* 4 | Copyright 2008-2013 Concur Technologies, Inc. 5 | 6 | Licensed under the Apache License, Version 2.0 (the "License"); you may 7 | not use this file except in compliance with the License. You may obtain 8 | a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, software 13 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 14 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 15 | License for the specific language governing permissions and limitations 16 | under the License. 17 | */ 18 | ;(function () { 19 | 'use strict'; 20 | 21 | var languages = []; 22 | 23 | window.setupLanguages = setupLanguages; 24 | window.activateLanguage = activateLanguage; 25 | window.getLanguageFromQueryString = getLanguageFromQueryString; 26 | 27 | function activateLanguage(language) { 28 | if (!language) return; 29 | if (language === "") return; 30 | 31 | $(".lang-selector a").removeClass('active'); 32 | $(".lang-selector a[data-language-name='" + language + "']").addClass('active'); 33 | for (var i=0; i < languages.length; i++) { 34 | $(".highlight.tab-" + languages[i]).hide(); 35 | $(".lang-specific." + languages[i]).hide(); 36 | } 37 | $(".highlight.tab-" + language).show(); 38 | $(".lang-specific." + language).show(); 39 | 40 | window.recacheHeights(); 41 | 42 | // scroll to the new location of the position 43 | if ($(window.location.hash).get(0)) { 44 | $(window.location.hash).get(0).scrollIntoView(true); 45 | } 46 | } 47 | 48 | // parseURL and stringifyURL are from https://github.com/sindresorhus/query-string 49 | // MIT licensed 50 | // https://github.com/sindresorhus/query-string/blob/7bee64c16f2da1a326579e96977b9227bf6da9e6/license 51 | function parseURL(str) { 52 | if (typeof str !== 'string') { 53 | return {}; 54 | } 55 | 56 | str = str.trim().replace(/^(\?|#|&)/, ''); 57 | 58 | if (!str) { 59 | return {}; 60 | } 61 | 62 | return str.split('&').reduce(function (ret, param) { 63 | var parts = param.replace(/\+/g, ' ').split('='); 64 | var key = parts[0]; 65 | var val = parts[1]; 66 | 67 | key = decodeURIComponent(key); 68 | // missing `=` should be `null`: 69 | // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 70 | val = val === undefined ? null : decodeURIComponent(val); 71 | 72 | if (!ret.hasOwnProperty(key)) { 73 | ret[key] = val; 74 | } else if (Array.isArray(ret[key])) { 75 | ret[key].push(val); 76 | } else { 77 | ret[key] = [ret[key], val]; 78 | } 79 | 80 | return ret; 81 | }, {}); 82 | }; 83 | 84 | function stringifyURL(obj) { 85 | return obj ? Object.keys(obj).sort().map(function (key) { 86 | var val = obj[key]; 87 | 88 | if (Array.isArray(val)) { 89 | return val.sort().map(function (val2) { 90 | return encodeURIComponent(key) + '=' + encodeURIComponent(val2); 91 | }).join('&'); 92 | } 93 | 94 | return encodeURIComponent(key) + '=' + encodeURIComponent(val); 95 | }).join('&') : ''; 96 | }; 97 | 98 | // gets the language set in the query string 99 | function getLanguageFromQueryString() { 100 | if (location.search.length >= 1) { 101 | var language = parseURL(location.search).language; 102 | if (language) { 103 | return language; 104 | } else if (jQuery.inArray(location.search.substr(1), languages) != -1) { 105 | return location.search.substr(1); 106 | } 107 | } 108 | 109 | return false; 110 | } 111 | 112 | // returns a new query string with the new language in it 113 | function generateNewQueryString(language) { 114 | var url = parseURL(location.search); 115 | if (url.language) { 116 | url.language = language; 117 | return stringifyURL(url); 118 | } 119 | return language; 120 | } 121 | 122 | // if a button is clicked, add the state to the history 123 | function pushURL(language) { 124 | if (!history) { return; } 125 | var hash = window.location.hash; 126 | if (hash) { 127 | hash = hash.replace(/^#+/, ''); 128 | } 129 | history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash); 130 | 131 | // save language as next default 132 | localStorage.setItem("language", language); 133 | } 134 | 135 | function setupLanguages(l) { 136 | var defaultLanguage = localStorage.getItem("language"); 137 | 138 | languages = l; 139 | 140 | var presetLanguage = getLanguageFromQueryString(); 141 | if (presetLanguage) { 142 | // the language is in the URL, so use that language! 143 | activateLanguage(presetLanguage); 144 | 145 | localStorage.setItem("language", presetLanguage); 146 | } else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) { 147 | // the language was the last selected one saved in localstorage, so use that language! 148 | activateLanguage(defaultLanguage); 149 | } else { 150 | // no language selected, so use the default 151 | activateLanguage(languages[0]); 152 | } 153 | } 154 | 155 | // if we click on a language tab, activate that language 156 | $(function() { 157 | $(".lang-selector a").on("click", function() { 158 | var language = $(this).data("language-name"); 159 | pushURL(language); 160 | activateLanguage(language); 161 | return false; 162 | }); 163 | }); 164 | })(); 165 | -------------------------------------------------------------------------------- /source/javascripts/app/_search.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_lunr 2 | //= require ../lib/_jquery 3 | //= require ../lib/_jquery.highlight 4 | ;(function () { 5 | 'use strict'; 6 | 7 | var content, searchResults; 8 | var highlightOpts = { element: 'span', className: 'search-highlight' }; 9 | var searchDelay = 0; 10 | var timeoutHandle = 0; 11 | 12 | var index = new lunr.Index(); 13 | 14 | index.ref('id'); 15 | index.field('title', { boost: 10 }); 16 | index.field('body'); 17 | index.pipeline.add(lunr.trimmer, lunr.stopWordFilter); 18 | 19 | $(populate); 20 | $(bind); 21 | 22 | function populate() { 23 | $('h1, h2').each(function() { 24 | var title = $(this); 25 | var body = title.nextUntil('h1, h2'); 26 | index.add({ 27 | id: title.prop('id'), 28 | title: title.text(), 29 | body: body.text() 30 | }); 31 | }); 32 | 33 | determineSearchDelay(); 34 | } 35 | function determineSearchDelay() { 36 | if(index.tokenStore.length>5000) { 37 | searchDelay = 300; 38 | } 39 | } 40 | 41 | function bind() { 42 | content = $('.content'); 43 | searchResults = $('.search-results'); 44 | 45 | $('#input-search').on('keyup',function(e) { 46 | var wait = function() { 47 | return function(executingFunction, waitTime){ 48 | clearTimeout(timeoutHandle); 49 | timeoutHandle = setTimeout(executingFunction, waitTime); 50 | }; 51 | }(); 52 | wait(function(){ 53 | search(e); 54 | }, searchDelay ); 55 | }); 56 | } 57 | 58 | function search(event) { 59 | 60 | var searchInput = $('#input-search')[0]; 61 | 62 | unhighlight(); 63 | searchResults.addClass('visible'); 64 | 65 | // ESC clears the field 66 | if (event.keyCode === 27) searchInput.value = ''; 67 | 68 | if (searchInput.value) { 69 | var results = index.search(searchInput.value).filter(function(r) { 70 | return r.score > 0.0001; 71 | }); 72 | 73 | if (results.length) { 74 | searchResults.empty(); 75 | $.each(results, function (index, result) { 76 | var elem = document.getElementById(result.ref); 77 | searchResults.append("
  • " + $(elem).text() + "
  • "); 78 | }); 79 | highlight.call(searchInput); 80 | } else { 81 | searchResults.html('
  • '); 82 | $('.search-results li').text('No Results Found for "' + searchInput.value + '"'); 83 | } 84 | } else { 85 | unhighlight(); 86 | searchResults.removeClass('visible'); 87 | } 88 | } 89 | 90 | function highlight() { 91 | if (this.value) content.highlight(this.value, highlightOpts); 92 | } 93 | 94 | function unhighlight() { 95 | content.unhighlight(highlightOpts); 96 | } 97 | })(); 98 | 99 | -------------------------------------------------------------------------------- /source/javascripts/app/_toc.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery 2 | //= require ../lib/_imagesloaded.min 3 | ;(function () { 4 | 'use strict'; 5 | 6 | var htmlPattern = /<[^>]*>/g; 7 | var loaded = false; 8 | 9 | var debounce = function(func, waitTime) { 10 | var timeout = false; 11 | return function() { 12 | if (timeout === false) { 13 | setTimeout(function() { 14 | func(); 15 | timeout = false; 16 | }, waitTime); 17 | timeout = true; 18 | } 19 | }; 20 | }; 21 | 22 | var closeToc = function() { 23 | $(".toc-wrapper").removeClass('open'); 24 | $("#nav-button").removeClass('open'); 25 | }; 26 | 27 | function loadToc($toc, tocLinkSelector, tocListSelector, scrollOffset) { 28 | var headerHeights = {}; 29 | var pageHeight = 0; 30 | var windowHeight = 0; 31 | var originalTitle = document.title; 32 | 33 | var recacheHeights = function() { 34 | headerHeights = {}; 35 | pageHeight = $(document).height(); 36 | windowHeight = $(window).height(); 37 | 38 | $toc.find(tocLinkSelector).each(function() { 39 | var targetId = $(this).attr('href'); 40 | if (targetId[0] === "#") { 41 | headerHeights[targetId] = $(targetId).offset().top; 42 | } 43 | }); 44 | }; 45 | 46 | var refreshToc = function() { 47 | var currentTop = $(document).scrollTop() + scrollOffset; 48 | 49 | if (currentTop + windowHeight >= pageHeight) { 50 | // at bottom of page, so just select last header by making currentTop very large 51 | // this fixes the problem where the last header won't ever show as active if its content 52 | // is shorter than the window height 53 | currentTop = pageHeight + 1000; 54 | } 55 | 56 | var best = null; 57 | for (var name in headerHeights) { 58 | if ((headerHeights[name] < currentTop && headerHeights[name] > headerHeights[best]) || best === null) { 59 | best = name; 60 | } 61 | } 62 | 63 | // Catch the initial load case 64 | if (currentTop == scrollOffset && !loaded) { 65 | best = window.location.hash; 66 | loaded = true; 67 | } 68 | 69 | var $best = $toc.find("[href='" + best + "']").first(); 70 | if (!$best.hasClass("active")) { 71 | // .active is applied to the ToC link we're currently on, and its parent
      s selected by tocListSelector 72 | // .active-expanded is applied to the ToC links that are parents of this one 73 | $toc.find(".active").removeClass("active"); 74 | $toc.find(".active-parent").removeClass("active-parent"); 75 | $best.addClass("active"); 76 | $best.parents(tocListSelector).addClass("active").siblings(tocLinkSelector).addClass('active-parent'); 77 | $best.siblings(tocListSelector).addClass("active"); 78 | $toc.find(tocListSelector).filter(":not(.active)").slideUp(150); 79 | $toc.find(tocListSelector).filter(".active").slideDown(150); 80 | if (window.history.replaceState) { 81 | window.history.replaceState(null, "", best); 82 | } 83 | var thisTitle = $best.data("title") 84 | if (thisTitle !== undefined && thisTitle.length > 0) { 85 | document.title = thisTitle + " – " + originalTitle; 86 | } else { 87 | document.title = originalTitle; 88 | } 89 | } 90 | }; 91 | 92 | var makeToc = function() { 93 | recacheHeights(); 94 | refreshToc(); 95 | 96 | $("#nav-button").click(function() { 97 | $(".toc-wrapper").toggleClass('open'); 98 | $("#nav-button").toggleClass('open'); 99 | return false; 100 | }); 101 | $(".page-wrapper").click(closeToc); 102 | $(".toc-link").click(closeToc); 103 | 104 | // reload immediately after scrolling on toc click 105 | $toc.find(tocLinkSelector).click(function() { 106 | setTimeout(function() { 107 | refreshToc(); 108 | }, 0); 109 | }); 110 | 111 | $(window).scroll(debounce(refreshToc, 200)); 112 | $(window).resize(debounce(recacheHeights, 200)); 113 | }; 114 | 115 | makeToc(); 116 | 117 | window.recacheHeights = recacheHeights; 118 | window.refreshToc = refreshToc; 119 | } 120 | 121 | window.loadToc = loadToc; 122 | })(); 123 | -------------------------------------------------------------------------------- /source/javascripts/lib/_energize.js: -------------------------------------------------------------------------------- 1 | /** 2 | * energize.js v0.1.0 3 | * 4 | * Speeds up click events on mobile devices. 5 | * https://github.com/davidcalhoun/energize.js 6 | */ 7 | 8 | (function() { // Sandbox 9 | /** 10 | * Don't add to non-touch devices, which don't need to be sped up 11 | */ 12 | if(!('ontouchstart' in window)) return; 13 | 14 | var lastClick = {}, 15 | isThresholdReached, touchstart, touchmove, touchend, 16 | click, closest; 17 | 18 | /** 19 | * isThresholdReached 20 | * 21 | * Compare touchstart with touchend xy coordinates, 22 | * and only fire simulated click event if the coordinates 23 | * are nearby. (don't want clicking to be confused with a swipe) 24 | */ 25 | isThresholdReached = function(startXY, xy) { 26 | return Math.abs(startXY[0] - xy[0]) > 5 || Math.abs(startXY[1] - xy[1]) > 5; 27 | }; 28 | 29 | /** 30 | * touchstart 31 | * 32 | * Save xy coordinates when the user starts touching the screen 33 | */ 34 | touchstart = function(e) { 35 | this.startXY = [e.touches[0].clientX, e.touches[0].clientY]; 36 | this.threshold = false; 37 | }; 38 | 39 | /** 40 | * touchmove 41 | * 42 | * Check if the user is scrolling past the threshold. 43 | * Have to check here because touchend will not always fire 44 | * on some tested devices (Kindle Fire?) 45 | */ 46 | touchmove = function(e) { 47 | // NOOP if the threshold has already been reached 48 | if(this.threshold) return false; 49 | 50 | this.threshold = isThresholdReached(this.startXY, [e.touches[0].clientX, e.touches[0].clientY]); 51 | }; 52 | 53 | /** 54 | * touchend 55 | * 56 | * If the user didn't scroll past the threshold between 57 | * touchstart and touchend, fire a simulated click. 58 | * 59 | * (This will fire before a native click) 60 | */ 61 | touchend = function(e) { 62 | // Don't fire a click if the user scrolled past the threshold 63 | if(this.threshold || isThresholdReached(this.startXY, [e.changedTouches[0].clientX, e.changedTouches[0].clientY])) { 64 | return; 65 | } 66 | 67 | /** 68 | * Create and fire a click event on the target element 69 | * https://developer.mozilla.org/en/DOM/event.initMouseEvent 70 | */ 71 | var touch = e.changedTouches[0], 72 | evt = document.createEvent('MouseEvents'); 73 | evt.initMouseEvent('click', true, true, window, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null); 74 | evt.simulated = true; // distinguish from a normal (nonsimulated) click 75 | e.target.dispatchEvent(evt); 76 | }; 77 | 78 | /** 79 | * click 80 | * 81 | * Because we've already fired a click event in touchend, 82 | * we need to listed for all native click events here 83 | * and suppress them as necessary. 84 | */ 85 | click = function(e) { 86 | /** 87 | * Prevent ghost clicks by only allowing clicks we created 88 | * in the click event we fired (look for e.simulated) 89 | */ 90 | var time = Date.now(), 91 | timeDiff = time - lastClick.time, 92 | x = e.clientX, 93 | y = e.clientY, 94 | xyDiff = [Math.abs(lastClick.x - x), Math.abs(lastClick.y - y)], 95 | target = closest(e.target, 'A') || e.target, // needed for standalone apps 96 | nodeName = target.nodeName, 97 | isLink = nodeName === 'A', 98 | standAlone = window.navigator.standalone && isLink && e.target.getAttribute("href"); 99 | 100 | lastClick.time = time; 101 | lastClick.x = x; 102 | lastClick.y = y; 103 | 104 | /** 105 | * Unfortunately Android sometimes fires click events without touch events (seen on Kindle Fire), 106 | * so we have to add more logic to determine the time of the last click. Not perfect... 107 | * 108 | * Older, simpler check: if((!e.simulated) || standAlone) 109 | */ 110 | if((!e.simulated && (timeDiff < 500 || (timeDiff < 1500 && xyDiff[0] < 50 && xyDiff[1] < 50))) || standAlone) { 111 | e.preventDefault(); 112 | e.stopPropagation(); 113 | if(!standAlone) return false; 114 | } 115 | 116 | /** 117 | * Special logic for standalone web apps 118 | * See http://stackoverflow.com/questions/2898740/iphone-safari-web-app-opens-links-in-new-window 119 | */ 120 | if(standAlone) { 121 | window.location = target.getAttribute("href"); 122 | } 123 | 124 | /** 125 | * Add an energize-focus class to the targeted link (mimics :focus behavior) 126 | * TODO: test and/or remove? Does this work? 127 | */ 128 | if(!target || !target.classList) return; 129 | target.classList.add("energize-focus"); 130 | window.setTimeout(function(){ 131 | target.classList.remove("energize-focus"); 132 | }, 150); 133 | }; 134 | 135 | /** 136 | * closest 137 | * @param {HTMLElement} node current node to start searching from. 138 | * @param {string} tagName the (uppercase) name of the tag you're looking for. 139 | * 140 | * Find the closest ancestor tag of a given node. 141 | * 142 | * Starts at node and goes up the DOM tree looking for a 143 | * matching nodeName, continuing until hitting document.body 144 | */ 145 | closest = function(node, tagName){ 146 | var curNode = node; 147 | 148 | while(curNode !== document.body) { // go up the dom until we find the tag we're after 149 | if(!curNode || curNode.nodeName === tagName) { return curNode; } // found 150 | curNode = curNode.parentNode; // not found, so keep going up 151 | } 152 | 153 | return null; // not found 154 | }; 155 | 156 | /** 157 | * Add all delegated event listeners 158 | * 159 | * All the events we care about bubble up to document, 160 | * so we can take advantage of event delegation. 161 | * 162 | * Note: no need to wait for DOMContentLoaded here 163 | */ 164 | document.addEventListener('touchstart', touchstart, false); 165 | document.addEventListener('touchmove', touchmove, false); 166 | document.addEventListener('touchend', touchend, false); 167 | document.addEventListener('click', click, true); // TODO: why does this use capture? 168 | 169 | })(); -------------------------------------------------------------------------------- /source/javascripts/lib/_imagesloaded.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * imagesLoaded PACKAGED v3.1.8 3 | * JavaScript is all like "You images are done yet or what?" 4 | * MIT License 5 | */ 6 | 7 | (function(){function e(){}function t(e,t){for(var n=e.length;n--;)if(e[n].listener===t)return n;return-1}function n(e){return function(){return this[e].apply(this,arguments)}}var i=e.prototype,r=this,o=r.EventEmitter;i.getListeners=function(e){var t,n,i=this._getEvents();if("object"==typeof e){t={};for(n in i)i.hasOwnProperty(n)&&e.test(n)&&(t[n]=i[n])}else t=i[e]||(i[e]=[]);return t},i.flattenListeners=function(e){var t,n=[];for(t=0;e.length>t;t+=1)n.push(e[t].listener);return n},i.getListenersAsObject=function(e){var t,n=this.getListeners(e);return n instanceof Array&&(t={},t[e]=n),t||n},i.addListener=function(e,n){var i,r=this.getListenersAsObject(e),o="object"==typeof n;for(i in r)r.hasOwnProperty(i)&&-1===t(r[i],n)&&r[i].push(o?n:{listener:n,once:!1});return this},i.on=n("addListener"),i.addOnceListener=function(e,t){return this.addListener(e,{listener:t,once:!0})},i.once=n("addOnceListener"),i.defineEvent=function(e){return this.getListeners(e),this},i.defineEvents=function(e){for(var t=0;e.length>t;t+=1)this.defineEvent(e[t]);return this},i.removeListener=function(e,n){var i,r,o=this.getListenersAsObject(e);for(r in o)o.hasOwnProperty(r)&&(i=t(o[r],n),-1!==i&&o[r].splice(i,1));return this},i.off=n("removeListener"),i.addListeners=function(e,t){return this.manipulateListeners(!1,e,t)},i.removeListeners=function(e,t){return this.manipulateListeners(!0,e,t)},i.manipulateListeners=function(e,t,n){var i,r,o=e?this.removeListener:this.addListener,s=e?this.removeListeners:this.addListeners;if("object"!=typeof t||t instanceof RegExp)for(i=n.length;i--;)o.call(this,t,n[i]);else for(i in t)t.hasOwnProperty(i)&&(r=t[i])&&("function"==typeof r?o.call(this,i,r):s.call(this,i,r));return this},i.removeEvent=function(e){var t,n=typeof e,i=this._getEvents();if("string"===n)delete i[e];else if("object"===n)for(t in i)i.hasOwnProperty(t)&&e.test(t)&&delete i[t];else delete this._events;return this},i.removeAllListeners=n("removeEvent"),i.emitEvent=function(e,t){var n,i,r,o,s=this.getListenersAsObject(e);for(r in s)if(s.hasOwnProperty(r))for(i=s[r].length;i--;)n=s[r][i],n.once===!0&&this.removeListener(e,n.listener),o=n.listener.apply(this,t||[]),o===this._getOnceReturnValue()&&this.removeListener(e,n.listener);return this},i.trigger=n("emitEvent"),i.emit=function(e){var t=Array.prototype.slice.call(arguments,1);return this.emitEvent(e,t)},i.setOnceReturnValue=function(e){return this._onceReturnValue=e,this},i._getOnceReturnValue=function(){return this.hasOwnProperty("_onceReturnValue")?this._onceReturnValue:!0},i._getEvents=function(){return this._events||(this._events={})},e.noConflict=function(){return r.EventEmitter=o,e},"function"==typeof define&&define.amd?define("eventEmitter/EventEmitter",[],function(){return e}):"object"==typeof module&&module.exports?module.exports=e:this.EventEmitter=e}).call(this),function(e){function t(t){var n=e.event;return n.target=n.target||n.srcElement||t,n}var n=document.documentElement,i=function(){};n.addEventListener?i=function(e,t,n){e.addEventListener(t,n,!1)}:n.attachEvent&&(i=function(e,n,i){e[n+i]=i.handleEvent?function(){var n=t(e);i.handleEvent.call(i,n)}:function(){var n=t(e);i.call(e,n)},e.attachEvent("on"+n,e[n+i])});var r=function(){};n.removeEventListener?r=function(e,t,n){e.removeEventListener(t,n,!1)}:n.detachEvent&&(r=function(e,t,n){e.detachEvent("on"+t,e[t+n]);try{delete e[t+n]}catch(i){e[t+n]=void 0}});var o={bind:i,unbind:r};"function"==typeof define&&define.amd?define("eventie/eventie",o):e.eventie=o}(this),function(e,t){"function"==typeof define&&define.amd?define(["eventEmitter/EventEmitter","eventie/eventie"],function(n,i){return t(e,n,i)}):"object"==typeof exports?module.exports=t(e,require("wolfy87-eventemitter"),require("eventie")):e.imagesLoaded=t(e,e.EventEmitter,e.eventie)}(window,function(e,t,n){function i(e,t){for(var n in t)e[n]=t[n];return e}function r(e){return"[object Array]"===d.call(e)}function o(e){var t=[];if(r(e))t=e;else if("number"==typeof e.length)for(var n=0,i=e.length;i>n;n++)t.push(e[n]);else t.push(e);return t}function s(e,t,n){if(!(this instanceof s))return new s(e,t);"string"==typeof e&&(e=document.querySelectorAll(e)),this.elements=o(e),this.options=i({},this.options),"function"==typeof t?n=t:i(this.options,t),n&&this.on("always",n),this.getImages(),a&&(this.jqDeferred=new a.Deferred);var r=this;setTimeout(function(){r.check()})}function f(e){this.img=e}function c(e){this.src=e,v[e]=this}var a=e.jQuery,u=e.console,h=u!==void 0,d=Object.prototype.toString;s.prototype=new t,s.prototype.options={},s.prototype.getImages=function(){this.images=[];for(var e=0,t=this.elements.length;t>e;e++){var n=this.elements[e];"IMG"===n.nodeName&&this.addImage(n);var i=n.nodeType;if(i&&(1===i||9===i||11===i))for(var r=n.querySelectorAll("img"),o=0,s=r.length;s>o;o++){var f=r[o];this.addImage(f)}}},s.prototype.addImage=function(e){var t=new f(e);this.images.push(t)},s.prototype.check=function(){function e(e,r){return t.options.debug&&h&&u.log("confirm",e,r),t.progress(e),n++,n===i&&t.complete(),!0}var t=this,n=0,i=this.images.length;if(this.hasAnyBroken=!1,!i)return this.complete(),void 0;for(var r=0;i>r;r++){var o=this.images[r];o.on("confirm",e),o.check()}},s.prototype.progress=function(e){this.hasAnyBroken=this.hasAnyBroken||!e.isLoaded;var t=this;setTimeout(function(){t.emit("progress",t,e),t.jqDeferred&&t.jqDeferred.notify&&t.jqDeferred.notify(t,e)})},s.prototype.complete=function(){var e=this.hasAnyBroken?"fail":"done";this.isComplete=!0;var t=this;setTimeout(function(){if(t.emit(e,t),t.emit("always",t),t.jqDeferred){var n=t.hasAnyBroken?"reject":"resolve";t.jqDeferred[n](t)}})},a&&(a.fn.imagesLoaded=function(e,t){var n=new s(this,e,t);return n.jqDeferred.promise(a(this))}),f.prototype=new t,f.prototype.check=function(){var e=v[this.img.src]||new c(this.img.src);if(e.isConfirmed)return this.confirm(e.isLoaded,"cached was confirmed"),void 0;if(this.img.complete&&void 0!==this.img.naturalWidth)return this.confirm(0!==this.img.naturalWidth,"naturalWidth"),void 0;var t=this;e.on("confirm",function(e,n){return t.confirm(e.isLoaded,n),!0}),e.check()},f.prototype.confirm=function(e,t){this.isLoaded=e,this.emit("confirm",this,t)};var v={};return c.prototype=new t,c.prototype.check=function(){if(!this.isChecked){var e=new Image;n.bind(e,"load",this),n.bind(e,"error",this),e.src=this.src,this.isChecked=!0}},c.prototype.handleEvent=function(e){var t="on"+e.type;this[t]&&this[t](e)},c.prototype.onload=function(e){this.confirm(!0,"onload"),this.unbindProxyEvents(e)},c.prototype.onerror=function(e){this.confirm(!1,"onerror"),this.unbindProxyEvents(e)},c.prototype.confirm=function(e,t){this.isConfirmed=!0,this.isLoaded=e,this.emit("confirm",this,t)},c.prototype.unbindProxyEvents=function(e){n.unbind(e.target,"load",this),n.unbind(e.target,"error",this)},s}); -------------------------------------------------------------------------------- /source/javascripts/lib/_jquery.highlight.js: -------------------------------------------------------------------------------- 1 | /* 2 | * jQuery Highlight plugin 3 | * 4 | * Based on highlight v3 by Johann Burkard 5 | * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html 6 | * 7 | * Code a little bit refactored and cleaned (in my humble opinion). 8 | * Most important changes: 9 | * - has an option to highlight only entire words (wordsOnly - false by default), 10 | * - has an option to be case sensitive (caseSensitive - false by default) 11 | * - highlight element tag and class names can be specified in options 12 | * 13 | * Usage: 14 | * // wrap every occurrance of text 'lorem' in content 15 | * // with (default options) 16 | * $('#content').highlight('lorem'); 17 | * 18 | * // search for and highlight more terms at once 19 | * // so you can save some time on traversing DOM 20 | * $('#content').highlight(['lorem', 'ipsum']); 21 | * $('#content').highlight('lorem ipsum'); 22 | * 23 | * // search only for entire word 'lorem' 24 | * $('#content').highlight('lorem', { wordsOnly: true }); 25 | * 26 | * // don't ignore case during search of term 'lorem' 27 | * $('#content').highlight('lorem', { caseSensitive: true }); 28 | * 29 | * // wrap every occurrance of term 'ipsum' in content 30 | * // with 31 | * $('#content').highlight('ipsum', { element: 'em', className: 'important' }); 32 | * 33 | * // remove default highlight 34 | * $('#content').unhighlight(); 35 | * 36 | * // remove custom highlight 37 | * $('#content').unhighlight({ element: 'em', className: 'important' }); 38 | * 39 | * 40 | * Copyright (c) 2009 Bartek Szopka 41 | * 42 | * Licensed under MIT license. 43 | * 44 | */ 45 | 46 | jQuery.extend({ 47 | highlight: function (node, re, nodeName, className) { 48 | if (node.nodeType === 3) { 49 | var match = node.data.match(re); 50 | if (match) { 51 | var highlight = document.createElement(nodeName || 'span'); 52 | highlight.className = className || 'highlight'; 53 | var wordNode = node.splitText(match.index); 54 | wordNode.splitText(match[0].length); 55 | var wordClone = wordNode.cloneNode(true); 56 | highlight.appendChild(wordClone); 57 | wordNode.parentNode.replaceChild(highlight, wordNode); 58 | return 1; //skip added node in parent 59 | } 60 | } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children 61 | !/(script|style)/i.test(node.tagName) && // ignore script and style nodes 62 | !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted 63 | for (var i = 0; i < node.childNodes.length; i++) { 64 | i += jQuery.highlight(node.childNodes[i], re, nodeName, className); 65 | } 66 | } 67 | return 0; 68 | } 69 | }); 70 | 71 | jQuery.fn.unhighlight = function (options) { 72 | var settings = { className: 'highlight', element: 'span' }; 73 | jQuery.extend(settings, options); 74 | 75 | return this.find(settings.element + "." + settings.className).each(function () { 76 | var parent = this.parentNode; 77 | parent.replaceChild(this.firstChild, this); 78 | parent.normalize(); 79 | }).end(); 80 | }; 81 | 82 | jQuery.fn.highlight = function (words, options) { 83 | var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false }; 84 | jQuery.extend(settings, options); 85 | 86 | if (words.constructor === String) { 87 | words = [words]; 88 | } 89 | words = jQuery.grep(words, function(word, i){ 90 | return word != ''; 91 | }); 92 | words = jQuery.map(words, function(word, i) { 93 | return word.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"); 94 | }); 95 | if (words.length == 0) { return this; }; 96 | 97 | var flag = settings.caseSensitive ? "" : "i"; 98 | var pattern = "(" + words.join("|") + ")"; 99 | if (settings.wordsOnly) { 100 | pattern = "\\b" + pattern + "\\b"; 101 | } 102 | var re = new RegExp(pattern, flag); 103 | 104 | return this.each(function () { 105 | jQuery.highlight(this, re, settings.element, settings.className); 106 | }); 107 | }; 108 | 109 | -------------------------------------------------------------------------------- /source/layouts/layout.erb: -------------------------------------------------------------------------------- 1 | <%# 2 | Copyright 2008-2013 Concur Technologies, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | not use this file except in compliance with the License. You may obtain 6 | a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | License for the specific language governing permissions and limitations 14 | under the License. 15 | %> 16 | <% language_tabs = current_page.data.language_tabs || [] %> 17 | <% page_content = yield %> 18 | <% 19 | if current_page.data.includes 20 | current_page.data.includes.each do |include| 21 | page_content += partial("includes/#{include}") 22 | end 23 | end 24 | %> 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | <%= current_page.data.title || "API Documentation" %> 41 | 42 | 45 | <%= stylesheet_link_tag :screen, media: :screen %> 46 | <%= stylesheet_link_tag :print, media: :print %> 47 | <% if current_page.data.search %> 48 | <%= javascript_include_tag "all" %> 49 | <% else %> 50 | <%= javascript_include_tag "all_nosearch" %> 51 | <% end %> 52 | 53 | <%= favicon_tag 'https://audius.co/favicons/favicon.ico' %> 54 | 55 | 56 | 57 | 58 | 59 | NAV 60 | <%= image_tag('navbar.png') %> 61 | 62 | 63 |
      64 | <%= image_tag "logo.png", class: 'logo' %> 65 | <% if language_tabs.any? %> 66 |
      67 | <% language_tabs.each do |lang| %> 68 | <% if lang.is_a? Hash %> 69 | <%= lang.values.first %> 70 | <% else %> 71 | <%= lang %> 72 | <% end %> 73 | <% end %> 74 |
      75 | <% end %> 76 | <% if current_page.data.search %> 77 | 80 |
        81 | <% end %> 82 |
          83 | <% toc_data(page_content).each do |h1| %> 84 |
        • 85 | <%= h1[:content] %> 86 | <% if h1[:children].length > 0 %> 87 | 94 | <% end %> 95 |
        • 96 | <% end %> 97 |
        98 | <% if current_page.data.toc_footers %> 99 | 104 | <% end %> 105 |
        106 |
        107 |
        108 |
        109 | <%= page_content %> 110 |
        111 |
        112 | <% if language_tabs.any? %> 113 |
        114 | <% language_tabs.each do |lang| %> 115 | <% if lang.is_a? Hash %> 116 | <%= lang.values.first %> 117 | <% else %> 118 | <%= lang %> 119 | <% end %> 120 | <% end %> 121 |
        122 | <% end %> 123 |
        124 |
        125 | 126 | 127 | -------------------------------------------------------------------------------- /source/stylesheets/_icon-font.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'slate'; 3 | src:font-url('slate.eot?-syv14m'); 4 | src:font-url('slate.eot?#iefix-syv14m') format('embedded-opentype'), 5 | font-url('slate.woff2?-syv14m') format('woff2'), 6 | font-url('slate.woff?-syv14m') format('woff'), 7 | font-url('slate.ttf?-syv14m') format('truetype'), 8 | font-url('slate.svg?-syv14m#slate') format('svg'); 9 | font-weight: normal; 10 | font-style: normal; 11 | } 12 | 13 | /* Begin Manual Font Imports */ 14 | @font-face { 15 | font-family: 'Avenir Next LT Pro'; 16 | font-style: normal; 17 | font-weight: 100; 18 | src: font-url('AvenirNextLTPro-UltLt.ttf') format('truetype'), url('AvenirNextLTPro-UltLt.otf') format('opentype'); 19 | } 20 | @font-face { 21 | font-family: 'Avenir Next LT Pro'; 22 | font-style: normal; 23 | font-weight: 400; 24 | src: font-url('AvenirNextLTPro-Regular.ttf') format('truetype'), font-url('AvenirNextLTPro-Regular.otf') format('opentype'); 25 | } 26 | @font-face { 27 | font-family: 'Avenir Next LT Pro'; 28 | font-style: normal; 29 | font-weight: 500; 30 | src: font-url('AvenirNextLTPro-Medium.ttf') format('truetype'), font-url('AvenirNextLTPro-Medium.otf') format('opentype'); 31 | } 32 | @font-face { 33 | font-family: 'Avenir Next LT Pro'; 34 | font-style: normal; 35 | font-weight: 600; 36 | src: font-url('AvenirNextLTPro-Demi-Bold.ttf') format('truetype'), font-url('AvenirNextLTPro-Demi-Bold.otf') format('opentype'); 37 | } 38 | @font-face { 39 | font-family: 'Avenir Next LT Pro'; 40 | font-style: normal; 41 | font-weight: 700; 42 | src: font-url('AvenirNextLTPro-Bold.ttf') format('truetype'), font-url('AvenirNextLTPro-Bold.otf') format('opentype'); 43 | } 44 | @font-face { 45 | font-family: 'Avenir Next LT Pro'; 46 | font-style: normal; 47 | font-weight: 900; 48 | src: font-url('AvenirNextLTPro-Heavy.ttf') format('truetype'), font-url('AvenirNextLTPro-Heavy.otf') format('opentype'); 49 | } 50 | /* End Manual Font Imports */ 51 | 52 | %icon { 53 | font-family: 'slate'; 54 | speak: none; 55 | font-style: normal; 56 | font-weight: normal; 57 | font-variant: normal; 58 | text-transform: none; 59 | line-height: 1; 60 | } 61 | 62 | %icon-exclamation-sign { 63 | @extend %icon; 64 | content: "\e600"; 65 | } 66 | %icon-info-sign { 67 | @extend %icon; 68 | content: "\e602"; 69 | } 70 | %icon-ok-sign { 71 | @extend %icon; 72 | content: "\e606"; 73 | } 74 | %icon-search { 75 | @extend %icon; 76 | content: "\e607"; 77 | } 78 | -------------------------------------------------------------------------------- /source/stylesheets/_normalize.scss: -------------------------------------------------------------------------------- 1 | /*! normalize.css v3.0.2 | MIT License | git.io/normalize */ 2 | 3 | /** 4 | * 1. Set default font family to sans-serif. 5 | * 2. Prevent iOS text size adjust after orientation change, without disabling 6 | * user zoom. 7 | */ 8 | 9 | html { 10 | font-family: sans-serif; /* 1 */ 11 | -ms-text-size-adjust: 100%; /* 2 */ 12 | -webkit-text-size-adjust: 100%; /* 2 */ 13 | } 14 | 15 | /** 16 | * Remove default margin. 17 | */ 18 | 19 | body { 20 | margin: 0; 21 | } 22 | 23 | /* HTML5 display definitions 24 | ========================================================================== */ 25 | 26 | /** 27 | * Correct `block` display not defined for any HTML5 element in IE 8/9. 28 | * Correct `block` display not defined for `details` or `summary` in IE 10/11 29 | * and Firefox. 30 | * Correct `block` display not defined for `main` in IE 11. 31 | */ 32 | 33 | article, 34 | aside, 35 | details, 36 | figcaption, 37 | figure, 38 | footer, 39 | header, 40 | hgroup, 41 | main, 42 | menu, 43 | nav, 44 | section, 45 | summary { 46 | display: block; 47 | } 48 | 49 | /** 50 | * 1. Correct `inline-block` display not defined in IE 8/9. 51 | * 2. Normalize vertical alignment of `progress` in Chrome, Firefox, and Opera. 52 | */ 53 | 54 | audio, 55 | canvas, 56 | progress, 57 | video { 58 | display: inline-block; /* 1 */ 59 | vertical-align: baseline; /* 2 */ 60 | } 61 | 62 | /** 63 | * Prevent modern browsers from displaying `audio` without controls. 64 | * Remove excess height in iOS 5 devices. 65 | */ 66 | 67 | audio:not([controls]) { 68 | display: none; 69 | height: 0; 70 | } 71 | 72 | /** 73 | * Address `[hidden]` styling not present in IE 8/9/10. 74 | * Hide the `template` element in IE 8/9/11, Safari, and Firefox < 22. 75 | */ 76 | 77 | [hidden], 78 | template { 79 | display: none; 80 | } 81 | 82 | /* Links 83 | ========================================================================== */ 84 | 85 | /** 86 | * Remove the gray background color from active links in IE 10. 87 | */ 88 | 89 | a { 90 | background-color: transparent; 91 | } 92 | 93 | /** 94 | * Improve readability when focused and also mouse hovered in all browsers. 95 | */ 96 | 97 | a:active, 98 | a:hover { 99 | outline: 0; 100 | } 101 | 102 | /* Text-level semantics 103 | ========================================================================== */ 104 | 105 | /** 106 | * Address styling not present in IE 8/9/10/11, Safari, and Chrome. 107 | */ 108 | 109 | abbr[title] { 110 | border-bottom: 1px dotted; 111 | } 112 | 113 | /** 114 | * Address style set to `bolder` in Firefox 4+, Safari, and Chrome. 115 | */ 116 | 117 | b, 118 | strong { 119 | font-weight: bold; 120 | } 121 | 122 | /** 123 | * Address styling not present in Safari and Chrome. 124 | */ 125 | 126 | dfn { 127 | font-style: italic; 128 | } 129 | 130 | /** 131 | * Address variable `h1` font-size and margin within `section` and `article` 132 | * contexts in Firefox 4+, Safari, and Chrome. 133 | */ 134 | 135 | h1 { 136 | font-size: 2em; 137 | margin: 0.67em 0; 138 | } 139 | 140 | /** 141 | * Address styling not present in IE 8/9. 142 | */ 143 | 144 | mark { 145 | background: #ff0; 146 | color: #000; 147 | } 148 | 149 | /** 150 | * Address inconsistent and variable font size in all browsers. 151 | */ 152 | 153 | small { 154 | font-size: 80%; 155 | } 156 | 157 | /** 158 | * Prevent `sub` and `sup` affecting `line-height` in all browsers. 159 | */ 160 | 161 | sub, 162 | sup { 163 | font-size: 75%; 164 | line-height: 0; 165 | position: relative; 166 | vertical-align: baseline; 167 | } 168 | 169 | sup { 170 | top: -0.5em; 171 | } 172 | 173 | sub { 174 | bottom: -0.25em; 175 | } 176 | 177 | /* Embedded content 178 | ========================================================================== */ 179 | 180 | /** 181 | * Remove border when inside `a` element in IE 8/9/10. 182 | */ 183 | 184 | img { 185 | border: 0; 186 | } 187 | 188 | /** 189 | * Correct overflow not hidden in IE 9/10/11. 190 | */ 191 | 192 | svg:not(:root) { 193 | overflow: hidden; 194 | } 195 | 196 | /* Grouping content 197 | ========================================================================== */ 198 | 199 | /** 200 | * Address margin not present in IE 8/9 and Safari. 201 | */ 202 | 203 | figure { 204 | margin: 1em 40px; 205 | } 206 | 207 | /** 208 | * Address differences between Firefox and other browsers. 209 | */ 210 | 211 | hr { 212 | -moz-box-sizing: content-box; 213 | box-sizing: content-box; 214 | height: 0; 215 | } 216 | 217 | /** 218 | * Contain overflow in all browsers. 219 | */ 220 | 221 | pre { 222 | overflow: auto; 223 | } 224 | 225 | /** 226 | * Address odd `em`-unit font size rendering in all browsers. 227 | */ 228 | 229 | code, 230 | kbd, 231 | pre, 232 | samp { 233 | font-family: monospace, monospace; 234 | font-size: 1em; 235 | } 236 | 237 | /* Forms 238 | ========================================================================== */ 239 | 240 | /** 241 | * Known limitation: by default, Chrome and Safari on OS X allow very limited 242 | * styling of `select`, unless a `border` property is set. 243 | */ 244 | 245 | /** 246 | * 1. Correct color not being inherited. 247 | * Known issue: affects color of disabled elements. 248 | * 2. Correct font properties not being inherited. 249 | * 3. Address margins set differently in Firefox 4+, Safari, and Chrome. 250 | */ 251 | 252 | button, 253 | input, 254 | optgroup, 255 | select, 256 | textarea { 257 | color: inherit; /* 1 */ 258 | font: inherit; /* 2 */ 259 | margin: 0; /* 3 */ 260 | } 261 | 262 | /** 263 | * Address `overflow` set to `hidden` in IE 8/9/10/11. 264 | */ 265 | 266 | button { 267 | overflow: visible; 268 | } 269 | 270 | /** 271 | * Address inconsistent `text-transform` inheritance for `button` and `select`. 272 | * All other form control elements do not inherit `text-transform` values. 273 | * Correct `button` style inheritance in Firefox, IE 8/9/10/11, and Opera. 274 | * Correct `select` style inheritance in Firefox. 275 | */ 276 | 277 | button, 278 | select { 279 | text-transform: none; 280 | } 281 | 282 | /** 283 | * 1. Avoid the WebKit bug in Android 4.0.* where (2) destroys native `audio` 284 | * and `video` controls. 285 | * 2. Correct inability to style clickable `input` types in iOS. 286 | * 3. Improve usability and consistency of cursor style between image-type 287 | * `input` and others. 288 | */ 289 | 290 | button, 291 | html input[type="button"], /* 1 */ 292 | input[type="reset"], 293 | input[type="submit"] { 294 | -webkit-appearance: button; /* 2 */ 295 | cursor: pointer; /* 3 */ 296 | } 297 | 298 | /** 299 | * Re-set default cursor for disabled elements. 300 | */ 301 | 302 | button[disabled], 303 | html input[disabled] { 304 | cursor: default; 305 | } 306 | 307 | /** 308 | * Remove inner padding and border in Firefox 4+. 309 | */ 310 | 311 | button::-moz-focus-inner, 312 | input::-moz-focus-inner { 313 | border: 0; 314 | padding: 0; 315 | } 316 | 317 | /** 318 | * Address Firefox 4+ setting `line-height` on `input` using `!important` in 319 | * the UA stylesheet. 320 | */ 321 | 322 | input { 323 | line-height: normal; 324 | } 325 | 326 | /** 327 | * It's recommended that you don't attempt to style these elements. 328 | * Firefox's implementation doesn't respect box-sizing, padding, or width. 329 | * 330 | * 1. Address box sizing set to `content-box` in IE 8/9/10. 331 | * 2. Remove excess padding in IE 8/9/10. 332 | */ 333 | 334 | input[type="checkbox"], 335 | input[type="radio"] { 336 | box-sizing: border-box; /* 1 */ 337 | padding: 0; /* 2 */ 338 | } 339 | 340 | /** 341 | * Fix the cursor style for Chrome's increment/decrement buttons. For certain 342 | * `font-size` values of the `input`, it causes the cursor style of the 343 | * decrement button to change from `default` to `text`. 344 | */ 345 | 346 | input[type="number"]::-webkit-inner-spin-button, 347 | input[type="number"]::-webkit-outer-spin-button { 348 | height: auto; 349 | } 350 | 351 | /** 352 | * 1. Address `appearance` set to `searchfield` in Safari and Chrome. 353 | * 2. Address `box-sizing` set to `border-box` in Safari and Chrome 354 | * (include `-moz` to future-proof). 355 | */ 356 | 357 | input[type="search"] { 358 | -webkit-appearance: textfield; /* 1 */ 359 | -moz-box-sizing: content-box; 360 | -webkit-box-sizing: content-box; /* 2 */ 361 | box-sizing: content-box; 362 | } 363 | 364 | /** 365 | * Remove inner padding and search cancel button in Safari and Chrome on OS X. 366 | * Safari (but not Chrome) clips the cancel button when the search input has 367 | * padding (and `textfield` appearance). 368 | */ 369 | 370 | input[type="search"]::-webkit-search-cancel-button, 371 | input[type="search"]::-webkit-search-decoration { 372 | -webkit-appearance: none; 373 | } 374 | 375 | /** 376 | * Define consistent border, margin, and padding. 377 | */ 378 | 379 | fieldset { 380 | border: 1px solid #c0c0c0; 381 | margin: 0 2px; 382 | padding: 0.35em 0.625em 0.75em; 383 | } 384 | 385 | /** 386 | * 1. Correct `color` not being inherited in IE 8/9/10/11. 387 | * 2. Remove padding so people aren't caught out if they zero out fieldsets. 388 | */ 389 | 390 | legend { 391 | border: 0; /* 1 */ 392 | padding: 0; /* 2 */ 393 | } 394 | 395 | /** 396 | * Remove default vertical scrollbar in IE 8/9/10/11. 397 | */ 398 | 399 | textarea { 400 | overflow: auto; 401 | } 402 | 403 | /** 404 | * Don't inherit the `font-weight` (applied by a rule above). 405 | * NOTE: the default cannot safely be changed in Chrome and Safari on OS X. 406 | */ 407 | 408 | optgroup { 409 | font-weight: bold; 410 | } 411 | 412 | /* Tables 413 | ========================================================================== */ 414 | 415 | /** 416 | * Remove most spacing between table cells. 417 | */ 418 | 419 | table { 420 | border-collapse: collapse; 421 | border-spacing: 0; 422 | } 423 | 424 | td, 425 | th { 426 | padding: 0; 427 | } 428 | -------------------------------------------------------------------------------- /source/stylesheets/_rtl.scss: -------------------------------------------------------------------------------- 1 | //////////////////////////////////////////////////////////////////////////////// 2 | // RTL Styles Variables 3 | //////////////////////////////////////////////////////////////////////////////// 4 | 5 | $default: auto; 6 | 7 | //////////////////////////////////////////////////////////////////////////////// 8 | // TABLE OF CONTENTS 9 | //////////////////////////////////////////////////////////////////////////////// 10 | 11 | #toc>ul>li>a>span { 12 | float: left; 13 | } 14 | 15 | .toc-wrapper { 16 | transition: right 0.3s ease-in-out !important; 17 | left: $default !important; 18 | #{right}: 0; 19 | } 20 | 21 | .toc-h2 { 22 | padding-#{right}: $nav-padding + $nav-indent; 23 | } 24 | 25 | #nav-button { 26 | #{right}: 0; 27 | transition: right 0.3s ease-in-out; 28 | &.open { 29 | right: $nav-width 30 | } 31 | } 32 | 33 | //////////////////////////////////////////////////////////////////////////////// 34 | // PAGE LAYOUT AND CODE SAMPLE BACKGROUND 35 | //////////////////////////////////////////////////////////////////////////////// 36 | .page-wrapper { 37 | margin-#{left}: $default !important; 38 | margin-#{right}: $nav-width; 39 | .dark-box { 40 | #{right}: $default; 41 | #{left}: 0; 42 | } 43 | } 44 | 45 | .lang-selector { 46 | width: $default !important; 47 | a { 48 | float: right; 49 | } 50 | } 51 | 52 | //////////////////////////////////////////////////////////////////////////////// 53 | // CODE SAMPLE STYLES 54 | //////////////////////////////////////////////////////////////////////////////// 55 | .content { 56 | &>h1, 57 | &>h2, 58 | &>h3, 59 | &>h4, 60 | &>h5, 61 | &>h6, 62 | &>p, 63 | &>table, 64 | &>ul, 65 | &>ol, 66 | &>aside, 67 | &>dl { 68 | margin-#{left}: $examples-width; 69 | margin-#{right}: $default !important; 70 | } 71 | &>ul, 72 | &>ol { 73 | padding-#{right}: $main-padding + 15px; 74 | } 75 | table { 76 | th, 77 | td { 78 | text-align: right; 79 | } 80 | } 81 | dd { 82 | margin-#{right}: 15px; 83 | } 84 | aside { 85 | aside:before { 86 | padding-#{left}: 0.5em; 87 | } 88 | .search-highlight { 89 | background: linear-gradient(to top right, #F7E633 0%, #F1D32F 100%); 90 | } 91 | } 92 | pre, 93 | blockquote { 94 | float: left !important; 95 | clear: left !important; 96 | } 97 | } 98 | 99 | //////////////////////////////////////////////////////////////////////////////// 100 | // TYPOGRAPHY 101 | //////////////////////////////////////////////////////////////////////////////// 102 | h1, 103 | h2, 104 | h3, 105 | h4, 106 | h5, 107 | h6, 108 | p, 109 | aside { 110 | text-align: right; 111 | direction: rtl; 112 | } 113 | 114 | .toc-wrapper { 115 | text-align: right; 116 | direction: rtl; 117 | font-weight: 100 !important; 118 | } 119 | 120 | 121 | //////////////////////////////////////////////////////////////////////////////// 122 | // RESPONSIVE DESIGN 123 | //////////////////////////////////////////////////////////////////////////////// 124 | @media (max-width: $tablet-width) { 125 | .toc-wrapper { 126 | #{right}: -$nav-width; 127 | &.open { 128 | #{right}: 0; 129 | } 130 | } 131 | .page-wrapper { 132 | margin-#{right}: 0; 133 | } 134 | } 135 | 136 | @media (max-width: $phone-width) { 137 | %left-col { 138 | margin-#{left}: 0; 139 | } 140 | } 141 | -------------------------------------------------------------------------------- /source/stylesheets/_variables.scss: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2008-2013 Concur Technologies, Inc. 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); you may 5 | not use this file except in compliance with the License. You may obtain 6 | a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 12 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 13 | License for the specific language governing permissions and limitations 14 | under the License. 15 | */ 16 | 17 | 18 | //////////////////////////////////////////////////////////////////////////////// 19 | // CUSTOMIZE SLATE 20 | //////////////////////////////////////////////////////////////////////////////// 21 | // Use these settings to help adjust the appearance of Slate 22 | 23 | 24 | // BACKGROUND COLORS 25 | //////////////////// 26 | $nav-bg: #3F415B !default; 27 | $examples-bg: #3F415B !default; 28 | $code-bg: #393A54 !default; 29 | $code-annotation-bg: #5A5E78 !default; 30 | $nav-subitem-bg: #32334D !default; 31 | $nav-active-bg: rgba(145, 71, 204, 0.4) !default; 32 | $nav-active-parent-bg: rgba(145, 71, 204, 0.2)!default; // parent links of the current section 33 | $lang-select-border: #000 !default; 34 | $lang-select-bg: #32334D !default; 35 | $lang-select-active-bg: $examples-bg !default; // feel free to change this to blue or something 36 | $lang-select-pressed-bg: #4E4F6A !default; // color of language tab bg when mouse is pressed 37 | $main-bg: #32334D !default; 38 | $aside-notice-bg: #8fbcd4 !default; 39 | $aside-warning-bg: #c97a7e !default; 40 | $aside-success-bg: #6ac174 !default; 41 | $search-notice-bg: #c97a7e !default; 42 | 43 | 44 | // TEXT COLORS 45 | //////////////////// 46 | $main-text: #BEC5E0 !default; // main content text color 47 | $nav-text: rgba(190, 197, 224, 0.8) !default; 48 | $nav-active-text: #FAFAFA !default; 49 | $nav-active-parent-text:rgba(190, 197, 224, 0.8) !default; // parent links of the current section 50 | $lang-select-text: #BEC5E0 !default; // color of unselected language tab text 51 | $lang-select-active-text: #BEC5E0 !default; // color of selected language tab text 52 | $lang-select-pressed-text: #BEC5E0 !default; // color of language tab text when mouse is pressed 53 | 54 | 55 | // SIZES 56 | //////////////////// 57 | $nav-width: 230px !default; // width of the navbar 58 | $examples-width: 50% !default; // portion of the screen taken up by code examples 59 | $logo-margin: 0px !default; // margin below logo 60 | $main-padding: 28px !default; // padding to left and right of content & examples 61 | $nav-padding: 15px !default; // padding to left and right of navbar 62 | $nav-v-padding: 10px !default; // padding used vertically around search boxes and results 63 | $nav-indent: 10px !default; // extra padding for ToC subitems 64 | $code-annotation-padding: 13px !default; // padding inside code annotations 65 | $h1-margin-bottom: 21px !default; // padding under the largest header tags 66 | $tablet-width: 930px !default; // min width before reverting to tablet size 67 | $phone-width: $tablet-width - $nav-width !default; // min width before reverting to mobile size 68 | 69 | 70 | // FONTS 71 | //////////////////// 72 | %default-font { 73 | font-family: 'Avenir Next LT Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif; 74 | font-size: 16px; 75 | font-weight: 500; 76 | } 77 | 78 | %header-font { 79 | @extend %default-font; 80 | font-weight: bold; 81 | } 82 | 83 | %code-font { 84 | font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif; 85 | font-size: 12px; 86 | line-height: 1.5; 87 | } 88 | 89 | 90 | // OTHER 91 | //////////////////// 92 | $nav-footer-border-color: #484459 !default; 93 | $search-box-border-color: #CBD1E3 !default; 94 | 95 | 96 | //////////////////////////////////////////////////////////////////////////////// 97 | // INTERNAL 98 | //////////////////////////////////////////////////////////////////////////////// 99 | // These settings are probably best left alone. 100 | 101 | %break-words { 102 | word-break: break-all; 103 | hyphens: auto; 104 | } 105 | -------------------------------------------------------------------------------- /source/stylesheets/print.css.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | @import 'normalize'; 3 | @import 'variables'; 4 | @import 'icon-font'; 5 | 6 | /* 7 | Copyright 2008-2013 Concur Technologies, Inc. 8 | 9 | Licensed under the Apache License, Version 2.0 (the "License"); you may 10 | not use this file except in compliance with the License. You may obtain 11 | a copy of the License at 12 | 13 | http://www.apache.org/licenses/LICENSE-2.0 14 | 15 | Unless required by applicable law or agreed to in writing, software 16 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 17 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 18 | License for the specific language governing permissions and limitations 19 | under the License. 20 | */ 21 | 22 | $print-color: #999; 23 | $print-color-light: #ccc; 24 | $print-font-size: 12px; 25 | 26 | body { 27 | @extend %default-font; 28 | } 29 | 30 | .tocify, .toc-footer, .lang-selector, .search, #nav-button { 31 | display: none; 32 | } 33 | 34 | .tocify-wrapper>img { 35 | margin: 0 auto; 36 | display: block; 37 | } 38 | 39 | .content { 40 | font-size: 12px; 41 | 42 | pre, code { 43 | @extend %code-font; 44 | @extend %break-words; 45 | border: 1px solid $print-color; 46 | border-radius: 5px; 47 | font-size: 0.8em; 48 | } 49 | 50 | pre { 51 | code { 52 | border: 0; 53 | } 54 | } 55 | 56 | pre { 57 | padding: 1.3em; 58 | } 59 | 60 | code { 61 | padding: 0.2em; 62 | } 63 | 64 | table { 65 | border: 1px solid $print-color; 66 | tr { 67 | border-bottom: 1px solid $print-color; 68 | } 69 | td,th { 70 | padding: 0.7em; 71 | } 72 | } 73 | 74 | p { 75 | line-height: 1.5; 76 | } 77 | 78 | a { 79 | text-decoration: none; 80 | color: #000; 81 | } 82 | 83 | h1 { 84 | @extend %header-font; 85 | font-size: 2.5em; 86 | padding-top: 0.5em; 87 | padding-bottom: 0.5em; 88 | margin-top: 1em; 89 | margin-bottom: $h1-margin-bottom; 90 | border: 2px solid $print-color-light; 91 | border-width: 2px 0; 92 | text-align: center; 93 | } 94 | 95 | h2 { 96 | @extend %header-font; 97 | font-size: 1.8em; 98 | margin-top: 2em; 99 | border-top: 2px solid $print-color-light; 100 | padding-top: 0.8em; 101 | } 102 | 103 | h1+h2, h1+div+h2 { 104 | border-top: none; 105 | padding-top: 0; 106 | margin-top: 0; 107 | } 108 | 109 | h3, h4 { 110 | @extend %header-font; 111 | font-size: 0.8em; 112 | margin-top: 1.5em; 113 | margin-bottom: 0.8em; 114 | text-transform: uppercase; 115 | } 116 | 117 | h5, h6 { 118 | text-transform: uppercase; 119 | } 120 | 121 | aside { 122 | padding: 1em; 123 | border: 1px solid $print-color-light; 124 | border-radius: 5px; 125 | margin-top: 1.5em; 126 | margin-bottom: 1.5em; 127 | line-height: 1.6; 128 | } 129 | 130 | aside:before { 131 | vertical-align: middle; 132 | padding-right: 0.5em; 133 | font-size: 14px; 134 | } 135 | 136 | aside.notice:before { 137 | @extend %icon-info-sign; 138 | } 139 | 140 | aside.warning:before { 141 | @extend %icon-exclamation-sign; 142 | } 143 | 144 | aside.success:before { 145 | @extend %icon-ok-sign; 146 | } 147 | } -------------------------------------------------------------------------------- /swagger/examples/playlists.search.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://usermetadata.audius.co/content/Qmc7RFzLGgW3DUTgKK49LzxEwe3Lmb47q85ZwJJRVYTXPr/150x150.jpg", 6 | "480x480": "https://usermetadata.audius.co/content/Qmc7RFzLGgW3DUTgKK49LzxEwe3Lmb47q85ZwJJRVYTXPr/480x480.jpg", 7 | "1000x1000": "https://usermetadata.audius.co/content/Qmc7RFzLGgW3DUTgKK49LzxEwe3Lmb47q85ZwJJRVYTXPr/1000x1000.jpg" 8 | }, 9 | "description": "All the latest hot & new tracks on Audius! Prepare to buckle in for a trip through various genres featuring artists you love and new artists you are about to discover.", 10 | "permalink": "/Audius/playlist/hot-new-on-audius-🔥", 11 | "id": "DOPRl", 12 | "is_album": false, 13 | "playlist_name": "Hot & New on Audius 🔥", 14 | "repost_count": 1776, 15 | "favorite_count": 1243059, 16 | "total_play_count": 129802, 17 | "user": { 18 | "album_count": 0, 19 | "artist_pick_track_id": null, 20 | "bio": "The official Audius account!\n\nCreating a decentralized and open-source streaming music platform controlled by artists, fans, & developers.\n\nhttps://discord.gg/audius\nhttps://t.me/audius", 21 | "cover_photo": { 22 | "640x": "https://usermetadata.audius.co/content/QmSeB4DY1qBtp9hbnmMwnkGepRY6tRrNQcgZU2oNk4SK1q/640x.jpg", 23 | "2000x": "https://usermetadata.audius.co/content/QmSeB4DY1qBtp9hbnmMwnkGepRY6tRrNQcgZU2oNk4SK1q/2000x.jpg" 24 | }, 25 | "followee_count": 856, 26 | "follower_count": 1525903, 27 | "does_follow_current_user": false, 28 | "handle": "Audius", 29 | "id": "eJ57D", 30 | "is_verified": true, 31 | "location": "SF & LA", 32 | "name": "Audius", 33 | "playlist_count": 6, 34 | "profile_picture": { 35 | "150x150": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/150x150.jpg", 36 | "480x480": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/480x480.jpg", 37 | "1000x1000": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/1000x1000.jpg" 38 | }, 39 | "repost_count": 3487, 40 | "track_count": 0, 41 | "is_deactivated": false, 42 | "is_available": true, 43 | "erc_wallet": "0x3256bd2d0b1984e7df4fa525017ad9ba48470760", 44 | "spl_wallet": "D1WXgUS2pnrVQTEqSGy2t2oxowahUL8Pw2Qy64CvTi79", 45 | "supporter_count": 215, 46 | "supporting_count": 4, 47 | "total_audio_balance": null 48 | } 49 | } 50 | ] 51 | } -------------------------------------------------------------------------------- /swagger/examples/playlists.trending.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://audius-content-12.cultur3stake.com/content/Qmf53YjSDjsu1w7sYian2tJcNpzvwQZWN8uS3ajBZUTEVZ/150x150.jpg", 6 | "480x480": "https://audius-content-12.cultur3stake.com/content/Qmf53YjSDjsu1w7sYian2tJcNpzvwQZWN8uS3ajBZUTEVZ/480x480.jpg", 7 | "1000x1000": "https://audius-content-12.cultur3stake.com/content/Qmf53YjSDjsu1w7sYian2tJcNpzvwQZWN8uS3ajBZUTEVZ/1000x1000.jpg" 8 | }, 9 | "description": "The first installment of Pala Chrome's 'You Stay High' remix EP is out now featuring:\n\nalex martian\nfreeloadr\nDust Of Apollon\nGabriel Earwood\n2chills\n\nArtworks by 6amsunset.", 10 | "permalink": "/kumocollective/playlist/pala-chrome-you-stay-high-remix-pack-part-1", 11 | "id": "5123bEX", 12 | "is_album": false, 13 | "playlist_name": "Pala Chrome - You Stay High REMIX PACK (part 1)", 14 | "repost_count": 18, 15 | "favorite_count": 27, 16 | "total_play_count": 1845, 17 | "user": { 18 | "album_count": 6, 19 | "artist_pick_track_id": "WNYwG6Z", 20 | "bio": "Record label from Italy, established in 2017. \n\nas free as a cloud ☁️\n\nVisit the KUMOverse\nhttps://kumocollective.com", 21 | "cover_photo": { 22 | "640x": "https://audius-content-12.cultur3stake.com/content/Qme9kcC1xNmRWYsfmzqXYiahUrAb5uuqrT1Lf48VU27goY/640x.jpg", 23 | "2000x": "https://audius-content-12.cultur3stake.com/content/Qme9kcC1xNmRWYsfmzqXYiahUrAb5uuqrT1Lf48VU27goY/2000x.jpg" 24 | }, 25 | "followee_count": 19, 26 | "follower_count": 13558, 27 | "does_follow_current_user": false, 28 | "handle": "kumocollective", 29 | "id": "Lj0ae", 30 | "is_verified": false, 31 | "location": "Amsterdam", 32 | "name": "KUMO Collective", 33 | "playlist_count": 32, 34 | "profile_picture": { 35 | "150x150": "https://audius-content-12.cultur3stake.com/content/QmWd4zNC8hEfTScBDi5YSHf6YV6ETUbstoDynXMGsoHX6Q/150x150.jpg", 36 | "480x480": "https://audius-content-12.cultur3stake.com/content/QmWd4zNC8hEfTScBDi5YSHf6YV6ETUbstoDynXMGsoHX6Q/480x480.jpg", 37 | "1000x1000": "https://audius-content-12.cultur3stake.com/content/QmWd4zNC8hEfTScBDi5YSHf6YV6ETUbstoDynXMGsoHX6Q/1000x1000.jpg" 38 | }, 39 | "repost_count": 533, 40 | "track_count": 134, 41 | "is_deactivated": false, 42 | "is_available": true, 43 | "erc_wallet": "0x62b166e2d2c8882e5e624ba1d6eba939424fc3f7", 44 | "spl_wallet": "5f5AkVbVPFDCVXBr1fcZ7kYaahQEXYYTFuxJ6RDvjeHS", 45 | "supporter_count": 12, 46 | "supporting_count": 0, 47 | "total_audio_balance": 1271 48 | } 49 | } 50 | ] 51 | } -------------------------------------------------------------------------------- /swagger/examples/playlists.{playlist_id}.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://usermetadata.audius.co/content/Qmc7RFzLGgW3DUTgKK49LzxEwe3Lmb47q85ZwJJRVYTXPr/150x150.jpg", 6 | "480x480": "https://usermetadata.audius.co/content/Qmc7RFzLGgW3DUTgKK49LzxEwe3Lmb47q85ZwJJRVYTXPr/480x480.jpg", 7 | "1000x1000": "https://usermetadata.audius.co/content/Qmc7RFzLGgW3DUTgKK49LzxEwe3Lmb47q85ZwJJRVYTXPr/1000x1000.jpg" 8 | }, 9 | "description": "All the latest hot & new tracks on Audius! Prepare to buckle in for a trip through various genres featuring artists you love and new artists you are about to discover.", 10 | "permalink": "/Audius/playlist/hot-new-on-audius-🔥", 11 | "id": "DOPRl", 12 | "is_album": false, 13 | "playlist_name": "Hot & New on Audius 🔥", 14 | "repost_count": 1776, 15 | "favorite_count": 1243059, 16 | "total_play_count": 129814, 17 | "user": { 18 | "album_count": 0, 19 | "artist_pick_track_id": null, 20 | "bio": "The official Audius account!\n\nCreating a decentralized and open-source streaming music platform controlled by artists, fans, & developers.\n\nhttps://discord.gg/audius\nhttps://t.me/audius", 21 | "cover_photo": { 22 | "640x": "https://usermetadata.audius.co/content/QmSeB4DY1qBtp9hbnmMwnkGepRY6tRrNQcgZU2oNk4SK1q/640x.jpg", 23 | "2000x": "https://usermetadata.audius.co/content/QmSeB4DY1qBtp9hbnmMwnkGepRY6tRrNQcgZU2oNk4SK1q/2000x.jpg" 24 | }, 25 | "followee_count": 856, 26 | "follower_count": 1525903, 27 | "does_follow_current_user": false, 28 | "handle": "Audius", 29 | "id": "eJ57D", 30 | "is_verified": true, 31 | "location": "SF & LA", 32 | "name": "Audius", 33 | "playlist_count": 6, 34 | "profile_picture": { 35 | "150x150": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/150x150.jpg", 36 | "480x480": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/480x480.jpg", 37 | "1000x1000": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/1000x1000.jpg" 38 | }, 39 | "repost_count": 3489, 40 | "track_count": 0, 41 | "is_deactivated": false, 42 | "is_available": true, 43 | "erc_wallet": "0x3256bd2d0b1984e7df4fa525017ad9ba48470760", 44 | "spl_wallet": "D1WXgUS2pnrVQTEqSGy2t2oxowahUL8Pw2Qy64CvTi79", 45 | "supporter_count": 215, 46 | "supporting_count": 4, 47 | "total_audio_balance": 16150 48 | } 49 | } 50 | ] 51 | } -------------------------------------------------------------------------------- /swagger/examples/playlists.{playlist_id}.tracks.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://blockdaemon-audius-content-06.bdnodes.net/content/QmZJ9dKg4S1BRnRiHPUpoDCjKtTxtg8Nhgei2vTkgNyQ1h/150x150.jpg", 6 | "480x480": "https://blockdaemon-audius-content-06.bdnodes.net/content/QmZJ9dKg4S1BRnRiHPUpoDCjKtTxtg8Nhgei2vTkgNyQ1h/480x480.jpg", 7 | "1000x1000": "https://blockdaemon-audius-content-06.bdnodes.net/content/QmZJ9dKg4S1BRnRiHPUpoDCjKtTxtg8Nhgei2vTkgNyQ1h/1000x1000.jpg" 8 | }, 9 | "description": "Louis Futon “David Blaine” Out Now: https://stem.ffm.to/davidblaine\n\nLouis Futon Merch, Tour Dates, and more... \nhttps://louisfutonbeats.com/\n\nSubscribe to Louis Futon\nhttps://bit.ly/LouisFutonYouTube\n\nFollow Louis Futon\nhttps://instagram.com/louisfutonbeats\nhttps://twitter.com/louisfutonbeats\nhttps://tiktok.com/@notlouisfuton\nhttps://facebook.com/Louisfutonbeats\nhttps://www.twitch.tv/louisfutontv\n\nJoin the community\nhttps://discord.gg/geshyzwA\n\n#LouisFuton #DavidBlaine\n\nMixed/Mastered byJacob Weinstein \nCo-written by Ariel Shrum\nSax, bass clarinet & flute by Hailey Niswanger", 10 | "genre": "Electronic", 11 | "id": "7dm4zrr", 12 | "track_cid": "QmWwMTU6rjCp2t3xtjjLUXSF85bxJkxQesrcrSd8fJ5P2d", 13 | "mood": "Sensual", 14 | "release_date": "Fri May 05 2023 10:10:02 GMT-0700", 15 | "remix_of": { 16 | "tracks": null 17 | }, 18 | "repost_count": 54, 19 | "favorite_count": 100, 20 | "tags": "louisfuton,davidblaine", 21 | "title": "Louis Futon - David Blaine", 22 | "user": { 23 | "album_count": 2, 24 | "artist_pick_track_id": null, 25 | "bio": "Management: eric@jet-mgmt.com", 26 | "cover_photo": { 27 | "640x": "https://blockdaemon-audius-content-06.bdnodes.net/content/QmWWPNRrzgasSoGt4SZceuukFf8FbJR8mzsgtYpDNRWkwf/640x.jpg", 28 | "2000x": "https://blockdaemon-audius-content-06.bdnodes.net/content/QmWWPNRrzgasSoGt4SZceuukFf8FbJR8mzsgtYpDNRWkwf/2000x.jpg" 29 | }, 30 | "followee_count": 15, 31 | "follower_count": 2239, 32 | "does_follow_current_user": false, 33 | "handle": "louisfutonbeats", 34 | "id": "n098k", 35 | "is_verified": true, 36 | "location": "Los Angeles, CA", 37 | "name": "Louis Futon", 38 | "playlist_count": 2, 39 | "profile_picture": { 40 | "150x150": "https://blockdaemon-audius-content-06.bdnodes.net/content/QmeRrmABZJTGGqQsTo19FkvepEHoZPsmkabGPcLxxfXx2q/150x150.jpg", 41 | "480x480": "https://blockdaemon-audius-content-06.bdnodes.net/content/QmeRrmABZJTGGqQsTo19FkvepEHoZPsmkabGPcLxxfXx2q/480x480.jpg", 42 | "1000x1000": "https://blockdaemon-audius-content-06.bdnodes.net/content/QmeRrmABZJTGGqQsTo19FkvepEHoZPsmkabGPcLxxfXx2q/1000x1000.jpg" 43 | }, 44 | "repost_count": 10, 45 | "track_count": 50, 46 | "is_deactivated": false, 47 | "is_available": true, 48 | "erc_wallet": "0x4ef00cc32ce488af3ec291a89549712b2dd14f2e", 49 | "spl_wallet": "1hfVnihF2p6F6n22easszN3wpn5efVaDGTDFsUxmJ9V", 50 | "supporter_count": 6, 51 | "supporting_count": 0, 52 | "total_audio_balance": 62 53 | }, 54 | "duration": 197, 55 | "downloadable": true, 56 | "play_count": 24254, 57 | "permalink": "/louisfutonbeats/louis-futon-david-blaine", 58 | "is_streamable": true 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /swagger/examples/resolve.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "artwork": { 4 | "150x150": "https://audius-content-1.cultur3stake.com/content/QmRSVdvMkVnV4UhGNQzNm8pJLLsGwQXyZkCp1dAMYfZx9d/150x150.jpg", 5 | "480x480": "https://audius-content-1.cultur3stake.com/content/QmRSVdvMkVnV4UhGNQzNm8pJLLsGwQXyZkCp1dAMYfZx9d/480x480.jpg", 6 | "1000x1000": "https://audius-content-1.cultur3stake.com/content/QmRSVdvMkVnV4UhGNQzNm8pJLLsGwQXyZkCp1dAMYfZx9d/1000x1000.jpg" 7 | }, 8 | "description": "HYPERMANTRA.\n1 play, 7 chapters, no breaks.\n\nget it here: http://tiny.cc/hypermantra\n\npremiered on Ä Live 8/22.\n\ncredits: ilian, the salsoul orchestra, brian bennett, 100% pure poison, you & explosion band, yuji ohno, frank ocean.", 9 | "genre": "Electronic", 10 | "id": "V4W8r", 11 | "track_cid": "QmcPiBC9eszbYnFaBTxWW1njhWrhYGb2GyfsmsrALNvgcK", 12 | "mood": "Yearning", 13 | "release_date": "Mon Aug 24 2020 21:08:36 GMT+0200", 14 | "remix_of": { 15 | "tracks": null 16 | }, 17 | "repost_count": 78, 18 | "favorite_count": 173, 19 | "tags": null, 20 | "title": "HYPERMANTRA", 21 | "user": { 22 | "album_count": 0, 23 | "artist_pick_track_id": null, 24 | "bio": "kawaii bounce 🌟\n\nmy sample pack: gum.co/camocandybox1\n\nheader by paprikaworm", 25 | "cover_photo": { 26 | "640x": "https://audius-content-1.cultur3stake.com/content/QmRf3uh9tS8EbV59ArZwJN8UnpsjMyRyp2LVrpU7K1DYm2/640x.jpg", 27 | "2000x": "https://audius-content-1.cultur3stake.com/content/QmRf3uh9tS8EbV59ArZwJN8UnpsjMyRyp2LVrpU7K1DYm2/2000x.jpg" 28 | }, 29 | "followee_count": 208, 30 | "follower_count": 17635, 31 | "does_follow_current_user": false, 32 | "handle": "camouflybeats", 33 | "id": "nd6JD", 34 | "is_verified": true, 35 | "location": "", 36 | "name": "camoufly", 37 | "playlist_count": 5, 38 | "profile_picture": { 39 | "150x150": "https://audius-content-1.cultur3stake.com/content/QmP7RZkooL73JNMDSQ34TYYARzmYD8Xd9onA7kh7U5h3PR/150x150.jpg", 40 | "480x480": "https://audius-content-1.cultur3stake.com/content/QmP7RZkooL73JNMDSQ34TYYARzmYD8Xd9onA7kh7U5h3PR/480x480.jpg", 41 | "1000x1000": "https://audius-content-1.cultur3stake.com/content/QmP7RZkooL73JNMDSQ34TYYARzmYD8Xd9onA7kh7U5h3PR/1000x1000.jpg" 42 | }, 43 | "repost_count": 162, 44 | "track_count": 80, 45 | "is_deactivated": false, 46 | "is_available": true, 47 | "erc_wallet": "0xa65a69a3c38b55b9a3f83266bcc36fe6950cd85f", 48 | "spl_wallet": "2bnJKYk6WnseedNWkDEACmS5563uxLCrSRAsQqora947", 49 | "supporter_count": 32, 50 | "supporting_count": 0, 51 | "total_audio_balance": 3496 52 | }, 53 | "duration": 1741, 54 | "downloadable": false, 55 | "play_count": 12927, 56 | "permalink": "/camouflybeats/hypermantra-86216", 57 | "is_streamable": true 58 | } 59 | } -------------------------------------------------------------------------------- /swagger/examples/tips.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "amount": "3000000000000000000", 5 | "sender": { 6 | "album_count": 0, 7 | "artist_pick_track_id": null, 8 | "bio": "Comunidad de habla Hispana de Audius. Comparte tu música en tus redes sociales y etiquétanos https://linktr.ee/audiusspanish\n\nhttps://discord.com/channels/557662127305785361/862740191046533170", 9 | "cover_photo": { 10 | "640x": "https://blockdaemon-audius-content-04.bdnodes.net/content/QmdQcjCgPa5N1Jb2JrqsFZcHYAR1RGd9YJuiswc4WyHDg9/640x.jpg", 11 | "2000x": "https://blockdaemon-audius-content-04.bdnodes.net/content/QmdQcjCgPa5N1Jb2JrqsFZcHYAR1RGd9YJuiswc4WyHDg9/2000x.jpg" 12 | }, 13 | "followee_count": 283, 14 | "follower_count": 97, 15 | "does_follow_current_user": false, 16 | "handle": "AudiusSpanishCommunity", 17 | "id": "Y99y7Jq", 18 | "is_verified": false, 19 | "location": "Latin America & Spain", 20 | "name": "Audius Español 🎧", 21 | "playlist_count": 3, 22 | "profile_picture": { 23 | "150x150": "https://blockdaemon-audius-content-04.bdnodes.net/content/QmWSefzBeuv98mTCKz6sMYdhrLEJDXYzdptQ2RyrNs5EWH/150x150.jpg", 24 | "480x480": "https://blockdaemon-audius-content-04.bdnodes.net/content/QmWSefzBeuv98mTCKz6sMYdhrLEJDXYzdptQ2RyrNs5EWH/480x480.jpg", 25 | "1000x1000": "https://blockdaemon-audius-content-04.bdnodes.net/content/QmWSefzBeuv98mTCKz6sMYdhrLEJDXYzdptQ2RyrNs5EWH/1000x1000.jpg" 26 | }, 27 | "repost_count": 92, 28 | "track_count": 0, 29 | "is_deactivated": false, 30 | "is_available": true, 31 | "erc_wallet": "0x2225f4d82ae264d247f2821e3be5d0a3e3fcd2a7", 32 | "spl_wallet": "F1xQ7nYN1h5PL2biNGoTsChMHBKgprvPE7Frr6kBLadb", 33 | "supporter_count": 5, 34 | "supporting_count": 51, 35 | "total_audio_balance": 191 36 | }, 37 | "receiver": { 38 | "album_count": 0, 39 | "artist_pick_track_id": null, 40 | "bio": "Electronic Music Artist From Buenos Aires - Argentina (Minimal - Tech House)\n\nRoad to Music Decentralization ♥", 41 | "cover_photo": { 42 | "640x": "https://audius-content-7.figment.io/content/QmYRKtSfYVPWJYezhKhA4WzAMuqpQDPZcR3DVfdzkvHWaM/640x.jpg", 43 | "2000x": "https://audius-content-7.figment.io/content/QmYRKtSfYVPWJYezhKhA4WzAMuqpQDPZcR3DVfdzkvHWaM/2000x.jpg" 44 | }, 45 | "followee_count": 1131, 46 | "follower_count": 1024, 47 | "does_follow_current_user": false, 48 | "handle": "xguidosantiago", 49 | "id": "dEY9m", 50 | "is_verified": false, 51 | "location": "", 52 | "name": "Guido Santiago", 53 | "playlist_count": 0, 54 | "profile_picture": { 55 | "150x150": "https://audius-content-7.figment.io/content/QmUC1ddv4sd3qw5GgRSTDw5HUdDs8QPngZ195Zk9RXHvXB/150x150.jpg", 56 | "480x480": "https://audius-content-7.figment.io/content/QmUC1ddv4sd3qw5GgRSTDw5HUdDs8QPngZ195Zk9RXHvXB/480x480.jpg", 57 | "1000x1000": "https://audius-content-7.figment.io/content/QmUC1ddv4sd3qw5GgRSTDw5HUdDs8QPngZ195Zk9RXHvXB/1000x1000.jpg" 58 | }, 59 | "repost_count": 1, 60 | "track_count": 5, 61 | "is_deactivated": false, 62 | "is_available": true, 63 | "erc_wallet": "0x53fde452fc2d54f523da5dcde511948109c71bff", 64 | "spl_wallet": "FZg7NYCsfFLBeXbdm1xXoTsBUCPZ6brZnJvDzP41Ndze", 65 | "supporter_count": 1, 66 | "supporting_count": 0, 67 | "total_audio_balance": 5 68 | }, 69 | "created_at": "2023-05-15 22:31:02" 70 | } 71 | ] 72 | } -------------------------------------------------------------------------------- /swagger/examples/tracks.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/150x150.jpg", 6 | "480x480": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/480x480.jpg", 7 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/1000x1000.jpg" 8 | }, 9 | "description": "@baauer b2b @partyfavor live set at Brownies & Lemonade Block Party LA at The Shrine on 7.3.19.", 10 | "genre": "Electronic", 11 | "id": "D7KyD", 12 | "track_cid": "QmeeTjhUvwQRtNYQwiC7Uebuhi4p9mNQNESb3AFaJCYqNz", 13 | "mood": "Fiery", 14 | "release_date": "Mon Sep 23 2019 12:35:10 GMT-0700", 15 | "remix_of": { 16 | "tracks": null 17 | }, 18 | "repost_count": 430, 19 | "favorite_count": 977, 20 | "tags": "baauer,partyfavor,browniesandlemonade,live", 21 | "title": "Paauer | Baauer B2B Party Favor | B&L Block Party LA (Live Set)", 22 | "user": { 23 | "album_count": 0, 24 | "artist_pick_track_id": "D7KyD", 25 | "bio": "Makin' moves & keeping you on your toes.\nlinktr.ee/browniesandlemonade", 26 | "cover_photo": { 27 | "640x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/640x.jpg", 28 | "2000x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/2000x.jpg" 29 | }, 30 | "followee_count": 26, 31 | "follower_count": 34503, 32 | "does_follow_current_user": false, 33 | "handle": "TeamBandL", 34 | "id": "nlGNe", 35 | "is_verified": true, 36 | "location": "Los Angeles, CA", 37 | "name": "Brownies & Lemonade", 38 | "playlist_count": 2, 39 | "profile_picture": { 40 | "150x150": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/150x150.jpg", 41 | "480x480": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/480x480.jpg", 42 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/1000x1000.jpg" 43 | }, 44 | "repost_count": 5, 45 | "track_count": 10, 46 | "is_deactivated": false, 47 | "is_available": true, 48 | "erc_wallet": "0x8bc337e467cec1e7b05e54c7d1f90814a78d259e", 49 | "spl_wallet": "WXBYqzejMr5qxmuDrvVTDQopr7vdZt5szsoSSb3EvQH", 50 | "supporter_count": 9, 51 | "supporting_count": 0, 52 | "total_audio_balance": 3123 53 | }, 54 | "duration": 5265, 55 | "downloadable": false, 56 | "play_count": 355660, 57 | "permalink": "/TeamBandL/paauer-|-baauer-b2b-party-favor-|-bl-block-party-la-live-set-725", 58 | "is_streamable": true 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /swagger/examples/tracks.search.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/150x150.jpg", 6 | "480x480": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/480x480.jpg", 7 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/1000x1000.jpg" 8 | }, 9 | "description": "@baauer b2b @partyfavor live set at Brownies & Lemonade Block Party LA at The Shrine on 7.3.19.", 10 | "genre": "Electronic", 11 | "id": "D7KyD", 12 | "track_cid": "QmeeTjhUvwQRtNYQwiC7Uebuhi4p9mNQNESb3AFaJCYqNz", 13 | "mood": "Fiery", 14 | "release_date": "Mon Sep 23 2019 12:35:10 GMT-0700", 15 | "remix_of": { 16 | "tracks": null 17 | }, 18 | "repost_count": 430, 19 | "favorite_count": 977, 20 | "tags": "baauer,partyfavor,browniesandlemonade,live", 21 | "title": "Paauer | Baauer B2B Party Favor | B&L Block Party LA (Live Set)", 22 | "user": { 23 | "album_count": 0, 24 | "artist_pick_track_id": "D7KyD", 25 | "bio": "Makin' moves & keeping you on your toes.\nlinktr.ee/browniesandlemonade", 26 | "cover_photo": { 27 | "640x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/640x.jpg", 28 | "2000x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/2000x.jpg" 29 | }, 30 | "followee_count": 26, 31 | "follower_count": 34503, 32 | "does_follow_current_user": false, 33 | "handle": "TeamBandL", 34 | "id": "nlGNe", 35 | "is_verified": true, 36 | "location": "Los Angeles, CA", 37 | "name": "Brownies & Lemonade", 38 | "playlist_count": 2, 39 | "profile_picture": { 40 | "150x150": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/150x150.jpg", 41 | "480x480": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/480x480.jpg", 42 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/1000x1000.jpg" 43 | }, 44 | "repost_count": 5, 45 | "track_count": 10, 46 | "is_deactivated": false, 47 | "is_available": true, 48 | "erc_wallet": "0x8bc337e467cec1e7b05e54c7d1f90814a78d259e", 49 | "spl_wallet": "WXBYqzejMr5qxmuDrvVTDQopr7vdZt5szsoSSb3EvQH", 50 | "supporter_count": 9, 51 | "supporting_count": 0, 52 | "total_audio_balance": null 53 | }, 54 | "duration": 5266, 55 | "downloadable": false, 56 | "play_count": 355659, 57 | "permalink": "/TeamBandL/paauer-|-baauer-b2b-party-favor-|-bl-block-party-la-live-set-725", 58 | "is_streamable": true 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /swagger/examples/tracks.trending.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://creatornode3.audius.co/content/QmY7uocBHuSyW3aWuzZ6MeHNod8ph4TmStJJa2v4KXCdXe/150x150.jpg", 6 | "480x480": "https://creatornode3.audius.co/content/QmY7uocBHuSyW3aWuzZ6MeHNod8ph4TmStJJa2v4KXCdXe/480x480.jpg", 7 | "1000x1000": "https://creatornode3.audius.co/content/QmY7uocBHuSyW3aWuzZ6MeHNod8ph4TmStJJa2v4KXCdXe/1000x1000.jpg" 8 | }, 9 | "description": "PBJ with NITTI out now!! ", 10 | "genre": "Electronic", 11 | "id": "2o8qVY6", 12 | "track_cid": "QmVbmiJQ5vHB5RfTGWDrUdHUrd4aTKVV4SpCx48aBoPdS6", 13 | "mood": "Energizing", 14 | "release_date": "Mon May 08 2023 06:37:27 GMT-0700", 15 | "remix_of": { 16 | "tracks": null 17 | }, 18 | "repost_count": 33, 19 | "favorite_count": 58, 20 | "tags": "henryfong,nitti,pbj,basshouse", 21 | "title": "Henry Fong & NITTI - PBJ", 22 | "user": { 23 | "album_count": 0, 24 | "artist_pick_track_id": "y8Nvx", 25 | "bio": "DJ/Producer", 26 | "cover_photo": { 27 | "640x": "https://creatornode3.audius.co/content/QmSADrMwcqUFHjnuh3r3aWGgZjYFYovfsUxDDtxYwWHsv2/640x.jpg", 28 | "2000x": "https://creatornode3.audius.co/content/QmSADrMwcqUFHjnuh3r3aWGgZjYFYovfsUxDDtxYwWHsv2/2000x.jpg" 29 | }, 30 | "followee_count": 19, 31 | "follower_count": 511, 32 | "does_follow_current_user": false, 33 | "handle": "henryfong", 34 | "id": "nolY2", 35 | "is_verified": true, 36 | "location": "Los Angeles", 37 | "name": "Henry Fong", 38 | "playlist_count": 1, 39 | "profile_picture": { 40 | "150x150": "https://creatornode3.audius.co/content/QmaxRd8YNYzzhU1gkzfaX3vCucNHfyZTiUKCTRtv9QCUjh/150x150.jpg", 41 | "480x480": "https://creatornode3.audius.co/content/QmaxRd8YNYzzhU1gkzfaX3vCucNHfyZTiUKCTRtv9QCUjh/480x480.jpg", 42 | "1000x1000": "https://creatornode3.audius.co/content/QmaxRd8YNYzzhU1gkzfaX3vCucNHfyZTiUKCTRtv9QCUjh/1000x1000.jpg" 43 | }, 44 | "repost_count": 2, 45 | "track_count": 12, 46 | "is_deactivated": false, 47 | "is_available": true, 48 | "erc_wallet": "0x106a6b57ca0731cf57bf4fc7ef6b6bd447f5f5dd", 49 | "spl_wallet": "3WZRg5pbFLP4ey7RhF4n95hR4WnGJTAq6KZBrfmwxBct", 50 | "supporter_count": 7, 51 | "supporting_count": 0, 52 | "total_audio_balance": 133 53 | }, 54 | "duration": 222, 55 | "downloadable": false, 56 | "play_count": 13424, 57 | "permalink": "/henryfong/henry-fong-nitti-pbj", 58 | "is_streamable": true 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /swagger/examples/tracks.trending.underground.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://audius-content-1.cultur3stake.com/content/QmNwXj3vESow9b1hvessexnuiHhAA8Bhwzycf2UWsQXHGW/150x150.jpg", 6 | "480x480": "https://audius-content-1.cultur3stake.com/content/QmNwXj3vESow9b1hvessexnuiHhAA8Bhwzycf2UWsQXHGW/480x480.jpg", 7 | "1000x1000": "https://audius-content-1.cultur3stake.com/content/QmNwXj3vESow9b1hvessexnuiHhAA8Bhwzycf2UWsQXHGW/1000x1000.jpg" 8 | }, 9 | "description": null, 10 | "genre": "Electronic", 11 | "id": "MYvY63X", 12 | "track_cid": "QmWXgp758zKWd4KtmQJwTaLnGR2oGubVhZH7qjiu7Vwi6f", 13 | "mood": "Empowering", 14 | "release_date": null, 15 | "remix_of": { 16 | "tracks": null 17 | }, 18 | "repost_count": 14, 19 | "favorite_count": 31, 20 | "tags": "bass,dubstep,trap,beats,downtempo", 21 | "title": "04_Mindex - Wormhole", 22 | "user": { 23 | "album_count": 1, 24 | "artist_pick_track_id": "gQRgZ", 25 | "bio": "Storytelling Bass Music", 26 | "cover_photo": { 27 | "640x": "https://audius-content-1.cultur3stake.com/content/QmQGJeLf73YymgeL9nrtDgSrM255ownEAw8pKupbCbVHFj/640x.jpg", 28 | "2000x": "https://audius-content-1.cultur3stake.com/content/QmQGJeLf73YymgeL9nrtDgSrM255ownEAw8pKupbCbVHFj/2000x.jpg" 29 | }, 30 | "followee_count": 12, 31 | "follower_count": 419, 32 | "does_follow_current_user": false, 33 | "handle": "mindex", 34 | "id": "n6OJl", 35 | "is_verified": false, 36 | "location": "Austin, TX", 37 | "name": "MINDEX", 38 | "playlist_count": 0, 39 | "profile_picture": { 40 | "150x150": "https://audius-content-1.cultur3stake.com/content/QmPFsokU1XFz9aKfyd1x2jqZjrJyiPNrXVN6SKf4fkdqBx/150x150.jpg", 41 | "480x480": "https://audius-content-1.cultur3stake.com/content/QmPFsokU1XFz9aKfyd1x2jqZjrJyiPNrXVN6SKf4fkdqBx/480x480.jpg", 42 | "1000x1000": "https://audius-content-1.cultur3stake.com/content/QmPFsokU1XFz9aKfyd1x2jqZjrJyiPNrXVN6SKf4fkdqBx/1000x1000.jpg" 43 | }, 44 | "repost_count": 1, 45 | "track_count": 11, 46 | "is_deactivated": false, 47 | "is_available": true, 48 | "erc_wallet": "0x6f69411eb84a058ec4df2f8da426c420ddbede06", 49 | "spl_wallet": "FQavSBuMGzsavG2M2WbeGWpFDyZwiC4y1XmXeBw13mSw", 50 | "supporter_count": 3, 51 | "supporting_count": 0, 52 | "total_audio_balance": 7 53 | }, 54 | "duration": 219, 55 | "downloadable": false, 56 | "play_count": 5557, 57 | "permalink": "/mindex/04_mindex-wormhole", 58 | "is_streamable": true 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /swagger/examples/tracks.{track_id}.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "artwork": { 4 | "150x150": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/150x150.jpg", 5 | "480x480": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/480x480.jpg", 6 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/1000x1000.jpg" 7 | }, 8 | "description": "@baauer b2b @partyfavor live set at Brownies & Lemonade Block Party LA at The Shrine on 7.3.19.", 9 | "genre": "Electronic", 10 | "id": "D7KyD", 11 | "track_cid": "QmeeTjhUvwQRtNYQwiC7Uebuhi4p9mNQNESb3AFaJCYqNz", 12 | "mood": "Fiery", 13 | "release_date": "Mon Sep 23 2019 12:35:10 GMT-0700", 14 | "remix_of": { 15 | "tracks": null 16 | }, 17 | "repost_count": 430, 18 | "favorite_count": 977, 19 | "tags": "baauer,partyfavor,browniesandlemonade,live", 20 | "title": "Paauer | Baauer B2B Party Favor | B&L Block Party LA (Live Set)", 21 | "user": { 22 | "album_count": 0, 23 | "artist_pick_track_id": "D7KyD", 24 | "bio": "Makin' moves & keeping you on your toes.\nlinktr.ee/browniesandlemonade", 25 | "cover_photo": { 26 | "640x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/640x.jpg", 27 | "2000x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/2000x.jpg" 28 | }, 29 | "followee_count": 26, 30 | "follower_count": 34503, 31 | "does_follow_current_user": false, 32 | "handle": "TeamBandL", 33 | "id": "nlGNe", 34 | "is_verified": true, 35 | "location": "Los Angeles, CA", 36 | "name": "Brownies & Lemonade", 37 | "playlist_count": 2, 38 | "profile_picture": { 39 | "150x150": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/150x150.jpg", 40 | "480x480": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/480x480.jpg", 41 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/1000x1000.jpg" 42 | }, 43 | "repost_count": 5, 44 | "track_count": 10, 45 | "is_deactivated": false, 46 | "is_available": true, 47 | "erc_wallet": "0x8bc337e467cec1e7b05e54c7d1f90814a78d259e", 48 | "spl_wallet": "WXBYqzejMr5qxmuDrvVTDQopr7vdZt5szsoSSb3EvQH", 49 | "supporter_count": 9, 50 | "supporting_count": 0, 51 | "total_audio_balance": 3123 52 | }, 53 | "duration": 5265, 54 | "downloadable": false, 55 | "play_count": 355660, 56 | "permalink": "/TeamBandL/paauer-|-baauer-b2b-party-favor-|-bl-block-party-la-live-set-725", 57 | "is_streamable": true 58 | } 59 | } -------------------------------------------------------------------------------- /swagger/examples/users.handle.{handle}.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "album_count": 1, 4 | "artist_pick_track_id": "bbzxO", 5 | "bio": "Grammy award winning recording artist", 6 | "cover_photo": { 7 | "640x": "https://creatornode3.audius.co/content/QmajqvB5WHRzkkE9dxgxoTcAoRwZ9Mnhd7ZSbZxyheQvzK/640x.jpg", 8 | "2000x": "https://creatornode3.audius.co/content/QmajqvB5WHRzkkE9dxgxoTcAoRwZ9Mnhd7ZSbZxyheQvzK/2000x.jpg" 9 | }, 10 | "followee_count": 19, 11 | "follower_count": 64352, 12 | "does_follow_current_user": false, 13 | "handle": "RAC", 14 | "id": "nkwv1", 15 | "is_verified": true, 16 | "location": "Portland, OR", 17 | "name": "RAC", 18 | "playlist_count": 0, 19 | "profile_picture": { 20 | "150x150": "https://creatornode3.audius.co/content/QmeZmZsxNbZ6prX9yg6sa2pk4bPPRUfdYJPqqndRanUrsf/150x150.jpg", 21 | "480x480": "https://creatornode3.audius.co/content/QmeZmZsxNbZ6prX9yg6sa2pk4bPPRUfdYJPqqndRanUrsf/480x480.jpg", 22 | "1000x1000": "https://creatornode3.audius.co/content/QmeZmZsxNbZ6prX9yg6sa2pk4bPPRUfdYJPqqndRanUrsf/1000x1000.jpg" 23 | }, 24 | "repost_count": 12, 25 | "track_count": 16, 26 | "is_deactivated": false, 27 | "is_available": true, 28 | "erc_wallet": "0x346dfbfaf04f40a7f4d327a4935ee98a5bdbd478", 29 | "spl_wallet": "2AXmXpWwbFTRWJWkmfjfKajapgAkQEQKkqxooBRZd5cf", 30 | "supporter_count": 23, 31 | "supporting_count": 1, 32 | "total_audio_balance": 114101 33 | } 34 | } -------------------------------------------------------------------------------- /swagger/examples/users.handle.{handle}.tracks.ai_attributed.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://creatornode2.audius.co/content/QmSQpJrsBM5Vjbifa4e6Xok3mEoyJ3k7YT9YTcM5bcuqDP/150x150.jpg", 6 | "480x480": "https://creatornode2.audius.co/content/QmSQpJrsBM5Vjbifa4e6Xok3mEoyJ3k7YT9YTcM5bcuqDP/480x480.jpg", 7 | "1000x1000": "https://creatornode2.audius.co/content/QmSQpJrsBM5Vjbifa4e6Xok3mEoyJ3k7YT9YTcM5bcuqDP/1000x1000.jpg" 8 | }, 9 | "description": "Made with Boomy", 10 | "genre": "Electronic", 11 | "id": "wzwEM32", 12 | "track_cid": "Qme14CQbQPTK1snP8Gt3JSdGAHHdWFJAg25FnVue4s1oT7", 13 | "mood": "Sophisticated", 14 | "release_date": "Mon May 01 2023 17:17:23 GMT-0700", 15 | "remix_of": { 16 | "tracks": null 17 | }, 18 | "repost_count": 1, 19 | "favorite_count": 2, 20 | "tags": "ai,aimusic", 21 | "title": "PhutureAI", 22 | "user": { 23 | "album_count": 0, 24 | "artist_pick_track_id": null, 25 | "bio": "Founder of Phuture Collective", 26 | "cover_photo": { 27 | "640x": "https://creatornode2.audius.co/content/QmbB1yiGWF7JpWfW42LbhWY27v7GMfLKuLE3fd84hFKDS7/640x.jpg", 28 | "2000x": "https://creatornode2.audius.co/content/QmbB1yiGWF7JpWfW42LbhWY27v7GMfLKuLE3fd84hFKDS7/2000x.jpg" 29 | }, 30 | "followee_count": 8, 31 | "follower_count": 247, 32 | "does_follow_current_user": false, 33 | "handle": "synchronistic", 34 | "id": "LRNZL", 35 | "is_verified": false, 36 | "location": "Portland, OR", 37 | "name": "synchronistic", 38 | "playlist_count": 0, 39 | "profile_picture": { 40 | "150x150": "https://creatornode2.audius.co/content/QmcBGJSkkWqfc1kx23jVuDfMenMS8u1ctPmm3A5VcLboSH/150x150.jpg", 41 | "480x480": "https://creatornode2.audius.co/content/QmcBGJSkkWqfc1kx23jVuDfMenMS8u1ctPmm3A5VcLboSH/480x480.jpg", 42 | "1000x1000": "https://creatornode2.audius.co/content/QmcBGJSkkWqfc1kx23jVuDfMenMS8u1ctPmm3A5VcLboSH/1000x1000.jpg" 43 | }, 44 | "repost_count": 2, 45 | "track_count": 3, 46 | "is_deactivated": false, 47 | "is_available": true, 48 | "erc_wallet": "0x0b0e6bd939a6165a98ed8f4ea350a96d1127676f", 49 | "spl_wallet": "4eKrNigZuzvAR4rYBLFJMRSULA1Me9LSwygMjqzEYJGc", 50 | "supporter_count": 0, 51 | "supporting_count": 0, 52 | "total_audio_balance": 1 53 | }, 54 | "duration": 67, 55 | "downloadable": false, 56 | "play_count": 1529, 57 | "permalink": "/synchronistic/phutureai", 58 | "is_streamable": true 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /swagger/examples/users.id.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "user_id": "nlGNe" 4 | } 5 | } -------------------------------------------------------------------------------- /swagger/examples/users.search.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "album_count": 0, 5 | "artist_pick_track_id": "D7KyD", 6 | "bio": "Makin' moves & keeping you on your toes.\nlinktr.ee/browniesandlemonade", 7 | "cover_photo": { 8 | "640x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/640x.jpg", 9 | "2000x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/2000x.jpg" 10 | }, 11 | "followee_count": 26, 12 | "follower_count": 34503, 13 | "does_follow_current_user": false, 14 | "handle": "TeamBandL", 15 | "id": "nlGNe", 16 | "is_verified": true, 17 | "location": "Los Angeles, CA", 18 | "name": "Brownies & Lemonade", 19 | "playlist_count": 2, 20 | "profile_picture": { 21 | "150x150": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/150x150.jpg", 22 | "480x480": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/480x480.jpg", 23 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/1000x1000.jpg" 24 | }, 25 | "repost_count": 5, 26 | "track_count": 10, 27 | "is_deactivated": false, 28 | "is_available": true, 29 | "erc_wallet": "0x8bc337e467cec1e7b05e54c7d1f90814a78d259e", 30 | "spl_wallet": "WXBYqzejMr5qxmuDrvVTDQopr7vdZt5szsoSSb3EvQH", 31 | "supporter_count": 9, 32 | "supporting_count": 0, 33 | "total_audio_balance": null 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /swagger/examples/users.verify_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "userId": "1416115", 4 | "email": "isaactest451@gmail.com", 5 | "name": "testing12", 6 | "handle": "testtest451", 7 | "verified": false, 8 | "profilePicture": null, 9 | "sub": "1416115", 10 | "iat": "1656518333" 11 | } 12 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.connected_wallets.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "erc_wallets": [ 4 | "0x42b53313f643D2a8007a169C2eC973100A1F84C3" 5 | ], 6 | "spl_wallets": [ 7 | "EF1zneAqA2mwjkD3Lj7sQnMhR2uorGqEHXNtAWfGdCu2" 8 | ] 9 | } 10 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.favorites.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "favorite_item_id": "5O2pg", 5 | "favorite_type": "SaveType.track", 6 | "user_id": "nlGNe", 7 | "created_at": "2022-07-27 01:25:15" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.followers.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "album_count": 0, 5 | "artist_pick_track_id": null, 6 | "bio": "The official Audius account!\n\nCreating a decentralized and open-source streaming music platform controlled by artists, fans, & developers.\n\nhttps://discord.gg/audius\nhttps://t.me/audius", 7 | "cover_photo": { 8 | "640x": "https://usermetadata.audius.co/content/QmSeB4DY1qBtp9hbnmMwnkGepRY6tRrNQcgZU2oNk4SK1q/640x.jpg", 9 | "2000x": "https://usermetadata.audius.co/content/QmSeB4DY1qBtp9hbnmMwnkGepRY6tRrNQcgZU2oNk4SK1q/2000x.jpg" 10 | }, 11 | "followee_count": 856, 12 | "follower_count": 1525903, 13 | "does_follow_current_user": false, 14 | "handle": "Audius", 15 | "id": "eJ57D", 16 | "is_verified": true, 17 | "location": "SF & LA", 18 | "name": "Audius", 19 | "playlist_count": 6, 20 | "profile_picture": { 21 | "150x150": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/150x150.jpg", 22 | "480x480": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/480x480.jpg", 23 | "1000x1000": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/1000x1000.jpg" 24 | }, 25 | "repost_count": 3489, 26 | "track_count": 0, 27 | "is_deactivated": false, 28 | "is_available": true, 29 | "erc_wallet": "0x3256bd2d0b1984e7df4fa525017ad9ba48470760", 30 | "spl_wallet": "D1WXgUS2pnrVQTEqSGy2t2oxowahUL8Pw2Qy64CvTi79", 31 | "supporter_count": 215, 32 | "supporting_count": 4, 33 | "total_audio_balance": 16150 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.following.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "album_count": 0, 5 | "artist_pick_track_id": null, 6 | "bio": "The official Audius account!\n\nCreating a decentralized and open-source streaming music platform controlled by artists, fans, & developers.\n\nhttps://discord.gg/audius\nhttps://t.me/audius", 7 | "cover_photo": { 8 | "640x": "https://usermetadata.audius.co/content/QmSeB4DY1qBtp9hbnmMwnkGepRY6tRrNQcgZU2oNk4SK1q/640x.jpg", 9 | "2000x": "https://usermetadata.audius.co/content/QmSeB4DY1qBtp9hbnmMwnkGepRY6tRrNQcgZU2oNk4SK1q/2000x.jpg" 10 | }, 11 | "followee_count": 856, 12 | "follower_count": 1525903, 13 | "does_follow_current_user": false, 14 | "handle": "Audius", 15 | "id": "eJ57D", 16 | "is_verified": true, 17 | "location": "SF & LA", 18 | "name": "Audius", 19 | "playlist_count": 6, 20 | "profile_picture": { 21 | "150x150": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/150x150.jpg", 22 | "480x480": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/480x480.jpg", 23 | "1000x1000": "https://usermetadata.audius.co/content/QmNjJv1wQf2DJq3GNXjXzSL8UXFUGXfchg4NhL7UpbnF1f/1000x1000.jpg" 24 | }, 25 | "repost_count": 3489, 26 | "track_count": 0, 27 | "is_deactivated": false, 28 | "is_available": true, 29 | "erc_wallet": "0x3256bd2d0b1984e7df4fa525017ad9ba48470760", 30 | "spl_wallet": "D1WXgUS2pnrVQTEqSGy2t2oxowahUL8Pw2Qy64CvTi79", 31 | "supporter_count": 215, 32 | "supporting_count": 4, 33 | "total_audio_balance": 16150 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": { 3 | "album_count": 0, 4 | "artist_pick_track_id": "D7KyD", 5 | "bio": "Makin' moves & keeping you on your toes.\nlinktr.ee/browniesandlemonade", 6 | "cover_photo": { 7 | "640x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/640x.jpg", 8 | "2000x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/2000x.jpg" 9 | }, 10 | "followee_count": 26, 11 | "follower_count": 34503, 12 | "does_follow_current_user": false, 13 | "handle": "TeamBandL", 14 | "id": "nlGNe", 15 | "is_verified": true, 16 | "location": "Los Angeles, CA", 17 | "name": "Brownies & Lemonade", 18 | "playlist_count": 2, 19 | "profile_picture": { 20 | "150x150": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/150x150.jpg", 21 | "480x480": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/480x480.jpg", 22 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/1000x1000.jpg" 23 | }, 24 | "repost_count": 5, 25 | "track_count": 10, 26 | "is_deactivated": false, 27 | "is_available": true, 28 | "erc_wallet": "0x8bc337e467cec1e7b05e54c7d1f90814a78d259e", 29 | "spl_wallet": "WXBYqzejMr5qxmuDrvVTDQopr7vdZt5szsoSSb3EvQH", 30 | "supporter_count": 9, 31 | "supporting_count": 0, 32 | "total_audio_balance": 3123 33 | } 34 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.related.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "album_count": 0, 5 | "artist_pick_track_id": null, 6 | "bio": "we are here for now. \n\ninquiries: joey@keel.la", 7 | "cover_photo": { 8 | "640x": "https://creatornode3.audius.co/content/QmZFh4413dNdy8RCg6bAx7jLeqMKxVHbKPdq18rG4JhPg1/640x.jpg", 9 | "2000x": "https://creatornode3.audius.co/content/QmZFh4413dNdy8RCg6bAx7jLeqMKxVHbKPdq18rG4JhPg1/2000x.jpg" 10 | }, 11 | "followee_count": 8, 12 | "follower_count": 39042, 13 | "does_follow_current_user": false, 14 | "handle": "LouisTheChild", 15 | "id": "LxQm2", 16 | "is_verified": true, 17 | "location": "Chicago, IL", 18 | "name": "Louis The Child", 19 | "playlist_count": 0, 20 | "profile_picture": { 21 | "150x150": "https://creatornode3.audius.co/content/Qmat15zauKpvWK83WiYiQLJ7LHXTEDViXFAUZayC1AFN5v/150x150.jpg", 22 | "480x480": "https://creatornode3.audius.co/content/Qmat15zauKpvWK83WiYiQLJ7LHXTEDViXFAUZayC1AFN5v/480x480.jpg", 23 | "1000x1000": "https://creatornode3.audius.co/content/Qmat15zauKpvWK83WiYiQLJ7LHXTEDViXFAUZayC1AFN5v/1000x1000.jpg" 24 | }, 25 | "repost_count": 1, 26 | "track_count": 94, 27 | "is_deactivated": false, 28 | "is_available": true, 29 | "erc_wallet": "0x0fd1293443c366bc433d85c94be56ca8117d0ef6", 30 | "spl_wallet": "4V5UASoUDPSMRNU1AJ8vNh2kC7y1DXoMnaoehXCxNZsk", 31 | "supporter_count": 4, 32 | "supporting_count": 0, 33 | "total_audio_balance": 12 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.reposts.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "timestamp": "2021-05-03 02:48:00", 5 | "item_type": "track", 6 | "item": { 7 | "artwork": { 8 | "150x150": "https://creatornode3.audius.co/content/QmWGQf6CnFJJ4he13eDF2vZwDyoaWcHL3HziQyaSPwVFd3/150x150.jpg", 9 | "480x480": "https://creatornode3.audius.co/content/QmWGQf6CnFJJ4he13eDF2vZwDyoaWcHL3HziQyaSPwVFd3/480x480.jpg", 10 | "1000x1000": "https://creatornode3.audius.co/content/QmWGQf6CnFJJ4he13eDF2vZwDyoaWcHL3HziQyaSPwVFd3/1000x1000.jpg" 11 | }, 12 | "description": null, 13 | "genre": "Electronic", 14 | "id": "y7XX7", 15 | "track_cid": "QmXFnuP57woE7ZZ3HTkWggXuzZL13SJVLiL7rVE9qSFTyf", 16 | "mood": "Other", 17 | "release_date": "Sun Mar 28 2021 11:52:35 GMT-0700", 18 | "remix_of": { 19 | "tracks": null 20 | }, 21 | "repost_count": 46, 22 | "favorite_count": 100, 23 | "tags": null, 24 | "title": "PAULINE HERR @ BROWNIES & LEMONADE OPEN AUX 1/30", 25 | "user": { 26 | "album_count": 1, 27 | "artist_pick_track_id": "JbQN0", 28 | "bio": "producer, singer, human\n\nsocials: @paulineherr", 29 | "cover_photo": { 30 | "640x": "https://creatornode3.audius.co/content/QmZXwdQDq5QDJW3W17g4n4zXVjaDGDbvuzsMWqhis61W7h/640x.jpg", 31 | "2000x": "https://creatornode3.audius.co/content/QmZXwdQDq5QDJW3W17g4n4zXVjaDGDbvuzsMWqhis61W7h/2000x.jpg" 32 | }, 33 | "followee_count": 144, 34 | "follower_count": 41573, 35 | "does_follow_current_user": false, 36 | "handle": "paulineherr", 37 | "id": "eGEam", 38 | "is_verified": true, 39 | "location": "Burbank, CA", 40 | "name": "Pauline Herr", 41 | "playlist_count": 1, 42 | "profile_picture": { 43 | "150x150": "https://creatornode3.audius.co/content/QmbqwCk1axAdXk9iFfeU48iu1P73ChUA3kxpeg7PJBRHsC/150x150.jpg", 44 | "480x480": "https://creatornode3.audius.co/content/QmbqwCk1axAdXk9iFfeU48iu1P73ChUA3kxpeg7PJBRHsC/480x480.jpg", 45 | "1000x1000": "https://creatornode3.audius.co/content/QmbqwCk1axAdXk9iFfeU48iu1P73ChUA3kxpeg7PJBRHsC/1000x1000.jpg" 46 | }, 47 | "repost_count": 155, 48 | "track_count": 35, 49 | "is_deactivated": false, 50 | "is_available": true, 51 | "erc_wallet": "0xf568ab060acd91fe4861e52136deb08ca1f26574", 52 | "spl_wallet": "3DeyiqjmCAtqPUzGX6MQP2C62kKRANy7LFvcBzUEHqPc", 53 | "supporter_count": 8, 54 | "supporting_count": 0, 55 | "total_audio_balance": 131 56 | }, 57 | "duration": 1708, 58 | "downloadable": false, 59 | "play_count": 958, 60 | "permalink": "/paulineherr/pauline-herr-brownies-lemonade-open-aux-130-316935", 61 | "is_streamable": true 62 | } 63 | } 64 | ] 65 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.subscribers.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "album_count": 1, 5 | "artist_pick_track_id": "QVkPv", 6 | "bio": "🌞👄🌞\noak", 7 | "cover_photo": { 8 | "640x": "https://blockchange-audius-content-03.bdnodes.net/content/QmUk61QDUTzhNqjnCAWipSp3jnMmXBmtTUC2mtF5F6VvUy/640x.jpg", 9 | "2000x": "https://blockchange-audius-content-03.bdnodes.net/content/QmUk61QDUTzhNqjnCAWipSp3jnMmXBmtTUC2mtF5F6VvUy/2000x.jpg" 10 | }, 11 | "followee_count": 1543, 12 | "follower_count": 8276, 13 | "does_follow_current_user": false, 14 | "handle": "rayjacobson", 15 | "id": "7eP5n", 16 | "is_verified": false, 17 | "location": "chik fil yay!!", 18 | "name": "raymont", 19 | "playlist_count": 8, 20 | "profile_picture": { 21 | "150x150": "https://blockchange-audius-content-03.bdnodes.net/content/QmYRHAJ4YuLjT4fLLRMg5STnQA4yDpiBmzk5R3iCDTmkmk/150x150.jpg", 22 | "480x480": "https://blockchange-audius-content-03.bdnodes.net/content/QmYRHAJ4YuLjT4fLLRMg5STnQA4yDpiBmzk5R3iCDTmkmk/480x480.jpg", 23 | "1000x1000": "https://blockchange-audius-content-03.bdnodes.net/content/QmYRHAJ4YuLjT4fLLRMg5STnQA4yDpiBmzk5R3iCDTmkmk/1000x1000.jpg" 24 | }, 25 | "repost_count": 3891, 26 | "track_count": 17, 27 | "is_deactivated": false, 28 | "is_available": true, 29 | "erc_wallet": "0x7d273271690538cf855e5b3002a0dd8c154bb060", 30 | "spl_wallet": "EXfHYvqN7GTeQa7aiRhq4UMMZBC9PmUXmskgCH7BSaTn", 31 | "supporter_count": 8, 32 | "supporting_count": 110, 33 | "total_audio_balance": 205 34 | } 35 | ] 36 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.supporters.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "rank": 1, 5 | "amount": "6000000000000000000", 6 | "sender": { 7 | "album_count": 0, 8 | "artist_pick_track_id": "G0RNQ8w", 9 | "bio": "Bebig Music is a record label part of treinta3tres records dedicated to dance commercial music.\nBebig Music is Dance!\nbebigmusic@gmail.com", 10 | "cover_photo": { 11 | "640x": "https://creatornode2.audius.co/content/QmQRATHCJEiwsCu4f1rGjPefF8fcwYnGzv2wuiKFnA3hv2/640x.jpg", 12 | "2000x": "https://creatornode2.audius.co/content/QmQRATHCJEiwsCu4f1rGjPefF8fcwYnGzv2wuiKFnA3hv2/2000x.jpg" 13 | }, 14 | "followee_count": 58, 15 | "follower_count": 81, 16 | "does_follow_current_user": false, 17 | "handle": "bebigmusic", 18 | "id": "aW8mr", 19 | "is_verified": false, 20 | "location": "Barcelona", 21 | "name": "Bebig Music", 22 | "playlist_count": 0, 23 | "profile_picture": { 24 | "150x150": "https://creatornode2.audius.co/content/QmXrmgMy5fwfr6q6ucU4qkvwkq8cvFXfbms32NNctZDmoB/150x150.jpg", 25 | "480x480": "https://creatornode2.audius.co/content/QmXrmgMy5fwfr6q6ucU4qkvwkq8cvFXfbms32NNctZDmoB/480x480.jpg", 26 | "1000x1000": "https://creatornode2.audius.co/content/QmXrmgMy5fwfr6q6ucU4qkvwkq8cvFXfbms32NNctZDmoB/1000x1000.jpg" 27 | }, 28 | "repost_count": 81, 29 | "track_count": 12, 30 | "is_deactivated": false, 31 | "is_available": true, 32 | "erc_wallet": "0xcdc88b59fc7f2ea01ff6781bae25c1a59a2378cd", 33 | "spl_wallet": "3EDj16wey6nfw26LhEXTyVmCnvvAMw4ruHfc76kWKkq8", 34 | "supporter_count": 0, 35 | "supporting_count": 1, 36 | "total_audio_balance": 0 37 | } 38 | } 39 | ] 40 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.supporting.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "rank": 1, 5 | "amount": "6000000000000000000", 6 | "receiver": { 7 | "album_count": 9, 8 | "artist_pick_track_id": "oPRA7", 9 | "bio": "house music\ntreinta3tres@gmail.com", 10 | "cover_photo": { 11 | "640x": "https://creatornode2.audius.co/content/QmRUUUoeJmhbpvqSr9d34Gb71zk7xZkNtswHdixzhMkXYG/640x.jpg", 12 | "2000x": "https://creatornode2.audius.co/content/QmRUUUoeJmhbpvqSr9d34Gb71zk7xZkNtswHdixzhMkXYG/2000x.jpg" 13 | }, 14 | "followee_count": 12, 15 | "follower_count": 103, 16 | "does_follow_current_user": false, 17 | "handle": "treinta3tres", 18 | "id": "lzkyZ", 19 | "is_verified": false, 20 | "location": "Barcelona", 21 | "name": "treinta3tres", 22 | "playlist_count": 3, 23 | "profile_picture": { 24 | "150x150": "https://creatornode2.audius.co/content/QmdJJf81jjRhpmrj2JzeMEzDNbPKfrUWkECE3NjfWnLDMr/150x150.jpg", 25 | "480x480": "https://creatornode2.audius.co/content/QmdJJf81jjRhpmrj2JzeMEzDNbPKfrUWkECE3NjfWnLDMr/480x480.jpg", 26 | "1000x1000": "https://creatornode2.audius.co/content/QmdJJf81jjRhpmrj2JzeMEzDNbPKfrUWkECE3NjfWnLDMr/1000x1000.jpg" 27 | }, 28 | "repost_count": 24, 29 | "track_count": 71, 30 | "is_deactivated": false, 31 | "is_available": true, 32 | "erc_wallet": "0xa18d959231ca5728fefbf7b45ddc87f44e0832db", 33 | "spl_wallet": "3Mm5mdBT3jtRifHpxBfJavRXyfM4G4kbV7KKrX2nj12M", 34 | "supporter_count": 2, 35 | "supporting_count": 0, 36 | "total_audio_balance": 21 37 | } 38 | } 39 | ] 40 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.tags.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | "browniesandlemonade" 4 | ] 5 | } -------------------------------------------------------------------------------- /swagger/examples/users.{id}.tracks.json: -------------------------------------------------------------------------------- 1 | { 2 | "data": [ 3 | { 4 | "artwork": { 5 | "150x150": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/150x150.jpg", 6 | "480x480": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/480x480.jpg", 7 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmVJjA6zXhDZn3BjcjYa33P9NDiPZj7Vyq9TCx1bHjvHmG/1000x1000.jpg" 8 | }, 9 | "description": "@baauer b2b @partyfavor live set at Brownies & Lemonade Block Party LA at The Shrine on 7.3.19.", 10 | "genre": "Electronic", 11 | "id": "D7KyD", 12 | "track_cid": "QmeeTjhUvwQRtNYQwiC7Uebuhi4p9mNQNESb3AFaJCYqNz", 13 | "mood": "Fiery", 14 | "release_date": "Mon Sep 23 2019 12:35:10 GMT-0700", 15 | "remix_of": { 16 | "tracks": null 17 | }, 18 | "repost_count": 430, 19 | "favorite_count": 977, 20 | "tags": "baauer,partyfavor,browniesandlemonade,live", 21 | "title": "Paauer | Baauer B2B Party Favor | B&L Block Party LA (Live Set)", 22 | "user": { 23 | "album_count": 0, 24 | "artist_pick_track_id": "D7KyD", 25 | "bio": "Makin' moves & keeping you on your toes.\nlinktr.ee/browniesandlemonade", 26 | "cover_photo": { 27 | "640x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/640x.jpg", 28 | "2000x": "https://audius.prod.capturealpha.io/content/QmcVZH5C2ygxoVS4ihPBJrkFrS1Ua6YJB5srNtXafPzihZ/2000x.jpg" 29 | }, 30 | "followee_count": 26, 31 | "follower_count": 34503, 32 | "does_follow_current_user": false, 33 | "handle": "TeamBandL", 34 | "id": "nlGNe", 35 | "is_verified": true, 36 | "location": "Los Angeles, CA", 37 | "name": "Brownies & Lemonade", 38 | "playlist_count": 2, 39 | "profile_picture": { 40 | "150x150": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/150x150.jpg", 41 | "480x480": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/480x480.jpg", 42 | "1000x1000": "https://audius.prod.capturealpha.io/content/QmU9L4beAM96MpiNqqVTZdiDiCRTeBku1AJCh3NXrE5PxV/1000x1000.jpg" 43 | }, 44 | "repost_count": 5, 45 | "track_count": 10, 46 | "is_deactivated": false, 47 | "is_available": true, 48 | "erc_wallet": "0x8bc337e467cec1e7b05e54c7d1f90814a78d259e", 49 | "spl_wallet": "WXBYqzejMr5qxmuDrvVTDQopr7vdZt5szsoSSb3EvQH", 50 | "supporter_count": 9, 51 | "supporting_count": 0, 52 | "total_audio_balance": 3123 53 | }, 54 | "duration": 5265, 55 | "downloadable": false, 56 | "play_count": 355660, 57 | "permalink": "/TeamBandL/paauer-|-baauer-b2b-party-favor-|-bl-block-party-la-live-set-725", 58 | "is_streamable": true 59 | } 60 | ] 61 | } -------------------------------------------------------------------------------- /swagger/generateExamples.js: -------------------------------------------------------------------------------- 1 | require('isomorphic-fetch') 2 | const fs = require('fs').promises 3 | const path = require('path') 4 | const { convert } = require('widdershins/lib/index') 5 | const { convertPathToFilename } = require('./helpers') 6 | 7 | const OUTPUT_DIR = path.resolve(__dirname, 'examples/') 8 | 9 | const setupData = (data) => { 10 | data.operationUniqueSlug = data.method.slug 11 | data.operation = data.method.operation 12 | data.methodUpper = data.method.verb.toUpperCase() 13 | data.url = data.utils.slashes(data.baseUrl + data.method.path) 14 | data.parameters = data.operation.parameters 15 | data.enums = [] 16 | data.utils.fakeProdCons(data) 17 | data.utils.fakeBodyParameter(data) 18 | data.utils.mergePathParameters(data) 19 | data.utils.getParameters(data) 20 | } 21 | 22 | const getContentType = (operation, statusCode) => { 23 | let content = operation.responses[`${statusCode}`] 24 | content = content ? content.content : null 25 | content = Object.keys(content || {}) 26 | content = content.length > 0 ? content[0] : null 27 | return content 28 | } 29 | 30 | const fetchAndSaveExample = async (urlToFetch, filename, operation) => { 31 | const res = await fetch(urlToFetch) 32 | let content = await res.text() 33 | const contentType = getContentType(operation, res.status) 34 | if (!contentType || contentType === 'application/json') { 35 | let json 36 | try { 37 | json = JSON.parse(content) 38 | } catch (_) { 39 | console.warn('Skipping output for', urlToFetch, "as it's not JSON") 40 | } 41 | if (json) { 42 | console.log('Parsing as JSON', urlToFetch) 43 | if (Array.isArray(json.data)) { 44 | // Shorten lists 45 | json.data = json.data.slice(0, 1) 46 | } 47 | content = JSON.stringify(json, null, 2) 48 | const filePath = path.resolve(OUTPUT_DIR, filename) 49 | console.log('Writing to', filePath) 50 | await fs.writeFile(filePath, content, 'utf-8') 51 | } 52 | } else { 53 | console.warn('Skipping output for', urlToFetch, "as it's not JSON") 54 | } 55 | } 56 | 57 | const generateExamples = async (swagger, baseUrl) => { 58 | await fs.mkdir(OUTPUT_DIR, { recursive: true }) 59 | const toFetch = [] 60 | await convert(swagger, { 61 | templateCallback: (templateName, stage, data) => { 62 | data.baseUrl = data.baseUrl.replace('AUDIUS_API_HOST', baseUrl) 63 | if (templateName === 'main' && stage === 'post') { 64 | for (const resource in data.resources) { 65 | data.resource = data.resources[resource] 66 | for (const method in data.resource.methods) { 67 | data.method = data.resource.methods[method] 68 | setupData(data) 69 | const operation = data.operation 70 | const urlToFetch = data.baseUrl + data.requiredUriExample 71 | const filename = convertPathToFilename(data.method.path) 72 | console.log('Fetchidang', urlToFetch) 73 | toFetch.push(fetchAndSaveExample(urlToFetch, filename, operation)) 74 | } 75 | } 76 | } 77 | return data 78 | } 79 | }) 80 | await Promise.all(toFetch) 81 | } 82 | 83 | module.exports = { 84 | generateExamples 85 | } 86 | -------------------------------------------------------------------------------- /swagger/helpers.js: -------------------------------------------------------------------------------- 1 | const paramMapping = { 2 | '/playlists/search': { 3 | get: { 4 | query: 'Hot & New' 5 | } 6 | }, 7 | '/playlists/{playlist_id}': { 8 | get: { 9 | playlist_id: 'DOPRl' 10 | } 11 | }, 12 | '/playlists/{playlist_id}/tracks': { 13 | get: { 14 | playlist_id: 'DOPRl' 15 | } 16 | }, 17 | '/tracks': { 18 | get: { 19 | permalink: 20 | '/TeamBandL/paauer-|-baauer-b2b-party-favor-|-bl-block-party-la-live-set-725' 21 | } 22 | }, 23 | '/tracks/search': { 24 | get: { 25 | query: 'baauer b2b' 26 | } 27 | }, 28 | '/tracks/{track_id}': { 29 | get: { 30 | track_id: 'D7KyD' 31 | } 32 | }, 33 | '/tracks/{track_id}/stream': { 34 | get: { 35 | track_id: 'D7KyD' 36 | } 37 | }, 38 | '/users/search': { 39 | get: { 40 | query: 'Brownies' 41 | } 42 | }, 43 | '/users/{id}': { 44 | get: { 45 | id: 'nlGNe' 46 | } 47 | }, 48 | '/users/{id}/favorites': { 49 | get: { 50 | id: 'nlGNe' 51 | } 52 | }, 53 | '/users/{id}/followers': { 54 | get: { 55 | id: 'nlGNe' 56 | } 57 | }, 58 | '/users/{id}/following': { 59 | get: { 60 | id: 'nlGNe' 61 | } 62 | }, 63 | '/users/{id}/related': { 64 | get: { 65 | id: 'nlGNe' 66 | } 67 | }, 68 | '/users/{id}/subscribers': { 69 | get: { 70 | id: 'nlGNe' 71 | } 72 | }, 73 | '/users/{id}/tracks': { 74 | get: { 75 | id: 'nlGNe' 76 | } 77 | }, 78 | '/users/{id}/connected_wallets': { 79 | get: { 80 | id: 'Wem1e' 81 | } 82 | }, 83 | '/users/{id}/tags': { 84 | get: { 85 | id: 'nlGNe' 86 | } 87 | }, 88 | '/users/{id}/reposts': { 89 | get: { 90 | id: 'nlGNe' 91 | } 92 | }, 93 | '/users/id': { 94 | get: { 95 | associated_wallet: '0x087F08462BbD30fC1775bBA3E58821F4CaD47b6b' 96 | } 97 | }, 98 | '/users/handle/{handle}': { 99 | get: { 100 | handle: 'rac' 101 | } 102 | }, 103 | '/users/handle/{handle}/tracks/ai_attributed': { 104 | get: { 105 | handle: 'phuture' 106 | } 107 | }, 108 | '/users/verify_token': { 109 | get: { 110 | token: 111 | 'eyJ0eXAiOiJKV1QiLCJhbGciOiJrZWNjYWsyNTYifQ.eyJ1c2VySWQiOjE0MTYxMTUsImVtYWlsIjoiaXNhYWN0ZXN0NDUxQGdtYWlsLmNvbSIsIm5hbWUiOiJ0ZXN0aW5nMTIiLCJoYW5kbGUiOiJ0ZXN0dGVzdDQ1MSIsInZlcmlmaWVkIjpmYWxzZSwic3ViIjoxNDE2MTE1LCJpYXQiOjE2NTY1MTgzMzN9.MHhkZmYyYWY5ZThmNDAxZDUyZDlhNjUxNGRiOTg0ZjM5YjFhOTZkYmNmZmViZjMzZjNkNmEzMTk4OTVlZWE2MTZjNjg0NWIwOGEyOGQ4MTA4OTEyMTc4ZDU0ODRhZGU4M2I1Yzg4ZTUwM2Y3OGYzMDYzZjYxMmQxZDQwYTYwMGZmZDFi' 112 | } 113 | }, 114 | '/users/{id}/supporters': { 115 | get: { 116 | id: 'lzkyZ' 117 | } 118 | }, 119 | '/users/{id}/supporting': { 120 | get: { 121 | id: 'aW8mr' 122 | } 123 | }, 124 | '/resolve': { 125 | get: { 126 | url: 'https://audius.co/camouflybeats/hypermantra-86216' 127 | } 128 | } 129 | } 130 | 131 | const operationIdMapping = { 132 | '/users/{id}/tracks': "Get User's Tracks", 133 | '/users/{id}/favorites': "Get User's Favorite", 134 | '/users/{id}/reposts': "Get User's Reposts", 135 | '/users/{id}/tags': "Get User's Most Used Track Tags", 136 | '/users/{id}/connected_wallets': "Get User's Connected Wallets", 137 | '/users/handle/{handle}/tracks/ai_attributed': 'Get AI Tracks by Handle', 138 | '/users/verify_token': 'Verify ID Token' 139 | } 140 | 141 | const routeOrdering = { 142 | tracks: ['/tracks/{track_id}', '/tracks'], 143 | users: [ 144 | '/users/{id}', 145 | '/users/id', 146 | '/users/search', 147 | '/users/verify_token', 148 | '/users/{id}/connected_wallets', 149 | '/users/{id}/favorites', 150 | '/users/{id}/reposts', 151 | '/users/{id}/followers', 152 | '/users/{id}/following', 153 | '/users/{id}/supporters', 154 | '/users/{id}/supporting', 155 | '/users/{id}/tracks', 156 | '/users/{id}/related', 157 | '/users/{id}/subscribers', 158 | '/users/{id}/tags', 159 | '/users/handle/{handle}', 160 | '/users/handle/{handle}/tracks/ai_attributed' 161 | ], 162 | playlists: ['/playlists/{playlist_id}'] 163 | } 164 | 165 | const convertPathToFilename = (path) => { 166 | return path.substring(1).replace(/\//g, '.') + '.json' 167 | } 168 | 169 | module.exports = { 170 | paramMapping, 171 | operationIdMapping, 172 | routeOrdering, 173 | convertPathToFilename 174 | } 175 | -------------------------------------------------------------------------------- /swagger/index.js: -------------------------------------------------------------------------------- 1 | require('isomorphic-fetch') 2 | const fs = require('fs') 3 | const path = require('path') 4 | const { program } = require('commander') 5 | const { convert } = require('widdershins/lib/index') 6 | const { generateExamples } = require('./generateExamples') 7 | const { 8 | insertParameters, 9 | insertExamples, 10 | renameOperations, 11 | reorderRoutes, 12 | writeSwaggerToFile, 13 | readSwaggerFromFile, 14 | insertAppName 15 | } = require('./swaggerModifiers') 16 | 17 | const DEFAULT_SWAGGER_LOCATION = 'http://dn1_web-server_1:5000/v1/swagger.json' 18 | const DEFAULT_BASE_URL = 'https://discoveryprovider.audius.co' 19 | 20 | program 21 | .option( 22 | '-e, --generate-examples [url]', 23 | 'Generate example documentation from the given discovery node', 24 | false 25 | ) 26 | .option( 27 | '-f, --fetch-swagger [url]', 28 | 'Fetch the swagger.json from a DN', 29 | false 30 | ) 31 | .option( 32 | '-r, --insert-responses', 33 | 'Whether to pre-process the schema to insert example responses', 34 | false 35 | ) 36 | .option( 37 | '-p, --insert-parameters', 38 | 'Whether to pre-process the schema to insert example parameters', 39 | false 40 | ) 41 | .option( 42 | '-o, --rename-operations', 43 | 'Whether to pre-process the schema to rename select operation IDs to more human-friendly titles', 44 | false 45 | ) 46 | .option( 47 | '-v, --verbose', 48 | 'Whether to run widdershins with vebose option set to true', 49 | false 50 | ) 51 | 52 | program.parse() 53 | 54 | const options = program.opts() 55 | 56 | const main = async (options) => { 57 | let swagger = {} 58 | if (options.fetchSwagger) { 59 | const swaggerUrl = 60 | options.fetchSwagger === true 61 | ? DEFAULT_SWAGGER_LOCATION 62 | : options.fetchSwagger 63 | console.log('Fetching swagger from', swaggerUrl) 64 | const res = await fetch(swaggerUrl) 65 | const json = await res.json() 66 | json.basePath = `AUDIUS_API_HOST${json.basePath}` 67 | swagger = json 68 | } else { 69 | console.log('Reading swagger.json...') 70 | swagger = readSwaggerFromFile() 71 | } 72 | 73 | if (options.insertParameters) { 74 | console.log('Inserting app_name query parameter...') 75 | swagger = insertAppName(swagger) 76 | console.log('Inserting example parameters...') 77 | swagger = insertParameters(swagger) 78 | } 79 | if (options.generateExamples) { 80 | const baseUrl = 81 | options.generateExamples === true 82 | ? DEFAULT_BASE_URL 83 | : options.generateExamples 84 | console.log('Generating response examples from', baseUrl) 85 | await generateExamples(swagger, baseUrl) 86 | } 87 | if (options.insertResponses) { 88 | console.log('Inserting response examples...') 89 | swagger = insertExamples(swagger) 90 | } 91 | if (options.renameOperations) { 92 | console.log('Renaming operations...') 93 | swagger = renameOperations(swagger) 94 | } 95 | 96 | console.log('Reordering routes...') 97 | swagger = reorderRoutes(swagger) 98 | 99 | console.log('Saving swagger.json...') 100 | writeSwaggerToFile(swagger) 101 | console.log('Generating docs...') 102 | const doc = await convert(swagger, { 103 | omitHeader: true, 104 | codeSamples: true, 105 | tocSummary: false, 106 | user_templates: path.resolve(__dirname, 'templates'), 107 | verbose: options.verbose 108 | }) 109 | const filePath = path.resolve(__dirname, '../source/includes/_docs.md') 110 | console.log('Saving output to', filePath) 111 | fs.writeFileSync(filePath, doc) 112 | console.log('Done!') 113 | } 114 | 115 | main(options) 116 | -------------------------------------------------------------------------------- /swagger/swaggerModifiers.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs') 2 | const path = require('path') 3 | const { 4 | operationIdMapping, 5 | paramMapping, 6 | routeOrdering, 7 | convertPathToFilename 8 | } = require('./helpers') 9 | 10 | const SWAGGER_PATH = path.resolve(__dirname, 'swagger.json') 11 | 12 | const renameOperations = (swagger) => { 13 | Object.keys(operationIdMapping).forEach((key) => { 14 | swagger.paths[key].get.operationId = operationIdMapping[key] 15 | }) 16 | return swagger 17 | } 18 | 19 | const reorderRoutes = (swagger) => { 20 | const tagNames = swagger.tags.map((tag) => { 21 | return tag.name 22 | }) 23 | const tagGroups = tagNames.reduce((prev, tagName) => { 24 | prev[tagName] = [] 25 | return prev 26 | }, {}) 27 | Object.keys(routeOrdering).forEach((tag) => { 28 | routeOrdering[tag].forEach((route) => { 29 | tagGroups[tag].push([route, swagger.paths[route]]) 30 | delete swagger.paths[route] 31 | }) 32 | }) 33 | Object.entries(swagger.paths).forEach((entry) => { 34 | const value = entry[1] 35 | tagGroups[value.get.tags[0]].push(entry) 36 | }) 37 | const orderedRoutes = Object.values(tagGroups).reduce( 38 | (prevGroups, tagGroup) => { 39 | const flatGroup = tagGroup.reduce( 40 | (prevRoutes, [routeName, routeData]) => { 41 | const currGroup = { 42 | ...prevRoutes 43 | } 44 | currGroup[routeName] = routeData 45 | return currGroup 46 | }, 47 | {} 48 | ) 49 | return { ...prevGroups, ...flatGroup } 50 | }, 51 | {} 52 | ) 53 | swagger.paths = orderedRoutes 54 | return swagger 55 | } 56 | const insertParameters = (swagger) => { 57 | Object.keys(paramMapping).forEach((key) => { 58 | const methods = paramMapping[key] 59 | Object.keys(methods).forEach((method) => { 60 | const params = methods[method] 61 | Object.keys(params).forEach((param) => { 62 | swagger.paths[key][method].parameters.forEach((p) => { 63 | if (p.name === param) { 64 | p.example = params[param] 65 | } 66 | }) 67 | }) 68 | }) 69 | }) 70 | return swagger 71 | } 72 | 73 | const insertExamples = (swagger) => { 74 | Object.keys(swagger.paths).forEach((key) => { 75 | // Add example 76 | const filepath = path.resolve( 77 | __dirname, 78 | 'examples', 79 | convertPathToFilename(key) 80 | ) 81 | if (fs.existsSync(filepath)) { 82 | if (!swagger.paths[key].get.responses['200']) { 83 | swagger.paths[key].get.responses['200'] = {} 84 | } 85 | swagger.paths[key].get.responses['200'].examples = { 86 | 'application/json': require(filepath) 87 | } 88 | // Remove description 89 | delete swagger.paths[key].get.responses['200'].description 90 | } else { 91 | console.warn( 92 | 'Warning:', 93 | filepath, 94 | 'does not exist so no response was inserted' 95 | ) 96 | } 97 | }) 98 | return swagger 99 | } 100 | 101 | const insertAppName = (swagger) => { 102 | Object.keys(swagger.paths).forEach((key) => { 103 | if (!swagger.paths[key].get.parameters) { 104 | swagger.paths[key].get.parameters = [] 105 | } 106 | swagger.paths[key].get.parameters.push({ 107 | name: 'app_name', 108 | in: 'query', 109 | type: 'string', 110 | description: 'Your app name', 111 | example: 'EXAMPLEAPP' 112 | }) 113 | }) 114 | return swagger 115 | } 116 | 117 | const writeSwaggerToFile = (swagger) => { 118 | try { 119 | fs.writeFileSync(SWAGGER_PATH, JSON.stringify(swagger)) 120 | console.log('Successfully wrote', SWAGGER_PATH) 121 | } catch (e) { 122 | console.error('Failed to write swagger output:', e) 123 | } 124 | } 125 | 126 | const readSwaggerFromFile = () => { 127 | return require(SWAGGER_PATH) 128 | } 129 | 130 | module.exports = { 131 | insertExamples, 132 | insertParameters, 133 | insertAppName, 134 | renameOperations, 135 | reorderRoutes, 136 | writeSwaggerToFile, 137 | readSwaggerFromFile 138 | } 139 | -------------------------------------------------------------------------------- /swagger/templates/README.md: -------------------------------------------------------------------------------- 1 | ## Swagger / OpenAPI 2 and OpenAPI 3 template parameters 2 | 3 | Note that properties of OpenAPI objects will be in OpenAPI 3.0 form, as 4 | Swagger / OpenAPI 2.0 definitions are converted automatically. 5 | 6 | ### Code templates 7 | 8 | * `method` - the HTTP method of the operation (in lower-case) 9 | * `methodUpper` - the HTTP method of the operation (in upper-case) 10 | * `url` - the full URL of the operation (including protocol and host) 11 | * `consumes[]` - an array of MIME-types the operation consumes 12 | * `produces[]` - an array of MIME-types the operation produces 13 | * `operation` - the current operation object 14 | * `operationId` - the current operation id 15 | * `opName` - the operationId if set, otherwise the method + path 16 | * `tags[]` - the full list of tags applying to the operation 17 | * `security` - the security definitions applying to the operation 18 | * `resource` - the current tag/path object 19 | * `parameters[]` - an array of parameters for the operation (see below) 20 | * `queryString` - an example queryString, urlEncoded 21 | * `requiredQueryString` - an example queryString for `required:true` parameters 22 | * `queryParameters[]` - a subset of `parameters` that are `in:query` 23 | * `requiredParameters[]` - a subset of `queryParameters` that are `required:true` 24 | * `headerParameters[]` - a subset of `parameters` that are `in:header` 25 | * `allHeaders[]` - a concatenation of `headerParameters` and pseudo-parameters `Accept` and `Content-Type`, and optionally `Authorization` (the latter has an `isAuth` boolean property set true so it can be omitted in templates if desired 26 | 27 | ### Parameter template 28 | 29 | * `parameters[]` - an array of [parameters](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#parameterObject), including the following pseudo-properties 30 | * `shortDesc` - a truncated version of the parameter description 31 | * `safeType` - a computed version of the parameter type, including Body and schema names 32 | * `originalType` - the original type of the parameter 33 | * `exampleValues` - an object containing examples for use in code-templates 34 | * `json` - example values in JSON compatible syntax 35 | * `object` - example values in raw object form (unquoted strings etc) 36 | * `depth` - a zero-based indicator of the depth of expanded request body parameters 37 | * `enums[]` - an array of (parameter)name/value pairs 38 | 39 | ### Responses template 40 | 41 | * `responses[]` - an array of [responses](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#responseObject), including `status` and `meaning` properties 42 | 43 | ### Authentication template 44 | 45 | * `authenticationStr` - a simple string of methods (and scopes where appropriate) 46 | * `securityDefinitions[]` - an array of applicable [securityDefinitions](https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securityRequirementObject) 47 | 48 | ### Schema Property template 49 | 50 | * `schemaProperties[]` - an array of 51 | * `name` 52 | * `type` 53 | * `required` 54 | * `description` 55 | * `enums[]` - an array of (schema property)name/value pairs 56 | 57 | ### Common to all templates 58 | 59 | * `openapi` - the top-level OpenAPI / Swagger document 60 | * `header` - the front-matter of the Slate/Shins markdown document 61 | * `host` - the (computed) host of the API 62 | * `protocol` - the default/first protocol of the API 63 | * `baseUrl` - the (computed) baseUrl of the API (including protocol and host) 64 | * `widdershins` - the contents of widdershins `package.json` 65 | -------------------------------------------------------------------------------- /swagger/templates/authentication.def: -------------------------------------------------------------------------------- 1 | 5 | 6 | -------------------------------------------------------------------------------- /swagger/templates/authentication_none.def: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/AudiusProject/api-docs/5714eeb1c1f2a25f574c6e9a2ae3db7313bb10f2/swagger/templates/authentication_none.def -------------------------------------------------------------------------------- /swagger/templates/callbacks.def: -------------------------------------------------------------------------------- 1 | {{? typeof data.operation.callbacks === 'object'}} 2 | 3 | ### Callbacks 4 | 5 | {{ data.operationStack.push(data.operation); }} 6 | 7 | {{ for (var c of Object.keys(data.operation.callbacks)) { }} 8 | 9 | #### {{=c}} 10 | 11 | {{ var callback = data.operation.callbacks && data.operation.callbacks[c]; }} 12 | 13 | {{ for (var e in callback) { }} 14 | 15 | **{{=e}}** 16 | 17 | {{ var exp = callback[e]; }} 18 | 19 | {{ for (var m in exp) { }} 20 | 21 | {{ data.operation = exp[m]; }} 22 | {{ data.method.operation = data.operation; }} 23 | 24 | {{= data.templates.operation(data) }} 25 | 26 | {{ } /* of methods */ }} 27 | 28 | {{ } /* of expressions */ }} 29 | 30 | {{ } /* of callbacks */ }} 31 | 32 | {{ data.operation = data.operationStack.pop(); }} 33 | {{ data.method.operation = data.operation; }} 34 | 35 | {{?}} 36 | -------------------------------------------------------------------------------- /swagger/templates/code_csharp.dot: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Net.Http; 4 | using System.Net.Http.Headers; 5 | using System.Text; 6 | using System.Threading.Tasks; 7 | using Newtonsoft.Json; 8 | 9 | /// <> 10 | /// Example of Http Client 11 | /// <> 12 | public class HttpExample 13 | { 14 | private HttpClient Client { get; set; } 15 | 16 | /// <> 17 | /// Setup http client 18 | /// <> 19 | public HttpExample() 20 | { 21 | Client = new HttpClient(); 22 | } 23 | {{? data.methodUpper == "GET"}} 24 | /// Make a dummy request 25 | public async Task MakeGetRequest() 26 | { 27 | string url = "{{=data.url}}"; 28 | var result = await GetAsync(url); 29 | } 30 | 31 | /// Performs a GET Request 32 | public async Task GetAsync(string url) 33 | { 34 | //Start the request 35 | HttpResponseMessage response = await Client.GetAsync(url); 36 | 37 | //Validate result 38 | response.EnsureSuccessStatusCode(); 39 | 40 | }{{? }} 41 | {{? data.methodUpper == "POST"}} 42 | /// Make a dummy request 43 | public async Task MakePostRequest() 44 | { 45 | string url = "{{=data.url}}"; 46 | {{? data.bodyParameter.refName !== undefined }} 47 | string json = @"{{=data.bodyParameter.exampleValues.json.replace(new RegExp('"', "g"), '""')}}"; 48 | {{=data.bodyParameter.refName}} content = JsonConvert.DeserializeObject(json); 49 | await PostAsync(content, url); 50 | {{? }} 51 | {{? data.bodyParameter.refName === undefined }} 52 | await PostAsync(null, url); 53 | {{? }} 54 | } 55 | 56 | /// Performs a POST Request 57 | public async Task PostAsync({{=data.bodyParameter.refName}} content, string url) 58 | { 59 | //Serialize Object 60 | StringContent jsonContent = SerializeObject(content); 61 | 62 | //Execute POST request 63 | HttpResponseMessage response = await Client.PostAsync(url, jsonContent); 64 | }{{? }} 65 | {{? data.methodUpper == "PUT"}} 66 | /// Make a dummy request 67 | public async Task MakePutRequest() 68 | { 69 | int id = 1; 70 | string url = "{{=data.url}}"; 71 | 72 | {{? data.bodyParameter.refName !== undefined }} 73 | string json = @"{{=data.bodyParameter.exampleValues.json.replace(new RegExp('"', "g"), '""')}}"; 74 | {{=data.bodyParameter.refName}} content = JsonConvert.DeserializeObject(json); 75 | var result = await PutAsync(id, content, url); 76 | {{? }} 77 | {{? data.bodyParameter.refName === undefined }} 78 | var result = await PutAsync(id, null, url); 79 | {{? }} 80 | } 81 | 82 | /// Performs a PUT Request 83 | public async Task PutAsync(int id, {{=data.bodyParameter.refName}} content, string url) 84 | { 85 | //Serialize Object 86 | StringContent jsonContent = SerializeObject(content); 87 | 88 | //Execute PUT request 89 | HttpResponseMessage response = await Client.PutAsync(url + $"/{id}", jsonContent); 90 | 91 | //Return response 92 | return await DeserializeObject(response); 93 | }{{? }} 94 | {{? data.methodUpper == "DELETE"}} 95 | /// Make a dummy request 96 | public async Task MakeDeleteRequest() 97 | { 98 | int id = 1; 99 | string url = "{{=data.url}}"; 100 | 101 | await DeleteAsync(id, url); 102 | } 103 | 104 | /// Performs a DELETE Request 105 | public async Task DeleteAsync(int id, string url) 106 | { 107 | //Execute DELETE request 108 | HttpResponseMessage response = await Client.DeleteAsync(url + $"/{id}"); 109 | 110 | //Return response 111 | await DeserializeObject(response); 112 | }{{? }} 113 | {{? data.methodUpper == "POST" || data.methodUpper == "PUT"}} 114 | /// Serialize an object to Json 115 | private StringContent SerializeObject({{=data.bodyParameter.refName}} content) 116 | { 117 | //Serialize Object 118 | string jsonObject = JsonConvert.SerializeObject(content); 119 | 120 | //Create Json UTF8 String Content 121 | return new StringContent(jsonObject, Encoding.UTF8, "application/json"); 122 | } 123 | {{? }} 124 | /// Deserialize object from request response 125 | private async Task DeserializeObject(HttpResponseMessage response) 126 | { 127 | //Read body 128 | string responseBody = await response.Content.ReadAsStringAsync(); 129 | 130 | //Deserialize Body to object 131 | var result = JsonConvert.DeserializeObject(responseBody); 132 | } 133 | } 134 | -------------------------------------------------------------------------------- /swagger/templates/code_go.dot: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "net/http" 6 | ) 7 | 8 | func main() { 9 | 10 | {{?data.allHeaders.length}} 11 | headers := map[string][]string{ 12 | {{~data.allHeaders :p:index}}"{{=p.name}}": []string{"{{=p.exampleValues.object}}"},{{?index < data.allHeaders.length-1}} 13 | {{?}}{{~}} 14 | }{{?}} 15 | 16 | data := bytes.NewBuffer([]byte{jsonReq}) 17 | req, err := http.NewRequest("{{=data.methodUpper}}", "{{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample.replace(data.requiredQueryString, ""))}}", data) 18 | req.Header = headers 19 | 20 | client := &http.Client{} 21 | resp, err := client.Do(req) 22 | // ... 23 | } 24 | -------------------------------------------------------------------------------- /swagger/templates/code_http.dot: -------------------------------------------------------------------------------- 1 | {{=data.methodUpper}} {{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample)}} HTTP/1.1 2 | {{? data.host}}Host: {{=data.host}}{{?}} 3 | {{?data.headerParameters.length}}{{~ data.headerParameters :p:index}}{{=p.name}}: {{=p.exampleValues.object}} 4 | {{~}} 5 | {{?}} 6 | -------------------------------------------------------------------------------- /swagger/templates/code_java.dot: -------------------------------------------------------------------------------- 1 | URL obj = new URL("{{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample)}}"); 2 | HttpURLConnection con = (HttpURLConnection) obj.openConnection(); 3 | con.setRequestMethod("{{=data.methodUpper}}"); 4 | int responseCode = con.getResponseCode(); 5 | BufferedReader in = new BufferedReader( 6 | new InputStreamReader(con.getInputStream())); 7 | String inputLine; 8 | StringBuffer response = new StringBuffer(); 9 | while ((inputLine = in.readLine()) != null) { 10 | response.append(inputLine); 11 | } 12 | in.close(); 13 | System.out.println(response.toString()); 14 | -------------------------------------------------------------------------------- /swagger/templates/code_javascript.dot: -------------------------------------------------------------------------------- 1 | {{?data.bodyParameter.present}}const inputBody = '{{=data.bodyParameter.exampleValues.json}}';{{?}} 2 | {{?data.allHeaders.length}}const headers = { 3 | {{~data.allHeaders :p:index}} '{{=p.name}}':{{=p.exampleValues.json}}{{?index < data.allHeaders.length-1}},{{?}} 4 | {{~}}}; 5 | {{?}} 6 | fetch('{{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample)}}', 7 | { 8 | method: '{{=data.methodUpper}}'{{?data.bodyParameter.present || data.allHeaders.length}},{{?}} 9 | {{?data.bodyParameter.present}} body: inputBody{{?}}{{? data.bodyParameter.present && data.allHeaders.length}},{{?}} 10 | {{?data.allHeaders.length}} headers: headers{{?}} 11 | }) 12 | .then(function(res) { 13 | return res.json(); 14 | }).then(function(body) { 15 | console.log(body); 16 | }); 17 | -------------------------------------------------------------------------------- /swagger/templates/code_jquery.dot: -------------------------------------------------------------------------------- 1 | {{?data.allHeaders.length}}var headers = { 2 | {{~data.allHeaders :p:index}} '{{=p.name}}':{{=p.exampleValues.json}}{{?index < data.allHeaders.length-1}},{{?}} 3 | {{~}} 4 | }; 5 | {{?}} 6 | $.ajax({ 7 | url: '{{=data.url}}', 8 | method: '{{=data.method.verb}}', 9 | {{?data.requiredQueryString}} data: '{{=data.requiredQueryString}}',{{?}} 10 | {{?data.allHeaders.length}} headers: headers,{{?}} 11 | success: function(data) { 12 | console.log(JSON.stringify(data)); 13 | } 14 | }) 15 | -------------------------------------------------------------------------------- /swagger/templates/code_nodejs.dot: -------------------------------------------------------------------------------- 1 | const fetch = require('node-fetch'); 2 | {{?data.bodyParameter.present}}const inputBody = {{=data.bodyParameter.exampleValues.json}};{{?}} 3 | {{?data.allHeaders.length}}const headers = { 4 | {{~data.allHeaders :p:index}} '{{=p.name}}':{{=p.exampleValues.json}}{{?index < data.allHeaders.length-1}},{{?}} 5 | {{~}}}; 6 | {{?}} 7 | fetch('{{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample)}}', 8 | { 9 | method: '{{=data.methodUpper}}'{{?data.bodyParameter.present || data.allHeaders.length}},{{?}} 10 | {{?data.bodyParameter.present}} body: JSON.stringify(inputBody){{?}}{{? data.bodyParameter.present && data.allHeaders.length}},{{?}} 11 | {{?data.allHeaders.length}} headers: headers{{?}} 12 | }) 13 | .then(function(res) { 14 | return res.json(); 15 | }).then(function(body) { 16 | console.log(body); 17 | }); 18 | -------------------------------------------------------------------------------- /swagger/templates/code_php.dot: -------------------------------------------------------------------------------- 1 | '{{=p.exampleValues.object}}', 8 | {{?index < data.allHeaders.length-1}} {{?}}{{~}});{{?}} 9 | 10 | $client = new \GuzzleHttp\Client(); 11 | 12 | // Define array of request body. 13 | $request_body = array(); 14 | 15 | try { 16 | $response = $client->request('{{=data.methodUpper}}','{{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample.replace(data.requiredQueryString, ""))}}', array( 17 | 'headers' => $headers, 18 | 'json' => $request_body, 19 | ) 20 | ); 21 | print_r($response->getBody()->getContents()); 22 | } 23 | catch (\GuzzleHttp\Exception\BadResponseException $e) { 24 | // handle exception or api errors. 25 | print_r($e->getMessage()); 26 | } 27 | 28 | // ... 29 | -------------------------------------------------------------------------------- /swagger/templates/code_python.dot: -------------------------------------------------------------------------------- 1 | import requests 2 | {{?data.allHeaders.length}}headers = { 3 | {{~data.allHeaders :p:index}} '{{=p.name}}': {{=p.exampleValues.json}}{{?index < data.allHeaders.length-1}},{{?}} 4 | {{~}}} 5 | {{?}} 6 | r = requests.{{=data.method.verb}}('{{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample.replace(data.requiredQueryString, ""))}}'{{? data.requiredParameters.length}}, params={ 7 | {{~ data.requiredParameters :p:index}} '{{=p.name}}': {{=p.exampleValues.json}}{{? data.requiredParameters.length-1 != index }},{{?}}{{~}} 8 | }{{?}}{{?data.allHeaders.length}}, headers = headers{{?}}) 9 | 10 | print(r.json()) 11 | -------------------------------------------------------------------------------- /swagger/templates/code_ruby.dot: -------------------------------------------------------------------------------- 1 | require 'rest-client' 2 | require 'json' 3 | 4 | {{?data.allHeaders.length}}headers = { 5 | {{~data.allHeaders :p:index}} '{{=p.name}}' => {{=p.exampleValues.json}}{{?index < data.allHeaders.length-1}},{{?}} 6 | {{~}}}{{?}} 7 | 8 | result = RestClient.{{=data.method.verb}} '{{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample.replace(data.requiredQueryString, ""))}}', 9 | params: { 10 | {{~ data.requiredParameters :p:index}}'{{=p.name}}' => '{{=p.safeType}}'{{? data.requiredParameters.length-1 != index }},{{?}} 11 | {{~}}}{{? data.allHeaders.length}}, headers: headers 12 | {{?}} 13 | 14 | p JSON.parse(result) 15 | -------------------------------------------------------------------------------- /swagger/templates/code_shell.dot: -------------------------------------------------------------------------------- 1 | curl {{=data.baseUrl}}{{=decodeURIComponent(data.requiredUriExample)}}{{?data.allHeaders.length}} {{?}} 2 | {{~data.allHeaders :p:index}} {{?index < data.allHeaders.length-1}} \{{?}} 3 | {{~}} 4 | -------------------------------------------------------------------------------- /swagger/templates/debug.def: -------------------------------------------------------------------------------- 1 | {{= data.utils.inspect(data) }} 2 | -------------------------------------------------------------------------------- /swagger/templates/discovery.def: -------------------------------------------------------------------------------- 1 | 12 | -------------------------------------------------------------------------------- /swagger/templates/footer.def: -------------------------------------------------------------------------------- 1 | 2 | 3 | -------------------------------------------------------------------------------- /swagger/templates/links.def: -------------------------------------------------------------------------------- 1 | {{? data.response.links }} 2 | 3 | #### Links 4 | 5 | {{ for (var l in data.response.links) { }} 6 | {{ var link = data.response.links[l]; }} 7 | 8 | **{{=l}}** => {{?link.operationId}}{{=link.operationId}}{{??}}{{=link.operationRef}}{{?}} 9 | 10 | {{? link.parameters }} 11 | |Parameter|Expression| 12 | |---|---| 13 | {{for (var p in link.parameters) { }}|{{=p}}|{{=link.parameters[p]}}|{{ } }} 14 | {{?}} 15 | 16 | {{ } /* of links */ }} 17 | 18 | {{?}} 19 | -------------------------------------------------------------------------------- /swagger/templates/main.dot: -------------------------------------------------------------------------------- 1 | {{= data.tags.section }} 2 | 3 | 4 | {{? data.api.info && data.api.info.termsOfService}}Terms of service{{?}} 5 | {{? data.api.info && data.api.info.contact}}{{? data.api.info.contact.email}}Email: {{=data.api.info.contact.name || 'Support'}} {{?}}{{? data.api.info.contact.url}}Web: {{= data.api.info.contact.name || 'Support'}} {{?}}{{?}} 6 | {{? data.api.info && data.api.info.license}}{{? data.api.info.license.url}}License: {{=data.api.info.license.name}}{{??}} License: {{=data.api.info.license.name}}{{?}}{{?}} 7 | {{= data.tags.endSection }} 8 | 9 | {{? data.api.components && data.api.components.securitySchemes }} 10 | {{#def.security}} 11 | {{?}} 12 | 13 | {{ for (var r in data.resources) { }} 14 | {{ data.resource = data.resources[r]; }} 15 | 16 | {{= data.tags.section }} 17 |

        {{= r}}

        18 | 19 | {{? data.resource.externalDocs}} 20 | {{=data.resource.externalDocs.description||'External documentation'}} 21 | {{?}} 22 | 23 | {{ for (var m in data.resource.methods) { }} 24 | {{ data.operationUniqueName = m; }} 25 | {{ data.method = data.resource.methods[m]; }} 26 | {{ data.operationUniqueSlug = data.method.slug; }} 27 | {{ data.operation = data.method.operation; }} 28 | {{= data.templates.operation(data) }} 29 | {{ } /* of methods */ }} 30 | 31 | {{= data.tags.endSection }} 32 | {{ } /* of resources */ }} 33 | 34 | {{? data.api.components && data.api.components.schemas }} 35 | {{= data.tags.section }} 36 | 37 | # Schemas 38 | 39 | The following are examples of response formats you can expect to receive from the API. 40 | 41 | {{ for (var s in data.components.schemas) { }} 42 | {{ var origSchema = data.components.schemas[s]; }} 43 | {{ var schema = data.api.components.schemas[s]; }} 44 | 45 | {{= data.tags.section }} 46 | {{ /* backwards compatibility */ }} 47 | 48 | 49 | 50 | 51 |

        {{=s}}

        52 | 53 | {{? data.options.yaml }} 54 | ```yaml 55 | {{=data.utils.yaml.stringify(data.utils.getSample(schema,data.options,{quiet:true},data.api))}} 56 | {{??}} 57 | ```json 58 | {{=data.utils.safejson(data.utils.getSample(schema,data.options,{quiet:true},data.api),null,2)}} 59 | {{?}} 60 | ``` 61 | 62 | {{ var enums = []; }} 63 | {{ var blocks = data.utils.schemaToArray(origSchema,-1,{trim:true,join:true},data); }} 64 | {{ for (var block of blocks) { 65 | for (var p of block.rows) { 66 | if (p.schema && p.schema.enum) { 67 | for (var e of p.schema.enum) { 68 | enums.push({name:p.name,value:e}); 69 | } 70 | } 71 | } 72 | } 73 | }} 74 | 75 | {{~ blocks :block}} 76 | {{? block.title }}{{= block.title}}{{= '\n\n'}}{{?}} 77 | {{? block.externalDocs}} 78 | {{=block.externalDocs.description||'External documentation'}} 79 | {{?}} 80 | 81 | {{? block===blocks[0] }} 82 | {{= data.tags.section }} 83 | 84 | ### Properties 85 | {{?}} 86 | 87 | {{? block.rows.length}}|Name|Type|Required|Restrictions|Description| 88 | |---|---|---|---|---|{{?}} 89 | {{~ block.rows :p}}|{{=p.displayName}}|{{=p.safeType}}|{{=p.required}}|{{=p.restrictions||'none'}}|{{=p.description||'none'}}| 90 | {{~}} 91 | {{~}} 92 | {{? (blocks[0].rows.length === 0) && (blocks.length === 1) }} 93 | *None* 94 | {{?}} 95 | 96 | {{? enums.length > 0 }} 97 | {{= data.tags.section }} 98 | 99 | #### Enumerated Values 100 | 101 | |Property|Value| 102 | |---|---| 103 | {{~ enums :e}}|{{=e.name}}|{{=data.utils.toPrimitive(e.value)}}| 104 | {{~}} 105 | 106 | {{= data.tags.endSection }} 107 | {{?}} 108 | 109 | {{= data.tags.endSection }} 110 | {{= data.tags.endSection }} 111 | 112 | {{ } /* of schemas */ }} 113 | 114 | {{?}} 115 | 116 | {{#def.footer}} 117 | 118 | {{? data.options.discovery}} 119 | {{#def.discovery}} 120 | {{?}} 121 | -------------------------------------------------------------------------------- /swagger/templates/operation.dot: -------------------------------------------------------------------------------- 1 | {{= data.tags.section }} 2 | 3 | ## {{= data.operationUniqueName}} 4 | 5 | {{? data.operation.operationId}} 6 | 7 | {{?}} 8 | 9 | {{ data.methodUpper = data.method.verb.toUpperCase(); }} 10 | {{ data.url = data.utils.slashes(data.baseUrl + data.method.path); }} 11 | {{ data.parameters = data.operation.parameters; }} 12 | {{ data.enums = []; }} 13 | {{ data.utils.fakeProdCons(data); }} 14 | {{ data.utils.fakeBodyParameter(data); }} 15 | {{ data.utils.mergePathParameters(data); }} 16 | {{ data.utils.getParameters(data); }} 17 | 18 | {{? data.options.codeSamples || data.operation["x-code-samples"] }} 19 | > Code Sample 20 | 21 | {{= data.utils.getCodeSamples(data) }} 22 | {{?}} 23 | 24 | `{{= data.methodUpper}} {{=data.method.path}}` 25 | 26 | {{? data.operation.summary && !data.options.tocSummary}}*{{= data.operation.summary }}*{{?}} 27 | 28 | {{ const linkify = (text) => { 29 | return text.replace(/(https?\:\/\/[^\s]*)/g, '$1') 30 | }; }} 31 | {{? data.operation.description}}{{= linkify(data.operation.description) }}{{?}} 32 | 33 | {{? data.operation.requestBody}} 34 | > Body parameter 35 | 36 | {{? data.bodyParameter.exampleValues.description }} 37 | > {{= data.bodyParameter.exampleValues.description }} 38 | {{?}} 39 | 40 | {{= data.utils.getBodyParameterExamples(data) }} 41 | {{?}} 42 | 43 | {{? data.parameters && data.parameters.length }} 44 | {{#def.parameters}} 45 | {{?}} 46 | 47 | {{#def.responses}} 48 | 49 | {{#def.callbacks}} 50 | 51 | {{ data.security = data.operation.security ? data.operation.security : data.api.security; }} 52 | {{? data.security && data.security.length }} 53 | {{#def.authentication}} 54 | {{??}} 55 | {{#def.authentication_none}} 56 | {{?}} 57 | {{= data.tags.endSection }} 58 | -------------------------------------------------------------------------------- /swagger/templates/parameters.def: -------------------------------------------------------------------------------- 1 | {{= data.tags.section }} 2 |

        Query Parameters

        3 | 4 | |Name|Type|Required|Description| 5 | |---|---|---|---|---|---| 6 | {{~ data.parameters :p}}|{{=p.name}}|{{=p.safeType}}|{{=p.required}}|{{=p.shortDesc || 'none'}}{{? p.schema && p.schema.enum}}{{~ p.schema.enum :e}}{{~}}
        Available values:{{=e}}
        {{?}}| 7 | {{~}} 8 | 9 | {{? data.longDescs }} 10 | #### Detailed descriptions 11 | {{~ data.parameters :p}}{{? p.shortDesc !== p.description}} 12 | **{{=p.name}}**: {{=p.description}}{{?}} 13 | {{~}} 14 | {{?}} 15 | 16 | {{~ data.parameters :p}} 17 | 18 | {{? p.schema && p.schema.items && p.schema.items.enum }} 19 | {{~ p.schema.items.enum :e}} 20 | {{ var entry = {}; entry.name = p.name; entry.value = e; data.enums.push(entry); }} 21 | {{~}} 22 | {{?}} 23 | 24 | {{~}} 25 | 26 | {{? data.enums && data.enums.length }} 27 | #### Enumerated Values 28 | 29 | |Parameter|Value| 30 | |---|---| 31 | {{~ data.enums :e}}|{{=e.name}}|{{=data.utils.toPrimitive(e.value)}}| 32 | {{~}} 33 | {{?}} 34 | {{= data.tags.endSection }} 35 | -------------------------------------------------------------------------------- /swagger/templates/responses.def: -------------------------------------------------------------------------------- 1 | {{ data.responses = data.utils.getResponses(data); }} 2 | {{ data.responseSchemas = false; }} 3 | {{~ data.responses :response }} 4 | {{ if (response.content) data.responseSchemas = true; }} 5 | {{~}} 6 | 7 | {{? data.responseSchemas }} 8 | > Example Response 9 | 10 | {{= data.utils.getResponseExamples(data) }} 11 | {{?}} 12 | 13 | {{= data.tags.section }} 14 |

        Responses

        15 | 16 | |Status|Meaning|Description|Schema| 17 | |---|---|---|---| 18 | {{~ data.responses :r}}|{{=r.status}}|{{=r.meaning}}|{{=r.description || 'none'}}|{{=r.schema}}| 19 | {{~}} 20 | 21 | {{ data.responseSchemas = false; }} 22 | {{~ data.responses :response }} 23 | {{ if (response.content && !response.$ref && !data.utils.isPrimitive(response.type)) data.responseSchemas = true; }} 24 | {{~}} 25 | {{? data.responseSchemas }} 26 |

        Response Schema

        27 | {{~ data.responses :response}} 28 | {{? response.content && !response.$ref && !data.utils.isPrimitive(response.type)}} 29 | {{? Object.keys(response.content).length }} 30 | {{ var responseKey = Object.keys(response.content)[0]; }} 31 | {{ var responseSchema = response.content[responseKey].schema; }} 32 | {{ var enums = []; }} 33 | {{ var blocks = data.utils.schemaToArray(responseSchema,0,{trim:true,join:true},data); }} 34 | {{ for (var block of blocks) { 35 | for (var p of block.rows) { 36 | if (p.schema && p.schema.enum) { 37 | for (var e of p.schema.enum) { 38 | enums.push({name:p.name,value:e}); 39 | } 40 | } 41 | } 42 | } 43 | }} 44 | 45 | {{? blocks[0].rows.length || blocks[0].title }} 46 | Status Code **{{=response.status}}** 47 | 48 | {{~ blocks :block}} 49 | {{? block.title }}*{{=block.title}}* 50 | {{?}} 51 | |Name|Type|Required|Restrictions|Description| 52 | |---|---|---|---|---| 53 | {{~block.rows :p}}|{{=p.displayName}}|{{=p.safeType}}|{{=p.required}}|{{=p.restrictions||'none'}}|{{=p.description||'none'}}| 54 | {{~}} 55 | {{~}} 56 | {{?}} 57 | 58 | {{? enums.length > 0 }} 59 | #### Enumerated Values 60 | 61 | |Property|Value| 62 | |---|---| 63 | {{~ enums :e}}|{{=e.name}}|{{=data.utils.toPrimitive(e.value)}}| 64 | {{~}} 65 | 66 | {{?}} 67 | {{?}} 68 | 69 | {{ data.response = response; }} 70 | {{#def.links}} 71 | 72 | {{?}} 73 | {{~}} 74 | {{?}} 75 | 76 | {{ data.responseHeaders = data.utils.getResponseHeaders(data); }} 77 | {{? data.responseHeaders.length }} 78 | 79 | ### Response Headers 80 | 81 | |Status|Header|Type|Format|Description| 82 | |---|---|---|---|---| 83 | {{~ data.responseHeaders :h}}|{{=h.status}}|{{=h.header}}|{{=h.type}}|{{=h.format||''}}|{{=h.description||'none'}}| 84 | {{~}} 85 | 86 | {{?}} 87 | {{= data.tags.endSection }} 88 | -------------------------------------------------------------------------------- /swagger/templates/security.def: -------------------------------------------------------------------------------- 1 | {{= data.tags.section }} 2 | 3 | # Authentication 4 | 5 | {{ for (var s in data.api.components.securitySchemes) { }} 6 | {{ var sd = data.api.components.securitySchemes[s]; }} 7 | {{? sd.type == 'apiKey' }} 8 | * API Key ({{=s}}) 9 | - Parameter Name: **{{=sd.name}}**, in: {{=sd.in}}. {{=sd.description || ''}} 10 | {{?}} 11 | {{? sd.type == 'http'}} 12 | - HTTP Authentication, scheme: {{=sd.scheme}} {{=sd.description || ''}} 13 | {{?}} 14 | {{? sd.type == 'oauth2'}} 15 | - oAuth2 authentication. {{=sd.description || ''}} 16 | {{ for (var f in sd.flows) { }} 17 | {{ var flow = sd.flows[f]; }} 18 | - Flow: {{=f}} 19 | {{? flow.authorizationUrl}} - Authorization URL = [{{=flow.authorizationUrl}}]({{=flow.authorizationUrl}}){{?}} 20 | {{? flow.tokenUrl}} - Token URL = [{{=flow.tokenUrl}}]({{=flow.tokenUrl}}){{?}} 21 | {{? flow.scopes && Object.keys(flow.scopes).length}} 22 | |Scope|Scope Description| 23 | |---|---| 24 | {{ for (var sc in flow.scopes) { }}|{{=sc}}|{{=data.utils.join(flow.scopes[sc])}}| 25 | {{ } /* of scopes */ }} 26 | {{?}} 27 | {{ } /* of flows */ }} 28 | {{?}} 29 | {{ } /* of securitySchemes */ }} 30 | 31 | {{= data.tags.endSection }} 32 | -------------------------------------------------------------------------------- /swagger/templates/translations.dot: -------------------------------------------------------------------------------- 1 | {{ 2 | data.translations.defaultTag = 'Default'; 3 | data.translations.response = 'Response'; 4 | data.translations.responseDefault = 'Default'; 5 | data.translations.responseUnknown = 'Unknown'; 6 | data.translations.schemaInline = 'Inline'; 7 | data.translations.schemaNone = 'None'; 8 | data.translations.externalDocs = 'External documentation'; 9 | data.translations.secDefNone = 'None'; 10 | data.translations.secDefScopes = 'Scopes'; 11 | data.translations.anonymous = 'anonymous'; 12 | data.translations.continued = 'continued'; 13 | data.translations.indent = '»'; 14 | data.translations.readOnly = 'read-only'; 15 | data.translations.writeOnly = 'write-only'; 16 | data.tags = {}; 17 | data.tags.section = data.options.respec ? '
        ' : ''; 18 | data.tags.endSection = data.options.respec ? '
        ' : ''; 19 | }} 20 | --------------------------------------------------------------------------------