├── .github └── workflows │ └── build.yml ├── .gitignore ├── .travis.yml ├── CONTRIBUTING.md ├── Dockerfile ├── Gemfile ├── Gemfile.lock ├── LICENSE ├── README.md ├── Rakefile ├── config.rb ├── font-selection.json └── source ├── fonts ├── FontAwesome.otf ├── fontawesome-webfont.eot ├── fontawesome-webfont.svg ├── fontawesome-webfont.ttf ├── fontawesome-webfont.woff ├── fontawesome-webfont.woff2 ├── fontello.eot ├── fontello.svg ├── fontello.ttf ├── fontello.woff ├── slate.eot ├── slate.svg ├── slate.ttf ├── slate.woff └── slate.woff2 ├── images ├── logo.png ├── navbar.png └── qb.png ├── includes ├── categories │ └── _index.md.erb ├── commerce │ └── _index.md.erb ├── gettingstarted │ └── _index.md.erb ├── openbox │ ├── _category.md │ ├── _index.md.erb │ ├── _multiple-skus.md │ └── _single-sku.md ├── overview │ ├── _cursormark.md │ ├── _errors.md │ ├── _facets.md │ ├── _index.md.erb │ ├── _pagination.md │ ├── _postman.md │ ├── _responseFormat.md │ ├── _retrievingCollections.md │ ├── _show.md │ └── _sort.md ├── products │ ├── _availability-and-delivery.md │ ├── _categorizations.md │ ├── _detail.md │ ├── _images.md │ ├── _index.md.erb │ ├── _links.md │ ├── _listing-products.md │ ├── _offers-and-deals.md │ ├── _pricing-and-ranking.md │ ├── _proposition65.md │ └── _warranty.md ├── recommendations │ ├── _also-bought.md │ ├── _also-viewed.md │ ├── _index.md.erb │ ├── _most-viewed.md │ ├── _trending.md │ └── _viewed-ultimately-bought.md ├── search │ └── _index.md └── stores │ └── _index.md.erb ├── index.md ├── javascripts ├── all.js ├── all_nosearch.js ├── app │ ├── _lang.js │ ├── _replaceText.js │ ├── _search.js │ └── _toc.js ├── fakeloader.js └── lib │ ├── _energize.js │ ├── _imagesloaded.min.js │ ├── _jquery.highlight.js │ ├── _jquery.tocify.js │ ├── _jquery_ui.js │ └── _lunr.js ├── layouts └── layout.erb └── stylesheets ├── _bby-custom.scss ├── _icon-font.scss ├── _normalize.css ├── _syntax.scss.erb ├── _variables.scss ├── fakeloader.css ├── print.css.scss └── screen.css.scss /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build and publish 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | jobs: 9 | build: 10 | name: Build the project 11 | runs-on: ubuntu-latest 12 | 13 | steps: 14 | - uses: actions/checkout@v2 15 | 16 | - name: Set up ruby-2.6 17 | uses: actions/setup-ruby@v1 18 | with: 19 | ruby-version: '2.6' 20 | 21 | - name: Configure git 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | run: | 25 | git config --global user.name github-actions 26 | git config --global user.email github-actions@github.com 27 | git remote set-url origin "https://${GITHUB_ACTOR}:${GITHUB_TOKEN}@github.com/${GITHUB_REPOSITORY}.git" 28 | 29 | - name: Build and publish 30 | run: | 31 | bundle install 32 | rake publish -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Sublime files we don't want to get included 2 | *.tmlanguage.cache 3 | *.tmPreferences.cache 4 | *.stTheme.cache 5 | *.sublime-workspace 6 | sftp-config.json 7 | 8 | # Default Slate .gitignore starts after here 9 | *.gem 10 | *.rbc 11 | .bundle 12 | .config 13 | coverage 14 | InstalledFiles 15 | lib/bundler/man 16 | pkg 17 | rdoc 18 | spec/reports 19 | test/tmp 20 | test/version_tmp 21 | tmp 22 | *.DS_STORE 23 | build/ 24 | .cache 25 | 26 | # YARD artifacts 27 | .yardoc 28 | _yardoc 29 | doc/ 30 | .idea/ 31 | npm-debug.log 32 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: false 2 | 3 | language: ruby 4 | 5 | rvm: 6 | - 1.9.3 7 | - 2.0.0 8 | 9 | cache: bundler 10 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Best Buy's API Documentation 2 | 3 | Thanks for being interested in contributing to Best Buy's API! 4 | 5 | - If you find a bug or want to add a feature, create an issue on [GitHub](https://github.com/BestBuyAPIs/api-documentation) 6 | - If you have questions, you can [contact us](https://developer.bestbuy.com/contact-us) 7 | - If you'd like to learn more, please visit https://developer.bestbuy.com/ 8 | 9 | # Contributing to Slate 10 | 11 | See [Slate's Contribution Guide](https://github.com/tripit/slate/blob/master/CONTRIBUTING.md) for information on how to contribute. 12 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM ubuntu:trusty 2 | 3 | RUN apt-get update 4 | RUN apt-get install -yq ruby ruby-dev build-essential git 5 | RUN gem install --no-ri --no-rdoc bundler 6 | ADD Gemfile /app/Gemfile 7 | ADD Gemfile.lock /app/Gemfile.lock 8 | RUN cd /app; bundle install 9 | ADD . /app 10 | EXPOSE 4567 11 | WORKDIR /app 12 | CMD ["bundle", "exec", "middleman", "server"] 13 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source 'https://rubygems.org' 2 | 3 | # Middleman 4 | gem 'middleman', '~>3.3.10' 5 | gem 'middleman-gh-pages', '~> 0.0.3' 6 | gem 'middleman-syntax', '~> 2.0.0' 7 | gem 'middleman-autoprefixer', '~> 2.4.4' 8 | gem 'rouge', '~> 1.9.0' 9 | gem 'redcarpet', '~> 3.3.2' 10 | 11 | gem 'rake', '~> 10.4.2' 12 | gem 'therubyracer', '~> 0.12.1', platforms: :ruby 13 | gem 'json', '>=1.8.3' -------------------------------------------------------------------------------- /Gemfile.lock: -------------------------------------------------------------------------------- 1 | GEM 2 | remote: https://rubygems.org/ 3 | specs: 4 | activesupport (4.1.16) 5 | i18n (~> 0.6, >= 0.6.9) 6 | json (~> 1.7, >= 1.7.7) 7 | minitest (~> 5.1) 8 | thread_safe (~> 0.1) 9 | tzinfo (~> 1.1) 10 | autoprefixer-rails (5.2.1.3) 11 | execjs 12 | json 13 | celluloid (0.16.0) 14 | timers (~> 4.0.0) 15 | chunky_png (1.4.0) 16 | coffee-script (2.4.1) 17 | coffee-script-source 18 | execjs 19 | coffee-script-source (1.12.2) 20 | compass (1.0.3) 21 | chunky_png (~> 1.2) 22 | compass-core (~> 1.0.2) 23 | compass-import-once (~> 1.0.5) 24 | rb-fsevent (>= 0.9.3) 25 | rb-inotify (>= 0.9) 26 | sass (>= 3.3.13, < 3.5) 27 | compass-core (1.0.3) 28 | multi_json (~> 1.0) 29 | sass (>= 3.3.0, < 3.5) 30 | compass-import-once (1.0.5) 31 | sass (>= 3.2, < 3.5) 32 | erubis (2.7.0) 33 | execjs (2.7.0) 34 | ffi (1.14.2) 35 | haml (5.2.1) 36 | temple (>= 0.8.0) 37 | tilt 38 | hike (1.2.3) 39 | hitimes (2.0.0) 40 | hooks (0.4.1) 41 | uber (~> 0.0.14) 42 | i18n (0.7.0) 43 | json (1.8.6) 44 | kramdown (1.17.0) 45 | libv8 (3.16.14.19) 46 | listen (2.10.1) 47 | celluloid (~> 0.16.0) 48 | rb-fsevent (>= 0.9.3) 49 | rb-inotify (>= 0.9) 50 | middleman (3.3.12) 51 | coffee-script (~> 2.2) 52 | compass (>= 1.0.0, < 2.0.0) 53 | compass-import-once (= 1.0.5) 54 | execjs (~> 2.0) 55 | haml (>= 4.0.5) 56 | kramdown (~> 1.2) 57 | middleman-core (= 3.3.12) 58 | middleman-sprockets (>= 3.1.2) 59 | sass (>= 3.4.0, < 4.0) 60 | uglifier (~> 2.5) 61 | middleman-autoprefixer (2.4.4) 62 | autoprefixer-rails (~> 5.2.0) 63 | middleman-core (>= 3.3.3) 64 | middleman-core (3.3.12) 65 | activesupport (~> 4.1.0) 66 | bundler (~> 1.1) 67 | erubis 68 | hooks (~> 0.3) 69 | i18n (~> 0.7.0) 70 | listen (>= 2.7.9, < 3.0) 71 | padrino-helpers (~> 0.12.3) 72 | rack (>= 1.4.5, < 2.0) 73 | rack-test (~> 0.6.2) 74 | thor (>= 0.15.2, < 2.0) 75 | tilt (~> 1.4.1, < 2.0) 76 | middleman-gh-pages (0.0.3) 77 | rake (> 0.9.3) 78 | middleman-sprockets (3.5.0) 79 | middleman-core (>= 3.3) 80 | sprockets (~> 2.12.1) 81 | sprockets-helpers (~> 1.1.0) 82 | sprockets-sass (~> 1.3.0) 83 | middleman-syntax (2.0.0) 84 | middleman-core (~> 3.2) 85 | rouge (~> 1.0) 86 | minitest (5.14.3) 87 | multi_json (1.15.0) 88 | padrino-helpers (0.12.9) 89 | i18n (~> 0.6, >= 0.6.7) 90 | padrino-support (= 0.12.9) 91 | tilt (>= 1.4.1, < 3) 92 | padrino-support (0.12.9) 93 | activesupport (>= 3.1) 94 | rack (1.6.13) 95 | rack-test (0.6.3) 96 | rack (>= 1.0) 97 | rake (10.4.2) 98 | rb-fsevent (0.10.4) 99 | rb-inotify (0.10.1) 100 | ffi (~> 1.0) 101 | redcarpet (3.3.4) 102 | ref (2.0.0) 103 | rouge (1.9.1) 104 | sass (3.4.25) 105 | sprockets (2.12.5) 106 | hike (~> 1.2) 107 | multi_json (~> 1.0) 108 | rack (~> 1.0) 109 | tilt (~> 1.1, != 1.3.0) 110 | sprockets-helpers (1.1.0) 111 | sprockets (~> 2.0) 112 | sprockets-sass (1.3.1) 113 | sprockets (~> 2.0) 114 | tilt (~> 1.1) 115 | temple (0.8.2) 116 | therubyracer (0.12.3) 117 | libv8 (~> 3.16.14.15) 118 | ref 119 | thor (1.1.0) 120 | thread_safe (0.3.6) 121 | tilt (1.4.1) 122 | timers (4.0.4) 123 | hitimes 124 | tzinfo (1.2.9) 125 | thread_safe (~> 0.1) 126 | uber (0.0.15) 127 | uglifier (2.7.2) 128 | execjs (>= 0.3.0) 129 | json (>= 1.8.0) 130 | 131 | PLATFORMS 132 | ruby 133 | 134 | DEPENDENCIES 135 | json (>= 1.8.3) 136 | middleman (~> 3.3.10) 137 | middleman-autoprefixer (~> 2.4.4) 138 | middleman-gh-pages (~> 0.0.3) 139 | middleman-syntax (~> 2.0.0) 140 | rake (~> 10.4.2) 141 | redcarpet (~> 3.3.2) 142 | rouge (~> 1.9.0) 143 | therubyracer (~> 0.12.1) 144 | 145 | BUNDLED WITH 146 | 1.17.3 147 | -------------------------------------------------------------------------------- /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 | # Best Buy API Documentation 2 | This project is the public home for the source that will eventually generate the API documentation for [Best Buy's API](https://api.bestbuy.com). It will be served at https://developer.bestbuy.com/documentation once it is production-ready, but for now is available at https://bestbuyapis.github.io/api-documentation/. 3 | 4 | The documentation is powered by the fantastic [Slate](https://github.com/tripit/slate) project, an API documentation generator that is open source and very popular. 5 | 6 | In the spirit of being a public API, we've chosen to publicize the generators that create our documentation. By doing this we hope to be more transparent when we make changes and provide a gateway for our consumers to become contributors. 7 | 8 | ## Frequently Asked Questions 9 | #### Where can I see the actual documentation? 10 | You'll want to go to https://bestbuyapis.github.io/api-documentation/ for the compiled version. This project just shows the source code we used to generate it. 11 | 12 | #### How do I get my API documentation to look as good as yours? 13 | Check out [Slate](https://github.com/tripit/slate). 14 | 15 | #### Where do I go to get an API key? 16 | Go to https://developer.bestbuy.com and click "Get API Key" 17 | 18 | #### How can I learn more about the Best Buy API? 19 | Visit https://developer.bestbuy.com 20 | 21 | ## Getting Started with the Best Buy API Documentation 22 | *Yes, this is identical to getting started with Slate.* 23 | ### You're going to need: 24 | - **Linux or OS X** — Windows may work, but is unsupported. 25 | - **Ruby, version 1.9.3 or newer** 26 | - **Bundler** — If Ruby is already installed, but the `bundle` command doesn't work, just run `gem install bundler` in a terminal. 27 | 28 | ### Getting Set Up 29 | 1. Fork this repository on Github. 30 | 2. Clone *your forked repository* (not our original one) to your hard drive with `git clone https://github.com/YOURUSERNAME/api-documentation.git` 31 | 3. `cd api-documentation` 32 | 4. Install all dependencies: `bundle install` 33 | 5. Start the test server: `bundle exec middleman server` 34 | 35 | You can now see the docs at . 36 | 37 | ## Need Help? Found a bug? 38 | You can either [submit an issue](https://github.com/BestBuyAPIs/api-documentation/issues) or [contact us](https://developer.bestbuy.com/contact-us). 39 | 40 | Once your issue has been resolved, the Best Buy team will publish the documentation changes (using `rake publish`). 41 | 42 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'middleman-gh-pages' 2 | require 'rake/clean' 3 | 4 | CLOBBER.include('build') 5 | 6 | task :default => [:build] 7 | -------------------------------------------------------------------------------- /config.rb: -------------------------------------------------------------------------------- 1 | # Markdown 2 | set :markdown_engine, :redcarpet 3 | set :markdown, 4 | fenced_code_blocks: true, 5 | smartypants: true, 6 | disable_indented_code_blocks: true, 7 | prettify: true, 8 | tables: true, 9 | with_toc_data: true, 10 | no_intra_emphasis: true 11 | 12 | # Assets 13 | set :css_dir, 'stylesheets' 14 | set :js_dir, 'javascripts' 15 | set :images_dir, 'images' 16 | set :fonts_dir, 'fonts' 17 | 18 | # Activate the syntax highlighter 19 | activate :syntax 20 | 21 | 22 | 23 | # Github pages require relative links 24 | activate :relative_assets 25 | set :relative_links, true 26 | 27 | # Build Configuration 28 | configure :build do 29 | activate :minify_css 30 | activate :minify_javascript 31 | # activate :relative_assets 32 | # activate :asset_hash 33 | # activate :gzip 34 | activate :autoprefixer do |config| 35 | config.browsers = ['last 2 version', 'Firefox ESR'] 36 | config.cascade = false 37 | config.inline = true 38 | end 39 | end 40 | -------------------------------------------------------------------------------- /font-selection.json: -------------------------------------------------------------------------------- 1 | { 2 | "IcoMoonType": "selection", 3 | "icons": [ 4 | { 5 | "icon": { 6 | "paths": [ 7 | "M475.429 292.571q0-45.714-32-77.714t-77.714-32-77.714 32-32 77.714q0 24 10.857 47.429-23.429-10.857-47.429-10.857-45.714 0-77.714 32t-32 77.714 32 77.714 77.714 32 77.714-32 32-77.714q0-24-10.857-47.429 23.429 10.857 47.429 10.857 45.714 0 77.714-32t32-77.714zM961.714 694.857q0 9.714-28 37.714t-37.714 28q-5.143 0-16.286-9.143t-20.857-18.857-22-22.857-14-14.857l-54.857 54.857 125.714 125.714q16 16 16 38.857 0 24-22.286 46.286t-46.286 22.286q-22.857 0-38.857-16l-383.429-383.429q-100.571 74.857-208.571 74.857-93.143 0-151.714-58.571t-58.571-151.714q0-91.429 54.286-178.857t141.714-141.714 178.857-54.286q93.143 0 151.714 58.571t58.571 151.714q0 108-74.857 208.571l202.857 202.857 54.857-54.857q-1.714-1.714-14.857-14t-22.857-22-18.857-20.857-9.143-16.286q0-9.714 28-37.714t37.714-28q7.429 0 13.143 5.714 3.429 3.429 26.286 25.429t46.857 45.429 49.429 49.143 41.714 44.571 16.286 23.429z" 8 | ], 9 | "attrs": [], 10 | "isMulticolor": false, 11 | "tags": [ 12 | "key" 13 | ], 14 | "defaultCode": 61572, 15 | "grid": 14 16 | }, 17 | "attrs": [], 18 | "properties": { 19 | "id": 124, 20 | "order": 6, 21 | "prevSize": 14, 22 | "name": "key", 23 | "code": 61572 24 | }, 25 | "setIdx": 0, 26 | "setId": 2, 27 | "iconIdx": 124 28 | }, 29 | { 30 | "icon": { 31 | "paths": [ 32 | "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" 33 | ], 34 | "attrs": [], 35 | "isMulticolor": false, 36 | "tags": [ 37 | "exclamation-circle" 38 | ], 39 | "defaultCode": 61546, 40 | "grid": 14 41 | }, 42 | "attrs": [], 43 | "properties": { 44 | "id": 100, 45 | "order": 3, 46 | "prevSize": 14, 47 | "code": 58880, 48 | "name": "exclamation-sign", 49 | "ligatures": "" 50 | }, 51 | "setIdx": 1, 52 | "setId": 1, 53 | "iconIdx": 0 54 | }, 55 | { 56 | "icon": { 57 | "paths": [ 58 | "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" 59 | ], 60 | "attrs": [], 61 | "isMulticolor": false, 62 | "tags": [ 63 | "info-circle" 64 | ], 65 | "defaultCode": 61530, 66 | "grid": 14 67 | }, 68 | "attrs": [], 69 | "properties": { 70 | "id": 85, 71 | "order": 2, 72 | "name": "info-sign", 73 | "prevSize": 14, 74 | "code": 58882 75 | }, 76 | "setIdx": 1, 77 | "setId": 1, 78 | "iconIdx": 1 79 | }, 80 | { 81 | "icon": { 82 | "paths": [ 83 | "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" 84 | ], 85 | "attrs": [], 86 | "isMulticolor": false, 87 | "tags": [ 88 | "check-circle" 89 | ], 90 | "defaultCode": 61528, 91 | "grid": 14 92 | }, 93 | "attrs": [], 94 | "properties": { 95 | "id": 83, 96 | "order": 4, 97 | "prevSize": 14, 98 | "code": 58886, 99 | "name": "ok-sign" 100 | }, 101 | "setIdx": 1, 102 | "setId": 1, 103 | "iconIdx": 2 104 | }, 105 | { 106 | "icon": { 107 | "paths": [ 108 | "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" 109 | ], 110 | "width": 951, 111 | "attrs": [], 112 | "isMulticolor": false, 113 | "tags": [ 114 | "search" 115 | ], 116 | "defaultCode": 61442, 117 | "grid": 14 118 | }, 119 | "attrs": [], 120 | "properties": { 121 | "id": 2, 122 | "order": 1, 123 | "prevSize": 14, 124 | "code": 58887, 125 | "name": "icon-search" 126 | }, 127 | "setIdx": 1, 128 | "setId": 1, 129 | "iconIdx": 3 130 | } 131 | ], 132 | "height": 1024, 133 | "metadata": { 134 | "name": "slate", 135 | "license": "SIL OFL 1.1" 136 | }, 137 | "preferences": { 138 | "showGlyphs": true, 139 | "showQuickUse": true, 140 | "showQuickUse2": true, 141 | "showSVGs": true, 142 | "fontPref": { 143 | "prefix": "icon-", 144 | "metadata": { 145 | "fontFamily": "slate", 146 | "majorVersion": 1, 147 | "minorVersion": 0, 148 | "description": "Based on FontAwesome", 149 | "license": "SIL OFL 1.1" 150 | }, 151 | "metrics": { 152 | "emSize": 1024, 153 | "baseline": 6.25, 154 | "whitespace": 50 155 | }, 156 | "resetPoint": 58880, 157 | "showSelector": false, 158 | "selector": "class", 159 | "classSelector": ".icon", 160 | "showMetrics": false, 161 | "showMetadata": true, 162 | "showVersion": true, 163 | "ie7": false, 164 | "embed": false 165 | }, 166 | "imagePref": { 167 | "prefix": "icon-", 168 | "png": true, 169 | "useClassSelector": true, 170 | "color": 4473924, 171 | "bgColor": 16777215, 172 | "classSelector": ".icon" 173 | }, 174 | "historySize": 100, 175 | "showCodes": true, 176 | "gridSize": 16, 177 | "showLiga": false 178 | } 179 | } -------------------------------------------------------------------------------- /source/fonts/FontAwesome.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/FontAwesome.otf -------------------------------------------------------------------------------- /source/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /source/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /source/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /source/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /source/fonts/fontello.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/fontello.eot -------------------------------------------------------------------------------- /source/fonts/fontello.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Copyright (C) 2015 by original authors @ fontello.com 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /source/fonts/fontello.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/fontello.ttf -------------------------------------------------------------------------------- /source/fonts/fontello.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/fontello.woff -------------------------------------------------------------------------------- /source/fonts/slate.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/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/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/slate.ttf -------------------------------------------------------------------------------- /source/fonts/slate.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/slate.woff -------------------------------------------------------------------------------- /source/fonts/slate.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/fonts/slate.woff2 -------------------------------------------------------------------------------- /source/images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/images/logo.png -------------------------------------------------------------------------------- /source/images/navbar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/images/navbar.png -------------------------------------------------------------------------------- /source/images/qb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/BestBuyAPIs/api-documentation/0ee523fda53f184cca082ace6f6663eed72e0c6e/source/images/qb.png -------------------------------------------------------------------------------- /source/includes/categories/_index.md.erb: -------------------------------------------------------------------------------- 1 | # Categories API 2 | 3 | The Categories API allows you to traverse the many categories on **BESTBUY.COM** and perform product searches based on category names or identifiers. The Categories API also allows you to search for specific product attributes within a specific category (example: TVs less than $100), search using multiple product attributes within a specific category (example: TVs released in the last year that are less than $100) or look at Best Buy taxonomy to better search and present Best Buy product data (example: HD TVs released in the last year that are less than $100). 4 | 5 | ### Category and Subcategory Paths 6 | 7 | As part of the category details, we provide a flat hierarchical path for each category. The `path` is a collection of all the categories in the path, starting with the root. 8 | 9 | Similarly, the Subcategories path attributes provide a collection of subcategories for the parent category. Each category can have one or more subcategories associated to it, which are identified by subcategory ids and names. 10 | 11 | _The Products API also includes the category path information for each product. For additional information on the category attributes in Products API, refer to [Categorizations.](#categorizations)_ 12 | 13 | 14 | ## Common Attributes 15 | 16 | Attribute | Description 17 | --------- | ----------- 18 | **name** | Used to find all subcategories (e.g., parents, siblings, children) within a specific category 19 | **id** | Used to find all results within a specific category (e.g., abcat0100000) 20 | **url** | URL to corresponding BESTBUY.COM category page 21 | **path.name** | Used to find all categories, starting with the root, within a particular path (e.g., electronics) 22 | **path.id** | Used to find all categories, starting with the root, within a particular path (e.g., abcat0014001) 23 | **subCategories.name** | Used to identify subcategories within a specific category (e.g., Kitchen Essentials within Gift Ideas) 24 | **subCategories.id** | Used to identify subcategories within a specific category (e.g., abcat0011002) 25 | 26 | ## Get All Categories 27 | 28 | ```shell 29 | curl "https://api.bestbuy.com/v1/categories?format=json&show=id&apiKey=YourAPIKey" 30 | ``` 31 | 32 | ```javascript 33 | var bby = require('bestbuy')('YourAPIKey'); 34 | bby.categories('',{show:'id'}).then(function(data){ 35 | console.log(data); 36 | }); 37 | ``` 38 | 39 | ```json-doc 40 | { 41 | "from": 1, 42 | "to": 10, 43 | "total": 4328, 44 | "currentPage": 1, 45 | "totalPages": 433, 46 | "queryTime": "0.003", 47 | "totalTime": "0.025", 48 | "partial": false, 49 | "canonicalUrl": "/v1/categories?show=id,url&format=json&apiKey=YourAPIKey", 50 | "categories": [ 51 | { 52 | "id": "abcat0010000", 53 | "url": "http://www.bestbuy.com/site/electronics/gift-ideas/abcat0010000.c?id=abcat0010000" 54 | }, 55 | { 56 | "id": "abcat0020001", 57 | "url": "http://www.bestbuy.com/site/electronics/gift-ideas/abcat0020001.c?id=abcat0020001" 58 | }, 59 | { 60 | "id": "abcat0020002", 61 | "url": "http://www.bestbuy.com/site/electronics/gift-ideas/abcat0020002.c?id=abcat0020002" 62 | }, 63 | { 64 | "id": "abcat0020004", 65 | "url": "http://www.bestbuy.com/site/electronics/gift-ideas/abcat0020004.c?id=abcat0020004" 66 | }, 67 | { 68 | "id": "abcat0100000", 69 | "url": "http://www.bestbuy.com/site/electronics/gift-ideas/abcat0100000.c?id=abcat0100000" 70 | }] 71 | } 72 | ``` 73 | 74 | The query to the right will return all the Best Buy product categories. Query is filtered to show only `id`s. 75 | 76 |
77 | 78 | ## Search for a Category 79 | 80 | ```shell 81 | curl "https://api.bestbuy.com/v1/categories(name=Sony%20DSLR%20Camera*)?format=json&show=path&apiKey=YourAPIKey" 82 | ``` 83 | 84 | ```javascript 85 | var bby = require('bestbuy')('YourAPIKey'); 86 | bby.categories('name=Sony DSLR Camera*',{show:'path'}).then(function(data){ 87 | // The util package is loaded to print the complete object structure 88 | console.log(require('util').inspect(data, false, null)); 89 | }); 90 | ``` 91 | 92 | ```json-doc 93 | { 94 | "from": 1, 95 | "to": 1, 96 | "total": 1, 97 | "currentPage": 1, 98 | "totalPages": 1, 99 | "queryTime": "0.011", 100 | "totalTime": "0.014", 101 | "partial": false, 102 | "canonicalUrl": "/v1/categories(name=\"Sony DSLR Camera*\")?show=path&format=json&apiKey=YourAPIKey", 103 | "categories": [ 104 | { 105 | "path": [ 106 | { 107 | "id": "cat00000", 108 | "name": "Best Buy" 109 | }, 110 | { 111 | "id": "pcmcat128500050004", 112 | "name": "Name Brands" 113 | }, 114 | { 115 | "id": "cat15063", 116 | "name": "Sony" 117 | }, 118 | { 119 | "id": "pcmcat97200050015", 120 | "name": "Sony DSLR Camera" 121 | } 122 | ] 123 | } 124 | ] 125 | } 126 | ``` 127 | 128 | The following query will return the category path for the category `name` specified in the input. In the below example we are requesting the category path for a **Sony DSLR Camera**. The query results are shown in a flat hierarchical path starting from the root. In this case **Best Buy** is the root category which is the first in the path, followed by its child category **Name Brands**, whose child is **Sony**, and its child **Sony DSLR Camera**, which is also the last category in this path. 129 | -------------------------------------------------------------------------------- /source/includes/commerce/_index.md.erb: -------------------------------------------------------------------------------- 1 | # Commerce API 2 | The Best Buy Commerce API allows our partners to introduce a seamless cart experience to their customers, exposing the ability to select various fulfillment options including *Store Pickup* at one of our 1,400+ locations, *Ship To Home* and *Home Delivery*. If you have not yet been issued a Commerce API key, please [contact us](https://developer.bestbuy.com/contact-us?topic=commerce-api). 3 | 4 | Within the Commerce APIs, partners have the ability to integrate your e-commerce solution with Best Buy's online experience. 5 | 6 | ## Functionality 7 | Full documentation supplied once you have a CAPI Key. Commerce API functionality includes: 8 | 9 | * Look up product availability, delivery dates, shipping costs prior to order submission 10 | * Create orders including *Store Pick Up*, *Ship to Home* and *Home Delivery* 11 | * Look up order information 12 | * Modify/Cancel an Order 13 | 14 | ## Getting a Commerce API Key 15 | Please [contact us](https://developer.bestbuy.com/contact-us?topic=commerce-api) to request an invite to the Commerce API program and a corresponding API Key. Current CAPI partners can access reporting and documentation via the same address. 16 | -------------------------------------------------------------------------------- /source/includes/gettingstarted/_index.md.erb: -------------------------------------------------------------------------------- 1 | # Getting Started 2 | 3 | ## Get a key 4 | Before you can start using our APIs, you need an API key. It's easy. Just visit **[GET API Key](https://developer.bestbuy.com/login)** and sign up with your email address. We'll send you an email with instructions on how to activate your new key. Once you've activated your key, you're ready to roll. 5 | 6 | ## Create your first query 7 | After you activate your key, you can start accessing Best Buy's data. 8 | 9 | ### Try our Query Builder 10 | [](http://bestbuyapis.github.io/bby-query-builder/#/productSearch) 11 | 12 | This easy-to-use tool will have you running queries in no time. The Query Builder tool will guide you through the creation of custom queries using most of the Best Buy APIs. You can use these queries as a base for your own custom queries, or use them to access Best Buy API data. You can access the Query Builder from our top menu bar or by going to [Query Builder](http://bestbuyapis.github.io/bby-query-builder/#/productSearch). 13 | 14 | ```shell 15 | curl "https://api.bestbuy.com/v1/products/8880044.json?apiKey=YourAPIKey" 16 | ``` 17 | 18 | > Returns the product document for SKU 8880044 19 | 20 | ```json-doc 21 | { 22 | "sku": 8880044, 23 | "productId": 1484301, 24 | "name": "Batman Begins (Blu-ray Disc)" 25 | 26 | ... 27 | } 28 | ``` 29 | 30 | ### Try accessing one of our APIs directly 31 | Use a basic GET request to get API data. For example, to find product information for a specific product, you can query our Products API using the SKU for that product. The SKU for *Batman Begins (Blu-ray Disc)* is 8880044, so you can retrieve it as shown below. The response will be returned as either JSON or XML depending on the extension specified in the URI. 32 | 33 | HINT: Don't forget to replace **YourAPIKey** with the API key that you received from us. 34 | -------------------------------------------------------------------------------- /source/includes/openbox/_category.md: -------------------------------------------------------------------------------- 1 | ## Open Box by Category 2 | ```shell 3 | curl "https://api.bestbuy.com/beta/products/openBox(categoryId=abcat0400000)?apiKey=YourAPIKey" 4 | ``` 5 | ```javascript 6 | var bby = require('bestbuy')('YourAPIKey'); 7 | bby.openBox('categoryId=abcat0400000)').then(function(data){ 8 | console.log(data); 9 | }); 10 | ``` 11 | 12 | > Search all Open Box offers for SKUs that are a part of category **abcat0400000**; *our Cameras & Camcorders category* 13 | 14 | ```json-doc 15 | { 16 | "results": [ 17 | { 18 | "customerReviews": { 19 | "averageScore": "4.7", 20 | "count": 145 21 | }, 22 | "descriptions": { 23 | "short": "Compatible with most Canon DSLR cameras; stepping motor; 52mm filter size; 11.8\" minimum focus distance" 24 | }, 25 | "images": { 26 | "standard": "http://img.bbystatic.com/BestBuy_US/images/products/5729/5729048_sc.jpg" 27 | }, 28 | "links": { 29 | "product": "https://api.bestbuy.com/v1/products/5729048.json?apiKey=YourAPIKey", 30 | "web": "http://www.bestbuy.com/site/canon-ef-40mm-f-2-8-stm-standard-lens-black/5729048.p?id=1218688218296&skuId=5729048&cmp=RMX&ky=2l9pmD3wUBb9cc0tkHo49KBFCMPCiIPY4#tab=buyingOptions", 31 | "addToCart": "https://api.bestbuy.com/click/-/5729048/cart" 32 | }, 33 | "names": { 34 | "title": "Canon - EF 40mm f/2.8 STM Standard Lens - Black" 35 | }, 36 | "offers": [ 37 | { 38 | "condition": "excellent", 39 | "prices": { 40 | "current": 167.99, 41 | "regular": 199.99 42 | } 43 | } 44 | ], 45 | "prices": { 46 | "current": 199.99, 47 | "regular": 199.99 48 | }, 49 | "sku": "5729048" 50 | } 51 | ] 52 | } 53 | ``` 54 | 55 | The Open Box by Category endpoint allows you to query all Open Box offers associated with the SKUs in the requested category. If there are no Open Box offers available, the query will return a HTTP 200 response code with an empty result set. You will want to search by Category ID. *It is not possible to search by Category Name at this time.* 56 | 57 | We recommend using our [Categories API](#categories-api) to identify the desired category. You can also look at the [Products API](#products-api) category attributes to help identify those categories that you want to use to search Open Box offers. 58 | 59 | Use [Pagination](#pagination) to review or retrieve the entire result set. If additional product information is needed you can use the `links.product` attribute to go to the [Products API](#products-api) for a wealth of product information. 60 | -------------------------------------------------------------------------------- /source/includes/openbox/_index.md.erb: -------------------------------------------------------------------------------- 1 | # Buying Options (Open Box) API 2 | 3 | The Buying Options API helps you access some of our best deals. This is where you'll find information about ship-from-store eligible Open Box products including availability, condition and special pricing, with more to come as we build out this API further. Our Open Box endpoints provide access to several categories of Best Buy merchandise, similar to the "Buying Options" tab on **BESTBUY.COM** product detail pages. We typically have multiple Open Box products for a single SKU. When a customer purchases an Open Box product on **BESTBUY.COM** we ship from the closest Best Buy store based on the customer shipping address. To assist in selecting the correct Open Box product we assign a condition of "excellent or certified" to the product in every Open Box offer. 4 | 5 | + "excellent" - products that look brand new in appearance, with no physical flaws, scratches or scuffs and include all original parts and accessories 6 | + "certified" - products that have passed the Geek Squad Certification process. 7 | 8 | We have split Open Box into multiple endpoints: 9 | 10 | + The **Open Box Single SKU** endpoint lets you query for a specific product using the product identifier (SKU) for any available Open Box offers. 11 | + The **Open Box by list of SKUs** endpoint lets you query for a list of products using product identifier (SKU) for any available Open Box offers. 12 | + The **Open Box by Category** endpoint lets you query for a set of products based on their categories. 13 | 14 | _All responses returned will be in a json format. In addition, we only return results for available product. We check for newly available product every five minutes. If you are an affiliate partner please see the [Affiliate FAQ](https://developer.bestbuy.com/affiliate-program#affiliateFaq) for instructions on proper use._ 15 | 16 | ## Common Attributes 17 | 18 | Attribute | Description 19 | --------- | ----------- 20 | **customerReviews.averageScore** | Provides an average of all the ratings submitted for a product by reviewers. The customer can rate the product on a scale of 1-5 where 5 is the highest. Ratings may be returned using decimals 21 | **customerReviews.count** | The total number of reviews collected 22 | **descriptions.short** | A brief description of a product 23 | **images.standard** | URL of BESTBUY.COM product detail page image 24 | **links.product** | Link to the specific product in the Products API using a product identifier (SKU) 25 | **links.web** | Link to the BESTBUY.COM product detail page using the Buying Options tab 26 | **links.addToCart** | URL to BESTBUY.COM with item in cart 27 | **names.title** | Name of the product 28 | **offers.condition** | The condition attribute will either be "excellent" (products that look brand new in appearance,with no physical flaws, scratches or scuffs and include all original parts and accessories) or "certified" (products that have passed the Geek Squad Certification process) 29 | **offers.prices.current,** | "Open box" product's current selling price 30 | **offers.prices.regular** | "Open box" product's regular selling price 31 | **prices.current** | "New" product's current selling price 32 | **prices.regular** | "New" product's regular selling price 33 | **sku** | Unique identifier for products sold by Best Buy 34 | 35 | <%= partial "includes/openbox/single-sku" %> 36 | <%= partial "includes/openbox/multiple-skus" %> 37 | <%= partial "includes/openbox/category" %> 38 | -------------------------------------------------------------------------------- /source/includes/openbox/_multiple-skus.md: -------------------------------------------------------------------------------- 1 | ## Open Box by List of SKUs 2 | ```shell 3 | curl "https://api.bestbuy.com/beta/products/openBox(sku%20in(5729048,7528703,4839357,8153056,8610161))?apiKey=YourAPIKey" 4 | ``` 5 | ```javascript 6 | var bby = require('bestbuy')('YourAPIKey'); 7 | bby.openBox('sku in(5729048,7528703,4839357,8153056,8610161)').then(function(data){ 8 | console.log(data); 9 | }); 10 | ``` 11 | 12 | > Returns available Open Box offers for 5 different SKUs 13 | 14 | ```json-doc 15 | { 16 | "metadata": { 17 | "resultSet": { 18 | "count": 6 19 | }, 20 | "context": { 21 | "canonicalUrl": "https://api.bestbuy.com/beta/products/openBox(sku%20in(5729048,7528703,4839357,8153056,8610161,4591017))?apiKey=YourAPIKey" 22 | } 23 | }, 24 | "results": [ 25 | { 26 | "customerReviews": { 27 | "averageScore": "4.5", 28 | "count": 471 29 | }, 30 | "descriptions": { 31 | "short": "Google Chrome 64-bitTechnical details: Intel® Celeron® processor; 11.6\" display; 2GB memory; 16GB eMMC flash memorySpecial features: Bluetooth; HDMI outputNote: DVD/CD drive not included" 32 | }, 33 | "images": { 34 | "standard": "http://img.bbystatic.com/BestBuy_US/images/products/8610/8610161_rc.jpg" 35 | }, 36 | "links": { 37 | "product": "https://api.bestbuy.com/v1/products/8610161.json?apiKey=YourAPIKey", 38 | "web": "http://www.bestbuy.com/site/acer-11-6-chromebook-intel-celeron-2gb-memory-16gb-emmc-flash-memory-moonstone-white/8610161.p?id=1219351773817&skuId=8610161&cmp=RMX&ky=2l9pmD3wUBb9cc0tkHo49KBFCMPCiIPY4#tab=buyingOptions", 39 | "addToCart": "https://api.bestbuy.com/click/-/8610161/cart" 40 | }, 41 | "names": { 42 | "title": "Acer - 11.6\" Chromebook - Intel Celeron - 2GB Memory - 16GB eMMC Flash Memory - Moonstone White" 43 | }, 44 | "offers": [ 45 | { 46 | "condition": "excellent", 47 | "prices": { 48 | "current": 175.99, 49 | "regular": 199 50 | } 51 | }, 52 | { 53 | "condition": "certified", 54 | "prices": { 55 | "current": 187.99, 56 | "regular": 199 57 | } 58 | } 59 | ], 60 | "prices": { 61 | "current": 199, 62 | "regular": 199 63 | }, 64 | "sku": "8610161" 65 | }, 66 | ``` 67 | 68 | The Open Box by List of SKUs endpoint allows you to query all Open Box offers associated with a list of SKUs. The endpoint will return any available Open Box offers. If there is not an offer for a particular SKU in the list, that SKU will not be represented in the results. If there are no offers for any of the SKUs in the list, the query will return an HTTP 200 (OK) response code with an empty result set. 69 | 70 | *NOTE: This endpoint accepts and returns at most 100 SKUs. The results are not paginated. Expect an HTTP 400 (Bad Request) response if you submit more than 100 SKUs.* 71 | -------------------------------------------------------------------------------- /source/includes/openbox/_single-sku.md: -------------------------------------------------------------------------------- 1 | ## Open Box Single SKU 2 | ```shell 3 | curl "https://api.bestbuy.com/beta/products/8610161/openBox?apiKey=YourAPIKey" 4 | ``` 5 | ```javascript 6 | var bby = require('bestbuy')('YourAPIKey'); 7 | bby.openBox(8610161).then(function(data){ 8 | console.log(data); 9 | }); 10 | ``` 11 | > Search all open box offers for SKU **8610161**. We can see there are at least two offers *excellent* and *certified*. 12 | 13 | ```json-doc 14 | { 15 | "results": [ 16 | { 17 | "customerReviews": { 18 | "averageScore": "4.5", 19 | "count": 471 20 | }, 21 | "descriptions": { 22 | "short": "Google Chrome 64-bitTechnical details: Intel® Celeron® processor; 11.6\" display; 2GB memory; 16GB eMMC flash memorySpecial features: Bluetooth; HDMI outputNote: DVD/CD drive not included" 23 | }, 24 | "images": { 25 | "standard": "http://img.bbystatic.com/BestBuy_US/images/products/8610/8610161_rc.jpg" 26 | }, 27 | "links": { 28 | "product": "https://api.bestbuy.com/v1/products/8610161.json?apiKey=YourAPIKey", 29 | "web": "http://www.bestbuy.com/site/acer-11-6-chromebook-intel-celeron-2gb-memory-16gb-emmc-flash-memory-moonstone-white/8610161.p?id=1219351773817&skuId=8610161&cmp=RMX&ky=2l9pmD3wUBb9cc0tkHo49KBFCMPCiIPY4#tab=buyingOptions", 30 | "addToCart": "https://api.bestbuy.com/click/-/8610161/cart" 31 | }, 32 | "names": { 33 | "title": "Acer - 11.6\" Chromebook - Intel Celeron - 2GB Memory - 16GB eMMC Flash Memory - Moonstone White" 34 | }, 35 | "offers": [ 36 | { 37 | "condition": "excellent", 38 | "prices": { 39 | "current": 175.99, 40 | "regular": 199 41 | } 42 | }, 43 | { 44 | "condition": "certified", 45 | "prices": { 46 | "current": 187.99, 47 | "regular": 199 48 | } 49 | } 50 | ], 51 | "prices": { 52 | "current": 199, 53 | "regular": 199 54 | }, 55 | "sku": "8610161" 56 | } 57 | ] 58 | } 59 | ``` 60 | The Open Box Single SKU endpoint allows you to query by SKU all Open Box offers associated with a SKU. If there are no Open Box offers available, the query will return a HTTP 200 response code with an empty result set. 61 | -------------------------------------------------------------------------------- /source/includes/overview/_cursormark.md: -------------------------------------------------------------------------------- 1 | ## Cursor Marks 2 | 3 | ```shell 4 | curl -G "https://api.bestbuy.com/v1/products(type=HardGood)?format=json&show=sku,name,salePrice&pageSize=100&apiKey=YourAPIKey" --data-urlencode "cursorMark=*" 5 | ``` 6 | 7 | ```javascript 8 | var bby = require('bestbuy')('YourAPIKey'); 9 | bby.products('type=HardGood',{show:'sku,name,salePrice',pageSize:100,cursorMark=*}).then(function(data){ 10 | console.log(data); 11 | }); 12 | ``` 13 | 14 | > In this example we ask for the first page of results and for each page to contain 100 products. 15 | 16 | ```json-doc 17 | { 18 | "nextCursorMark": "AoNeDQhAhoq2MnByb2R1Y3RfMTE0NjYzNV91cw==", 19 | "total": 49911, 20 | "totalPages": 500, 21 | "queryTime": "0.037", 22 | "totalTime": "0.362", 23 | "partial": false, 24 | "canonicalUrl": "/v1/products(type=\"HardGood\")?show=sku,name,salePrice&pageSize=100&cursorMark=*&format=json&apiKey=YourAPIKey", 25 | "products": [ 26 | { 27 | "sku": 5477500, 28 | "name": "Amazon - Fire TV Stick with Alexa Voice Remote - Black", 29 | "salePrice": 39.99 30 | }, 31 | { 32 | "sku": 4397400, 33 | "name": "Google - Chromecast - Black", 34 | "salePrice": 35 35 | }, 36 | ``` 37 | 38 | *Applies to: Products API • Stores API • Categories API* 39 | 40 | With large result sets - e.g., query sets with more than 10 pages of results - we recommend you use the `cursorMark` parameter to walk through your results. You can use `cursorMark` to walk through the full product or store catalog, deltas since you last queried for active products, or any other query result. The `cursorMark` works a lot like a bookmark, keeping track of what subset of items are currently shown in your result set and how to get to the next subset of items. 41 | 42 | To use the `cursorMark` with your result set, add `cursorMark=*` to your query parameters. A `nextCursorMark` parameter will be included in the metadata that you will use to walk through the full result set. After the initial result, replace the asterisk `*` with the `nextCursorMark` value noted in the current metadata to move to the next subset of results. For each subset, a fresh hash value will be presented. To avoid errors, please urlencode the hash returned when sending it as the `cursorMark` query parameter in subsequent requests. When you reach the end of the cursor marks, you will receive an empty result. 43 | 44 | **Tip:** To query for updates or deltas since you last walked through the result set you can use the `itemUpdateDate` attribute. To ensure that your query results include changes to a product's active/inactive status, add `active=*` to your query parameters. For example: `.../v1/products(itemUpdateDate>2017-02-06T16:00:00&active=*)?format=json&pageSize=100&cursorMark=*&apiKey=YOUR_API_KEY` 45 | 46 | Here is an explanation of the meta data when more than one subset is available: 47 | 48 | Name | Description | Additional Details 49 | -----|-------------|------------------- 50 | **canonicalURL** | the non-server part of the query | 51 | **cursorMark** | a hash indicating the current location within the result set | add `cursorMark=*` to your query to get the first subset of results 52 | **nextCursorMark** | a hash indicating the start of the next subset of items in your result set | we recommend only moving forward through your result sets using `cursorMark` 53 | **total** | the total number of items returned by the query | 54 | **totalPages** | the number of subsets of items in the full query result | can be used as an approximation of the number of cursor marks you will need to iterate through to walk the entire query result 55 | -------------------------------------------------------------------------------- /source/includes/overview/_errors.md: -------------------------------------------------------------------------------- 1 | ## Errors 2 | 3 | *Applies to: Products API • Stores API • Categories API • Recommendations API* 4 | 5 | Best Buy uses standard HTTP response codes to indicate success or failure of an API request. In general, codes in the 2xx range indicate success, codes in the 4xx range indicate an error that resulted from the provided information (e.g., a required parameter was missing), and codes in the 5xx range indicate an error with Best Buy's servers. 6 | 7 | Status Code | Explanation 8 | ------------|------------ 9 | **200** | It is all good. 10 | **400** | The request is missing key information or is malformed. 11 | **403** | The API key is not valid, or the allocated call limit has been exceeded. 12 | **404** | The requested item cannot be found. 13 | **405** | Particular method not allowed (error will be returned for methods like a POST). 14 | **500, 501, 503** | There is a server error on the Best Buy side. -------------------------------------------------------------------------------- /source/includes/overview/_facets.md: -------------------------------------------------------------------------------- 1 | ## Facets 2 | 3 | ```shell 4 | curl 'https://api.bestbuy.com/v1/products(categoryPath.name="All%20Flat-Panel%20TVs")?format=json&show=sku,name,salePrice&facet=manufacturer,5&apiKey=YourAPIKey' 5 | ``` 6 | 7 | ```javascript 8 | var bby = require('bestbuy')('YourAPIKey'); 9 | bby.products('categoryPath.name="All Flat-Panel TVs"',{show:'sku,name,salePrice',facet:'manufacturer,5'}).then(function(data){ 10 | console.log(data); 11 | }); 12 | ``` 13 | 14 | > Show the 5 manufacturers for which we have the most flat-panel TVs. 15 | 16 | ```json-doc 17 | { 18 | "products": [ 19 | ], 20 | "facets": { 21 | "manufacturer": { 22 | "samsung": 96, 23 | "lg": 46, 24 | "sharp": 24, 25 | "vizio": 23, 26 | "insignia™": 18 27 | } 28 | } 29 | } 30 | ``` 31 | 32 | *Applies to: Products API • Stores API • Categories API* 33 | 34 | You can retrieve summary information about the items that are returned by your query by using the `facets` query parameter. -------------------------------------------------------------------------------- /source/includes/overview/_index.md.erb: -------------------------------------------------------------------------------- 1 | # Overview 2 | 3 | Welcome to the Best Buy Developer API site! Whether you're an API pro, a beginning developer or a Best Buy partner, our extensive API catalog is waiting for your imagination. Our API suite allows you to query Products, Stores and much more. Come on in to explore our data, browse descriptions of the available attributes and see examples of working requests and responses. 4 | 5 | If this is your first time using our APIs, please check out our [Getting Started](http://developer.bestbuy.com/documentation/getting-started) guide. If you already have your API key, our Search and Response Formats can help you refine your results. 6 | 7 | <%= partial "includes/overview/responseFormat" %> 8 | <%= partial "includes/overview/show" %> 9 | <%= partial "includes/overview/sort" %> 10 | <%= partial "includes/overview/facets" %> 11 | <%= partial "includes/overview/pagination" %> 12 | <%= partial "includes/overview/cursormark" %> 13 | <%= partial "includes/overview/retrievingCollections" %> 14 | <%= partial "includes/overview/errors" %> 15 | <%= partial "includes/overview/postman" %> 16 | -------------------------------------------------------------------------------- /source/includes/overview/_pagination.md: -------------------------------------------------------------------------------- 1 | ## Pagination 2 | 3 | ```shell 4 | curl 'https://api.bestbuy.com/v1/products(type=Movie)?format=json&show=sku,name,salePrice&pageSize=3&page=10&apiKey=YourAPIKey' 5 | ``` 6 | 7 | ```javascript 8 | var bby = require('bestbuy')('YourAPIKey'); 9 | bby.products('type=Movie',{show:'sku,name,salePrice',page:10,pageSize:3}).then(function(data){ 10 | console.log(data); 11 | }); 12 | ``` 13 | 14 | > In this example we ask for the 10th page of results and for each page to contain just 3 products. 15 | 16 | ```json-doc 17 | { 18 | "from": 28, 19 | "to": 30, 20 | "total": 101727, 21 | "currentPage": 1000, 22 | "totalPages": 33909, 23 | "queryTime": "0.039", 24 | "totalTime": "0.048", 25 | "partial": false, 26 | "canonicalUrl": "/v1/products(type=\"Movie\")?show=sku,name,salePrice&format=json&pageSize=3&page=10&apiKey=YourAPIKey", 27 | "products": [ 28 | { 29 | "sku": 17215997, 30 | "name": "AC/DC: Rock Power (DVD)", 31 | "salePrice": 11.99 32 | }, 33 | { 34 | "sku": 23003222, 35 | "name": "AC/DC: Rocks Detroit (DVD)", 36 | "salePrice": 10.99 37 | } 38 | ``` 39 | 40 | *Applies to: Products API • Stores API • Categories API • Recommendations API • Buying Options API* 41 | 42 | Even if you've trimmed down the number of products returned by making use of search, many of our APIs have the potential to return lots of results. To make these large responses more manageable, we break them into pages. By default, we include 10 results per page, but you can ask for up to 100 per page by making use of the `pageSize` parameter. Use the `page` parameter to choose which page of results you'd like returned. 43 | 44 | **Note:** If your result set is more than 10 pages, you should use the `cursorMark` parameter to walk through your results. See [Cursor Marks](#cursor-marks) for more information. 45 | 46 | Here is an explanation of the meta data when more than one page is available: 47 | 48 | Name | Description | Additional Details 49 | -----|-------------|------------------- 50 | **canonicalURL** | the non-server part of the query | 51 | **currentPage** | the page being returned | referred to as "page.current" for the Recommendations and Buying Options APIs 52 | **from** | the index of the first item returned on the current page | not available on the Recommendations and Buying Options APIs 53 | **size** | the number of results returned per page | only available on the Recommendations and Buying Options APIs 54 | **to** | the index of the last item returned on the current page | not available on the Recommendations and Buying Options APIs 55 | **total** | the total number of items returned by the query | referred to as "resultSet.count" for the Recommendations and Buying Options APIs 56 | **totalPages** | the number of pages required to list all items | referred to as "page.total" for the Recommendations and Buying Options APIs -------------------------------------------------------------------------------- /source/includes/overview/_postman.md: -------------------------------------------------------------------------------- 1 | ## Postman 2 | 3 | Here's a collection of sample queries in Postman that'll help you get up to speed with our APIs faster. 4 | 5 | [![Run in Postman](https://run.pstmn.io/button.png)](https://www.getpostman.com/run-collection/fdbd434f83a8e3855c62) 6 | 7 | ### Important Notes 8 | 9 | * You must defined `apiKey` within in an [environment](https://www.getpostman.com/docs/environments). 10 | * Some portions of the query parameters for Best Buy’s APIs are included in the path: (e.g., …/v1/products(categoryPath.id=pcmcat194000050022&manufacturer=Apple)?apiKey={{apiKey}}&format=json). You should update the in-path parameters within Postman's grey bar that shows the URL. 11 | * v2 of the Best Buy API will move these parameters out of the path and into the query string. 12 | -------------------------------------------------------------------------------- /source/includes/overview/_responseFormat.md: -------------------------------------------------------------------------------- 1 | ## Response Format 2 | 3 | Responses can be returned in either **JSON** or **XML**. 4 | 5 | *Applies to: Products API • Stores API • Categories API* 6 | 7 | To request a single item, such as a specific product, indicate the desired response format with the extension added after the item's identifier. For example, `/products/8880044.json`. 8 | 9 | To request a collection of items, such as all the products in our catalog, the desired response format is specified in the `format` query parameter. An example of this can be seen in the Retrieving Collections section. If no format is specified then xml will be returned. 10 | 11 | *Applies to: Recommendations API* 12 | 13 | When using any of the endpoints in the Recommendations API the response format returned will be json. The **XML** format is not supported for the Recommendations API endpoints. You can specify the format using `/6534009/alsoViewed.json` or not specify a format like `/6534009/alsoViewed`. 14 | 15 | 16 | *Applies to: Products API* 17 | 18 | By agreeing to Best Buy’s [terms of service](https://developer.bestbuy.com/legal), you also agree not to cache any content except on a temporary basis. As such, our response links will expire after seven days. Here are several examples of appropriately formatted response URLs: 19 | 20 | `url: https://api.bestbuy.com/click/5592e2b895800000/12345678/pdp` 21 | 22 | `mobileUrl: https://api.bestbuy.com/click/5592e2b895800000/12345678/pdp` 23 | 24 | `addToCartUrl: https://api.bestbuy.com/click/5592e2b895800000/12345678/cart` 25 | -------------------------------------------------------------------------------- /source/includes/overview/_retrievingCollections.md: -------------------------------------------------------------------------------- 1 | ## Retrieving Collections 2 | 3 | *Applies to: Products API • Stores API • Categories API* 4 | 5 | To retrieve more than one item at a time (e.g. all Products in our catalog), use one of the following queries. *By default the max page size is 100 (meaning 100 unique results). See Pagination for more information on returning results greater than 100.* 6 | 7 | Description | Query | Result 8 | ------------|-------|------- 9 | **retrieve all products** | https://api.bestbuy.com/v1/products?apiKey=YourAPIKey | returns a collection of products 10 | **retrieve all stores** | https://api.bestbuy.com/v1/stores?apiKey=YourAPIKey | returns a collection of stores 11 | **retrieve all categories** | https://api.bestbuy.com/v1/categories?apiKey=YourAPIKey | returns a collection of categories 12 | 13 | Other sections in this documentation explain how to modify these queries to retrieve only the information that you need. 14 | 15 | + Pagination: describes how results consisting of multiple pages are returned 16 | + Search: describes how to perform search operations 17 | + Sort: describes how to specify sort criteria for collections 18 | + Facets: describes how to ask for summarized information about collections 19 | 20 | ### Collection Header 21 | 22 | When a query results in a collection, the response includes an information header containing the following attributes: 23 | 24 | Name | Description 25 | -----|------------ 26 | **item** | the type of items returned and counted 27 | **current page** | the page being returned 28 | **totalPages** | the number of pages required to list all items 29 | **from** | the index of the first item returned on the current page 30 | **to** | the index of the last item returned on the current page 31 | **total** | the total number of items returned by the query 32 | **queryTime** | the time required to search the database 33 | **totalTime** | the time required to parse, search, format and return results 34 | **canonicalURL** | the non-server part of the query URL 35 | **partial** | flag indicating whether or not the query returned only partial results (in the event of a timeout) -------------------------------------------------------------------------------- /source/includes/overview/_show.md: -------------------------------------------------------------------------------- 1 | ## Returned Attributes 2 | 3 | ```shell 4 | curl "https://api.bestbuy.com/v1/products/8880044.json?show=sku,name,salePrice&apiKey=YourAPIKey" 5 | ``` 6 | 7 | ```javascript 8 | var bby = require('bestbuy')('YourAPIKey'); 9 | bby.products(8880044,{show:'sku,name,salePrice'}).then(function(data){ 10 | console.log(data); 11 | }); 12 | ``` 13 | 14 | > Only returns the `sku`, `name` and `salePrice` attributes for products. 15 | 16 | ```json-doc 17 | { 18 | "sku": 8880044, 19 | "name": "Batman Begins (Blu-ray Disc)", 20 | "salePrice": 7.99 21 | } 22 | ``` 23 | 24 | 25 | *Applies to: Products API • Stores API • Categories API* 26 | 27 | The **`show`** attribute allows you to control which attributes are returned. You can return specific attributes by following the syntax below. To return all attributes, use `show=all`. 28 | 29 | If you tried the example query in the Getting Started section, you probably noticed that our Products API returns a lot of attributes for each product. For convenience, we provide a `show` query parameter that allows you to specify just the attributes that you want returned in the response. 30 | 31 | ### Show All 32 | 33 | *Applies to: Products API • Stores API* 34 | 35 | In order to make the API responses more manageable, we don't return all available attributes for those items that contain many (e.g. Products and Stores). In the event that you want to get all of these hidden attributes, you can set `show=all` in the query parameters for the API 36 | 37 | For example, the Stores API does not return the `detailedHours` attribute by default. By setting `show=all` you will receive `detailedHours` in the response. 38 | -------------------------------------------------------------------------------- /source/includes/overview/_sort.md: -------------------------------------------------------------------------------- 1 | ## Sort 2 | 3 | ```shell 4 | curl 'https://api.bestbuy.com/v1/products(categoryPath.name="All%20Flat-Screen%20TVs")?format=json&show=sku,name,salePrice&sort=salePrice&apiKey=YourAPIKey' 5 | ``` 6 | 7 | ```javascript 8 | var bby = require('bestbuy')('YourAPIKey'); 9 | bby.products('categoryPath.name="All Flat-Screen TVs"',{show:'sku,name,salePrice',sort:'salePrice.asc'}).then(function(data){ 10 | console.log(data); 11 | }); 12 | ``` 13 | 14 | > Lists all flat-panel TVs with prices and sorts by the best-selling products over the last week. 15 | 16 | ```json-doc 17 | { 18 | "from": 1, 19 | "to": 10, 20 | "total": 307, 21 | "currentPage": 1, 22 | "totalPages": 31, 23 | "queryTime": "0.005", 24 | "totalTime": "0.035", 25 | "partial": false, 26 | "canonicalUrl": "/v1/products(categoryPath.name=All Flat-Screen TVs)?show=sku,name,salePrice&sort=salePrice&format=json&apiKey=YourAPIKey", 27 | "products": [ 28 | { 29 | "sku": 6164904, 30 | "name": "Insignia™ - 19\" Class - LED - 720p - HDTV", 31 | "salePrice": 69.99 32 | }, 33 | { 34 | "sku": 6260936, 35 | "name": "Insignia™ - 22\" Class - LED - 1080p - HDTV", 36 | "salePrice": 69.99 37 | }, 38 | ``` 39 | 40 | *Applies to: Products API • Stores API • Categories API* 41 | 42 | You can specify the way in which you'd like to have the results sorted by one or more attribute value(s). 43 | 44 | + `sort=attribute.asc` - Sort the results in ascending order of the specified attribute 45 | + `sort=attribute.dsc` - Sort the results in descending order of the specified attribute 46 | + `sort=attribute.desc` - Sort the results in descending order of the specified attribute 47 | 48 | ### Sort by multiple attributes 49 | 50 | To sort by multiple attributes, separate the sort terms with commas. The results will initially be sorted by the first attribute in the direction specified. Then, the results within each set will be sorted by the second attribute. 51 | 52 | + `sort=attribute1.asc,attribute2.dsc` - Sort by attribute 1 in ascending order, then by attribute 2 in descending order 53 | 54 | ### Child attribute sort limitation 55 | 56 | The text after the period in the sort parameter is interpreted as the sort direction. Therefore, you cannot sort by a child attribute, as it inherently includes a period in its name. 57 | -------------------------------------------------------------------------------- /source/includes/products/_availability-and-delivery.md: -------------------------------------------------------------------------------- 1 | ## Availability 2 | The Availability attributes provide details into which products can be purchased online and which products can be picked up in stores. 3 | 4 | *Note: For store-specific availability, please refer to our [Stores API](#stores-api) documentation.* 5 | 6 | Attribute | Description 7 | --------- | ----------- 8 | **friendsAndFamilyPickup** | Identifies if a product is eligible for friends and family pickup 9 | **homeDelivery** | Identifies if a product must be fulfilled using home delivery instead of shipping 10 | **inStoreAvailability** | Identifies if a product is available for purchase in a Best Buy store 11 | **inStoreAvailabilityUpdateDate** | Provides date and time inStoreAvailability last updated 12 | **inStorePickup** | Identifies if a product can be purchased online and picked up in a store 13 | **onlineAvailability** | Identifies if a product can be purchased online 14 | **onlineAvailabilityUpdateDate** | Provides date and time onlineAvailability was last updated 15 | **orderable** | Product ordering status 16 | **specialOrder** | Identifies whether a product will require special handling for delivery 17 | 18 | 19 | ## Shipping and Delivery 20 | The Shipping and Delivery attributes provide details about the cost of shipping or delivery of a product. A product can be shippable or deliverable, but not both. 21 | 22 | > Sample `shippingLevelsOfService` response 23 | 24 | ```json-doc 25 | { 26 | "shippingLevelsOfService":[ 27 | { 28 | "serviceLevelId": 1, 29 | "serviceLevelName": "Standard", 30 | "unitShippingPrice": 2.99 31 | }, 32 | { 33 | "serviceLevelId": 3, 34 | "serviceLevelName": "Expedited", 35 | "unitShippingPrice": 10.99 36 | }, 37 | { 38 | "serviceLevelId": 5, 39 | "serviceLevelName": "Express", 40 | "unitShippingPrice": 14.99 41 | } 42 | ] 43 | } 44 | ``` 45 | Attribute | Description 46 | --------- | ----------- 47 | **freeShipping** | Identifies if a product qualifies for free shipping 48 | **freeShippingEligible** | Identifies if a product is currently eligible to receive free shipping from an existing offer 49 | **shippingCost** | Provides product's lowest shipping costs 50 | **shippingWeight** | Identifies product's shipping weight (pounds) 51 | **shippingLevelsOfService** | An array of shipping options 52 | **shippingLevelsOfService.serviceLevelId** | ID of the shipping level of service 53 | **shippingLevelsOfService.serviceLevelName** | Name of the shipping level of service 54 | **shippingLevelsOfService.unitShippingPrice** | Price of the shipping level of service 55 | -------------------------------------------------------------------------------- /source/includes/products/_categorizations.md: -------------------------------------------------------------------------------- 1 | ## Categorizations 2 | Best Buy provides multiple ways to group products based on your needs. 3 | 4 | The department, class and subclass attributes provide categorization structure or groupings of products. These attributes are returned as separate attributes but are related. The department attribute provides the more general categorization while the class and subclass attributes narrow the focus to be more specific. The class and subclass attributes are less volatile than category attributes and are the recommended attributes for grouping products. 5 | 6 | Attribute | Description | Type 7 | --------- | ----------- | ---- 8 | **class** | Class name | string 9 | **classId** | Class identifiers | integer 10 | **department** | Department name | string 11 | **departmentId** | Department identifiers | integer 12 | **subclass** | Subclass name | string 13 | **subclassId** | Subclass identifier | integer 14 | 15 | The categoryPath attributes provide a hierarchal view of a product returned as a collection. The collections start with the most general categorization, while subsequent categories narrow to be more specific. The number of categories returned can be 3+ layers deep. The products within the categories also tend to be slightly more volatile than department, class and subclass groupings. 16 | 17 | Attribute | Description | Type 18 | --------- | ----------- | ---- 19 | **categoryPath.id** | Category identifiers | string 20 | **categoryPath.name** | Category names | string 21 | 22 | The list attributes are used for specific events such as Valentine's Day. These lists are curated by Best Buy merchant teams for customer visibility for a specific event or purpose. 23 | 24 | Attribute | Description | Type 25 | --------- | ----------- | ---- 26 | **lists.endDate** | End date shown in list | string 27 | **lists.listId** | Name shown in list | string 28 | **lists.startDate** | Start date shown in list | string 29 | -------------------------------------------------------------------------------- /source/includes/products/_detail.md: -------------------------------------------------------------------------------- 1 | ## Detail 2 | The Best Buy Detail attributes contain a wealth of knowledge about Best Buy products. The intention of these attributes is to provide product descriptions, dimensions, accessories and reviews. 3 | 4 | ### Attribute List 5 | 6 | Attribute | Description | Type 7 | --------- | ----------- | ---- 8 | **accessories.sku** | Collection of SKUs that could be an accessory to originating SKU | long 9 | **color** | Product color | string 10 | **condition** | Identifies if the product is new, refurbished or pre-owned | string 11 | **customerReviewAverage** | Average "score" or ratings as submitted by reviewers | float 12 | **customerReviewCount** | Number of customer reviews | integer 13 | **customerTopRated** | Identifies if the product is top rated based on ratings from reviewers. If the Avg rating >= 4.5 and Qty of ratings >= 15, customerTopRated is set to be "true", else is set to "false" | boolean 14 | **depth** | Product depth (inches) | string 15 | **description** | Product description | string 16 | **details.name** | Collection of details about product (Example: whether a camera has a zoom) | string 17 | **details.value** | Collection of values that support the product (Example: A camera's number of Megapixels or amount of zoom) | string 18 | **digital** | Identifies if product is available in a digital format | boolean 19 | **features.feature** | Collection of product features | string 20 | **format** | Identifies media product format | string 21 | **height** | Product height (inches) | string 22 | **includedItemList.includedItem** | Collection of items included with product (Example: Canon EOS 60D Digital SLR Camera, EF-S 18-135mm IS lens, Battery pack, Battery charger) | string 23 | **longDescription** | Detailed product description | string 24 | **longDescriptionHtml** | Detailed product description with HTML formatting | string 25 | **manufacturer** | Product manufacturer | string 26 | **modelNumber** | Manufacturer product model number | string 27 | **name** | Product name | string 28 | **preowned** | Identifies if product has been previously owned (used) | boolean 29 | **productVariations.sku** | Collection of related SKUs that are variations (e.g. color, size) of the originating SKU | long 30 | **quantityLimit** | Maximum quantity of product that can be ordered |integer 31 | **releaseDate** | Date the product was released | date 32 | **shortDescription** | Brief product description | string 33 | **shortDescriptionHtml** | Brief product description (HTML formatting) | string 34 | **sku** | Best Buy unique 7-digit product identifier | long 35 | **upc** | Universal Product Code (UPC) | string 36 | **warrantyLabor** | Manufacture labor warranty description | string 37 | **warrantyParts** | Manufacture parts warranty description | string 38 | **weight** | Product weight | string 39 | **width** | Product width (inches) | string 40 | 41 | -------------------------------------------------------------------------------- /source/includes/products/_images.md: -------------------------------------------------------------------------------- 1 | ## Images 2 | The Images attributes provide multiple images for a product. These include large, small, and side images and even interactive 360 degree images. 3 | 4 | Attribute | Description 5 | --------- | ----------- 6 | **accessoriesImage** | URL of accessories image 7 | **alternateViewsImage** | URL of alternate image 8 | **angleImage** | URL of product's angle image 9 | **backViewImage** | URL of rear image 10 | **energyGuideImage** | URL of product's EnergyGuide image 11 | **image** | URL of BESTBUY.COM product detail page image 12 | **largeFrontImage** | URL of large front image 13 | **largeImage** | URL of image 14 | **leftViewImage** | URL of left image 15 | **mediumImage** | URL of medium image 16 | **remoteControlImage** | URL of remote control image 17 | **rightViewImage** | URL of right image 18 | **spin360Url** | URL of 360-degree image 19 | **thumbnailImage** | URL of image used on BESTBUY.COM listing pages 20 | **topViewImage** | URL of top image 21 | -------------------------------------------------------------------------------- /source/includes/products/_index.md.erb: -------------------------------------------------------------------------------- 1 | # Products API 2 | 3 | The Best Buy Product API provides a simple, REST-based interface for our entire product catalog, past and present. This includes pricing, availability, specifications, descriptions, and images for more than one million current and historical products. **Most product information is updated near real-time, including product pricing.** 4 | 5 | *PLEASE NOTE: Music and movie data may be used only where an ability to purchase the related music or movies from BESTBUY.COM is provided to end users. Developers using music and movie data to redirect to BESTBUY.COM must become members of the Best Buy Affiliate Program to allow the sale of music and movies through BESTBUY.COM under the terms of the Affiliate Program.* 6 | 7 | <%= partial "includes/products/detail" %> 8 | <%= partial "includes/products/proposition65" %> 9 | <%= partial "includes/products/pricing-and-ranking" %> 10 | <%= partial "includes/products/availability-and-delivery" %> 11 | <%= partial "includes/products/images" %> 12 | <%= partial "includes/products/links" %> 13 | <%= partial "includes/products/categorizations" %> 14 | <%= partial "includes/products/offers-and-deals" %> 15 | <%= partial "includes/products/listing-products" %> 16 | <%= partial "includes/products/warranty" %> 17 | -------------------------------------------------------------------------------- /source/includes/products/_links.md: -------------------------------------------------------------------------------- 1 | ## Links 2 | The Links attributes provide a way for you to direct customers to a BESTBUY.COM product detail page or create a BESTBUY.COM cart on their behalf while including the product in the cart. 3 | 4 | Attribute | Description 5 | --------- | ----------- 6 | **addToCartUrl** | URL to BESTBUY.COM with item in cart 7 | **url** | URL to BESTBUY.COM product detail page 8 | 9 |
10 | For our **affiliate partners** we provide this same functionality but use a special link so you can get credit for your sale. Affiliates add their Impact Partner ID (IPID) to their query request. The URL generated will direct the customer to BESTBUY.COM with this item in their cart and credit the affiliate with the sale. Additional information on the affiliate program can be found here. 11 | 12 | Attribute | Description 13 | --------- | ----------- 14 | **affiliateAddToCartUrl** | URL to BESTBUY.COM with item in cart 15 | **affiliateUrl** | URL to BESTBUY.COM product detail page -------------------------------------------------------------------------------- /source/includes/products/_listing-products.md: -------------------------------------------------------------------------------- 1 | ## Listing Products 2 | We offer various metadata to support you when listing Best Buy products. This includes information such as whether a product is active, if it is new or refurbished, the type of product (music, movie, hardgood, bundle, game, blacktie, or software) and more. 3 | 4 | Attribute | Description | Type 5 | --------- | ----------- | ---- 6 | **active** | Identifies if product is currently supported in the BESTBUY.COM catalog | boolean 7 | **activeUpdateDate** | Date and time the active attribute was last changed | date 8 | **bundledIn.sku** | Returns SKUs of bundles that include this product | long 9 | **itemUpdateDate** | Date and time any change was made to this product | date 10 | **members.sku** | Collection of skus within a bundle | long 11 | **new** | Identifies if the product was added within last 30 days | boolean 12 | **secondaryMarket** | Identifies if product is a secondary market product | boolean 13 | **startDate** | Date Best Buy began selling product | date 14 | **type** | Best Buy product type, see section below for more details | string 15 | 16 | ### Product Type Details 17 | Value | Description 18 | ----- | ----------- 19 | **blackTie** | Extended warranty services provided by the Best Buy GeekSquad team 20 | **bundle** | A group of products; group can include both material and digital products 21 | **game** | Games; includes both material and digital (downloadable) game products 22 | **hardgood** | Products that are not of type music, movie, game, blackTie, software or bundle 23 | **movie** | Movies; inclues both material and digital (downloadable) movie products 24 | **music** | Music; includes both material and digital (downloadable) music products 25 | **software** | Software; includes material and digital (downloadable) software products 26 | -------------------------------------------------------------------------------- /source/includes/products/_offers-and-deals.md: -------------------------------------------------------------------------------- 1 | ## Offers and Deals 2 | The Best Buy offer attributes provide a comprehensive view into the deals at Best Buy. This includes what is in our Sunday circular (also available online), our "Deal of the Day" and other special offers like "Free Shipping on Orders $35 and Up." Each offer will contain a description of the offer and a link to the offer on **BESTBUY.COM** where applicable. Offer information is grouped together in a collection. Each product can have one or more offers associated to it. 3 | 4 | *NOTE: Offers are updated on a daily basis. Offers are subject to change and applicability will be determined at checkout.* 5 | 6 | Attributes | Description 7 | ---------- | ----------- 8 | **offers.endDate** | Offer end date 9 | **offers.id** | Offer identifier 10 | **offers.startDate** | Offer start date 11 | **offers.text** | Description of offer 12 | **offers.type** | Offer types can include the following:
  • special_offer: identified by Best Buy marketing managers
  • digital_insert: identifies products that are featured in Best Buy's Top Deals
  • deal_of_the_day: small group of products being promoted for one day only
  • 13 | **offers.url** | URL of offer information on BESTBUY.COM 14 | -------------------------------------------------------------------------------- /source/includes/products/_pricing-and-ranking.md: -------------------------------------------------------------------------------- 1 | ## Pricing 2 | Best Buy's Pricing attributes make it easy to identify the product price, if a product is on sale, how much you can save and even when we made our last pricing changes. 3 | 4 | Attribute | Description 5 | --------- | ----------- 6 | **contracts.type** | Type of contract for Mobile phone 7 | **contracts.prices** | Regular and current monthly contract pricing for Mobile phone 8 | **contracts.priceNote** | Description of contract pricing for Mobile phone 9 | **dollarSavings** | Identifies amount saved 10 | **lowPriceGuarantee** | Identifies if a product qualifies for the Best Buy low price guarantee 11 | **onSale** | Identifies if sale price is less than regular price 12 | **percentSavings** | Identifies the percent saved between the regularPrice and salePrice 13 | **priceRestriction** | Identifies product sale price display restrictions:
  • MAP restriction identifies Minimum Advertised Price; actual selling price may not be shown until prodcut is added to cart
  • ICR restriction identifies In-Checkout Rebate Price; actual selling price may not be shown until checkout
  • 14 | **priceUpdateDate** | Date and time product price was last updated 15 | **priceWithPlan.newTwoYearPlan** | Mobile phone price when purchased with new 2-year plan 16 | **priceWithPlan.upgradeTwoYearPlan** | Mobile phone price when purchased with 2-year upgrade plan 17 | **priceWithPlan.newTwoYearPlanSalePrice** | Mobile phone sale price when purchased with 2-year plan 18 | **priceWithPlan.upgradeTwoYearPlanSalePrice** | Mobile phone sale price when purchased with 2-year upgrade plan 19 | **priceWithPlan.newTwoYearPlanRegularPrice** | Mobile phone price when purchased with new 2-year plan 20 | **priceWithPlan.upgradeTwoYearPlanRegularPrice** | Mobile phone price when purchased with 2-year upgrade plan 21 | **regularPrice** | Product's regular selling price 22 | **salePrice** | Current item selling price -------------------------------------------------------------------------------- /source/includes/products/_proposition65.md: -------------------------------------------------------------------------------- 1 | ## California Proposition 65 2 | 3 | California Proposition 65 (CA Prop 65) is a California regulation requiring businesses with 10 or more employees to provide a “clear and reasonable warning” before knowingly and intentionally exposing individuals in California to a chemical listed by the state as known to cause cancer or reproductive toxicity. The CA Prop 65 regulation provides safe harbor warnings that meet the “clear and reasonable warning” requirement. As of August 30, 2018, these safe harbor warnings require either a short-form warning or a chemical-specific warning for any product containing a listed chemical. Websites and mobile applications that sell products must provide the same warning that is displayed on the product and/or product packaging. 4 | 5 | In order to comply with CA Prop 65, the warning is required for all products offered for purchase. The warning may be implemented by displaying the CA Prop 65 warning at a point prior to purchase of an affected product to (a) all customers, or (b) only to customers who enter a California ship-to address. 6 | 7 | Best Buy's Products API provides the following fields for this purpose: 8 | 9 | ### Attribute List 10 | 11 | Attribute | Description | Type 12 | --------- | ----------- | ---- 13 | **proposition65WarningMessage** | A custom warning message which can be up to 360 characters. It can be null/empty depending on the product. | string 14 | **proposition65WarningType** | Values of 01 to 05 indicating the type of warning required for this product. This field will ALWAYS contain a value.
    01 - None (There is no warning message required for this product)
    02 - Cancer
    03 - Reproductive Harm
    04 - Cancer and Reproductive Harm
    05 - Unknown (We currently do not have information about warnings on this product) | string 15 | 16 | For more information on this regulation including the list of chemicals, please go to [https://oehha.ca.gov/proposition-65](https://oehha.ca.gov/proposition-65). -------------------------------------------------------------------------------- /source/includes/products/_warranty.md: -------------------------------------------------------------------------------- 1 | ## Warranties 2 | 3 | The Warranties endpoint within the Best Buy Products API helps you access a list of warranties associated with a Best Buy product, along with select data associated with the warranty. For more detailed information about a specific warranty, you can look at that warranty by SKU in our Products endpoint. 4 | 5 | > Search for warranties associated with SKU 5005633 6 | 7 | ```shell 8 | curl "https://api.bestbuy.com/v1/products/5005633/warranties.json?apiKey=YourAPIKey" 9 | ``` 10 | 11 | ```json-doc 12 | [{ 13 | "skuId": "2745188", 14 | "shortName": "1-Year Accidental Geek Squad Protection", 15 | "currentPrice": 149.99, 16 | "type": "GSP", 17 | "department": "7", 18 | "subclass": "210", 19 | "protectionType": "Accidental", 20 | "paymentType": "ONETIME", 21 | "term": "12 months", 22 | "class": "332" 23 | } 24 | ] 25 | ``` 26 | 27 | ### Common Attributes 28 | 29 | Attribute | Description | Type 30 | --------- | ----------- | ---- 31 | **protectionType** | Collection of warranties offering specific protections | string 32 | **paymentType** | Collection of warranties available with a specific type of payment | string 33 | **term** | Collection of warranties available for a certain length of time | string 34 | 35 | **Note:** Descriptions of other warranty-related attributes, including `skuId`, `shortName`, `currentPrice`, `type`, `department`, `class`, and `subclass` can be found in our core Products documentation. -------------------------------------------------------------------------------- /source/includes/recommendations/_also-bought.md: -------------------------------------------------------------------------------- 1 | ## Also Bought 2 | ```shell 3 | curl "https://api.bestbuy.com/v1/products/8880044/alsoBought?apiKey=YourAPIKey" 4 | ``` 5 | ```javascript 6 | var bby = require('bestbuy')('YourAPIKey'); 7 | bby.recommendations('alsoBought', 8880044).then(function(data){ 8 | console.log(data); 9 | }); 10 | ``` 11 | ```json-doc 12 | { 13 | "metadata": { 14 | "context": { 15 | "canonicalUrl": "https://api.bestbuy.com/v1/products/8880044/alsoBought?apiKey=YourAPIKey" 16 | }, 17 | "resultSet": { 18 | "count": 10 19 | } 20 | }, 21 | "results": [ 22 | { 23 | "sku": "9124743", 24 | "customerReviews": { 25 | "averageScore": 4.9, 26 | "count": 2003 27 | }, 28 | "descriptions": { 29 | "short": null 30 | }, 31 | "images": { 32 | "standard": "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/9124/9124743_sa.jpg" 33 | }, 34 | "names": { 35 | "title": "The Dark Knight [WS] [2 Discs] [Blu-ray] [2008]" 36 | }, 37 | "prices": { 38 | "regular": 9.99, 39 | "current": 9.99 40 | }, 41 | "links": { 42 | "product": "https://api.bestbuy.com/v1/products/9124743.json?apiKey=YourAPIKey", 43 | "web": "https://api.bestbuy.com/click/-/9124743/pdp", 44 | "addToCart": "https://api.bestbuy.com/click/-/9124743/cart" 45 | }, 46 | "rank": 1 47 | }, 48 | // ... 49 | ] 50 | } 51 | 52 | ``` 53 | 54 | The Also Bought Products endpoint can be used to identify the top ten products that were bought along with the originating product. These results are determined based on aggregated customer purchases over the past thirty days. 55 | 56 | ### Endpoint-Specific Attributes 57 | 58 | Attribute | Description 59 | --------- | ----------- 60 | **rank** | The rank of the product based on how often it was purchased together with the originating SKU. 61 | -------------------------------------------------------------------------------- /source/includes/recommendations/_also-viewed.md: -------------------------------------------------------------------------------- 1 | ## Also Viewed 2 | ```shell 3 | curl "https://api.bestbuy.com/v1/products/8880044/alsoViewed?apiKey=YourAPIKey" 4 | ``` 5 | ```javascript 6 | var bby = require('bestbuy')('YourAPIKey'); 7 | bby.recommendations('alsoViewed',8880044).then(function(data){ 8 | console.log(data); 9 | }); 10 | ``` 11 | ```json-doc 12 | { 13 | "metadata": { 14 | "context": { 15 | "canonicalUrl": "https://api.bestbuy.com/v1/products/8880044/alsoViewed?apiKey=YourAPIKey" 16 | }, 17 | "resultSet": { 18 | "count": 10 19 | } 20 | }, 21 | "results": [ 22 | { 23 | "sku": "6111518", 24 | "customerReviews": { 25 | "averageScore": 4.7, 26 | "count": 1292 27 | }, 28 | "descriptions": { 29 | "short": null 30 | }, 31 | "images": { 32 | "standard": "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/6111/6111518_sa.jpg" 33 | }, 34 | "names": { 35 | "title": "Batman Begins [4K Ultra HD Blu-ray/Blu-ray] [2005]" 36 | }, 37 | "prices": { 38 | "regular": 23.99, 39 | "current": 23.99 40 | }, 41 | "links": { 42 | "product": "https://api.bestbuy.com/v1/products/6111518.json?apiKey=YourAPIKey", 43 | "web": "https://api.bestbuy.com/click/-/6111518/pdp", 44 | "addToCart": "https://api.bestbuy.com/click/-/6111518/cart" 45 | }, 46 | "rank": 1 47 | }, 48 | // ... 49 | ] 50 | } 51 | ``` 52 | 53 | The Also Viewed Products endpoint can be used to identify top ten products that were viewed along with the originating product. These results are determined based on aggregated customer browsing behavior over the past thirty days on **BESTBUY.COM**. 54 | 55 | ### Endpoint-Specific Attributes 56 | 57 | Attribute | Description 58 | --------- | ----------- 59 | **rank** | The rank of the product based on how many views a product received after starting with originating SKU. The number 1 rank identifies the highest number of page views an associated product received while looking at originating SKU while the number 10 rank identifies the product with the 10th highest page views while look at same originating product -------------------------------------------------------------------------------- /source/includes/recommendations/_index.md.erb: -------------------------------------------------------------------------------- 1 | # Recommendations API 2 | 3 | The Recommendations API offers Trending, Most Viewed and Also Viewed information about **Best Buy** products based on customer behavior at **BESTBUY.COM**. 4 | 5 | ## Shared Attributes 6 | 7 | Attribute | Description 8 | --------- | ----------- 9 | **customerReviews.averageScore** | An average of all the ratings submitted for a product by reviewers 10 | **customerReviews.count** | Total number of reviews collected 11 | **description.short** | Brief description of a product 12 | **images.standard** | URL of the BESTBUY.COM product detail page image 13 | **links.addToCart** | URL that will direct the customer to BESTBUY.COM with the item in their cart 14 | **links.product** | Link to the specific sku in the Products API 15 | **links.web** | Link to the BESTBUY.COM product detail page 16 | **names.title** | Name of the product 17 | **prices.current** | Current selling price 18 | **prices.regular** | Regular selling price 19 | **sku** | Unique identifier for products sold by Best Buy 20 | 21 | <%= partial "includes/recommendations/trending" %> 22 | <%= partial "includes/recommendations/most-viewed" %> 23 | <%= partial "includes/recommendations/also-viewed" %> 24 | <%= partial "includes/recommendations/also-bought" %> 25 | <%= partial "includes/recommendations/viewed-ultimately-bought" %> 26 | -------------------------------------------------------------------------------- /source/includes/recommendations/_most-viewed.md: -------------------------------------------------------------------------------- 1 | ## Most Popular Viewed 2 | ```shell 3 | curl "https://api.bestbuy.com/v1/products/mostViewed(categoryId=abcat0107000)?apiKey=YourAPIKey" 4 | ``` 5 | ```javascript 6 | var bby = require('bestbuy')('YourAPIKey'); 7 | bby.recommendations('mostViewed','abcat0107000').then(function(data){ 8 | console.log(data); 9 | }); 10 | ``` 11 | 12 | > Request Most Viewed products based on category abcat0107000 otherwise known as "TV & Home Theater Accessories." When pulling by category you should always use the category id. It is not possible to query by category name. 13 | 14 | ```json-doc 15 | { 16 | "metadata": { 17 | "context": { 18 | "canonicalUrl": "https://api.bestbuy.com/v1/products/mostViewed(categoryId=abcat0107000)?apiKey=YourAPIKey" 19 | }, 20 | "resultSet": { 21 | "count": 10 22 | } 23 | }, 24 | "results": [ 25 | { 26 | "sku": "5852832", 27 | "customerReviews": { 28 | "averageScore": 4.3, 29 | "count": 4816 30 | }, 31 | "descriptions": { 32 | "short": "Compatible with more than 270,000 entertainment device brands; replaces up to 10 remotes; programmable buttons" 33 | }, 34 | "images": { 35 | "standard": "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/5852/5852832_sa.jpg" 36 | }, 37 | "names": { 38 | "title": "Logitech - Harmony 665 10-Device Universal Remote - Black" 39 | }, 40 | "prices": { 41 | "regular": 79.99, 42 | "current": 79.99 43 | }, 44 | "links": { 45 | "product": "https://api.bestbuy.com/v1/products/5852832.json?apiKey=YourAPIKey", 46 | "web": "https://api.bestbuy.com/click/-/5852832/pdp", 47 | "addToCart": "https://api.bestbuy.com/click/-/5852832/cart" 48 | }, 49 | "rank": 1 50 | }, 51 | // ... 52 | ] 53 | } 54 | 55 | ``` 56 | 57 | The Most Popular Viewed endpoint returns the top ten products, by rank, of the most frequently viewed products on **BESTBUY.COM**. You can also pull this same information by **category** or **subcategory**. To find out additional information about identifying category ids please refer to our [Categories API](#categories-api) documentation. This data for Most Popular Viewed is refreshed every two hours with a maximum accumulation time of 48 hours when determining the top ten products. 58 | 59 | _Note: The difference between Trending Products and Most Popular Viewed Products is that Trending Products reflects change in velocity of product views while Most Popular Viewed reflects page views only._ 60 | 61 | ### Endpoint-Specific Attributes 62 | 63 | Attribute | Description 64 | --------- | ----------- 65 | **rank** | The rank of a product based on how frequently it is viewed on BESTBUY.COM product detailed page -------------------------------------------------------------------------------- /source/includes/recommendations/_trending.md: -------------------------------------------------------------------------------- 1 | ## Trending Products 2 | ```shell 3 | curl "https://api.bestbuy.com/v1/products/trendingViewed(categoryId=abcat0400000)?apiKey=YourAPIKey" 4 | ``` 5 | ```javascript 6 | var bby = require('bestbuy')('YourAPIKey'); 7 | bby.recommendations('trendingViewed','abcat0400000').then(function(data){ 8 | console.log(data); 9 | }); 10 | ``` 11 | 12 | > In this example we request Trending products based on category abcat0400000 otherwise known as "Cameras & Camcorders". When pulling by category you should always use the category id. It is not possible to query by category name. For more information about identifying category ids please refer to our [Categories API](#categories-api) documentation. 13 | 14 | ```json-doc 15 | { 16 | "metadata": { 17 | "context": { 18 | "canonicalUrl": "https://api.bestbuy.com/v1/products/trendingViewed(categoryId=abcat0400000)?apiKey=YourAPIKey" 19 | }, 20 | "resultSet": { 21 | "count": 10 22 | } 23 | }, 24 | "results": [ 25 | { 26 | "sku": "6323759", 27 | "customerReviews": { 28 | "averageScore": 4.8, 29 | "count": 1477 30 | }, 31 | "descriptions": { 32 | "short": "24.1-megapixel APS-C format CMOS sensorISO 100-6,400, expandable to 12,800Shooting speeds up to 3 fps9 points of focus1920 x 1080 (Full HD) 30 fps video recording capabilityBuilt-in Wi-Fi, NFC, and GPS capable" 33 | }, 34 | "images": { 35 | "standard": "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/6323/6323759_sa.jpg" 36 | }, 37 | "names": { 38 | "title": "Canon - EOS Rebel T7 DSLR Video Two Lens Kit with EF-S 18-55mm and EF 75-300mm Lenses" 39 | }, 40 | "prices": { 41 | "regular": 549.99, 42 | "current": 549.99 43 | }, 44 | "links": { 45 | "product": "https://api.bestbuy.com/v1/products/6323759.json?apiKey=YourAPIKey", 46 | "web": "https://api.bestbuy.com/click/-/6323759/pdp", 47 | "addToCart": "https://api.bestbuy.com/click/-/6323759/cart" 48 | }, 49 | "rank": 1 50 | }, 51 | // ... 52 | ] 53 | } 54 | 55 | ``` 56 | 57 | The Trending Products endpoint returns top ten products, by rank, based on customer views of the **BESTBUY.COM** product detail page over a rolling three hour time period. Trending growth is based on a comparison against the previous three hour time period. You can also pull this same information by **category** or **subcategory**. For more information about identifying category ids please refer to our [Categories API](#categories-api) documentation. 58 | 59 | *Note: Minimum of 50 page views/hr required for inclusion. In addition, deep subcategories may not have enough user traffic to generate trending data.* 60 | 61 | ### Endpoint-Specific Attributes 62 | 63 | Attribute | Description 64 | --------- | ----------- 65 | **rank** | The rank of a product as compared to the velocity of other trending products. The number rank 1 identifies the most highly trending product while a number 10 rank would identify the 10th trending product -------------------------------------------------------------------------------- /source/includes/recommendations/_viewed-ultimately-bought.md: -------------------------------------------------------------------------------- 1 | ## Viewed Ultimately Bought 2 | ```shell 3 | curl "https://api.bestbuy.com/v1/products/8880044/viewedUltimatelyBought?apiKey=YourAPIKey" 4 | ``` 5 | ```javascript 6 | var bby = require('bestbuy')('YourAPIKey'); 7 | bby.recommendations('viewedUltimatelyBought', 8880044).then(function(data){ 8 | console.log(data); 9 | }); 10 | ``` 11 | ```json-doc 12 | { 13 | "metadata": { 14 | "context": { 15 | "canonicalUrl": "https://api.bestbuy.com/v1/products/8880044/viewedUltimatelyBought?apiKey=YourApiKey" 16 | }, 17 | "resultSet": { 18 | "count": 10 19 | } 20 | }, 21 | "results": [ 22 | { 23 | "sku": "3921114", 24 | "customerReviews": { 25 | "averageScore": 4.7, 26 | "count": 2113 27 | }, 28 | "descriptions": { 29 | "short": null 30 | }, 31 | "images": { 32 | "standard": "https://pisces.bbystatic.com/image2/BestBuy_US/images/products/3921/3921114_sa.jpg" 33 | }, 34 | "names": { 35 | "title": "The Wolf of Wall Street [2 Discs] [Blu-ray/DVD] [Includes Digital Copy] [2013]" 36 | }, 37 | "prices": { 38 | "regular": 4.99, 39 | "current": 4.99 40 | }, 41 | "links": { 42 | "product": "https://api.bestbuy.com/v1/products/3921114.json?apiKey=YourAPIKey", 43 | "web": "https://api.bestbuy.com/click/-/3921114/pdp", 44 | "addToCart": "https://api.bestbuy.com/click/-/3921114/cart" 45 | }, 46 | "rank": 1 47 | }, 48 | // ... 49 | ] 50 | } 51 | ``` 52 | 53 | The Viewed Ultimately Bought Products endpoint can be used to identify the top ten products that were bought after having viewed the originating product. These results are determined based on aggregated customer purchases and views over the past thirty days. 54 | 55 | ### Endpoint-Specific Attributes 56 | 57 | Attribute | Description 58 | --------- | ----------- 59 | **rank** | The rank of the product based on how often it was purchased after having viewed the originating SKU. 60 | -------------------------------------------------------------------------------- /source/includes/search/_index.md: -------------------------------------------------------------------------------- 1 | # Search Techniques 2 | *Applies to: Products API • Stores API • Categories API* 3 | 4 | Search consists of one or more terms that generally include an attribute, operator and value. Terms are combined with ampersands `&` or pipes `|`. Searches are implemented as part of an HTTP GET request to the deisred Best Buy API. `term1&term2` - specifies term1 AND term2 `term1|term2` - specifies term1 OR term2. 5 | 6 | Attribute *names* are case sensitive; attribute *values* are not. 7 | 8 | ## Available Operators 9 | 10 | + `=` - attribute **equals** a specified value 11 | + `!=`- attribute **does not equal** a specified value 12 | + `>` - attribute **greater than** a specified value 13 | + `<` - attribute **less than** a specified value 14 | + `>=` - attribute **greater than or equal to** a specified value 15 | + `<=` - attribute **less than or equal to** a specified value 16 | + `in` - search based on a **list** of attribute values 17 | 18 | 19 | 20 | ## Search by a single attribute 21 | 22 | ```shell 23 | curl "https://api.bestbuy.com/v1/stores(region=ut)?format=json&show=storeId,city,region&apiKey=YourAPIKey" 24 | ``` 25 | 26 | ```javascript 27 | var bby = require('bestbuy')('YourAPIKey'); 28 | bby.stores('region=ut',{show:'storeId,city,region'}).then(function(data){ 29 | console.log(data); 30 | }); 31 | ``` 32 | 33 | ```json-doc 34 | { 35 | "from": 1, 36 | "to": 10, 37 | "total": 10, 38 | "currentPage": 1, 39 | "totalPages": 1, 40 | "queryTime": "0.002", 41 | "totalTime": "0.007", 42 | "partial": false, 43 | "canonicalUrl": "/v1/stores(region=\"ut\")?format=json&show=storeId,city,region&apiKey=YourAPIKey", 44 | "stores": [ 45 | { 46 | "storeId": 1402, 47 | "city": "American Fork", 48 | "region": "UT" 49 | }, 50 | { 51 | "storeId": 773, 52 | "city": "Orem", 53 | "region": "UT" 54 | } 55 | ``` 56 | 57 | Our Products, Stores and Categories APIs can be searched by nearly all available attributes. For example, to find only the stores located in Utah, you can use the query shown to the right. 58 | 59 | ## Search by all attributes (AND) 60 | 61 | ```shell 62 | curl 'https://api.bestbuy.com/v1/products(manufacturer=canon&salePrice<1000)?format=json&show=sku,name,salePrice&apiKey=YourAPIKey' 63 | ``` 64 | 65 | ```javascript 66 | var bby = require('bestbuy')('YourAPIKey'); 67 | bby.products('manufacturer=canon&salePrice<1000',{show:'sku,name,salePrice'}).then(function(data){ 68 | console.log(data); 69 | }); 70 | ``` 71 | 72 | ```json-doc 73 | { 74 | "from": 1, 75 | "to": 10, 76 | "total": 210, 77 | "currentPage": 1, 78 | "totalPages": 21, 79 | "queryTime": "0.095", 80 | "totalTime": "0.115", 81 | "partial": false, 82 | "canonicalUrl": "/v1/products(manufacturer=\"canon\"&salePrice<1000)?show=sku,name,salePrice&format=json&apiKey=YourAPIKey", 83 | "products": [ 84 | { 85 | "sku": 6101087, 86 | "name": "Canon - 1.9x Tele Converter Lens", 87 | "salePrice": 99.99 88 | }, 89 | { 90 | "sku": 8795075, 91 | "name": "Canon - 100-Pack 4\" x 6\" Glossy Photo Paper", 92 | "salePrice": 17.49 93 | } 94 | ``` 95 | 96 | If you need to search for the values of more than one attribute and **all** of the attributes must be present, combine them with an ampersand `&`. 97 | 98 | ## Search by any attributes (OR) 99 | 100 | ```shell 101 | curl "https://api.bestbuy.com/v1/products(wifiReady=true|wifiBuiltIn=true)?format=json&show=sku,name,salePrice&apiKey=YourAPIKey" 102 | ``` 103 | 104 | ```javascript 105 | var bby = require('bestbuy')('YourAPIKey'); 106 | bby.products('wifiReady=true|wifiBuiltIn=true',{show:'sku,name,salePrice'}).then(function(data){ 107 | console.log(data); 108 | }); 109 | ``` 110 | 111 | ```json-doc 112 | { 113 | "from": 1, 114 | "to": 10, 115 | "total": 500, 116 | "currentPage": 1, 117 | "totalPages": 50, 118 | "queryTime": "0.005", 119 | "totalTime": "0.030", 120 | "partial": false, 121 | "canonicalUrl": "/v1/products(wifiReady=true|wifiBuiltIn=true)?show=sku,name,salePrice&format=json&apiKey=YourAPIKey", 122 | "products": [ 123 | { 124 | "sku": 1012749, 125 | "name": "Acer - Aspire 11.6 inch Tablet with 120GB Memory", 126 | "salePrice": 661.98 127 | }, 128 | { 129 | "sku": 4255007, 130 | "name": "Acer - B1-720 7\" Android Tablet - 16GB - Iron Gray", 131 | "salePrice": 128.98 132 | } 133 | ``` 134 | 135 | 136 | 137 | If you want items with **any** of the specified attributes, combine them with a pipe `|` 138 | 139 | ## Complex Searches 140 | 141 | ```shell 142 | curl "https://api.bestbuy.com/v1/products(platform=psp&(salePrice<=15|(salePrice<=20&inStorePickup=true)))?format=json&show=sku,name,salePrice,inStorePickup,platform&apiKey=YourAPIKey" 143 | ``` 144 | 145 | ```javascript 146 | var bby = require('bestbuy')('YourAPIKey'); 147 | bby.products('platform=psp&(salePrice<=15|(salePrice<=20&inStorePickup=true))',{show:'sku,name,salePrice,inStorePickup,platform'}).then(function(data){ 148 | console.log(data); 149 | }); 150 | ``` 151 | 152 | ```json-doc 153 | [ 154 | { 155 | "sku":8005115, 156 | "name":"Lumines II - PSP", 157 | "salePrice":9.99, 158 | "inStorePickup":true, 159 | "platform":"PSP" 160 | }, 161 | { 162 | "sku":8376027, 163 | "name":"Practical Intelligence Quotient 2 - PSP", 164 | "salePrice":14.99, 165 | "inStorePickup":true, 166 | "platform":"PSP" 167 | }, 168 | { 169 | "sku":9335436, 170 | "name":"Chessmaster: The Art of Learning - PSP", 171 | "salePrice":9.99, 172 | "inStorePickup":true, 173 | "platform":"PSP" 174 | } 175 | ] 176 | ``` 177 | 178 | Complex searches can be performed by combining AND `&` and OR `|` operations with parantheses. For example: let's say that you're looking for a Play Station Portable video game `(platform=psp)`. You don't want to spend more than $15 `(salePrice<=15)`. However, because you will trade in the game when you're done, you could spend up to $20 `(salePrice<=20)`. You also want to make sure the game is available to buy online and pickup at a store `(inStorePickup=true)`. 179 | 180 | The search terms for this example can be combined as: 181 | 182 | `platform=psp & (salePrice<=15 | (salePrice<=20 & inStorePickup=true))` 183 | 184 | ## Search by date range 185 | 186 | ```shell 187 | curl "https://api.bestbuy.com/v1/products(releaseDate>=2014-02-01&releaseDate<=2014-02-28)?format=json&show=sku,name,salePrice&apiKey=YourAPIKey" 188 | ``` 189 | 190 | ```javascript 191 | var bby = require('bestbuy')('YourAPIKey'); 192 | bby.products('releaseDate>=2014-02-01&releaseDate<=2014-02-28',{show:'sku,name,salePrice'}).then(function(data){ 193 | console.log(data); 194 | }); 195 | ``` 196 | 197 | ```json-doc 198 | { 199 | "from": 1, 200 | "to": 10, 201 | "total": 4407, 202 | "currentPage": 1, 203 | "totalPages": 441, 204 | "queryTime": "0.064", 205 | "totalTime": "0.226", 206 | "partial": false, 207 | "canonicalUrl": "/v1/products(releaseDate>=2014-02-01&releaseDate<=2014-02-28)?show=sku,name,salePrice&format=json&apiKey=YourAPIKey", 208 | "products": [ 209 | { 210 | "sku": 24311154, 211 | "name": "#lovestrock-CD", 212 | "salePrice": 22.99 213 | }, 214 | { 215 | "sku": 23374755, 216 | "name": "(Untitled) - CD", 217 | "salePrice": 39.99 218 | } 219 | ``` 220 | If you want to find all products that were released February 2014, use this query: 221 | 222 | ## Search by date relative to today 223 | 224 | ```shell 225 | curl "https://api.bestbuy.com/v1/products(releaseDate>today)?format=json&show=sku,name,salePrice&apiKey=YourAPIKey" 226 | ``` 227 | 228 | ```javascript 229 | var bby = require('bestbuy')('YourAPIKey'); 230 | bby.products('releaseDate>today',{show:'sku,name,salePrice'}).then(function(data){ 231 | console.log(data); 232 | }); 233 | ``` 234 | 235 | ```json-doc 236 | { 237 | "from": 1, 238 | "to": 10, 239 | "total": 7688, 240 | "currentPage": 1, 241 | "totalPages": 769, 242 | "queryTime": "0.007", 243 | "totalTime": "0.032", 244 | "partial": false, 245 | "canonicalUrl": "/v1/products(releaseDate>today)?show=sku,name,salePrice&format=json&apiKey=YourAPIKey", 246 | "products": [ 247 | { 248 | "sku": 24987148, 249 | "name": "$Ellebrity (DVD)", 250 | "salePrice": 19.99 251 | }, 252 | { 253 | "sku": 6121399, 254 | "name": "& Then You Shoot Your Cousin - CD", 255 | "salePrice": 12.99 256 | } 257 | ``` 258 | 259 | You can also use the value `today` to represent the current day. If you want to see all the products that were released today, use this query. 260 | 261 | ## Search for multiple attribute values 262 | 263 | ```shell 264 | curl "https://api.bestbuy.com/v1/products(categoryPath.id=abcat0901005&color%20in(white,bisque,stainless-steel))?format=json&show=sku,name,salePrice&apiKey=YourAPIKey" 265 | ``` 266 | 267 | ```javascript 268 | var bby = require('bestbuy')('YourAPIKey'); 269 | bby.products('categoryPath.id=abcat0901005&color in(white,bisque,stainless-steel)',{show:'sku,name,salePrice'}).then(function(data){ 270 | console.log(data); 271 | }); 272 | ``` 273 | 274 | ```json-doc 275 | { 276 | "from": 1, 277 | "to": 10, 278 | "total": 52, 279 | "currentPage": 1, 280 | "totalPages": 6, 281 | "queryTime": "0.007", 282 | "totalTime": "0.033", 283 | "partial": false, 284 | "canonicalUrl": "/v1/products(categoryPath.id=abcat0901005&color in(\"white\",\"bisque\",\"stainless-steel\"))?show=sku,name,salePrice&format=json&apiKey=YourAPIKey", 285 | "products": [ 286 | { 287 | "sku": 1614013, 288 | "name": "Amana - 25.4 Cu. Ft. Side-by-Side Refrigerator with Thru-the-Door Ice and Water - Stainless-Steel", 289 | "salePrice": 1099.99 290 | }, 291 | { 292 | "sku": 1609858, 293 | "name": "Amana - 25.4 Cu. Ft. Side-by-Side Refrigerator with Thru-the-Door Ice and Water - White", 294 | "salePrice": 999.99 295 | } 296 | ``` 297 | 298 | If you want multiple values of a single attribute, you can specify them individually. For example, if you want to see white, bisque, or stainless-steel side-by-side refrigerators, use this query. 299 | 300 | *NOTE: To search for products based on a list of attribute values, we recommend using the `in` operator. Most attributes can be used with the `in` operator. The most common attribute used is `SKU`. Using the `in` operator helps to avoid Query Per Second errors (QPS).* 301 | 302 | *For example: `https://api.bestbuy.com/v1/products(sku in(43900,2088495,7150065))?apiKey=YourAPIKey`* 303 | 304 | ## Wildcards - Value is present 305 | 306 | ```shell 307 | curl "https://api.bestbuy.com/v1/products(categoryPath.id=abcat0502000&driveCapacityGb=*)?format=json&show=sku,name,salePrice&apiKey=YourAPIKey" 308 | ``` 309 | 310 | ```javascript 311 | var bby = require('bestbuy')('YourAPIKey'); 312 | bby.products('categoryPath.id=abcat0502000&driveCapacityGb=*',{show:'sku,name,salePrice'}).then(function(data){ 313 | console.log(data); 314 | }); 315 | ``` 316 | 317 | ```json-doc 318 | { 319 | "from": 1, 320 | "to": 10, 321 | "total": 381, 322 | "currentPage": 1, 323 | "totalPages": 39, 324 | "queryTime": "0.008", 325 | "totalTime": "0.039", 326 | "partial": false, 327 | "canonicalUrl": "/v1/products(categoryPath.id=abcat0502000&driveCapacityGb=*)?show=sku,name,salePrice&format=json&apiKey=YourAPIKey", 328 | "products": [ 329 | { 330 | "sku": 4591017, 331 | "name": "Acer - 11.6\" Touch-Screen Chromebook - Intel Celeron - 2GB Memory - 32GB Solid State Drive - Moonstone White", 332 | "salePrice": 299.00 333 | }, 334 | { 335 | "sku": 5009309, 336 | "name": "Acer - 14\" Touch-Screen Laptop - Intel Core i5 - 6GB Memory - 500GB HDD + 20GB Solid State Drive - Silver", 337 | "salePrice": 740.98 338 | } 339 | ``` 340 | 341 | You can use the asterisk `*` as a wildcard character. The wildcard can be used to: 342 | 343 | + indicate the presence of attribute values 344 | + request all values for filtered attributes 345 | + tokenize the string and represent additional characters 346 | 347 | Some attributes apply only to specific items. Even then, because much of this attribute information comes from the manufacturer, not all items of a given type will have values set for that attribute. You can use the wildcard to specify items that have data for a specific attribute. 348 | 349 | 350 | + attribute=* - requests items for which the attribute has values 351 | + attribute!=* - requests items for which the attribute has no value 352 | 353 | ## Wildcards - Value is NOT present 354 | 355 | ```shell 356 | curl "https://api.bestbuy.com/v1/products(categoryPath.id=abcat0502000&driveCapacityGb!=*)?format=json&show=sku,name,salePrice&apiKey=YourAPIKey" 357 | ``` 358 | 359 | ```javascript 360 | var bby = require('bestbuy')('YourAPIKey'); 361 | bby.products('categoryPath.id=abcat0502000&driveCapacityGb!=*',{show:'sku,name,salePrice'}).then(function(data){ 362 | console.log(data); 363 | }); 364 | ``` 365 | 366 | ```json-doc 367 | { 368 | "from": 1, 369 | "to": 10, 370 | "total": 42, 371 | "currentPage": 1, 372 | "totalPages": 5, 373 | "queryTime": "0.007", 374 | "totalTime": "0.270", 375 | "partial": false, 376 | "canonicalUrl": "/v1/products(categoryPath.id=abcat0502000&driveCapacityGb!=*)?show=sku,name,salePrice&format=json&apiKey=YourAPIKey", 377 | "products": [ 378 | { 379 | "sku": 6941496, 380 | "name": "Apple® - MacBook Pro with Retina display - 13.3\" Display - 4GB Memory - 128GB Flash Storage", 381 | "salePrice": 1299.99 382 | }, 383 | { 384 | "sku": 6293168, 385 | "name": "Apple® - MacBook Pro with Retina display - 13.3\" Display - 8GB Memory - 256GB Flash Storage", 386 | "salePrice": 1499.99 387 | } 388 | ``` 389 | 390 | This will return results in which there is no value present. In the following example, with the addition of the !, the return result has shifted from Solid State Drive. 391 | 392 | 393 | ## Wildcards - String 394 | 395 | ```shell 396 | curl 'https://api.bestbuy.com/v1/products(longDescription=iPhone*|sku=7619002)?show=sku,name&pageSize=15&page=5&apiKey=YourAPIKey&format=json' 397 | ``` 398 | 399 | ```javascript 400 | var bby = require('bestbuy')('YourAPIKey'); 401 | bby.products('longDescription=iPhone*|sku=7619002',{show:'sku,name',pageSize:15,page:5}).then(function(data){ 402 | console.log(data); 403 | }); 404 | ``` 405 | 406 | ```json-doc 407 | { 408 | "from": 61, 409 | "to": 75, 410 | "total": 2753, 411 | "currentPage": 5, 412 | "totalPages": 184, 413 | "queryTime": "0.010", 414 | "totalTime": "0.045", 415 | "partial": false, 416 | "canonicalUrl": "/v1/products(longDescription=\"iPhone*\"|sku=7619002)?show=sku,name&page=5&format=json&apiKey=YourAPIKey", 417 | "products": [ 418 | { 419 | "sku": 1752654, 420 | "name": "Apple - iPhone 4s 8GB Cell Phone - White (AT&T)" 421 | }, 422 | { 423 | "sku": 1761045, 424 | "name": "Apple - iPhone 4s 8GB Cell Phone - White (Verizon Wireless)" 425 | }, 426 | { 427 | "sku": 1729354, 428 | "name": "Apple - iPhone 5c 16GB Cell Phone - Green (AT&T)" 429 | }, 430 | { 431 | "sku": 1752291, 432 | "name": "Apple - iPhone 5c 16GB Cell Phone - Blue (AT&T)" 433 | } 434 | ] 435 | } 436 | ``` 437 | 438 | When used as part of a string search, the wildcard performs two functions. First, it tokenizes the string, breaking it into words. Second, it operates as a standard wildcard, matching any set of characters in the tokenized string. The following example illustrates both functions. When searching for a string value, you may want to search for variations on a specific word. 439 | 440 | There are several description attributes by which you can search, including `longDescription`, `shortDescription`, `description` or `name`. There is a single `SKU` attribute to search based on `SKU`. 441 | 442 | In this example we are searching the `longDescription` for iPhone*. We have appended iPhone with a wildcard `*` so we can search for iPhones with any suffix. We are also looking for any products that have a SKU with a value of **7619002** - note the **or** `|`. Finally, in our example we have updated the number of results that can be returned per page to **15**. Our search will return page **5** of the total **184** pages. Additional information on how to specify the number of results that should be returned per page and which page to return can be found in our Pagination section. 443 | 444 | ## Wildcard - Limitations 445 | 446 | + You cannot use a wildcard to begin a string search (e.g. (name=*top)); this type of search is extremely resource intensive and doing so will result in a 400 error. 447 | + Wildcard with data is valid for strings only. When used alone, the wildcard can represent any data type. When used with other characters, the wildcard can only represent string data. For example, to find Canon products with customer reviews of 4.x, you cannot use (manufacturer=canon&customerReviewAverage=4.*) as the search string. You would have to use a search string like this: (manufacturer=canon&customerReviewAverage>4&customerReviewAverage<5). 448 | 449 | ## Filtered product attribute 450 | 451 | Certain attributes, such as `active=true`, `digital=false` or `preowned=false` inherently filter results. 452 | 453 | If your search string is `sku=*`, you will only return active products, not all products. This is the same as specifying `sku=*&active=true`. If you want a list of all active and inactive products, you can specify `sku=*&active=*`. 454 | 455 | Because `active` is a boolean attribute, `active=*` will return products for which `active` is either true or false. It's the same as `sku=*&(active=true|active=false)`. 456 | 457 | *If your search string goes to sku.xml or sku.json these filters are ignored.* 458 | 459 | 460 | ## Keyword Search Function 461 | 462 | ```shell 463 | curl "https://api.bestbuy.com/v1/products(search=oven&search=stainless&search=steel)?format=json&show=sku,name,salePrice&apiKey=YourAPIKey" 464 | ``` 465 | 466 | ```javascript 467 | var bby = require('bestbuy')('YourAPIKey'); 468 | bby.products('search=oven&search=stainless&search=steel',{show:'sku,name,salePrice'}).then(function(data){ 469 | console.log(data); 470 | }); 471 | ``` 472 | 473 | > This example looks for 'stainless steel ovens'. 474 | 475 | ```json-doc 476 | { 477 | "products": [ 478 | { 479 | "sku": 6916066, 480 | "name": "Amana - 30 Self-Cleaning Freestanding Electric Range - Stainless-Steel", 481 | "salePrice": 584.99 482 | }, 483 | { 484 | "sku": 2267329, 485 | "name": "Applica - 4-Slice Toaster Oven - Stainless Steel", 486 | "salePrice": 39.99 487 | } 488 | ``` 489 | 490 | *Applies to: Products API* 491 | 492 | Our **Keyword Search** function `(search=searchterm)` allows you to search text accross several common attributes. To search for a term that includes a space, include an `&` ampersand between the words or it will be treated as an `|` or. The **Keyword Search** includes the following attributes: 493 | 494 | + name 495 | + manufacturer 496 | + shortDescription 497 | + longDescription 498 | + features.feature 499 | + details.value 500 | 501 | ## Search on Reviews 502 | ```shell 503 | curl "https://api.bestbuy.com/v1/products(customerReviewAverage>=4&customerReviewCount>100)?show=customerReviewAverage,customerReviewCount,name,sku&format=json&apiKey=YourAPIKey" 504 | ``` 505 | ```javascript 506 | var bby = require('bestbuy')('YourAPIKey'); 507 | bby.products('customerReviewAverage>=4&customerReviewCount>100',{show:'customerReviewAverage,customerReviewCount,name,sku'}).then(function(data){ 508 | console.log(data); 509 | }); 510 | ``` 511 | ```json-doc 512 | { 513 | "products": [ 514 | { 515 | "customerReviewAverage": "4.1", 516 | "customerReviewCount": 411, 517 | "name": "Insignia™ - Soundbar Home Theater Speaker System", 518 | "sku": 4841342 519 | }, 520 | { 521 | "customerReviewAverage": "4.3", 522 | "customerReviewCount": 411, 523 | "name": "Sunpak - PlatinumPlus 6000PG 61\" Tripod", 524 | "sku": 1205204 525 | } 526 | ] 527 | } 528 | ``` 529 | 530 | To search for products based on customer review criteria, you can use the `customerReviewAverage` and/or the `customerReviewCount` attributes. You can also limit the product information returned using our `show` functionality. *HINT: You can specify additional attributes in your search or to be included in the response document for most attributes in the Products API.* 531 | 532 | In this example, we are searching for all products that have a customer review average greater than four and a customer review count greater than 100. In addition, we are limiting the product information returned to customer review average, customer review count, name and sku, and forcing a format of json (default is xml when using the Products API). 533 | -------------------------------------------------------------------------------- /source/includes/stores/_index.md.erb: -------------------------------------------------------------------------------- 1 | --- 2 | layout: documentation 3 | path: documentation/stores-api 4 | title: Stores API 5 | --- 6 | 7 | # Stores API 8 | ```shell 9 | curl "https://api.bestbuy.com/v1/stores?format=json&show=city,longName&pageSize=2&apiKey=YourAPIKey" 10 | ``` 11 | 12 | ```javascript 13 | var bby = require('bestbuy')('YourAPIKey'); 14 | bby.stores('',{show:'city,longName',pageSize:2}).then(function(data){ 15 | console.log(data); 16 | }); 17 | ``` 18 | 19 | > Returns the city and store name of 2 stores 20 | 21 | ```json-doc 22 | { 23 | "from": 1, 24 | "to": 2, 25 | "total": 1587, 26 | "currentPage": 1, 27 | "totalPages": 794, 28 | "stores": [ 29 | { 30 | "city": "San Juan", 31 | "longName": "Best Buy - Hato Rey" 32 | }, 33 | { 34 | "city": "Bayamon", 35 | "longName": "Best Buy - Rio Hondo Mall" 36 | } 37 | ] 38 | } 39 | ``` 40 | 41 | The Best Buy Stores API provides store information for all Best Buy stores in the United States and Puerto Rico. This information includes address, location, hours and services offered. 42 | 43 | In addition, store availability of a product can be determined by querying the Products API together with the Stores API. Refer to In Store Availability for more information on these type of queries. 44 | 45 |
    46 | 47 | ## Common Attributes 48 | 49 | ```shell 50 | curl "https://api.bestbuy.com/v1/stores(postalCode=55423)?format=json&show=storeId,storeType,name,city,region&apiKey=YourAPIKey" 51 | ``` 52 | 53 | ```javascript 54 | var bby = require('bestbuy')('YourAPIKey'); 55 | bby.stores('postalCode=55423', {show: 'storeId,storeType,name,city,region'}).then(function(data){ 56 | console.log(data); 57 | }); 58 | ``` 59 | 60 | > Returns all stores at the ZIP code 55423 (Richfield, MN) 61 | 62 | 63 | ```json-doc 64 | { 65 | "from": 1, 66 | "to": 2, 67 | "total": 2, 68 | "currentPage": 1, 69 | "totalPages": 1, 70 | "stores": [ 71 | { 72 | "storeId": 281, 73 | "storeType": "Big Box", 74 | "name": "Richfield", 75 | "city": "Richfield", 76 | "region": "MN" 77 | }, 78 | { 79 | "storeId": 8001, 80 | "storeType": "Express Kiosk", 81 | "name": "Best Buy HQ", 82 | "city": "Richfield", 83 | "region": "MN" 84 | } 85 | ] 86 | } 87 | ``` 88 | 89 | The Stores API enables you to retrieve the basic store information for all Best Buy stores, a specific Best Buy store or those stores that match a set of search parameters. 90 | 91 | Attribute | Description 92 | --------- | ----------- 93 | **address** | Street address 94 | **address2** | Street address 2 provides additional street address information for the Best Buy store in the result set 95 | **city** | City name 96 | **country** | Country name 97 | **distance** | Store distance from specified location in miles; attribute is not queryable; use with lat and long or postal code 98 | **fullPostalCode** | 9-digit postal code if available for store location 99 | **lat** | Latitude 100 | **lng** | Longitude 101 | **location** | Details about location of a store; primarily used for identifying Best Buy Express Kiosk stores 102 | **locationType** | Whether the location is a Store or a Warehouse 103 | **longName** | Full store name 104 | **name** | Store name 105 | **phone** | Store phone number; phone number for Express stores goes to Best Buy Customer Service 106 | **postalCode** | 5-digit postal code 107 | **region** | State, territory 108 | **storeId** | Store number 109 | **storeType** | Indicates the type of store, and is only present if locationType is 'Store'. There are five types of Best Buy stores: "Big Box", "Express Kiosk", "Warehouse Sale", "Outlet Center" and "PAC Standalone Store"
  • "Big Box" value represents large showroom stores featuring HDTVs, computers, gaming, appliances, cell phones, tablets, Geek Squad services and more
  • "Express Kiosk" value represents vending machine-style, self-checkout stores offering audio goods and accessories, found in airports, on college campuses and more
  • "Warehouse Sale" value represents occasional sale locations
  • "Outlet Center" value represents locations that sell open box and clearance products. Outlet Centers are open only a portion of the week
  • "PAC Standalone Store" value represents Pacific Sales locations not located within a Big Box store - these locations only sell the Pacific Sales selection of kitchen and bath products 110 | 111 | 112 | ##Area Function 113 | 114 | ```shell 115 | curl "https://api.bestbuy.com/v1/stores(area(55423,10))?format=json&show=storeId,storeType,name&pageSize=1&apiKey=YourAPIKey" 116 | ``` 117 | 118 | ```javascript 119 | var bby = require('bestbuy')('YourAPIKey'); 120 | bby.stores('area(55423,10)',{show:'storeId,storeType,name', pageSize: 1}).then(function(data){ 121 | console.log(data); 122 | }); 123 | ``` 124 | 125 | > Returns stores within 10 miles of ZIP code 55423 (Richfield, MN) 126 | 127 | ```json-doc 128 | { 129 | "from": 1, 130 | "to": 1, 131 | "total": 22, 132 | "currentPage": 1, 133 | "totalPages": 11, 134 | "stores": [ 135 | { 136 | "storeId": 281, 137 | "storeType": "Big Box", 138 | "name": "Richfield" 139 | } 140 | ] 141 | } 142 | ``` 143 | 144 | The Stores API includes a special function `area(location,distance)` enabling you to locate stores near a specified location. 145 | 146 | Use the `postalCode` attribute or a `lat`-`lng` pair to search based on a location. When postal code is used the reference point in the postal code (zipcode) area is determined by a standard mapping service. If no distance is specified in the function, radius is defaulted to 10 miles. The `location` will be populated with the distance from the specified postal code or lat/long to the store in miles. 147 | 148 | _Note_: _You may notice the stores returned are stated to be just over 10 miles from the ZIP code. This is due to the way return distance is calculated. The search area is defined as a square, bounded by location point +/- distance identified in request. All stores in that square are returned. Return distance is calculated linearly from the location point (creates a circle). Stores near the corner of the square might be listed as farther than the query distance specified._ 149 | 150 | 151 | ## Hours 152 | 153 | ```shell 154 | curl "https://api.bestbuy.com/v1/stores(storeId=1118)?format=json&show=hours,hoursAmPm,gmtOffset,detailedHours&apiKey=YourAPIKey" 155 | ``` 156 | 157 | ```javascript 158 | var bby = require('bestbuy')('YourAPIKey'); 159 | bby.stores('storeId=1118',{show:'hours,hoursAmPm,gmtOffset,detailedHours'}) 160 | .then(function(data){ 161 | // The util package is loaded to print the complete object structure 162 | console.log(require('util').inspect(data, false, null)); 163 | }); 164 | ``` 165 | 166 | > Shows all hours that store #1118 (San Juan, PR) is open 167 | 168 | ```json-doc 169 | { 170 | "from": 1, 171 | "to": 1, 172 | "total": 1, 173 | "currentPage": 1, 174 | "totalPages": 1, 175 | "stores": [ 176 | { 177 | "hours": "Mon: 10-9; Tue: 10-9; Wed: 10-9; Fri: 12:01-10; Sat: 9-10; Sun: 11-8", 178 | "hoursAmPm": "Mon: 10am-9pm; Tue: 10am-9pm; Wed: 10am-9pm; Fri: 12:01am-10pm; Sat: 9am-10pm; Sun: 11am-8pm", 179 | "gmtOffset": -5, 180 | "detailedHours": [ 181 | { 182 | "day": "Sunday", 183 | "date": "2015-11-22", 184 | "open": "11:00", 185 | "close": "20:00" 186 | }, 187 | { 188 | "day": "Monday", 189 | "date": "2015-11-23", 190 | "open": "10:00", 191 | "close": "21:00" 192 | } 193 | // Typically returns 14 days, truncating from documentation 194 | ] 195 | } 196 | ] 197 | } 198 | ``` 199 | 200 | The Hours attributes provide the days and times each Best Buy store is open for the following two weeks. We start our weeks on Sunday and provide hours in both a 12-hour and 24-hour clock. The times displayed are for the local time zones of the Best Buy store being returned. The Detailed Hours attributes provide the most accurate information of when stores will be opened or closed. This can be helpful during holidays as store hours may vary during this time. 201 | 202 | *Hint: Detailed hours are filtered out from the search results by default. Query with `show=all` or `show=detailedHours` to see in the search results.* 203 | 204 | Attribute | Description 205 | --------- | ----------- 206 | **detailedHours.day** | Days of the week store will be open 207 | **detailedHours.date** | Dates store will be open 208 | **detailedHours.open** | Time store will open (24-hour clock) 209 | **detailedHours.close** | Time store will close (24-hour clock) 210 | **gmtOffset** | Time difference from GMT 211 | **hours** | Regular Best Buy store hours Monday through Friday for the calendar year; displayed in local time zone 212 | **hoursAmPm** | Regular Best Buy store hours Monday through Friday for the calendar year with am and pm identifiers; displayed in local time zone 213 | 214 | 215 | 216 | ## Services Offered 217 | ```shell 218 | curl "https://api.bestbuy.com/v1/stores(storeId=1118)?format=json&show=services&apiKey=YourAPIKey" 219 | ``` 220 | ```javascript 221 | var bby = require('bestbuy')('YourAPIKey'); 222 | bby.stores('storeId=1118',{show:'services'}).then(function(data){ 223 | // The util package is loaded to print the complete object structure 224 | console.log(require('util').inspect(data, false, null)); 225 | }); 226 | ``` 227 | > Shows all services available at store #1118 (San Juan, PR) 228 | 229 | ```json-doc 230 | { 231 | "from": 1, 232 | "to": 1, 233 | "total": 1, 234 | "currentPage": 1, 235 | "totalPages": 1, 236 | "stores": [ 237 | { 238 | "services": [ 239 | { 240 | "service": "Windows Store" 241 | }, 242 | { 243 | "service": "Geek Squad Services" 244 | }, 245 | { 246 | "service": "Best Buy Mobile" 247 | }, 248 | { 249 | "service": "Best Buy For Business" 250 | }, 251 | { 252 | "service": "Apple Shop" 253 | }, 254 | { 255 | "service": "Electronics Recycling" 256 | }, 257 | { 258 | "service": "Best Buy Marine Powered by Geek Squad" 259 | }, 260 | { 261 | "service": "Samsung Experience" 262 | }, 263 | { 264 | "service": "LG Experience" 265 | }, 266 | { 267 | "service": "Trade-In" 268 | }, 269 | { 270 | "service": "Car & GPS Installation Services" 271 | } 272 | ] 273 | } 274 | ] 275 | } 276 | ``` 277 | 278 | The Stores API includes information related to the services offered at each of the Best Buy stores. `services` is a collection of different services offered at a specified store. 279 | 280 | Attribute | Description 281 | --------- | ----------- 282 | **services.service** | Collection of services offered at each Best Buy store 283 | 284 | 285 | 286 | ## In-Store Availability 287 | 288 | ```shell 289 | curl "https://api.bestbuy.com/v1/products/4807511/stores.json?postalCode=55423&apiKey=YourAPIKey" 290 | ``` 291 | > Shows stores near 55423 (Richfield, MN) that carry SKU 4807511 (Insignia LED-TV) 292 | 293 | ```json-doc 294 | 295 | { 296 | "ispuEligible": true, 297 | "stores": [ 298 | { 299 | "storeID": "10", 300 | "name": "Maplewood", 301 | "address": "1795 County Rd D E", 302 | "city": "Maplewood", 303 | "state": "MN", 304 | "postalCode": "55109", 305 | "storeType": "Big_Box_Store", 306 | "minPickupHours": null, 307 | "lowStock": false, 308 | "distance": 16.594 309 | }, 310 | ] 311 | } 312 | ``` 313 | 314 | The Stores API, in conjunction with the Products API, allows you to search stores for a product and identify if it is available. In-store availability searches will return only those stores that have a given product in stock. Stores not returned do not have that product in stock. You can get near real time availability for specific SKUs based on either a store ID or postal code search. 315 | 316 | ###SKU Specific Availability 317 | 318 | You can look up near real time store availability for single SKUs. You may search either on `postalCode` or based on `storeId`. Results for `postalCode` queries will include all stores within a 250 mile radius, sorted by proximity. 319 | 320 | _HINT: The Products API attribute `inStoreAvailability` will tell you if a product is sold in stores but not if it's available at a particular store. Using the In-Store availability queries is equivalent to checking product availability in store._ 321 | 322 | Attribute | Description 323 | --------- | ----------- 324 | **stores.storeID** | The unique ID of the store 325 | **stores.name** | The store name 326 | **stores.address** | The street address of the store 327 | **stores.city** | The city in which the store is located 328 | **stores.postalCode** | The postal code in which the store is located 329 | **stores.storeType** | The type of store 330 | **stores.minPickupHours** | The minimum number of hours that must pass after placing a store pick up order before the item will be available for pick up. 331 | **stores.lowStock** | Whether or not the product availability at this store is low and may soon shift to out of stock. 332 | **stores.distance** | The store's distance (in miles) from the given postalCode 333 | 334 | -------------------------------------------------------------------------------- /source/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Best Buy Developer API Documentation 3 | 4 | language_tabs: 5 | - shell 6 | - javascript 7 | 8 | toc_footers: 9 | - Sign up for a Best Buy API Key 10 | - Contribute to Documentation 11 | - Powered by Slate 12 | - Run in Postman 13 | 14 | includes: 15 | - overview 16 | - gettingstarted 17 | - search 18 | - products 19 | - openbox 20 | - categories 21 | - recommendations 22 | - stores 23 | - commerce 24 | search: true 25 | --- 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /source/javascripts/all.js: -------------------------------------------------------------------------------- 1 | //= require ./lib/_energize 2 | //= require ./app/_lang 3 | //= require ./app/_search 4 | //= require ./app/_toc 5 | //= require ./app/_replaceText -------------------------------------------------------------------------------- /source/javascripts/all_nosearch.js: -------------------------------------------------------------------------------- 1 | //= require ./lib/_energize 2 | //= require ./app/_lang 3 | //= require ./app/_toc 4 | -------------------------------------------------------------------------------- /source/javascripts/app/_lang.js: -------------------------------------------------------------------------------- 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 | (function (global) { 17 | 'use strict'; 18 | 19 | var languages = []; 20 | 21 | global.setupLanguages = setupLanguages; 22 | global.activateLanguage = activateLanguage; 23 | 24 | function activateLanguage(language) { 25 | if (!language) return; 26 | if (language === "") return; 27 | 28 | $(".lang-selector a").removeClass('active'); 29 | $(".lang-selector a[data-language-name='" + language + "']").addClass('active'); 30 | for (var i=0; i < languages.length; i++) { 31 | $(".highlight." + languages[i]).hide(); 32 | } 33 | $(".highlight." + language).show(); 34 | 35 | global.toc.calculateHeights(); 36 | 37 | // scroll to the new location of the position 38 | if ($(window.location.hash).get(0)) { 39 | $(window.location.hash).get(0).scrollIntoView(true); 40 | } 41 | } 42 | 43 | // parseURL and stringifyURL are from https://github.com/sindresorhus/query-string 44 | // MIT licensed 45 | // https://github.com/sindresorhus/query-string/blob/7bee64c16f2da1a326579e96977b9227bf6da9e6/license 46 | function parseURL(str) { 47 | if (typeof str !== 'string') { 48 | return {}; 49 | } 50 | 51 | str = str.trim().replace(/^(\?|#|&)/, ''); 52 | 53 | if (!str) { 54 | return {}; 55 | } 56 | 57 | return str.split('&').reduce(function (ret, param) { 58 | var parts = param.replace(/\+/g, ' ').split('='); 59 | var key = parts[0]; 60 | var val = parts[1]; 61 | 62 | key = decodeURIComponent(key); 63 | // missing `=` should be `null`: 64 | // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 65 | val = val === undefined ? null : decodeURIComponent(val); 66 | 67 | if (!ret.hasOwnProperty(key)) { 68 | ret[key] = val; 69 | } else if (Array.isArray(ret[key])) { 70 | ret[key].push(val); 71 | } else { 72 | ret[key] = [ret[key], val]; 73 | } 74 | 75 | return ret; 76 | }, {}); 77 | }; 78 | 79 | function stringifyURL(obj) { 80 | return obj ? Object.keys(obj).sort().map(function (key) { 81 | var val = obj[key]; 82 | 83 | if (Array.isArray(val)) { 84 | return val.sort().map(function (val2) { 85 | return encodeURIComponent(key) + '=' + encodeURIComponent(val2); 86 | }).join('&'); 87 | } 88 | 89 | return encodeURIComponent(key) + '=' + encodeURIComponent(val); 90 | }).join('&') : ''; 91 | }; 92 | 93 | // gets the language set in the query string 94 | function getLanguageFromQueryString() { 95 | if (location.search.length >= 1) { 96 | var language = parseURL(location.search).language 97 | if (language) { 98 | return language; 99 | } else if (jQuery.inArray(location.search.substr(1), languages) != -1) { 100 | return location.search.substr(1); 101 | } 102 | } 103 | 104 | return false; 105 | } 106 | 107 | // returns a new query string with the new language in it 108 | function generateNewQueryString(language) { 109 | var url = parseURL(location.search); 110 | if (url.language) { 111 | url.language = language; 112 | return stringifyURL(url); 113 | } 114 | return language; 115 | } 116 | 117 | // if a button is clicked, add the state to the history 118 | function pushURL(language) { 119 | if (!history) { return; } 120 | var hash = window.location.hash; 121 | if (hash) { 122 | hash = hash.replace(/^#+/, ''); 123 | } 124 | history.pushState({}, '', '?' + generateNewQueryString(language) + '#' + hash); 125 | 126 | // save language as next default 127 | localStorage.setItem("language", language); 128 | } 129 | 130 | function setupLanguages(l) { 131 | var defaultLanguage = localStorage.getItem("language"); 132 | 133 | languages = l; 134 | 135 | var presetLanguage = getLanguageFromQueryString(); 136 | if (presetLanguage) { 137 | // the language is in the URL, so use that language! 138 | activateLanguage(presetLanguage); 139 | 140 | localStorage.setItem("language", presetLanguage); 141 | } else if ((defaultLanguage !== null) && (jQuery.inArray(defaultLanguage, languages) != -1)) { 142 | // the language was the last selected one saved in localstorage, so use that language! 143 | activateLanguage(defaultLanguage); 144 | } else { 145 | // no language selected, so use the default 146 | activateLanguage(languages[0]); 147 | } 148 | } 149 | 150 | // if we click on a language tab, activate that language 151 | $(function() { 152 | $(".lang-selector a").on("click", function() { 153 | var language = $(this).data("language-name"); 154 | pushURL(language); 155 | activateLanguage(language); 156 | return false; 157 | }); 158 | window.onpopstate = function() { 159 | activateLanguage(getLanguageFromQueryString()); 160 | }; 161 | }); 162 | })(window); 163 | -------------------------------------------------------------------------------- /source/javascripts/app/_replaceText.js: -------------------------------------------------------------------------------- 1 | // Loops through all the rendered code blocks and swaps them for the user's actual key. 2 | // Keeps track of the currently used key to permit swapping back-and-forth 3 | $(document).ready(function () { 4 | 'use strict'; 5 | var oldKey = 'YourAPIKey'; 6 | var targetedElements = 'pre.highlight code span.s1, pre.highlight code span.s2, code.prettyprint'; 7 | 8 | $('input.key-replace').on('keyup', function(e){ 9 | if (e.keyCode == 13) { 10 | $(this).blur(); 11 | } 12 | }); 13 | $('input.key-replace').on('blur', function(){ 14 | var newKey = $(this).val(); 15 | // We have a special exception so that if people empty the field, it reverts to the first value 16 | if (newKey.length > 0) { 17 | if (newKey.length < 12 || !/^\w+$/.test(newKey)) { 18 | alert('Best Buy API keys are at least 12 characters long, and only contain letters & numbers'); 19 | $('input.key-replace').focus(); 20 | return false; 21 | } 22 | } else { 23 | newKey = 'YourAPIKey'; 24 | } 25 | var oldKeyMatch = new RegExp(oldKey, 'g'); 26 | $(targetedElements).each(function () { 27 | $(this).text($(this).text().replace(oldKeyMatch, newKey)); 28 | }); 29 | oldKey = newKey; 30 | }); 31 | }); -------------------------------------------------------------------------------- /source/javascripts/app/_search.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_lunr 2 | //= require ../lib/_jquery.highlight 3 | (function () { 4 | 'use strict'; 5 | 6 | var content, searchResults; 7 | var highlightOpts = { element: 'span', className: 'search-highlight' }; 8 | 9 | var index = new lunr.Index(); 10 | 11 | index.ref('id'); 12 | index.field('title', { boost: 10 }); 13 | index.field('body'); 14 | index.pipeline.add(lunr.trimmer, lunr.stopWordFilter); 15 | 16 | $(populate); 17 | $(bind); 18 | 19 | function populate() { 20 | $('h1, h2').each(function() { 21 | var title = $(this); 22 | var body = title.nextUntil('h1, h2'); 23 | index.add({ 24 | id: title.prop('id'), 25 | title: title.text(), 26 | body: body.text() 27 | }); 28 | }); 29 | } 30 | 31 | function bind() { 32 | content = $('.content'); 33 | searchResults = $('.search-results'); 34 | 35 | $('#input-search').on('keyup', search); 36 | } 37 | 38 | function search(event) { 39 | unhighlight(); 40 | searchResults.addClass('visible'); 41 | 42 | // ESC clears the field 43 | if (event.keyCode === 27) this.value = ''; 44 | 45 | if (this.value) { 46 | var results = index.search(this.value).filter(function(r) { 47 | return r.score > 0.0001; 48 | }); 49 | 50 | if (results.length) { 51 | searchResults.empty(); 52 | $.each(results, function (index, result) { 53 | var elem = document.getElementById(result.ref); 54 | searchResults.append("
  • " + $(elem).text() + "
  • "); 55 | }); 56 | highlight.call(this); 57 | } else { 58 | searchResults.html('
  • '); 59 | $('.search-results li').text('No Results Found for "' + this.value + '"'); 60 | } 61 | } else { 62 | unhighlight(); 63 | searchResults.removeClass('visible'); 64 | } 65 | } 66 | 67 | function highlight() { 68 | if (this.value) content.highlight(this.value, highlightOpts); 69 | } 70 | 71 | function unhighlight() { 72 | content.unhighlight(highlightOpts); 73 | } 74 | })(); 75 | -------------------------------------------------------------------------------- /source/javascripts/app/_toc.js: -------------------------------------------------------------------------------- 1 | //= require ../lib/_jquery_ui 2 | //= require ../lib/_jquery.tocify 3 | //= require ../lib/_imagesloaded.min 4 | (function (global) { 5 | 'use strict'; 6 | 7 | var closeToc = function() { 8 | $(".tocify-wrapper").removeClass('open'); 9 | $("#nav-button").removeClass('open'); 10 | }; 11 | 12 | var makeToc = function() { 13 | global.toc = $("#toc").tocify({ 14 | selectors: 'h1, h2', 15 | extendPage: false, 16 | theme: 'none', 17 | smoothScroll: false, 18 | showEffectSpeed: 0, 19 | hideEffectSpeed: 180, 20 | ignoreSelector: '.toc-ignore', 21 | highlightOffset: 60, 22 | scrollTo: -1, 23 | scrollHistory: true, 24 | hashGenerator: function (text, element) { 25 | return element.prop('id'); 26 | } 27 | }).data('toc-tocify'); 28 | 29 | $("#nav-button").click(function() { 30 | $(".tocify-wrapper").toggleClass('open'); 31 | $("#nav-button").toggleClass('open'); 32 | return false; 33 | }); 34 | 35 | $(".page-wrapper").click(closeToc); 36 | $(".tocify-item").click(closeToc); 37 | }; 38 | 39 | // Hack to make already open sections to start opened, 40 | // instead of displaying an ugly animation 41 | function animate() { 42 | setTimeout(function() { 43 | toc.setOption('showEffectSpeed', 180); 44 | }, 50); 45 | } 46 | 47 | $(function() { 48 | makeToc(); 49 | animate(); 50 | $('.content').imagesLoaded( function() { 51 | global.toc.calculateHeights(); 52 | }); 53 | }); 54 | })(window); 55 | 56 | -------------------------------------------------------------------------------- /source/javascripts/fakeloader.js: -------------------------------------------------------------------------------- 1 | // 2 | // Fake Loader 3 | // 4 | window.FakeLoader = (function($, window, document) { 5 | 6 | var settings = { 7 | auto_hide: true, 8 | overlay_id: 'fakeloader-overlay', 9 | fade_timeout: 200, 10 | wait_for_images: true, 11 | wait_for_images_selector: 'body' 12 | } 13 | 14 | var $overlay = null; 15 | 16 | var fakeLoader = { 17 | 18 | hideOverlay: function() { 19 | $overlay.removeClass('visible'); 20 | 21 | window.setTimeout( 22 | function() { 23 | $overlay.addClass('hidden'); 24 | }, 25 | settings.fade_timeout 26 | ); 27 | }, 28 | 29 | showOverlay: function() { 30 | $overlay.removeClass('hidden').addClass('visible'); 31 | }, 32 | 33 | init: function( given_settings ) { 34 | 35 | $.extend( settings, given_settings ); 36 | 37 | if ( $('#' + settings.overlay_id).length <= 0 ) { 38 | $overlay = $('
    '); 39 | $('body').append($overlay); 40 | 41 | if (typeof(console) !== 'undefined' && typeof(console.log) !== 'undefined') { 42 | console.log( "You should put the fakeLoader loading overlay element in your markup directly for best results." ); 43 | } 44 | } 45 | else { 46 | $overlay = $('#' + settings.overlay_id); 47 | } 48 | 49 | $overlay.click( 50 | function() { 51 | fakeLoader.hideOverlay(); 52 | } 53 | ); 54 | 55 | $(window).bind('beforeunload', function() { 56 | 57 | $('#' + settings.overlay_id).removeClass('incoming').addClass('outgoing'); 58 | fakeLoader.showOverlay(); 59 | 60 | }); 61 | 62 | $(document).ready( 63 | function() { 64 | if ( settings.auto_hide == true ) { 65 | if ( typeof($.fn.waitForImages) == 'function' && settings.wait_for_images == true) { 66 | $(settings.wait_for_images_selector).waitForImages( 67 | function() { 68 | fakeLoader.hideOverlay(); 69 | } 70 | ) 71 | 72 | } 73 | else { 74 | fakeLoader.hideOverlay(); 75 | } 76 | } 77 | } 78 | ); 79 | 80 | } 81 | 82 | } 83 | 84 | return fakeLoader; 85 | 86 | })(jQuery, window, document); -------------------------------------------------------------------------------- /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 | 18 | 19 | 20 | 21 | 22 | 23 | <%= current_page.data.title || "API Documentation" %> 24 | 25 | <%= stylesheet_link_tag :screen, media: :screen %> 26 | <%= stylesheet_link_tag :print, media: :print %> 27 | 28 | 29 | 30 | 31 | <% if current_page.data.search %> 32 | <%= javascript_include_tag "all" %> 33 | <% else %> 34 | <%= javascript_include_tag "all_nosearch" %> 35 | <% end %> 36 | 37 | 50 | 51 | <% if language_tabs %> 52 | 62 | <% end %> 63 | 64 | 65 | 66 |
    67 | 68 | 69 | NAV 70 | <%= image_tag('navbar.png') %> 71 | 72 | 73 |
    74 | 77 | <% if language_tabs %> 78 |
    79 | <% language_tabs.each do |lang| %> 80 | <% if lang.is_a? Hash %> 81 | <%= lang.values.first %> 82 | <% else %> 83 | <%= lang %> 84 | <% end %> 85 | <% end %> 86 |
    87 | <% end %> 88 |
    89 | 90 |
    91 | <% if current_page.data.search %> 92 | 95 |
      96 | <% end %> 97 |
      98 |
      99 | <% if current_page.data.toc_footers %> 100 | 105 | <% end %> 106 |
      107 |
      108 |
      109 |
      110 | <%= yield %> 111 | <% current_page.data.includes && current_page.data.includes.each do |include| %> 112 | <%= partial "includes/#{include}/index" %> 113 | <% end %> 114 |
      115 |
      116 | <% if language_tabs %> 117 |
      118 | <% language_tabs.each do |lang| %> 119 | <% if lang.is_a? Hash %> 120 | <%= lang.values.first %> 121 | <% else %> 122 | <%= lang %> 123 | <% end %> 124 | <% end %> 125 |
      126 | <% end %> 127 |
      128 |
      129 | 130 | 131 | -------------------------------------------------------------------------------- /source/stylesheets/_bby-custom.scss: -------------------------------------------------------------------------------- 1 | //We assume the only things in tables will be attribute lists, and the only thing in bold 2 | //will be attributes. This gives all the attributes the feeling of being "code", within 3 | //having as heavy a presentation as the literal syntax 4 | table tbody td strong { 5 | font-family: monospace; 6 | } 7 | -------------------------------------------------------------------------------- /source/stylesheets/_icon-font.scss: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'slate'; 3 | src:font-url('slate.eot?qw5n1z'); 4 | src:font-url('slate.eot?qw5n1z#iefix') format('embedded-opentype'), 5 | font-url('slate.ttf?qw5n1z') format('truetype'), 6 | font-url('slate.woff?qw5n1z') format('woff'), 7 | font-url('slate.svg?qw5n1z#slate') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | %icon { 13 | font-family: 'slate' !important; 14 | speak: none; 15 | font-style: normal; 16 | font-weight: normal; 17 | font-variant: normal; 18 | text-transform: none; 19 | line-height: 1; 20 | 21 | /* Better Font Rendering =========== */ 22 | -webkit-font-smoothing: antialiased; 23 | -moz-osx-font-smoothing: grayscale; 24 | } 25 | 26 | %icon-key { 27 | @extend %icon; 28 | content: "\f084"; 29 | } 30 | %icon-exclamation-sign { 31 | @extend %icon; 32 | content: "\e600"; 33 | } 34 | %icon-info-sign { 35 | @extend %icon; 36 | content: "\e602"; 37 | } 38 | %icon-ok-sign { 39 | @extend %icon; 40 | content: "\e606"; 41 | } 42 | %icon-search { 43 | @extend %icon; 44 | content: "\e607"; 45 | } 46 | -------------------------------------------------------------------------------- /source/stylesheets/_normalize.css: -------------------------------------------------------------------------------- 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/_syntax.scss.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 | 17 | @import 'variables'; 18 | 19 | <%= Rouge::Themes::Base16::Monokai.render(:scope => '.highlight') %> 20 | 21 | .highlight .c, .highlight .cm, .highlight .c1, .highlight .cs { 22 | color: #909090; 23 | } 24 | 25 | .highlight, .highlight .w { 26 | background-color: $code-bg; 27 | } -------------------------------------------------------------------------------- /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 | // BBY COLORS 25 | //////////////////// 26 | $bby-blue: #053f68; 27 | $highlight: #a9e0ea; 28 | 29 | 30 | 31 | // BACKGROUND COLORS 32 | //////////////////// 33 | $nav-bg: $bby-blue; 34 | $examples-bg: #393939; 35 | $code-bg: #292929; 36 | $code-annotation-bg: #1c1c1c; 37 | $nav-subitem-bg: #262626; 38 | $nav-active-bg: #393939; 39 | $lang-select-border: #000; 40 | $lang-select-bg: #222; 41 | $lang-select-active-bg: #053f68; // feel free to change this to blue or something 42 | $lang-select-pressed-bg: #111; // color of language tab bg when mouse is pressed 43 | $main-bg: #fff; 44 | $aside-notice-bg: #8fbcd4; 45 | $aside-warning-bg: #c97a7e; 46 | $aside-success-bg: #6ac174; 47 | $search-notice-bg: #c97a7e; 48 | 49 | 50 | // TEXT COLORS 51 | //////////////////// 52 | $main-text: #49494a; // main content text color 53 | $nav-text: #fff; 54 | $nav-active-text: #fff; 55 | $lang-select-text: #fff; // color of unselected language tab text 56 | $lang-select-active-text: #fff; // color of selected language tab text 57 | $lang-select-pressed-text: #fff; // color of language tab text when mouse is pressed 58 | 59 | 60 | // SIZES 61 | //////////////////// 62 | $nav-width: 230px; // width of the navbar 63 | $examples-width: 50%; // portion of the screen taken up by code examples 64 | $logo-margin: 20px; // margin between nav items and logo, ignored if search is active 65 | $main-padding: 28px; // padding to left and right of content & examples 66 | $nav-padding: 15px; // padding to left and right of navbar 67 | $nav-v-padding: 10px; // padding used vertically around search boxes and results 68 | $nav-indent: 10px; // extra padding for ToC subitems 69 | $code-annotation-padding: 13px; // padding inside code annotations 70 | $h1-margin-bottom: 21px; // padding under the largest header tags 71 | $tablet-width: 930px; // min width before reverting to tablet size 72 | $phone-width: $tablet-width - $nav-width; // min width before reverting to mobile size 73 | 74 | 75 | // FONTS 76 | //////////////////// 77 | %default-font { 78 | font-family: "Avenir Next", "Avenir", "Proxima Nova", "proxima-nova", "Helvetica Neue", Helvetica, Arial, sans-serif; 79 | 80 | font-size: 14px; 81 | } 82 | 83 | %header-font { 84 | @extend %default-font; 85 | font-weight: bold; 86 | } 87 | 88 | %code-font { 89 | font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, serif; 90 | font-size: 12px; 91 | line-height: 1.5; 92 | } 93 | 94 | 95 | // OTHER 96 | //////////////////// 97 | $nav-active-shadow: #333333; 98 | $nav-footer-border-color: #666; 99 | $nav-embossed-border-top: #000; 100 | $nav-embossed-border-bottom: #939393; 101 | $main-embossed-text-shadow: 0px 1px 0px #fff; 102 | $search-box-border-color: #666; 103 | 104 | 105 | //////////////////////////////////////////////////////////////////////////////// 106 | // INTERNAL 107 | //////////////////////////////////////////////////////////////////////////////// 108 | // These settings are probably best left alone. 109 | 110 | %break-words { 111 | word-break: break-all; 112 | /* Non standard for webkit */ 113 | word-break: break-word; 114 | } 115 | -------------------------------------------------------------------------------- /source/stylesheets/fakeloader.css: -------------------------------------------------------------------------------- 1 | #fakeloader-overlay { 2 | opacity: 0; 3 | top: 0px; 4 | left: 0px; 5 | position: fixed; 6 | background-color: rgba(0, 59, 100, 0.8); 7 | height: 100%; 8 | width: 100%; 9 | z-index: 9998; 10 | -webkit-transition: opacity 0.2s linear; 11 | -moz-transition: opacity 0.2s linear; 12 | transition: opacity 0.2s linear; 13 | } 14 | 15 | #fakeloader-overlay.visible { 16 | opacity: 1; 17 | } 18 | 19 | #fakeloader-overlay.hidden { 20 | opacity: 0; 21 | height: 0px; 22 | width: 0px; 23 | z-index: -10000; 24 | } 25 | 26 | #fakeloader-overlay .loader-wrapper-outer { 27 | background-color: transparent; 28 | z-index: 9999; 29 | margin: auto; 30 | width: 100%; 31 | height: 100%; 32 | overflow: hidden; 33 | display: table; 34 | text-align: center; 35 | vertical-align: middle; 36 | } 37 | 38 | #fakeloader-overlay .loader-wrapper-inner { 39 | display: table-cell; 40 | vertical-align: middle; 41 | } 42 | 43 | #fakeloader-overlay .loader { 44 | margin: auto; 45 | font-size: 10px; 46 | position: relative; 47 | text-indent: -9999em; 48 | border-top: 8px solid rgba(255, 255, 255, 0.5); 49 | border-right: 8px solid rgba(255, 255, 255, 0.5); 50 | border-bottom: 8px solid rgba(255, 255, 255, 0.5); 51 | border-left: 8px solid #AAA; 52 | -webkit-transform: translateZ(0); 53 | -ms-transform: translateZ(0); 54 | transform: translateZ(0); 55 | -webkit-animation: fakeloader 1.1s infinite linear; 56 | animation: fakeloader 1.1s infinite linear; 57 | } 58 | 59 | #fakeloader-overlay .loader, #fakeloader-overlay .loader:after { 60 | 61 | border-radius: 50%; 62 | width: 50px; 63 | height: 50px; 64 | } 65 | 66 | @-webkit-keyframes fakeloader { 67 | 0% { 68 | -webkit-transform: rotate(0deg); 69 | transform: rotate(0deg); 70 | } 71 | 72 | 100% { 73 | -webkit-transform: rotate(360deg); 74 | transform: rotate(360deg); 75 | } 76 | } 77 | 78 | @keyframes fakeloader { 79 | 0% { 80 | -webkit-transform: rotate(0deg); 81 | transform: rotate(0deg); 82 | } 83 | 84 | 100% { 85 | -webkit-transform: rotate(360deg); 86 | transform: rotate(360deg); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /source/stylesheets/print.css.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | @import 'normalize'; 3 | @import 'compass'; 4 | @import 'variables'; 5 | @import 'icon-font'; 6 | @import 'bby-custom'; 7 | 8 | /* 9 | Copyright 2008-2013 Concur Technologies, Inc. 10 | 11 | Licensed under the Apache License, Version 2.0 (the "License"); you may 12 | not use this file except in compliance with the License. You may obtain 13 | a copy of the License at 14 | 15 | http://www.apache.org/licenses/LICENSE-2.0 16 | 17 | Unless required by applicable law or agreed to in writing, software 18 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 19 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 20 | License for the specific language governing permissions and limitations 21 | under the License. 22 | */ 23 | 24 | $print-color: #999; 25 | $print-color-light: #ccc; 26 | $print-font-size: 12px; 27 | 28 | body { 29 | @extend %default-font; 30 | } 31 | 32 | .tocify, .toc-footer, .lang-selector, .search, .key-replace, #nav-button { 33 | display: none; 34 | } 35 | 36 | .tocify-wrapper>img { 37 | margin: 0 auto; 38 | display: block; 39 | } 40 | 41 | .content { 42 | font-size: 12px; 43 | 44 | pre, code { 45 | @extend %code-font; 46 | @extend %break-words; 47 | border: 1px solid $print-color; 48 | border-radius: 5px; 49 | font-size: 0.8em; 50 | } 51 | 52 | pre { 53 | padding: 1.3em; 54 | } 55 | 56 | code { 57 | padding: 0.2em; 58 | } 59 | 60 | table { 61 | border: 1px solid $print-color; 62 | tr { 63 | border-bottom: 1px solid $print-color; 64 | } 65 | td,th { 66 | padding: 0.7em; 67 | } 68 | } 69 | 70 | p { 71 | line-height: 1.5; 72 | } 73 | 74 | a { 75 | text-decoration: none; 76 | color: #000; 77 | } 78 | 79 | h1 { 80 | @extend %header-font; 81 | font-size: 2.5em; 82 | padding-top: 0.5em; 83 | padding-bottom: 0.5em; 84 | margin-top: 1em; 85 | margin-bottom: $h1-margin-bottom; 86 | border: 2px solid $print-color-light; 87 | border-width: 2px 0; 88 | text-align: center; 89 | } 90 | 91 | h2 { 92 | @extend %header-font; 93 | font-size: 1.8em; 94 | margin-top: 2em; 95 | border-top: 2px solid $print-color-light; 96 | padding-top: 0.8em; 97 | } 98 | 99 | h1+h2, h1+div+h2 { 100 | border-top: none; 101 | padding-top: 0; 102 | margin-top: 0; 103 | } 104 | 105 | h3, h4 { 106 | @extend %header-font; 107 | font-size: 0.8em; 108 | margin-top: 1.5em; 109 | margin-bottom: 0.8em; 110 | text-transform: uppercase; 111 | } 112 | 113 | h5, h6 { 114 | text-transform: uppercase; 115 | } 116 | 117 | aside { 118 | padding: 1em; 119 | border: 1px solid $print-color-light; 120 | border-radius: 5px; 121 | margin-top: 1.5em; 122 | margin-bottom: 1.5em; 123 | line-height: 1.6; 124 | } 125 | 126 | aside:before { 127 | vertical-align: middle; 128 | padding-right: 0.5em; 129 | font-size: 14px; 130 | } 131 | 132 | aside.notice:before { 133 | @extend %icon-info-sign; 134 | } 135 | 136 | aside.warning:before { 137 | @extend %icon-exclamation-sign; 138 | } 139 | 140 | aside.success:before { 141 | @extend %icon-ok-sign; 142 | } 143 | } -------------------------------------------------------------------------------- /source/stylesheets/screen.css.scss: -------------------------------------------------------------------------------- 1 | @charset "utf-8"; 2 | @import 'normalize'; 3 | @import 'compass'; 4 | @import 'variables'; 5 | @import 'syntax'; 6 | @import 'icon-font'; 7 | @import 'bby-custom'; 8 | 9 | /* 10 | Copyright 2008-2013 Concur Technologies, Inc. 11 | 12 | Licensed under the Apache License, Version 2.0 (the "License"); you may 13 | not use this file except in compliance with the License. You may obtain 14 | a copy of the License at 15 | 16 | http://www.apache.org/licenses/LICENSE-2.0 17 | 18 | Unless required by applicable law or agreed to in writing, software 19 | distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 20 | WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the 21 | License for the specific language governing permissions and limitations 22 | under the License. 23 | */ 24 | 25 | //////////////////////////////////////////////////////////////////////////////// 26 | // GENERAL STUFF 27 | //////////////////////////////////////////////////////////////////////////////// 28 | 29 | html, body { 30 | color: $main-text; 31 | padding: 0; 32 | margin: 0; 33 | -webkit-font-smoothing: antialiased; 34 | -moz-osx-font-smoothing: grayscale; 35 | @extend %default-font; 36 | background-color: $main-bg; 37 | height: 100%; 38 | -webkit-text-size-adjust: none; /* Never autoresize text */ 39 | } 40 | 41 | .inline-link:link { 42 | color: #003b64; 43 | text-decoration: none; 44 | } 45 | 46 | .inline-link:visited { 47 | color: #003b64; 48 | text-decoration: none; 49 | } 50 | 51 | .inline-link:hover { 52 | color: #1646a8; 53 | text-decoration: underline; 54 | } 55 | 56 | .inline-link:active { 57 | color: #003b64; 58 | text-decoration: none; 59 | } 60 | 61 | //////////////////////////////////////////////////////////////////////////////// 62 | // TABLE OF CONTENTS 63 | //////////////////////////////////////////////////////////////////////////////// 64 | 65 | #toc > ul > li > a > span { 66 | float: right; 67 | background-color: #2484FF; 68 | border-radius: 40px; 69 | width: 20px; 70 | } 71 | 72 | @mixin embossed-bg { 73 | background: 74 | linear-gradient(to bottom, rgba(#000, 0.2), rgba(#000, 0) 8px), 75 | linear-gradient(to top, rgba(#000, 0.2), rgba(#000, 0) 8px), 76 | linear-gradient(to bottom, rgba($nav-embossed-border-top, 1), rgba($nav-embossed-border-top, 0) 1.5px), 77 | linear-gradient(to top, rgba($nav-embossed-border-bottom, 1), rgba($nav-embossed-border-bottom, 0) 1.5px), 78 | $nav-subitem-bg; 79 | } 80 | 81 | .logo-holder { 82 | moz-box-sizing: border-box; 83 | box-sizing: border-box; 84 | padding: 15px 15px 15px 15px; 85 | } 86 | 87 | 88 | .tocify-wrapper { 89 | transition: left 0.3s ease-in-out; 90 | overflow-y: auto; 91 | overflow-x: hidden; 92 | position: fixed; 93 | z-index: 30; 94 | top: 0; 95 | left: 0; 96 | bottom: 0; 97 | width: $nav-width; 98 | background-color: $nav-bg; 99 | font-size: 13px; 100 | font-weight: bold; 101 | 102 | // language selector for mobile devices 103 | .lang-selector { 104 | display: none; 105 | a { 106 | padding-top: 0.5em; 107 | padding-bottom: 0.5em; 108 | } 109 | } 110 | 111 | 112 | 113 | // This is the logo at the top of the ToC 114 | &>.logo-holder img { 115 | display: block; 116 | margin: 0 auto; 117 | max-width: 100%; 118 | } 119 | 120 | &>.search, &>.key-replace { 121 | position: relative; 122 | 123 | input { 124 | background: $nav-bg; 125 | border-width: 0 0 1px 0; 126 | border-color: $search-box-border-color; 127 | padding: 6px 0 6px 20px; 128 | box-sizing: border-box; 129 | margin: $nav-v-padding $nav-padding; 130 | width: $nav-width - 30; 131 | outline: none; 132 | color: $nav-text; 133 | border-radius: 0; /* ios has a default border radius */ 134 | } 135 | 136 | &.search:before { 137 | position: absolute; 138 | top: 17px; 139 | left: $nav-padding; 140 | color: $nav-text; 141 | @extend %icon-search; 142 | } 143 | &.key-replace:before { 144 | position: absolute; 145 | top: 17px; 146 | left: $nav-padding; 147 | color: $nav-text; 148 | @extend %icon-key; 149 | } 150 | } 151 | 152 | img+.tocify { 153 | margin-top: $logo-margin; 154 | } 155 | 156 | .search-results { 157 | margin-top: 0; 158 | box-sizing: border-box; 159 | height: 0; 160 | overflow-y: auto; 161 | overflow-x: hidden; 162 | transition-property: height, margin; 163 | transition-duration: 180ms; 164 | transition-timing-function: ease-in-out; 165 | &.visible { 166 | height: 30%; 167 | margin-bottom: 1em; 168 | } 169 | 170 | @include embossed-bg; 171 | 172 | li { 173 | margin: 1em $nav-padding; 174 | line-height: 1; 175 | } 176 | 177 | a { 178 | color: $nav-text; 179 | text-decoration: none; 180 | 181 | &:hover { 182 | text-decoration: underline; 183 | } 184 | } 185 | } 186 | 187 | 188 | .tocify-item>a, .toc-footer li { 189 | padding: 0 $nav-padding 0 $nav-padding; 190 | display: block; 191 | overflow-x: hidden; 192 | white-space: nowrap; 193 | text-overflow: ellipsis; 194 | } 195 | 196 | // The Table of Contents is composed of multiple nested 197 | // unordered lists. These styles remove the default 198 | // styling of an unordered list because it is ugly. 199 | ul, li { 200 | list-style: none; 201 | margin: 0; 202 | padding: 0; 203 | line-height: 28px; 204 | } 205 | 206 | li { 207 | color: $nav-text; 208 | transition-property: background; 209 | transition-timing-function: linear; 210 | transition-duration: 230ms; 211 | } 212 | 213 | // This is the currently selected ToC entry 214 | .tocify-focus { 215 | box-shadow: 0px 1px 0px $nav-active-shadow; 216 | background-color: $nav-active-bg; 217 | color: $nav-active-text; 218 | } 219 | 220 | // Subheaders are the submenus that slide open 221 | // in the table of contents. 222 | .tocify-subheader { 223 | display: none; // tocify will override this when needed 224 | background-color: $nav-subitem-bg; 225 | font-weight: 500; 226 | .tocify-item>a { 227 | padding-left: $nav-padding + $nav-indent; 228 | font-size: 12px; 229 | } 230 | 231 | // for embossed look: 232 | @include embossed-bg; 233 | &>li:last-child { 234 | box-shadow: none; // otherwise it'll overflow out of the subheader 235 | } 236 | } 237 | 238 | 239 | .toc-footer { 240 | padding: 1em 0; 241 | margin-top: 1em; 242 | border-top: 1px dashed $nav-footer-border-color; 243 | 244 | li,a { 245 | color: $nav-text; 246 | text-decoration: none; 247 | } 248 | 249 | 250 | li { 251 | font-size: 0.8em; 252 | line-height: 1.7; 253 | text-decoration: none; 254 | } 255 | 256 | li:hover { 257 | background-color: #fff; 258 | 259 | &>a{ 260 | color: $bby-blue; 261 | } 262 | 263 | } 264 | } 265 | 266 | } 267 | 268 | // button to show navigation on mobile devices 269 | #nav-button { 270 | span { 271 | display: block; 272 | $side-pad: $main-padding / 2 - 8px; 273 | padding: $side-pad $side-pad $side-pad; 274 | background-color: rgba($main-bg, 0.7); 275 | transform-origin: 0 0; 276 | transform: rotate(-90deg) translate(-100%, 0); 277 | border-radius: 0 0 0 5px; 278 | } 279 | padding: 0 1.5em 5em 0; // increase touch size area 280 | display: none; 281 | position: fixed; 282 | top: 0; 283 | left: 0; 284 | z-index: 100; 285 | color: #000; 286 | text-decoration: none; 287 | font-weight: bold; 288 | opacity: 0.7; 289 | line-height: 16px; 290 | img { 291 | height: 16px; 292 | vertical-align: bottom; 293 | } 294 | 295 | transition: left 0.3s ease-in-out; 296 | 297 | &:hover { opacity: 1; } 298 | &.open {left: $nav-width} 299 | } 300 | 301 | 302 | //////////////////////////////////////////////////////////////////////////////// 303 | // PAGE LAYOUT AND CODE SAMPLE BACKGROUND 304 | //////////////////////////////////////////////////////////////////////////////// 305 | 306 | .page-wrapper { 307 | margin-left: $nav-width; 308 | position: relative; 309 | z-index: 10; 310 | background-color: $main-bg; 311 | min-height: 100%; 312 | 313 | padding-bottom: 1px; // prevent margin overflow 314 | 315 | // The dark box is what gives the code samples their dark background. 316 | // It sits essentially under the actual content block, which has a 317 | // transparent background. 318 | // I know, it's hackish, but it's the simplist way to make the left 319 | // half of the content always this background color. 320 | .dark-box { 321 | width: $examples-width; 322 | background-color: $examples-bg; 323 | position: absolute; 324 | right: 0; 325 | top: 0; 326 | bottom: 0; 327 | } 328 | 329 | .lang-selector { 330 | position: fixed; 331 | z-index: 50; 332 | border-bottom: 5px solid $lang-select-active-bg; 333 | } 334 | } 335 | 336 | .lang-selector { 337 | background-color: $lang-select-bg; 338 | width: 100%; 339 | font-weight: bold; 340 | a { 341 | display: block; 342 | float:left; 343 | color: $lang-select-text; 344 | text-decoration: none; 345 | padding: 0 10px; 346 | line-height: 30px; 347 | outline: 0; 348 | 349 | &:active, &:focus { 350 | background-color: $lang-select-pressed-bg; 351 | color: $lang-select-pressed-text; 352 | } 353 | 354 | &.active { 355 | background-color: $lang-select-active-bg; 356 | color: $lang-select-active-text; 357 | } 358 | } 359 | 360 | &:after { 361 | content: ''; 362 | clear: both; 363 | display: block; 364 | } 365 | } 366 | 367 | //////////////////////////////////////////////////////////////////////////////// 368 | // CONTENT STYLES 369 | //////////////////////////////////////////////////////////////////////////////// 370 | // This is all the stuff with the light background in the left half of the page 371 | 372 | .content { 373 | // to place content above the dark box 374 | position: relative; 375 | z-index: 30; 376 | 377 | &:after { 378 | content: ''; 379 | display: block; 380 | clear: both; 381 | } 382 | 383 | &>h1, &>h2, &>h3, &>h4, &>h5, &>h6, &>p, &>table, &>ul, &>ol, &>aside, &>dl { 384 | margin-right: $examples-width; 385 | padding: 0 $main-padding; 386 | box-sizing: border-box; 387 | display: block; 388 | @include text-shadow($main-embossed-text-shadow); 389 | 390 | @extend %left-col; 391 | } 392 | 393 | &>ul, &>ol { 394 | padding-left: $main-padding + 15px; 395 | } 396 | 397 | // the div is the tocify hidden div for placeholding stuff 398 | &>h1, &>h2, &>div { 399 | clear:both; 400 | } 401 | 402 | h1 { 403 | @extend %header-font; 404 | font-size: 30px; 405 | padding-top: 0.5em; 406 | padding-bottom: 0.5em; 407 | border-bottom: 1px solid #ccc; 408 | margin-bottom: $h1-margin-bottom; 409 | margin-top: 2em; 410 | border-top: 1px solid #ddd; 411 | background-image: linear-gradient(to bottom, #fff, #f9f9f9); 412 | } 413 | 414 | h1:first-child, div:first-child + h1 { 415 | border-top-width: 0; 416 | margin-top: 0; 417 | } 418 | 419 | h2 { 420 | @extend %header-font; 421 | font-size: 20px; 422 | margin-top: 4em; 423 | margin-bottom: 0; 424 | border-top: 1px solid #ccc; 425 | padding-top: 1.2em; 426 | padding-bottom: 1.2em; 427 | background-image: linear-gradient(to bottom, rgba(#fff, 0.4), rgba(#fff, 0)); 428 | } 429 | 430 | // h2s right after h1s should bump right up 431 | // against the h1s. 432 | h1 + h2, h1 + div + h2 { 433 | margin-top: $h1-margin-bottom * -1; 434 | border-top: none; 435 | } 436 | 437 | h3, h4, h5, h6 { 438 | @extend %header-font; 439 | font-size: 15px; 440 | margin-top: 2.5em; 441 | margin-bottom: 0.8em; 442 | } 443 | 444 | h4, h5, h6 { 445 | font-size: 10px; 446 | } 447 | 448 | hr { 449 | margin: 2em 0; 450 | border-top: 2px solid $examples-bg; 451 | border-bottom: 2px solid $main-bg; 452 | } 453 | 454 | table { 455 | margin-bottom: 1em; 456 | overflow: auto; 457 | th,td { 458 | text-align: left; 459 | vertical-align: top; 460 | line-height: 1.6; 461 | } 462 | 463 | th { 464 | padding: 5px 10px; 465 | border-bottom: 1px solid #ccc; 466 | vertical-align: bottom; 467 | } 468 | 469 | td { 470 | padding: 10px; 471 | } 472 | 473 | tr:last-child { 474 | border-bottom: 1px solid #ccc; 475 | } 476 | 477 | tr:nth-child(odd)>td { 478 | background-color: lighten($main-bg,4.2%); 479 | } 480 | 481 | tr:nth-child(even)>td { 482 | background-color: #f8fafd; 483 | } 484 | } 485 | 486 | dt { 487 | font-weight: bold; 488 | } 489 | 490 | dd { 491 | margin-left: 15px; 492 | } 493 | 494 | p, li, dt, dd { 495 | line-height: 1.6; 496 | margin-top: 0; 497 | } 498 | 499 | a { 500 | color: $bby-blue; 501 | text-decoration: none; 502 | } 503 | 504 | a:hover { 505 | text-decoration: underline; 506 | color: #085eb9; 507 | } 508 | 509 | img { 510 | max-width: 100%; 511 | } 512 | 513 | code { 514 | background-color: #e1e1e3; 515 | color: $bby-blue; 516 | padding: 2px 4px; 517 | border-radius: 3px; 518 | @extend %break-words; 519 | @extend %code-font; 520 | } 521 | 522 | pre>code { 523 | background-color: transparent; 524 | color: #fff; 525 | padding: 0; 526 | } 527 | 528 | aside { 529 | padding-top: 1em; 530 | padding-bottom: 1em; 531 | @include text-shadow(0 1px 0 lighten($aside-notice-bg, 15%)); 532 | margin-top: 1.5em; 533 | margin-bottom: 1.5em; 534 | background: $aside-notice-bg; 535 | line-height: 1.6; 536 | 537 | &.warning { 538 | background-color: $aside-warning-bg; 539 | @include text-shadow(0 1px 0 lighten($aside-warning-bg, 15%)); 540 | } 541 | 542 | &.success { 543 | background-color: $aside-success-bg; 544 | @include text-shadow(0 1px 0 lighten($aside-success-bg, 15%)); 545 | } 546 | } 547 | 548 | aside:before { 549 | vertical-align: middle; 550 | padding-right: 0.5em; 551 | font-size: 14px; 552 | } 553 | 554 | aside.notice:before { 555 | @extend %icon-info-sign; 556 | } 557 | 558 | aside.warning:before { 559 | @extend %icon-exclamation-sign; 560 | } 561 | 562 | aside.success:before { 563 | @extend %icon-ok-sign; 564 | } 565 | 566 | .search-highlight { 567 | padding: 2px; 568 | margin: -2px; 569 | border-radius: 4px; 570 | border: 1px solid $highlight; 571 | @include text-shadow(1px 1px 0 #666); 572 | background: linear-gradient(to top left, $highlight 0%, #a7d2d8 100%); 573 | } 574 | } 575 | 576 | .inline-code { 577 | background-color: #e1e1e3; 578 | color: #053f68; 579 | } 580 | 581 | 582 | //////////////////////////////////////////////////////////////////////////////// 583 | // CODE SAMPLE STYLES 584 | //////////////////////////////////////////////////////////////////////////////// 585 | // This is all the stuff that appears in the right half of the page 586 | 587 | .content { 588 | pre, blockquote { 589 | background-color: $code-bg; 590 | color: #fff; 591 | 592 | padding: 1em $main-padding; 593 | margin: 0; 594 | width: $examples-width; 595 | 596 | float:right; 597 | clear:right; 598 | 599 | box-sizing: border-box; 600 | @include text-shadow(0px 1px 2px rgba(0,0,0,0.4)); 601 | 602 | @extend %right-col; 603 | 604 | &>p { margin: 0; } 605 | 606 | a { 607 | color: #fff; 608 | text-decoration: none; 609 | border-bottom: dashed 1px #ccc; 610 | } 611 | } 612 | 613 | pre { 614 | @extend %code-font; 615 | } 616 | 617 | blockquote { 618 | &>p { 619 | background-color: $code-annotation-bg; 620 | border-radius: 5px; 621 | padding: $code-annotation-padding; 622 | color: #ccc; 623 | border-top: 1px solid #000; 624 | border-bottom: 1px solid #404040; 625 | } 626 | } 627 | } 628 | 629 | //////////////////////////////////////////////////////////////////////////////// 630 | // RESPONSIVE DESIGN 631 | //////////////////////////////////////////////////////////////////////////////// 632 | // These are the styles for phones and tablets 633 | // There are also a couple styles disperesed 634 | 635 | @media (max-width: $tablet-width) { 636 | .tocify-wrapper { 637 | left: -$nav-width; 638 | 639 | &.open { 640 | left: 0; 641 | } 642 | } 643 | 644 | .page-wrapper { 645 | margin-left: 0; 646 | } 647 | 648 | #nav-button { 649 | display: block; 650 | } 651 | 652 | .tocify-wrapper .tocify-item > a { 653 | padding-top: 0.3em; 654 | padding-bottom: 0.3em; 655 | } 656 | } 657 | 658 | @media (max-width: $phone-width) { 659 | .dark-box { 660 | display: none; 661 | } 662 | 663 | %left-col { 664 | margin-right: 0; 665 | } 666 | 667 | .tocify-wrapper .lang-selector { 668 | display: block; 669 | } 670 | 671 | .page-wrapper .lang-selector { 672 | display: none; 673 | } 674 | 675 | %right-col { 676 | width: auto; 677 | float: none; 678 | } 679 | 680 | %right-col + %left-col { 681 | margin-top: $main-padding; 682 | } 683 | } 684 | 685 | thead th { 686 | font-size: 16px; 687 | } 688 | 689 | table tr td:nth-child(1) { 690 | width: 20%; 691 | } 692 | 693 | 694 | --------------------------------------------------------------------------------