diff --git a/.gitattributes b/.gitattributes
new file mode 100644
index 000000000..1111d65fd
--- /dev/null
+++ b/.gitattributes
@@ -0,0 +1,15 @@
+# Files to exclude when creating archive
+/tests export-ignore
+/.github export-ignore
+/.gitmodules export-ignore
+/.gitignore export-ignore
+/.php_cs export-ignore
+/.travis.yml export-ignore
+/.phpstan-src.neon export-ignore
+/.phpstan-src-71.neon export-ignore
+/.phpstan-tests.neon export-ignore
+/phpunit-integration.xml export-ignore
+/phpunit.xml export-ignore
+/ruleset.xml export-ignore
+/travis export-ignore
+/util export-ignore
diff --git a/.travis.yml b/.travis.yml
index 75abd31eb..0c9228144 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,24 +14,36 @@ branches:
 
 sudo: true
 
-php:
-  - 5.6
-  - 7.0
-  - 7.1
-  - hhvm
-
 matrix:
   fast_finish: true
   include:
+    - php: 5.6
+      env: ES_VERSION="5.0" TEST_BUILD_REF="origin/5.0"
+    - php: 5.6
+      env: ES_VERSION="5.5" TEST_BUILD_REF="origin/5.5"
+
+    - php: 7.0
+      env: ES_VERSION="5.0" TEST_BUILD_REF="origin/5.0"
+    - php: 7.0
+      env: ES_VERSION="5.5" TEST_BUILD_REF="origin/5.5"
+
     - php: 7.1
       env: ES_VERSION="5.0" TEST_BUILD_REF="origin/5.0"
-  allow_failures:
-    - php: hhvm
+    - php: 7.1
+      env: ES_VERSION="5.5" TEST_BUILD_REF="origin/5.5"
+
+    - php: 7.2
+      env: ES_VERSION="5.0" TEST_BUILD_REF="origin/5.0"
+    - php: 7.2
+      env: ES_VERSION="5.5" TEST_BUILD_REF="origin/5.5"
+
+    - php: 7.3
+      env: ES_VERSION="5.0" TEST_BUILD_REF="origin/5.0"
+    - php: 7.3
+      env: ES_VERSION="5.5" TEST_BUILD_REF="origin/5.5"
 
 env:
   global:
-    - ES_VERSION="5.x"
-    - TEST_BUILD_REF="origin/5.x"
     - ES_TEST_HOST=http://localhost:9200
     - JAVA_HOME="/usr/lib/jvm/java-8-oracle/jre"
 
@@ -40,10 +52,10 @@ before_install:
   - ./travis/download_and_run_es.sh
 
 install:
-  - composer install --prefer-source
+  - composer install --prefer-dist
 
 before_script:
-  - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then PHPUNIT_FLAGS="--coverage-clover ./build/logs/clover.xml"; fi
+  - if [ $TRAVIS_PHP_VERSION = '7.3' ]; then PHPUNIT_FLAGS="--coverage-clover ./build/logs/clover.xml"; fi
   - php util/RestSpecRunner.php
   - php util/EnsureClusterAlive.php
 
@@ -52,4 +64,4 @@ script:
   - vendor/bin/phpunit -c phpunit-integration.xml --group sync $PHPUNIT_FLAGS
 
 after_script:
-  - if [ $TRAVIS_PHP_VERSION = '7.0' ]; then php vendor/bin/coveralls; fi
+  - if [ $TRAVIS_PHP_VERSION = '7.3' ]; then php vendor/bin/coveralls; fi
diff --git a/BREAKING_CHANGES.md b/BREAKING_CHANGES.md
index df391834d..cba9966eb 100644
--- a/BREAKING_CHANGES.md
+++ b/BREAKING_CHANGES.md
@@ -3,10 +3,21 @@
 ## Breaking changes
 
 - Indices/Analyze Endpoint: `filters` and `char_filters` URI parameters have renamed to `filter` and `char_filter` respectively
-- SearchExists endpoint has been removed ([use `size=0` and `terminate_after=1` instead](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_search_changes.html#_search_exists_api_removed))
-- Warmers have been removed because they are [no longer useful](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_index_apis.html#_warmers)
-- Indices/Optimize Endpoint has been removed ([use `_forcemerge` instead](https://www.elastic.co/guide/en/elasticsearch/reference/master/breaking_50_rest_api_changes.html#_literal__optimize_literal_endpoint_removed))
+- SearchExists endpoint has been removed ([use `size=0` and `terminate_after=1` instead](https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking_50_search_changes.html#_search_exists_api_removed))
+- Warmers have been removed because they are [no longer useful](https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking_50_index_apis.html#_warmers)
+- Indices/Optimize Endpoint has been removed ([use `_forcemerge` instead](https://www.elastic.co/guide/en/elasticsearch/reference/current/breaking_50_rest_api_changes.html#_literal__optimize_literal_endpoint_removed))
+- MoreLikeThis (MLT) endpoint has been removed
+- DeleteByQuery endpoint has been removed.
+- Tasks/List and Tasks/Get are now separate endpoints (see: [[e0cc5f9]](http://github.com/elasticsearch/elasticsearch-php/commit/752d5a2))
+- Client requires PHP 5.6.6 or higher
 
 ## Deprecations
 
-- Percolator endpoints are deprecated and will be removed in Elasticsearch 6.0
\ No newline at end of file
+- Percolator endpoints are deprecated and will be removed in Elasticsearch 6.0
+
+## Internal BWC Breaks
+
+- Namespace injection has changed slightly.  If you use custom namespaces, you'll need to update your code (see: Add better ability to inject namespaces [[b1a27b7]](http://github.com/elasticsearch/elasticsearch-php/commit/b1a27b7))
+- Endpoints no longer use the Transport directly.  If you use custom endpoints, you'll need to do some minor
+refactoring (see: Refactor to remove Transport dependence in endpoints [[ecd454c]](http://github.com/elasticsearch/elasticsearch-php/commit/ecd454c))
+- To facilitate testing and other features, the `ConnectionInterface` has expanded to obtain some more methods ([[getPath()]](http://github.com/elasticsearch/elasticsearch-php/commit/8bcf1a8), [[getUserPass()]](http://github.com/elasticsearch/elasticsearch-php/commit/586fbdb), [[getHost()]](http://github.com/elasticsearch/elasticsearch-php/commit/445fdea))
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 52b66cb8c..ecee7b760 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,288 +1,305 @@
-## Release 2.2.2
-- Normalizing Reindex name (#466) [[e0cc5f9]](http://github.com/elasticsearch/elasticsearch-php/commit/e0cc5f9)
-- Add "extended" host configuration syntax [[99cd83f]](http://github.com/elasticsearch/elasticsearch-php/commit/99cd83f)
-- Reindex endpoint should not be camel-cased ("ReIndex") [[7ca34ab]](http://github.com/elasticsearch/elasticsearch-php/commit/7ca34ab)
-- Allow ConnectionFactory to be overridable (#459) [[81b2a23]](http://github.com/elasticsearch/elasticsearch-php/commit/81b2a23)
-- Reindex endpoint should accept a body parameter [[21ca68b]](http://github.com/elasticsearch/elasticsearch-php/commit/21ca68b)
+## Release 5.5.0
 
-### Documentation
-- Fix typo (#471) [[20af8fb]](http://github.com/elasticsearch/elasticsearch-php/commit/20af8fb)
-- [DOCS] Update index-operations.asciidoc (#470) [[74f2b19]](http://github.com/elasticsearch/elasticsearch-php/commit/74f2b19)
-- Php typos [[3d9d8e0]](http://github.com/elasticsearch/elasticsearch-php/commit/7fd0051)
-- [DOCS] Update changelog [[4c9aab0]](http://github.com/elasticsearch/elasticsearch-php/commit/4c9aab0)
+- Added `User-Agent` header equal to  `elasticsearch-php/5.5.0 (metadata-values)` [[26da9a33]](https://github.com/elastic/elasticsearch-php/commit/26da9a33)
+- Fix #846 choosing GET and POST in endpoints based on body [[cdbeab38]](https://github.com/elastic/elasticsearch-php/commit/cdbeab38)
+- Fix #843 adding `wait_for_active_shards` and `pipeline` in UpdateByQuery [[8b36458]](https://github.com/elastic/elasticsearch-php/commit/8b36458319b1734d1032817abf1f850d3fcfd4ec)
+
+## Release 5.4.0
+
+- fixed php 7.3 compatibility for elasticsearch 5 (#826) [[14a19ba]](http://github.com/elasticsearch/elasticsearch-php/commit/14a19ba)
+- Add `slices` param to whitelisted UBQ params (#752) [[13f248e]](http://github.com/elasticsearch/elasticsearch-php/commit/13f248e)
+- [DOCS] add link to community index helper (#681) (#726) [[6d414f2]](http://github.com/elasticsearch/elasticsearch-php/commit/6d414f2)
+- Fix issue with getting status of respository and snapshots. (#719) [[65aafc1]](http://github.com/elasticsearch/elasticsearch-php/commit/65aafc1)
+- fix DeleteByQuery param white list (#748) [[55e6a70]](http://github.com/elasticsearch/elasticsearch-php/commit/55e6a70)
+
+## Release 5.3.2
 
-## Release 2.2.1
+- Fix parsing of NodesInfo for Sniffing [[d771699]](http://github.com/elasticsearch/elasticsearch-php/commit/d771699)
+- [TEST] print elasticsearch.log if cluster fails to start [[e03cbb2]](http://github.com/elasticsearch/elasticsearch-php/commit/e03cbb2)
+- Fix bug where exceptions were being used as array in PHP 5.x [[c5db567]](http://github.com/elasticsearch/elasticsearch-php/commit/c5db567)
 
-- Reindex endpoint should accept a body parameter [[3d9d8e0]](http://github.com/elasticsearch/elasticsearch-php/commit/3d9d8e0)
-- `Tasks/Show` should be `Tasks/Get`. Deprecate `Show` [[fcc85b4]](http://github.com/elasticsearch/elasticsearch-php/commit/fcc85b4)
-- "Task" namespace should be plural ("Tasks") [[5e8bacf]](http://github.com/elasticsearch/elasticsearch-php/commit/5e8bacf)
+## Release 5.3.1
+
+- Do not schedule connection pool checks on 4xx level errors
+- Add 'terminate_after' to Count endpoint whitelist (#634) [[1a20259]](http://github.com/elasticsearch/elasticsearch-php/commit/1a20259)
+- Use upper-case "Host" header [[1621094]](http://github.com/elasticsearch/elasticsearch-php/commit/1621094)
+- Shrink API was not setting body correctly [[129ed4a]](http://github.com/elasticsearch/elasticsearch-php/commit/129ed4a)
+- Capitalize 'Content-Type' for maximum compatibility [[3f136b5]](http://github.com/elasticsearch/elasticsearch-php/commit/3f136b5)
+- Fix ClientBuilder - pass correct argument for Elasticsearch\Endpoints\MsearchTemplate::__construct. (#606) [[21f5ce4]](http://github.com/elasticsearch/elasticsearch-php/commit/21f5ce4)
 
 ### Testing
 
-- Update travis to include 2.3 [[7108ca0]](http://github.com/elasticsearch/elasticsearch-php/commit/7108ca0)
-
-## Release 2.2.0
-
-- 236a5e0 Added deprecated tag on deletebyquery and mlt
-- Update for 2.3 https://github.com/elastic/elasticsearch-php/pull/420
-  - Add Reindex Endpoint
-  - Add UpdateByQuery endpoint
-  - Add Tasks Namespace (Tasks/Cancel, Tasks/Show)
-  - Add `ignore_unavailable` to Cat/Snapshots
-  - Add `master_timeout`, `timeout` to Cluster/PutSettings
-  - Add `timeout` to Cluster/Stats
-  - Add `char_filters`, `char_filter`, `filter`, `explain`, `attributes` to Indices/Analyze
-  - Add `query`, `index`, `recycler`, `request` to Cache/Clear
-  - Add `update_all_types` to Indices/Create
-  - Add `local` to Indices/ExistsTypes
-  - Add `bytes` to Cat/Shards
-  - Add `wait_if_ongoing` to Indices/Flush
-  - Add `update_all_types` to Indices/PutMapping
-  - Add `verbose` to Indices/Segments
-  - Remove unused Indices/Snapshotindex (unlinked from any namespace)
-  - Add `ignore_unavailable`, `allow_no_indices`, `expand_wildcards`, `rewrite` to Indices/ValidateQuery
-  - Add `version`, `version_type` to MTermVectors
-  - Add `ignore_idle_threads` to Nodes/HotThreads
-  - Add `timeout` to Nodes/Info
-  - Add `timeout` to Nodes/Stats
-  - Add `percolate_routing`, `percolate_preference` to Percolate
-  - Add terminate_after`, `track_scores`, `request_cache` to Search
-  - Add `min_score` to SearchExists
-  - Add `verify` to Snapshot/CreateRepository
-  - Add `version`, `version_type` to Template/Delete
-  - Add `version`, `version_type` to Template/Get
-  - Add `version`, `version_type`, `op_type` to Template/Put
-  - Add `script_id`, `scripted_upsert` to Update
-- 6b6a1f6 feat(): allow to override client instantiation (#412)
-- 8b53f6b Fix bug when Create is called with an stdClass body
+- [TEST] move integration test to dedicated test file [[3e01b9e]](http://github.com/elasticsearch/elasticsearch-php/commit/3e01b9e)
+- [TEST] Client does not support accepting Yaml format responses [[e5d9fbb]](http://github.com/elasticsearch/elasticsearch-php/commit/e5d9fbb)
+- [TEST] Fix content-type assertions in test to match case [[d31a51b]](http://github.com/elasticsearch/elasticsearch-php/commit/d31a51b)
+- [TEST] Support headers in yaml runner, do some bad-comment cleaning [[5590a88]](http://github.com/elasticsearch/elasticsearch-php/commit/5590a88)
+- [TEST] Add some missing and required static configs [[b41c733]](http://github.com/elasticsearch/elasticsearch-php/commit/b41c733)
+- [TEST] add newer ES versions to Travis build matrix (#609) [[de6cde4]](http://github.com/elasticsearch/elasticsearch-php/commit/de6cde4)
+- [TEST] fix handling of format for Cat tests [[46f9d59]](http://github.com/elasticsearch/elasticsearch-php/commit/46f9d59)
+- [TEST] drop HHVM from build [#611] (#615) [[34d09a8]](http://github.com/elasticsearch/elasticsearch-php/commit/34d09a8)
+
+
+## Release 5.3.0
+- Add MsearchTemplate endpoint [[df7004f]](http://github.com/elasticsearch/elasticsearch-php/commit/df7004f)
+- Add Cat\Templates endpoint [[776c865]](http://github.com/elasticsearch/elasticsearch-php/commit/776c865)
+- Add FieldCaps endpoint [[0acccc6]](http://github.com/elasticsearch/elasticsearch-php/commit/0acccc6)
+- Add Remote Namespace and Remote\Info endpoint [[82121d9]](http://github.com/elasticsearch/elasticsearch-php/commit/82121d9)
+- Allow Sliced Scroll for the Search endpoint (#604) [[dfdb1a8]](http://github.com/elasticsearch/elasticsearch-php/commit/dfdb1a8)
+- Added "slices" parameter to the Reindex endpoint (#598) [[d9aaefd]](http://github.com/elasticsearch/elasticsearch-php/commit/d9aaefd)
+- fix conflict when merging timeout param (#562) [[505688d]](http://github.com/elasticsearch/elasticsearch-php/commit/505688d)
 
 ### Testing
-- 1009763 [TEST] Fix jq syntax for numeric branches (e.g. `2.2`)
-- c303676 Fixed phpunit to refer to server instead of env
-- 391b249 Updated ParseSpec to be able to run from console and use new api path
-- 9308a1a getApiPath function returns path without trailing slash
-- 16dfe8a [TEST] Automate snapshot retrieval
+- [TEST] Temporarily blacklist some yaml tests that aren't parsing [[d857ae1]](http://github.com/elasticsearch/elasticsearch-php/commit/d857ae1)
+- [TEST] Add missing `lt` and `lte` test operators [[02adc14]](http://github.com/elasticsearch/elasticsearch-php/commit/02adc14)
+
+### Docs
+- [Docs] Updating readme with mock testing instructions (#591) [[1623d44]](http://github.com/elasticsearch/elasticsearch-php/commit/1623d44)
+- [Docs] Symfony bundle added (#560) [[69dbd4c]](http://github.com/elasticsearch/elasticsearch-php/commit/69dbd4c)
+- [DOCS] Remove incorrect Composer instructions from README (#565) [[9606f52]](http://github.com/elasticsearch/elasticsearch-php/commit/9606f52)
+
+## Release 5.2.0
+
+- Add 'batched_reduce_size' / 'typed_keys' params to Search endpoint [[691ce24]](http://github.com/elasticsearch/elasticsearch-php/commit/691ce24)
+- Fix Scroll and ClearScroll syntax [[59b3c08]](http://github.com/elasticsearch/elasticsearch-php/commit/59b3c08)
+- Add 'request', 'request_cache' to ClearCache endpoint [[07ff0be]](http://github.com/elasticsearch/elasticsearch-php/commit/07ff0be)
+- Handle null `type` better [[9900cfd]](http://github.com/elasticsearch/elasticsearch-php/commit/9900cfd)
+- Add 'stored_fields' param to Exists, Explain and Search endpoints [[01f9a06]](http://github.com/elasticsearch/elasticsearch-php/commit/01f9a06)
+- Add endpoint index and type getters (#557) [[0d9cdfa]](http://github.com/elasticsearch/elasticsearch-php/commit/0d9cdfa)
+- added getTransport, getEndpoint, getRegisteredNamespacesBuilder to ClientBuilder.php (#551) [[608bfe8]](http://github.com/elasticsearch/elasticsearch-php/commit/608bfe8)
+- Add 'version' param to Exists whitelist [[f2ae26b]](http://github.com/elasticsearch/elasticsearch-php/commit/f2ae26b)
+- Add 'typed_keys' param to MSearch whitelist [[3884ca0]](http://github.com/elasticsearch/elasticsearch-php/commit/3884ca0)
+- Make id param optionnal for termvectors requests. (#542) [[e6f79de]](http://github.com/elasticsearch/elasticsearch-php/commit/e6f79de)
 
-### Documentation
-- 1b01244 [Docs] Fix typo. (#409)
-- 1f07b31 [DOCS] Usage example for creating ClientBuilder fixed (#406)
-- e7b8e83, a3c806a [DOCS] Generate reference docs
-- 836b499 Add script to generate docs
-- 951d576 Make it easier to note that 'client' is an array of options.
-
-## Release 2.1.5
-- whitelist search per-request cache parameters [[8105a9e]](http://github.com/elasticsearch/elasticsearch-php/commit/8105a9e)
-- Add 'routing' parameter to Mget endpoint whitelist [[bb0a623]](http://github.com/elasticsearch/elasticsearch-php/commit/bb0a623)
-- Add 'percolate_format' parameter to Percolate endpoint whitelist [[65462ba]](http://github.com/elasticsearch/elasticsearch-php/commit/65462ba)
-- Remove $scroll_id variable entirely Set $body = $scroll_id in setScrollID() Return $body in getBody() [[05999d8]](http://github.com/elasticsearch/elasticsearch-php/commit/05999d8)
-- Add update_all_types support to create index call [[6dcf4c5]](http://github.com/elasticsearch/elasticsearch-php/commit/6dcf4c5)
-- Allow update_all_types as index setting [[4161290]](http://github.com/elasticsearch/elasticsearch-php/commit/4161290)
-- Use request body for scroll ID instead of URI param [[016c191]](http://github.com/elasticsearch/elasticsearch-php/commit/016c191)
+### Testing
+
+- [TEST] Warning header format has changed slightly [[6c8699c]](http://github.com/elasticsearch/elasticsearch-php/commit/6c8699c)
+- [TEST] Added missing semicolon (#544) [[ccfb5a6]](http://github.com/elasticsearch/elasticsearch-php/commit/ccfb5a6)
+- [TEST] Allow JSON workaround, remove travis hackery [[3467c19]](http://github.com/elasticsearch/elasticsearch-php/commit/3467c19)
+
+### Docs
+
+- Update index-operations.asciidoc (#537) [[348fb4d]](http://github.com/elasticsearch/elasticsearch-php/commit/348fb4d)
+- [DOCS] use std class in example instead of empty array (#549) [[9c45775]](http://github.com/elasticsearch/elasticsearch-php/commit/9c45775)
+- [DOCS] Documentation fixes for 5.0 (typos, etc.) (#543) [[c4cf003]](http://github.com/elasticsearch/elasticsearch-php/commit/c4cf003)
+- [DOCS] bool query's "query" should use a "should" (#545) [[8ec26ba]](http://github.com/elasticsearch/elasticsearch-php/commit/8ec26ba)
+- [DOCS] Fix scrolling example [[006b3c2]](http://github.com/elasticsearch/elasticsearch-php/commit/006b3c2)
+
+## Release 5.1.3
+
+- allowBadJSONSerialization() builder method should be fluent [[f1812d4]](http://github.com/elasticsearch/elasticsearch-php/commit/f1812d4)
+
+## Release 5.1.2
+
+- A specific version of json-ext is no longer needed in 5.0 branch [[e1b5c2a]](http://github.com/elasticsearch/elasticsearch-php/commit/e1b5c2a)
+
+## Release 5.1.1
+
+- Add 'format' param to all Cat endpoints [[fc25a2c]](http://github.com/elasticsearch/elasticsearch-php/commit/fc25a2c)
+- Add opt-in for ignoring JSON_PRESERVE_ZERO_FRACTION when serializing [[e34fdfd]](http://github.com/elasticsearch/elasticsearch-php/commit/e34fdfd)
+- Prefer POST for Suggest endpoint [[aae7019]](http://github.com/elasticsearch/elasticsearch-php/commit/aae7019)
+- Whitelist 'include_segment_file_sizes' in Cluster/Nodes/Stats endpoint [[a2744b4]](http://github.com/elasticsearch/elasticsearch-php/commit/a2744b4)
+- Whitelist 'include_segment_file_sizes' in Indices/Stats endpoint [[2c6cd30]](http://github.com/elasticsearch/elasticsearch-php/commit/2c6cd30)
+- Automatically set Content-type and Accept headers [[3d52e11]](http://github.com/elasticsearch/elasticsearch-php/commit/3d52e11)
+- Put back UpdateByQuery (#531) [[6f4394f]](http://github.com/elasticsearch/elasticsearch-php/commit/6f4394f)
+- Add 'human' param to global whitelist [[d16e541]](http://github.com/elasticsearch/elasticsearch-php/commit/d16e541)
 
 ### Testing
-- Update snapshot download script for 2.2 [[350cd6e]](http://github.com/elasticsearch/elasticsearch-php/commit/350cd6e)
-- Update travis matrix [[04bcf81]](http://github.com/elasticsearch/elasticsearch-php/commit/04bcf81)
-- Invoke phpunit dependency instead of travis phpunit.phar [[f9e0d99]](http://github.com/elasticsearch/elasticsearch-php/commit/f9e0d99)
-- Do not track the util/elasticsearch directory [[25bd111]](http://github.com/elasticsearch/elasticsearch-php/commit/25bd111)
 
-### Documentation
-- Fix comment tag [[3b8e918]](http://github.com/elasticsearch/elasticsearch-php/commit/3b8e918)
-- Add .github templates [[104a7ea]](http://github.com/elasticsearch/elasticsearch-php/commit/104a7ea)
-- Minor fix to wrong documentation [[2863521]](http://github.com/elasticsearch/elasticsearch-php/commit/2863521)
-- Wrong syntax in bulk index example [[17eb43a]](http://github.com/elasticsearch/elasticsearch-php/commit/17eb43a)
-- Delete configuration.asciidoc~ [[3449d97]](http://github.com/elasticsearch/elasticsearch-php/commit/3449d97)
-- Syntax errors in Exception handling [[ba5b38b]](http://github.com/elasticsearch/elasticsearch-php/commit/ba5b38b)
-- Elasticsearch needed for autoload to find classes [[9410e14]](http://github.com/elasticsearch/elasticsearch-php/commit/9410e14)
-- Small doc fix in futures doc [[86e559a]](http://github.com/elasticsearch/elasticsearch-php/commit/86e559a)
-- Fix incorrect nesting of array [[3e041f3]](http://github.com/elasticsearch/elasticsearch-php/commit/3e041f3)
+- [TEST] Tidy up version check [[ec6b832]](http://github.com/elasticsearch/elasticsearch-php/commit/ec6b832)
 
+### Docs
 
-## Release 2.1.4
-- Fix the host path handling [[15b5be3]](http://github.com/elasticsearch/elasticsearch-php/commit/15b5be3)
-- fix body setter in bulk endpoint [[fa283ea]](http://github.com/elasticsearch/elasticsearch-php/commit/fa283ea)
-- add support for generators and iterators in bulk endpoint [[b3d951e]](http://github.com/elasticsearch/elasticsearch-php/commit/b3d951e)
+- [DOCS] Update search-operations.asciidoc (#520) [[4aba49b]](http://github.com/elasticsearch/elasticsearch-php/commit/4aba49b)
+- [DOCS] fix broken links to breaking changes docs [[7d1b0ec]](http://github.com/elasticsearch/elasticsearch-php/commit/7d1b0ec)
+
+## Release 5.1.0
+
+- Catch additional exceptions in the ping function for those who use multiple nodes in their connection pool. [[ffe0510]](http://github.com/elasticsearch/elasticsearch-php/commit/ffe0510)
+- Use `array_diff` to Check Endpoint Parameters (#514) [[46f7f36]](http://github.com/elasticsearch/elasticsearch-php/commit/46f7f36)
+- Re-Add the DeleteByQuery Functionality (#513) [[b262dca]](http://github.com/elasticsearch/elasticsearch-php/commit/b262dca)
+- Add 'full_id' to Cat/Nodes endpoint [[f32cc54]](http://github.com/elasticsearch/elasticsearch-php/commit/f32cc54)
+- add ClientBuilder->setConnectionParams() (#507) [[3923432]](http://github.com/elasticsearch/elasticsearch-php/commit/3923432)
+- Add new (undocumented) PHP-7 JSON error codes, better unknown handling [[0a7fd55]](http://github.com/elasticsearch/elasticsearch-php/commit/0a7fd55)
+- Add ext-json version constraint, update some docs [[ca2791a]](http://github.com/elasticsearch/elasticsearch-php/commit/ca2791a)
+- Add catch-all in exception handling [[eb4117c]](http://github.com/elasticsearch/elasticsearch-php/commit/eb4117c)
+- Revert "Simplify error parsing now that we don't support <2.0 errors" [[fd38538]](http://github.com/elasticsearch/elasticsearch-php/commit/fd38538)
 
 ### Testing
-- travis: drop PHP 7.0 from allowed failures, it passes well [[be5e710]](http://github.com/elasticsearch/elasticsearch-php/commit/be5e710)
-
-
-## Release 2.1.3
-- Fix bug where ping() and sniff() encounter NPE [[61ba0c5]](http://github.com/elasticsearch/elasticsearch-php/commit/61ba0c5)
-- Add Indices/ForceMerge endpoint  [[4934583]](http://github.com/elasticsearch/elasticsearch-php/commit/4934583) [[6d61880]](http://github.com/elasticsearch/elasticsearch-php/commit/6d61880) [[58e63d7]](http://github.com/elasticsearch/elasticsearch-php/commit/58e63d7) [[dcd8833]](http://github.com/elasticsearch/elasticsearch-php/commit/dcd8833)
-- Add Cat/Snapshots endpoint [[efa0e49]](http://github.com/elasticsearch/elasticsearch-php/commit/efa0e49)
-- Add Cat/Repositories endpoint [[0c32b20]](http://github.com/elasticsearch/elasticsearch-php/commit/0c32b20)
-- Add Cat/NodeAttrs endpoint [[724d64b]](http://github.com/elasticsearch/elasticsearch-php/commit/724d64b) [[4c3bde3]](http://github.com/elasticsearch/elasticsearch-php/commit/4c3bde3)
-- Implement \Countable interface for Scroll Helper. [[013a1c7]](http://github.com/elasticsearch/elasticsearch-php/commit/013a1c7) [[17a929f]](http://github.com/elasticsearch/elasticsearch-php/commit/17a929f) [[272429a]](http://github.com/elasticsearch/elasticsearch-php/commit/272429a) [[55f4c0c]](http://github.com/elasticsearch/elasticsearch-php/commit/55f4c0c)
-- Allows overwriting setters invoked from ClientBuilder::fromConfig method. [[08ac47c]](http://github.com/elasticsearch/elasticsearch-php/commit/08ac47c)
-- When using connectionPool setter through ClientBuilder::fromConfig() method, connectionPoolArgs were automatically set to null causing AbstractConnectionPool to throw exception on null parameter. [[0b25033]](http://github.com/elasticsearch/elasticsearch-php/commit/0b25033)
-- Ignore 404 for already cleared scroll_ids in SearchResponseIterator [[266aac4]](http://github.com/elasticsearch/elasticsearch-php/commit/266aac4)
-- Add 'wait_if_ongoing' to Indices/Flush whitelist [[7b9cf8c]](http://github.com/elasticsearch/elasticsearch-php/commit/7b9cf8c)
-- Set randomizeHosts = true by default [[dc91938]](http://github.com/elasticsearch/elasticsearch-php/commit/dc91938)
-- Update Cat/Shards whitelist [[fe1dbe8]](http://github.com/elasticsearch/elasticsearch-php/commit/fe1dbe8)
+
+- [TEST] Make sure property_exists calls only ocurr on objects [[30baa0d]](http://github.com/elasticsearch/elasticsearch-php/commit/30baa0d)
+- [TEST] Tweak travis to install better ext-json [[3409a81]](http://github.com/elasticsearch/elasticsearch-php/commit/3409a81)
+- [TEST] Mute rollover test temporarily [[2316d33]](http://github.com/elasticsearch/elasticsearch-php/commit/2316d33)
+- [TEST] Add support for warning header checks [[ac1b053]](http://github.com/elasticsearch/elasticsearch-php/commit/ac1b053)
 
 ### Documentation
-- PHPdoc fix: Exists endpoint returns bool or array [[d70acbf]](http://github.com/elasticsearch/elasticsearch-php/commit/d70acbf)
-- fixed wrong return param in phpdoc [[56a1107]](http://github.com/elasticsearch/elasticsearch-php/commit/56a1107)
-- Fix formatting [[c548337]](http://github.com/elasticsearch/elasticsearch-php/commit/c548337)
-- Update CatNamespace.php [[22cb3dc]](http://github.com/elasticsearch/elasticsearch-php/commit/22cb3dc)
+
+- [DOCS] Removed unwanted ) and added proper formatting (#497) [[8187fdd]](http://github.com/elasticsearch/elasticsearch-php/commit/8187fdd)
+- [DOCS] Update index-operations.asciidoc (#496) [[a4dd09f]](http://github.com/elasticsearch/elasticsearch-php/commit/a4dd09f)
+- [DOCS] Update version in monolog configuration. (#489)  [[90fbd53]](http://github.com/elasticsearch/elasticsearch-php/commit/90fbd53)
+- [DOCS] Update php-version-requirement.asciidoc (#491) [[4951439]](http://github.com/elasticsearch/elasticsearch-php/commit/4951439)
+- [DOCS] "password" param should be "password" [[8ee2bc9]](http://github.com/elasticsearch/elasticsearch-php/commit/8ee2bc9)
+- More asciidoc tweaks [[451f985]](http://github.com/elasticsearch/elasticsearch-php/commit/451f985)
+- Asciidoc != markdown [[8a816c1]](http://github.com/elasticsearch/elasticsearch-php/commit/8a816c1)
+- [Docs] More 5.0 readme tweaks [[a60dd09]](http://github.com/elasticsearch/elasticsearch-php/commit/a60dd09)
+- [DOCS] 5.0 doc updates, readme, breaking changes [[6fb6421]](http://github.com/elasticsearch/elasticsearch-php/commit/6fb6421)
+
+
+## Release 5.0.0
+
+Woo!
+
+### New Endpoints
+- Add Cat/Tasks endpoint [[42856dc]](http://github.com/elasticsearch/elasticsearch-php/commit/42856dc)
+- Add Reindex endpoint [[d2484c7]](http://github.com/elasticsearch/elasticsearch-php/commit/d2484c7)
+- Add Indices/Shrink endpoint [[b6b97a4]](http://github.com/elasticsearch/elasticsearch-php/commit/b6b97a4)
+- Add Indices/Rollover endpoint [[1ba8299]](http://github.com/elasticsearch/elasticsearch-php/commit/1ba8299)
+
+### Removals/BWC Breaks/Deprecations
+
+- Indices/Optimize endpoint has been removed in 5.0 [[4f0b9da]](http://github.com/elasticsearch/elasticsearch-php/commit/4f0b9da)
+- Warmers have been removed in 5.0 [[ef24d5d]](http://github.com/elasticsearch/elasticsearch-php/commit/ef24d5d)
+- Deprecate various Percolate endpoints [[959eee5]](http://github.com/elasticsearch/elasticsearch-php/commit/959eee5)
+- Remove old `percolate` parameter on docblocks [[f64345d]](http://github.com/elasticsearch/elasticsearch-php/commit/f64345d)
+- SearchExists Endpoint removed in 5.0 [[6dfc6a0]](http://github.com/elasticsearch/elasticsearch-php/commit/6dfc6a0)
+- [Internal BWC Break] Add better ability to inject namespaces [[b1a27b7]](http://github.com/elasticsearch/elasticsearch-php/commit/b1a27b7)
+- [Internal BWC Break] Refactor to remove Transport dependence in endpoints [[ecd454c]](http://github.com/elasticsearch/elasticsearch-php/commit/ecd454c)
+- [BWC Break] Remove MLT endpoint [[38c05da]](http://github.com/elasticsearch/elasticsearch-php/commit/38c05da)
+- [BWC Break] Remove DeleteByQuery endpoint [[9f3776a]](http://github.com/elasticsearch/elasticsearch-php/commit/9f3776a)
+- [BWC Break] Rename internal TermVector -> TermVectors, remove old public TermVector [[cbe8619]](http://github.com/elasticsearch/elasticsearch-php/commit/cbe8619)
+- [BWC] Add getPath() method to ConnectionInterface [[8bcf1a8]](http://github.com/elasticsearch/elasticsearch-php/commit/8bcf1a8)
+- [BWC] Add getUserPass() method to ConnectionInterface [[586fbdb]](http://github.com/elasticsearch/elasticsearch-php/commit/586fbdb)
+- [BWC] Add getHost() method to ConnectionInterface [[445fdea]](http://github.com/elasticsearch/elasticsearch-php/commit/445fdea)
+- Tasks/List and Tasks/Get are now separate endpoints [[e0cc5f9]](http://github.com/elasticsearch/elasticsearch-php/commit/752d5a2)
+
+### Updated/Added whitelist params
+
+- Add Ingest namespace and endpoints [[7b87954]](http://github.com/elasticsearch/elasticsearch-php/commit/7b87954)
+- Add `pipeline` parameter to Bulk endpoint whitelist [[3fa1c51]](http://github.com/elasticsearch/elasticsearch-php/commit/3fa1c51)
+- Add `pipeline` to Index endpoint [[db5d794]](http://github.com/elasticsearch/elasticsearch-php/commit/db5d794)
+- Add `include_defaults` param to Indices/GetSettings whitelist [[496071c]](http://github.com/elasticsearch/elasticsearch-php/commit/496071c)
+- Add `preserve_existing` param to Indices/PutSettings whitelist [[69389fc]](http://github.com/elasticsearch/elasticsearch-php/commit/69389fc)
+- Add Cluster/AllocationExplain endpoint [[f9c297c]](http://github.com/elasticsearch/elasticsearch-php/commit/f9c297c)
+- Add Ingest namespace and endpoints [[66c851f]](http://github.com/elasticsearch/elasticsearch-php/commit/66c851f)
+- Add missing params to Analyze endpoint: `char_filter`, `format`, `attributes`, `explain` [[8a0a932]](http://github.com/elasticsearch/elasticsearch-php/commit/8a0a932)
+- `filters` is now `filter` in Analyze endpoint [[94dbb15]](http://github.com/elasticsearch/elasticsearch-php/commit/94dbb15)
+- Add `size` param to Cat/Threadpool whitelist [[bece0e5]](http://github.com/elasticsearch/elasticsearch-php/commit/bece0e5)
+- Add `task_id` to Tasks/Get whitelist [[6a315e0]](http://github.com/elasticsearch/elasticsearch-php/commit/6a315e0)
+- Add `docvalue_fields` to Search whitelist, remove `fields` [[63ff8c5]](http://github.com/elasticsearch/elasticsearch-php/commit/63ff8c5)
+- Add `format` to Cat/Aliases whitelist [[68630a0]](http://github.com/elasticsearch/elasticsearch-php/commit/68630a0)
+- Add 'thread_pool_patterns' parameter to Cat\Threadpool endpoint [[c0820dc]](http://github.com/elasticsearch/elasticsearch-php/commit/c0820dc)
+- Add 's' sort param to all Cat endpoints [[87f23a1]](http://github.com/elasticsearch/elasticsearch-php/commit/87f23a1)
+- Add '_source' to Update whitelist [[d33be49]](http://github.com/elasticsearch/elasticsearch-php/commit/d33be49)
+- Add 'ignore_unavailable' to Snapshot/Status whitelist [[f90c2dd]](http://github.com/elasticsearch/elasticsearch-php/commit/f90c2dd)
+- Add 'ignore_unavailable' to Snapshot/Get whitelist [[93c4f22]](http://github.com/elasticsearch/elasticsearch-php/commit/93c4f22)
+- Add 'stored_fields' to Mget whitelist [[054ebed]](http://github.com/elasticsearch/elasticsearch-php/commit/054ebed)
+- Add 'wait_for_no_relocating_shards' to Cluster/Health whitelist [[8448f99]](http://github.com/elasticsearch/elasticsearch-php/commit/8448f99)
+- Add 'health' to Cat/Indices whitelist [[06a3bf5]](http://github.com/elasticsearch/elasticsearch-php/commit/06a3bf5)
+- Add '_source_include', '_source_exclude', 'pipeline' params to Bulk whitelist [[3ca12f4]](http://github.com/elasticsearch/elasticsearch-php/commit/3ca12f4)
+- Add 'stored_fields' to Get Endpoint [[c57a5a4]](http://github.com/elasticsearch/elasticsearch-php/commit/c57a5a4)
+- Add '_source' to Bulk endpoint whitelist [[35b7087]](http://github.com/elasticsearch/elasticsearch-php/commit/35b7087)
+
+### Documentation
+
+- [DOCS] Usage example for creating ClientBuilder fixed (#406) [[6a868ea]](http://github.com/elasticsearch/elasticsearch-php/commit/6a868ea)
+- [Docs] Fix typo. (#409) [[b013ab0]](http://github.com/elasticsearch/elasticsearch-php/commit/b013ab0)
+- Docs: Fixed broken link. [[17a4ed7]](http://github.com/elasticsearch/elasticsearch-php/commit/17a4ed7)
+- [DOCS] Rebuild auto-generated docs [[2904d7a]](http://github.com/elasticsearch/elasticsearch-php/commit/2904d7a)
+- Add script to generate docs [[4ce648c]](http://github.com/elasticsearch/elasticsearch-php/commit/4ce648c)
+- Update Readme with 5.0 branching information [[ddb8ecd]](http://github.com/elasticsearch/elasticsearch-php/commit/ddb8ecd)
+- [DOCS] Update URL/Email in class-level doc blocks [[8238cb3]](http://github.com/elasticsearch/elasticsearch-php/commit/8238cb3)
+- [DOCS] Update copyright year in licenses [[fcc4ad6]](http://github.com/elasticsearch/elasticsearch-php/commit/fcc4ad6)
+- [DOCS] Add Breaking Changes list for 5.0 [[65953ac]](http://github.com/elasticsearch/elasticsearch-php/commit/65953ac)
+- [DOCS] add getSource method to the readme (#465) [[90cbdfb]](http://github.com/elasticsearch/elasticsearch-php/commit/90cbdfb)
+- [DOCS] Replace deprecated filtered query with boolean [[3b81615]](http://github.com/elasticsearch/elasticsearch-php/commit/3b81615)
+- [DOCS] Add Plastic Laravel integration to community page [[e4530a7]](http://github.com/elasticsearch/elasticsearch-php/commit/e4530a7)
+- [DOCS] Fix return type in docblock for all Exists* endpoints [[498c003]](http://github.com/elasticsearch/elasticsearch-php/commit/498c003)
+- Add autogenerated reference documentation [[bd64d52]](http://github.com/elasticsearch/elasticsearch-php/commit/bd64d52)
+- [DOCS] Regenerate reference docs [[030d96e]](http://github.com/elasticsearch/elasticsearch-php/commit/030d96e)
+
+### Cleanup
+
+- Remove benchmark autoload [[74b5ad9]](http://github.com/elasticsearch/elasticsearch-php/commit/74b5ad9)
+- Remove old rest-spec parser [[07754c4]](http://github.com/elasticsearch/elasticsearch-php/commit/07754c4)
+- Remove unused benchmarks [[20a75b1]](http://github.com/elasticsearch/elasticsearch-php/commit/20a75b1)
+- Automated PSR-2 style cleanup [[fbe6f92]](http://github.com/elasticsearch/elasticsearch-php/commit/fbe6f92)
+- Tweak script for new cli format [[4adbe94]](http://github.com/elasticsearch/elasticsearch-php/commit/4adbe94)
+- Fix Indices/Flush after autogeneration [[d56e2c4]](http://github.com/elasticsearch/elasticsearch-php/commit/d56e2c4)
+- Tweak SpecParser template [[8341c4c]](http://github.com/elasticsearch/elasticsearch-php/commit/8341c4c)
+- Added output folder from SpecParser to gitignore [[cfd49ee]](http://github.com/elasticsearch/elasticsearch-php/commit/cfd49ee)
+- Updated ParseSpec to be able to run from console and use new api path [[e0cc5f9]](http://github.com/elasticsearch/elasticsearch-php/commit/d44a323)
+
+### Bugfixes and Misc.
+
+- Split Create out to its own internal endpoint for simplicity [[9eb573a]](http://github.com/elasticsearch/elasticsearch-php/commit/9eb573a)
+- Cat/Snapshots 'repository' param is not in-fact required, despite spec [[6c77f62]](http://github.com/elasticsearch/elasticsearch-php/commit/6c77f62)
+- Fix error handler when no structured error is present [[f380a69]](http://github.com/elasticsearch/elasticsearch-php/commit/f380a69)
+- add JSON_PRESERVE_ZERO_FRACTION for Json_encode (#481) [[2ab3971]](http://github.com/elasticsearch/elasticsearch-php/commit/2ab3971)
+- Simplify error parsing now that we don't support <2.0 errors [[a6d896b]](http://github.com/elasticsearch/elasticsearch-php/commit/a6d896b)
+- Added support for PHP 7.1 (#474) [[864d4d3]](http://github.com/elasticsearch/elasticsearch-php/commit/864d4d3)
+- Type exists URI has changed to index/_mapping/type [[dd63eaa]](http://github.com/elasticsearch/elasticsearch-php/commit/dd63eaa)
+- Index creation only accepts PUT verbs now [[9c620c2]](http://github.com/elasticsearch/elasticsearch-php/commit/9c620c2)
+- Update SearchResponseIterator to remove old-style scan/scroll flow [[72f3b15]](http://github.com/elasticsearch/elasticsearch-php/commit/72f3b15)
+- Add "extended" host configuration syntax [[a0ddad1]](http://github.com/elasticsearch/elasticsearch-php/commit/a0ddad1)
+- Allow ConnectionFactory to be override (#456) [[cc2a5fe]](http://github.com/elasticsearch/elasticsearch-php/commit/cc2a5fe)
+- Special-case unwrapping for async methods that use Exist* endpoints [[347e5c5]](http://github.com/elasticsearch/elasticsearch-php/commit/347e5c5)
+- composer: bump min version to PHP 5.6 (#451) [[6648646]](http://github.com/elasticsearch/elasticsearch-php/commit/6648646)
+- Allow to get multiple pipelines without id (#453) [[c7f737b]](http://github.com/elasticsearch/elasticsearch-php/commit/c7f737b)
+- Split, refactor and fix some tests (#447) [[68e819b]](http://github.com/elasticsearch/elasticsearch-php/commit/68e819b)
+- Tests cleaned up a little [[afc9af0]](http://github.com/elasticsearch/elasticsearch-php/commit/afc9af0)
+- Fix doc output on github [[62d6132]](http://github.com/elasticsearch/elasticsearch-php/commit/62d6132)
+- (pr/445) Move resultOrFuture from endpoint to transport [[80bfeea]](http://github.com/elasticsearch/elasticsearch-php/commit/80bfeea)
+- Manually convert true/false to "true"/"false" before http_build_query() [[bef93cb]](http://github.com/elasticsearch/elasticsearch-php/commit/bef93cb)
+- getApiPath function returns path without trailing slash [[8bcfaf0]](http://github.com/elasticsearch/elasticsearch-php/commit/8bcfaf0)
+- Use valid SPDX license identifier [[963e635]](http://github.com/elasticsearch/elasticsearch-php/commit/963e635)
+- Fix bug when Create is called with an stdClass body [[adcaa2c]](http://github.com/elasticsearch/elasticsearch-php/commit/adcaa2c)
+- Fix comment tag [[3b8e918]](http://github.com/elasticsearch/elasticsearch-php/commit/3b8e918)
+- Add .github templates [[104a7ea]](http://github.com/elasticsearch/elasticsearch-php/commit/104a7ea)
 
 ### Testing
-- [TEST] Update skiplist [[22e7cc5]](http://github.com/elasticsearch/elasticsearch-php/commit/22e7cc5)
-- [TRAVIS] Add node attribute for nodeattr tests [[0aa9638]](http://github.com/elasticsearch/elasticsearch-php/commit/0aa9638)
-- [TEST] cleanup cat repos [[bed0338]](http://github.com/elasticsearch/elasticsearch-php/commit/bed0338)
-- [Travis] update snapshot handling [[1e6fa0c]](http://github.com/elasticsearch/elasticsearch-php/commit/1e6fa0c)
-
-## Release 2.1.2
-
-- Remove IntrospectionProcessor from default to make logs less noisy [[0a80de4]](http://github.com/elasticsearch/elasticsearch-php/commit/0a80de4)
-- Remove redundant logging on failure [[f31a211]](http://github.com/elasticsearch/elasticsearch-php/commit/f31a211)
-
-## Release 2.1.1
-
-- More robust error logging during connection failure / retries [[0069fd6]](http://github.com/elasticsearch/elasticsearch-php/commit/0069fd6)
-
-## Release 2.1.0
-- Log failure when encountering non-retry hard curl exception [[8e7e03f]](http://github.com/elasticsearch/elasticsearch-php/commit/8e7e03f)
-- Embed a MaxRetriesException inside a TransportException when thrown due to retries [[deff12f]](http://github.com/elasticsearch/elasticsearch-php/commit/deff12f)
-- Add a SimpleConnectionPool [[4a3df40]](http://github.com/elasticsearch/elasticsearch-php/commit/4a3df40)
-- If body is null/empty, return string instead of trying to decode [[c4f9d41]](http://github.com/elasticsearch/elasticsearch-php/commit/c4f9d41)
-- Accept `field` on GetFieldMapping endpoint for bwc [[6ecf35e]](http://github.com/elasticsearch/elasticsearch-php/commit/6ecf35e)
-- Fix typo in GetFieldMapping endpoint (field -> fields) [[2b323c4]](http://github.com/elasticsearch/elasticsearch-php/commit/2b323c4)
-- Ping should return false on Transport/Connection errors [[699d9dd]](http://github.com/elasticsearch/elasticsearch-php/commit/699d9dd)
-
-### Documentation Related
-- [Docs] Clarify NoNodesAvailableException [[c0d6332]](http://github.com/elasticsearch/elasticsearch-php/commit/c0d6332)
-- [Docs] Fix missing code block [[6793ad4]](http://github.com/elasticsearch/elasticsearch-php/commit/6793ad4)
-- [Docs] Fix connection pool configuration docs [[26edc73]](http://github.com/elasticsearch/elasticsearch-php/commit/26edc73)
-- [Docs] Add docs about per-request timeouts [[d5be83f]](http://github.com/elasticsearch/elasticsearch-php/commit/d5be83f)
-- [Docs] Add missing subtitle [[22b51af]](http://github.com/elasticsearch/elasticsearch-php/commit/22b51af)
-- [Docs] add elasticsearcher to Community page [[b3dd9a2]](http://github.com/elasticsearch/elasticsearch-php/commit/b3dd9a2)
-- Update readme about versions [[8ad7709]](http://github.com/elasticsearch/elasticsearch-php/commit/8ad7709)
-- Remove accidentally added log file [[0f43a5c]](http://github.com/elasticsearch/elasticsearch-php/commit/0f43a5c)
-
-### Travis and Testing Related
-- Blacklist old 0.4 branch from travis [[ea8f775]](http://github.com/elasticsearch/elasticsearch-php/commit/ea8f775)
-- [Travis] Add 2.1 to travis matrix [[2f6d20f]](http://github.com/elasticsearch/elasticsearch-php/commit/2f6d20f)
-- Update crud.asciidoc [[4a679b7]](http://github.com/elasticsearch/elasticsearch-php/commit/4a679b7)
-- Readme: Travis badge added [[dce31b3]](http://github.com/elasticsearch/elasticsearch-php/commit/dce31b3)
-- [TESTS] Small tweak to make test runner PHP-7 compatible [[47ae254]](http://github.com/elasticsearch/elasticsearch-php/commit/47ae254)
-- [TESTS] temporary fix for cleaning up repos after tests [[d56da4b]](http://github.com/elasticsearch/elasticsearch-php/commit/d56da4b)
-- travis: add path.repo to config [[6576184]](http://github.com/elasticsearch/elasticsearch-php/commit/6576184)
-- [TESTS] Clear snapshots [[680cb90]](http://github.com/elasticsearch/elasticsearch-php/commit/680cb90)
-- [TESTS] Simplify exception matching and handling [[eba21eb]](http://github.com/elasticsearch/elasticsearch-php/commit/eba21eb)
-- Add RequestTimeout408 exception [[9d70653]](http://github.com/elasticsearch/elasticsearch-php/commit/9d70653)
-- [TESTS] debug output tweaks [[9276e5e]](http://github.com/elasticsearch/elasticsearch-php/commit/9276e5e)
-- travis: update version matrix [[6d47211]](http://github.com/elasticsearch/elasticsearch-php/commit/6d47211)
-- [TESTS] use multiHandler() in tests, since singleHandler is not available in older versions of PHP [[e7fa5c8]](http://github.com/elasticsearch/elasticsearch-php/commit/e7fa5c8)
-- travis: more find, less glob [[604e71a]](http://github.com/elasticsearch/elasticsearch-php/commit/604e71a)
-- travis: more script tweaks [[cca9216]](http://github.com/elasticsearch/elasticsearch-php/commit/cca9216)
-- travis: more script tweaks [[c92a5ad]](http://github.com/elasticsearch/elasticsearch-php/commit/c92a5ad)
-- travis: add repo to config for snapshot tests [[d17f1e1]](http://github.com/elasticsearch/elasticsearch-php/commit/d17f1e1)
-- travis: PHP 5.3 is no longer supported [[9eafee1]](http://github.com/elasticsearch/elasticsearch-php/commit/9eafee1)
-- travis: Just kidding, try glob path instead [[214b0e7]](http://github.com/elasticsearch/elasticsearch-php/commit/214b0e7)
-- travis: hardcode unzipping dir [[fe96602]](http://github.com/elasticsearch/elasticsearch-php/commit/fe96602)
-- travis: flush output of RestSpecRunner [[bcefcff]](http://github.com/elasticsearch/elasticsearch-php/commit/bcefcff)
-- travis: use snapshot builds per-branch instead of release versions [[18e4e72]](http://github.com/elasticsearch/elasticsearch-php/commit/18e4e72)
-- travis: Rest-Spec should be obtained after install [[59546cf]](http://github.com/elasticsearch/elasticsearch-php/commit/59546cf)
-- [Tests] Delete unreliable, bad tests [[31eb9e0]](http://github.com/elasticsearch/elasticsearch-php/commit/31eb9e0)
-- travis: Add util script to ensure cluster is alive before proceeding [[563412a]](http://github.com/elasticsearch/elasticsearch-php/commit/563412a)
-- travis: Use bwc startup options [[a8e63a5]](http://github.com/elasticsearch/elasticsearch-php/commit/a8e63a5)
-- travis: better startup options for Elasticsearch [[d6624a2]](http://github.com/elasticsearch/elasticsearch-php/commit/d6624a2)
-- travis: Set executable flag on shell script [[4b9fbcd]](http://github.com/elasticsearch/elasticsearch-php/commit/4b9fbcd)
-- travis: typo in download shell script name [[3e0141a]](http://github.com/elasticsearch/elasticsearch-php/commit/3e0141a)
-- Remove old, unused submodule [[c6e7570]](http://github.com/elasticsearch/elasticsearch-php/commit/c6e7570)
-- travis: run RestSpecRunner before tests [[5355ec8]](http://github.com/elasticsearch/elasticsearch-php/commit/5355ec8)
-
-## Release 2.0.3
-- Prefer root_cause reason over the main reason if available [[aa2e313]](http://github.com/elasticsearch/elasticsearch-php/commit/aa2e313)
-- Validate that index/type/id are non-null, non-empty when deleting [[8072aee]](http://github.com/elasticsearch/elasticsearch-php/commit/8072aee)
-- Attempt to decode 400-level exceptions too [[9ab8904]](http://github.com/elasticsearch/elasticsearch-php/commit/9ab8904)
-- [Docs] Header links are hard to see, make dedicated link [[7919ead]](http://github.com/elasticsearch/elasticsearch-php/commit/7919ead)
-- Merge pull request #317 from ssm2003/patch-3 [[4147f16]](http://github.com/elasticsearch/elasticsearch-php/commit/4147f16)
-- Merge pull request #316 from ssm2003/patch-2 [[d2b7552]](http://github.com/elasticsearch/elasticsearch-php/commit/d2b7552)
-- Merge pull request #315 from ssm2003/patch-1 [[ad5f113]](http://github.com/elasticsearch/elasticsearch-php/commit/ad5f113)
-- Populate lastRequestInfo with request/response [[68bfd10]](http://github.com/elasticsearch/elasticsearch-php/commit/68bfd10)
-- [Docs] Add community integration page [[bcffa45]](http://github.com/elasticsearch/elasticsearch-php/commit/bcffa45)
-- Merge pull request #313 from machour/patch-1 [[31137b3]](http://github.com/elasticsearch/elasticsearch-php/commit/31137b3)
-- Fixed the bulk indexed with batches example [[80b7bdc]](http://github.com/elasticsearch/elasticsearch-php/commit/80b7bdc)
-
-
-## Release 2.0.2
-- Use curl opts for auth instead of inline syntax [[4b01af8]](http://github.com/elasticsearch/elasticsearch-php/commit/4b01af8)
-
-## Release 2.0.1
-- Add ClientBuilder::FromConfig to allow easier automated building of Client [[a07486d]](http://github.com/elasticsearch/elasticsearch-php/commit/a07486d)
-
-## Release 2.0.0
-- Added helper iterators for scrolled search [[24598e7]](http://github.com/elasticsearch/elasticsearch-php/commit/24598e7)
-- comoposer command error [[8ed2885]](http://github.com/elasticsearch/elasticsearch-php/commit/8ed2885)
-
-## Release 2.0.0-beta5
-- [TESTS] Fix mistake due to poor cherry-picking skills :) [[1bae4ed]](http://github.com/elasticsearch/elasticsearch-php/commit/1bae4ed)
-- Add Indices/ShardStores endpoint [[aa0f13f]](http://github.com/elasticsearch/elasticsearch-php/commit/aa0f13f)
-- Add 'fields' param to Bulk Endpoint [[d434bf0]](http://github.com/elasticsearch/elasticsearch-php/commit/d434bf0)
-- Add RenderSearchTemplate Endpoint [[dfd041d]](http://github.com/elasticsearch/elasticsearch-php/commit/dfd041d)
-- Add `filter_path` to global param whitelist [[0943f73]](http://github.com/elasticsearch/elasticsearch-php/commit/0943f73)
-- [TEST] Fix bug where inline stash replacements were not being honored [[a4d162e]](http://github.com/elasticsearch/elasticsearch-php/commit/a4d162e)
-- [TEST] Fix stash replacement to make PHP 5.3 happy [[91a6e76]](http://github.com/elasticsearch/elasticsearch-php/commit/91a6e76)
-- Add alias for TermVectors -> TermVector [[c4330e8]](http://github.com/elasticsearch/elasticsearch-php/commit/c4330e8)
-- [TEST] fix bug where array_key_exists explodes due to doubles [[1b071b5]](http://github.com/elasticsearch/elasticsearch-php/commit/1b071b5)
-- Add ''fielddata_fields' and 'filter_path'' param to Search whitelist [[2c2632f]](http://github.com/elasticsearch/elasticsearch-php/commit/2c2632f)
-- Add 'human' param to Indices/Get whitelist [[e66197f]](http://github.com/elasticsearch/elasticsearch-php/commit/e66197f)
-- Add Indices/GetUpgrade endpoint [[8bc2124]](http://github.com/elasticsearch/elasticsearch-php/commit/8bc2124)
-- Add Indices/Upgrade endpoint [[138be12]](http://github.com/elasticsearch/elasticsearch-php/commit/138be12)
-- Add Indices/flushSynced endpoint [[04d909b]](http://github.com/elasticsearch/elasticsearch-php/commit/04d909b)
-- Add more missing query-string parameters [[a34c725]](http://github.com/elasticsearch/elasticsearch-php/commit/a34c725)
-- Add missing query-string parameters [[f59a521]](http://github.com/elasticsearch/elasticsearch-php/commit/f59a521)
-- Add missing whitelist parameters to SearchTemplate endpoint [[48aed04]](http://github.com/elasticsearch/elasticsearch-php/commit/48aed04)
-- [TESTS] Add workaround for rest-spec package path change in core [[5f3939e]](http://github.com/elasticsearch/elasticsearch-php/commit/5f3939e)
-- Add 'fields' parameter to FieldStats endpoint [[49a7ef4]](http://github.com/elasticsearch/elasticsearch-php/commit/49a7ef4)
-- FieldStats endpoint accepts a body [[79a47cb]](http://github.com/elasticsearch/elasticsearch-php/commit/79a47cb)
-- Add Cat/Segments Endpoint [[04a551f]](http://github.com/elasticsearch/elasticsearch-php/commit/04a551f)
-- NoDocumentsToGetException needs nested original exception [[4b7e14e]](http://github.com/elasticsearch/elasticsearch-php/commit/4b7e14e)
-- Fix error string handling when creating Exceptions [[f22c6c2]](http://github.com/elasticsearch/elasticsearch-php/commit/f22c6c2)
-
-
-## Release 2.0.0-beta4
-- [DOCS] Fix bulk example [[fce4848]](http://github.com/elasticsearch/elasticsearch-php/commit/fce4848)
-- Add Indices/Seal endpoint [[a08252c]](http://github.com/elasticsearch/elasticsearch-php/commit/a08252c)
-- [TEST] Fix YamlRunner to correctly stash values in object hierarchies [[2916727]](http://github.com/elasticsearch/elasticsearch-php/commit/2916727)
-- Add SearchExists Endpoint [[a47eb67]](http://github.com/elasticsearch/elasticsearch-php/commit/a47eb67)
-- Add more missing query-string parameters [[03bdb78]](http://github.com/elasticsearch/elasticsearch-php/commit/03bdb78)
-- Add missing query-string parameters [[6efdedd]](http://github.com/elasticsearch/elasticsearch-php/commit/6efdedd)
-- (pr/232) fix Warning for empty body when HEAD request - check if index exists [[e6fa2da]](http://github.com/elasticsearch/elasticsearch-php/commit/e6fa2da)
-
-## Release 2.0.0-beta3
-
--  (HEAD, origin/2.0, 2.0) Add missing whitelist parameters to SearchTemplate endpoint [[74a7ca5]](http://github.com/elasticsearch/elasticsearch-php/commit/74a7ca5)
--  [TEST] Update version parsing to handle new format [[b86fca5]](http://github.com/elasticsearch/elasticsearch-php/commit/b86fca5)
--  Add FieldStats endpoint [[4935fd9]](http://github.com/elasticsearch/elasticsearch-php/commit/4935fd9)
--  Merge pull request #217 from simplechris/patch-4 [[5a92117]](http://github.com/elasticsearch/elasticsearch-php/commit/5a92117)
--  Add PSR-2 check to the contributing guidelines [[2ad3609]](http://github.com/elasticsearch/elasticsearch-php/commit/2ad3609)
--  Add .php_cs file [[17d0eac]](http://github.com/elasticsearch/elasticsearch-php/commit/17d0eac)
--  Add missing docblocks [[7305d45]](http://github.com/elasticsearch/elasticsearch-php/commit/7305d45)
--  Misc cleanup [[35cb77e]](http://github.com/elasticsearch/elasticsearch-php/commit/35cb77e)
--  Normalize blank lines between methods [[0f2cdae]](http://github.com/elasticsearch/elasticsearch-php/commit/0f2cdae)
--  Add blank line before 'return' statements to aid readability [[fabd2cc]](http://github.com/elasticsearch/elasticsearch-php/commit/fabd2cc)
--  Normalize spacing after explicit type casting [[057b1cd]](http://github.com/elasticsearch/elasticsearch-php/commit/057b1cd)
--  Remove unused 'use' statements [[f6b2882]](http://github.com/elasticsearch/elasticsearch-php/commit/f6b2882)
--  Normalize Elasticsearch\Common\Exception docblocks [[0a3a7ec]](http://github.com/elasticsearch/elasticsearch-php/commit/0a3a7ec)
--  Remove NamespaceFutureUtil trait [[9a75582]](http://github.com/elasticsearch/elasticsearch-php/commit/9a75582)
--  Remove commented-out debugging [[21c2278]](http://github.com/elasticsearch/elasticsearch-php/commit/21c2278)
--  Normalize docblocks [[eaf18e2]](http://github.com/elasticsearch/elasticsearch-php/commit/eaf18e2)
--  Remove redundant comments [[5c304a2]](http://github.com/elasticsearch/elasticsearch-php/commit/5c304a2)
--  Use PSR-2 coding standard [[ad3db43]](http://github.com/elasticsearch/elasticsearch-php/commit/ad3db43)
--  [TEST] Populate response body with exception message so that it can be verified [[65f1676]](http://github.com/elasticsearch/elasticsearch-php/commit/65f1676)
--  Merge pull request #220 from simplechris/fix/client-builder-handler-selection [[563124d]](http://github.com/elasticsearch/elasticsearch-php/commit/563124d)
--  ClientBuilder fixes for PHP 5.4 [[25eaa71]](http://github.com/elasticsearch/elasticsearch-php/commit/25eaa71)
--  Remove save_to streaming functionality - not needed with curl handlers [[f32e038]](http://github.com/elasticsearch/elasticsearch-php/commit/f32e038)
--  Merge pull request #216 from simplechris/patch-2 [[6cbe2fe]](http://github.com/elasticsearch/elasticsearch-php/commit/6cbe2fe)
--  Add missing use statements [[58527d5]](http://github.com/elasticsearch/elasticsearch-php/commit/58527d5)
-
-## Release 2.0.0-beta2
-
-- `curl_reset` was added in 5.5, use `curl_multi_init` to check for curl instead [[b722802]](http://github.com/elasticsearch/elasticsearch-php/commit/b722802)
-- Update Composer.json with PSR-4 [[7bfd251]](http://github.com/elasticsearch/elasticsearch-php/commit/7bfd251)
-- Add Cat\Plugins endpoint [[3044da9]](http://github.com/elasticsearch/elasticsearch-php/commit/3044da9)
-- Indices/Stats endpoint should implode multi-valued metric parameters into a single string [[c2097b9]](http://github.com/elasticsearch/elasticsearch-php/commit/c2097b9)
-- Fix typo in 'metric' argument of Stats function in IndicesNamespace.php [[db85afb]](http://github.com/elasticsearch/elasticsearch-php/commit/db85afb)
+
+Lots of work re-working the REST Yaml test framework, getting travis to play nicely with Java8, and misc
+tweaks over time.  The test framework is in much better shape, largely thanks to help from community member @joelwurtz!
+
+- [TEST] Add 5.x to test matrix [[77b548d]](http://github.com/elasticsearch/elasticsearch-php/commit/77b548d)
+- [TEST] Fixup server startup [[18ea943]](http://github.com/elasticsearch/elasticsearch-php/commit/18ea943)
+- [TEST] Add ignore to custom param since ES now validates extraneous uri params [[61f62d8]](http://github.com/elasticsearch/elasticsearch-php/commit/61f62d8)
+- [TEST] Regex to detect "stashed" values is not useful, throws false-positives [[7ff9b20]](http://github.com/elasticsearch/elasticsearch-php/commit/7ff9b20)
+- [TEST] (Fix) Better context to true/false failures [[a9ee47d]](http://github.com/elasticsearch/elasticsearch-php/commit/a9ee47d)
+- [TEST] Better context to true/false failures [[9df055b]](http://github.com/elasticsearch/elasticsearch-php/commit/9df055b)
+- [TEST] Add 'indices.shrink/10_basic.yaml' to temp blacklist [[aa93f39]](http://github.com/elasticsearch/elasticsearch-php/commit/aa93f39)
+- [TEST] Only run sync tests on Travis [[2f7b863]](http://github.com/elasticsearch/elasticsearch-php/commit/2f7b863)
+- [TEST] Update travis config to use ES 5.0 branch [[cbad348]](http://github.com/elasticsearch/elasticsearch-php/commit/cbad348)
+- [TEST] Add back accidentally deleted annotations [[c7f8c06]](http://github.com/elasticsearch/elasticsearch-php/commit/c7f8c06)
+- [TEST] Better snapshot/repo clearing [[cc3a40d]](http://github.com/elasticsearch/elasticsearch-php/commit/cc3a40d)
+- [TEST] output tweaks for better debugging, add temporary blacklist for fatal parsing files [[cb1956b]](http://github.com/elasticsearch/elasticsearch-php/commit/cb1956b)
+- [TEST] Tweak verbosity of tests [[e0cc5f9]](http://github.com/elasticsearch/elasticsearch-php/commit/e0cc5f9)
+- [TEST] No need to test below PHP 5.6 on master [[7aad25a]](http://github.com/elasticsearch/elasticsearch-php/commit/7aad25a)
+- [TEST] Allow hhvm to fail [[fe6993d]](http://github.com/elasticsearch/elasticsearch-php/commit/fe6993d)
+- [TEST] Remove ES host/port so it starts in "dev" mode [[c91242d]](http://github.com/elasticsearch/elasticsearch-php/commit/c91242d)
+- [TEST] Bump travis file descriptors [[b24fc85]](http://github.com/elasticsearch/elasticsearch-php/commit/b24fc85)
+- [TEST] Bump travis file descriptors [[5cd7c37]](http://github.com/elasticsearch/elasticsearch-php/commit/5cd7c37)
+- [TEST] Bump travis file descriptors [[65f2eb9]](http://github.com/elasticsearch/elasticsearch-php/commit/65f2eb9)
+- [TEST] (Nuclear option) more Java8 JRE tweaks [[00ce1df]](http://github.com/elasticsearch/elasticsearch-php/commit/00ce1df)
+- [TEST] (Hundred and one time's a charm) more Java8 JRE tweaks [[c38e5fe]](http://github.com/elasticsearch/elasticsearch-php/commit/c38e5fe)
+- [TEST] (Hundredth time's a charm) more Java8 JRE tweaks [[2cef10d]](http://github.com/elasticsearch/elasticsearch-php/commit/2cef10d)
+- [TEST] (And yet) more Java8 JRE tweaks [[ecb44ab]](http://github.com/elasticsearch/elasticsearch-php/commit/ecb44ab)
+- [TEST] (Yet) more Java8 JRE tweaks [[afc6b8a]](http://github.com/elasticsearch/elasticsearch-php/commit/afc6b8a)
+- [TEST] More Java8 JRE tweaks [[0567579]](http://github.com/elasticsearch/elasticsearch-php/commit/0567579)
+- [TEST] More Java8 JRE tweaks [[9869977]](http://github.com/elasticsearch/elasticsearch-php/commit/9869977)
+- [TEST] Print java version for debug [[9dec069]](http://github.com/elasticsearch/elasticsearch-php/commit/9dec069)
+- [TEST] Manually configure Java8 JRE [[1fd3612]](http://github.com/elasticsearch/elasticsearch-php/commit/1fd3612)
+- Revert "[TEST] Use Java 8 for tests" [[6fc4c5c]](http://github.com/elasticsearch/elasticsearch-php/commit/6fc4c5c)
+- [TEST] Use Java 8 for tests [[2d59159]](http://github.com/elasticsearch/elasticsearch-php/commit/2d59159)
+- [TEST] Replace stash before finding nested variables in match [[2dae755]](http://github.com/elasticsearch/elasticsearch-php/commit/2dae755)
+- [TEST] Convert `tasks.list` to `tasks.get` because `list` is a reserved word [[e0956a5]](http://github.com/elasticsearch/elasticsearch-php/commit/e0956a5)
+- [TEST] Small tweak to timestamp regex [[d5e50c1]](http://github.com/elasticsearch/elasticsearch-php/commit/d5e50c1)
+- [TEST] return second level of exception message if possible, for further testing [[a76cbf2]](http://github.com/elasticsearch/elasticsearch-php/commit/a76cbf2)
+- [TEST] Master tests only track ES-master (5.0 alpha) now [[76e621c]](http://github.com/elasticsearch/elasticsearch-php/commit/76e621c)
+- [TEST] Fix jq syntax for numeric branches (e.g. `2.2`) [[eb48dab]](http://github.com/elasticsearch/elasticsearch-php/commit/eb48dab)
+- [TEST] Automate snapshot retrieval [[c08b08b]](http://github.com/elasticsearch/elasticsearch-php/commit/c08b08b)
+- [TEST] Update snapshot download script for 2.2 [[350cd6e]](http://github.com/elasticsearch/elasticsearch-php/commit/350cd6e)
+- [TEST] Update travis matrix [[04bcf81]](http://github.com/elasticsearch/elasticsearch-php/commit/04bcf81)
+- [TEST] Invoke phpunit dependency instead of travis phpunit.phar [[f9e0d99]](http://github.com/elasticsearch/elasticsearch-php/commit/f9e0d99)
+- Revert "[TEST] fix object notation" [[b966328]](http://github.com/elasticsearch/elasticsearch-php/commit/b966328)
+- Make test fail on Yaml parse error [[f1b3adb]](http://github.com/elasticsearch/elasticsearch-php/commit/f1b3adb)
+- Only show log when test fails [[f2acb43]](http://github.com/elasticsearch/elasticsearch-php/commit/f2acb43)
diff --git a/README.md b/README.md
index 50df218ee..fe14d7273 100644
--- a/README.md
+++ b/README.md
@@ -25,19 +25,19 @@ Version Matrix
 
 | Elasticsearch Version | Elasticsearch-PHP Branch |
 | --------------------- | ------------------------ |
-| >= 5.0                | dev-master               |
+| >= 5.0                | 5.0               |
 | >= 2.0, < 5.0         | 1.0 or 2.0               |
 | >= 1.0, < 2.0         | 1.0 or 2.0               |
 | <= 0.90.x             | 0.4                      |
 
- - If you are using Elasticsearch 5.0+ (master, alpha, beta), use Elasticsearch-PHP dev-master.  A 5.x branch will be cut when Elasticsearch 5.0 GA is released
+ - If you are using Elasticsearch 5.0+ , use Elasticsearch-PHP 5.0 branch.
  - If you are using Elasticsearch 1.x or 2.x, prefer using the Elasticsearch-PHP 2.0 branch.  The 1.0 branch is compatible however.
  - If you are using a version older than 1.0, you must install the `0.4` Elasticsearch-PHP branch. Since ES 0.90.x and below is now EOL, the corresponding `0.4` branch will not receive any more development or bugfixes.  Please upgrade.
  - You should never use Elasticsearch-PHP Master branch, as it tracks Elasticearch master and may contain incomplete features or breaks in backwards compat.  Only use ES-PHP master if you are developing against ES master for some reason.
 
 Documentation
 --------------
-[Full documentation can be found here.](http://www.elasticsearch.org/guide/en/elasticsearch/client/php-api/2.0/index.html)  Docs are stored within the repo under /docs/, so if you see a typo or problem, please submit a PR to fix it!
+[Full documentation can be found here.](http://www.elasticsearch.org/guide/en/elasticsearch/client/php-api/5.0/index.html)  Docs are stored within the repo under /docs/, so if you see a typo or problem, please submit a PR to fix it!
 
 Installation via Composer
 -------------------------
@@ -48,7 +48,7 @@ The recommended method to install _Elasticsearch-PHP_ is through [Composer](http
     ```json
         {
             "require": {
-                "elasticsearch/elasticsearch": "~2.0"
+                "elasticsearch/elasticsearch": "~5.0"
             }
         }
     ```
@@ -62,7 +62,7 @@ The recommended method to install _Elasticsearch-PHP_ is through [Composer](http
 3. Install your dependencies:
 
     ```bash
-        php composer.phar install --no-dev
+        php composer.phar install
     ```
 
 4. Require Composer's autoloader
@@ -80,19 +80,16 @@ The recommended method to install _Elasticsearch-PHP_ is through [Composer](http
     ```
 You can find out more on how to install Composer, configure autoloading, and other best-practices for defining dependencies at [getcomposer.org](http://getcomposer.org).
 
-You'll notice that the installation command specified `--no-dev`.  This prevents Composer from installing the various testing and development dependencies.  For average users, there is no need to install the test suite (which also includes the complete source code of Elasticsearch).  If you wish to contribute to development, just omit the `--no-dev` flag to be able to run tests.
-
 PHP Version Requirement
 ----
-Version 2.0 of this library requires at least PHP version 5.4.0 to function.  If you are on an older version of PHP, it is recommended
-that you upgrade, as PHP 5.3 is official EOL.  Elasticsearch-PHP v0.4.x and v1.x are compatible with PHP 5.3.9+, but will
-eventually stop being supported.
+Version 5.0 of this library requires at least PHP version 5.6.6 to function.  In addition, it requires the native JSON
+extension to be version 1.3.7 or higher.
 
-| PHP Version | Elasticsearch-PHP Branch |
+| Elasticsearch-PHP Branch | PHP Version |
 | ----------- | ------------------------ |
-| >= 5.6.6    | Dev-Master              |
-| >= 5.4.0    | 2.0                      |
-| >= 5.3.9    | 0.4, 1.0                 |
+| 5.0         | >= 5.6.6                 |
+| 2.0         | >= 5.4.0                 |
+| 0.4, 1.0    | >= 5.3.9                 |
 
 
 Quickstart
@@ -320,7 +317,27 @@ Array
 )
 ```
 
-
+Unit Testing using Mock a Elastic Client
+========================================
+```php
+use GuzzleHttp\Ring\Client\MockHandler;
+use Elasticsearch\ClientBuilder;
+
+// The connection class requires 'body' to be a file stream handle
+// Depending on what kind of request you do, you may need to set more values here
+$handler = new MockHandler([
+  'status' => 200,
+  'transfer_stats' => [
+     'total_time' => 100
+  ],
+  'body' => fopen('somefile.json')
+]);
+$builder = ClientBuilder::create();
+$builder->setHosts(['somehost']);
+$builder->setHandler($handler);
+$client = $builder->build();
+// Do a request and you'll get back the 'body' response above
+```
 
 Wrap up
 =======
diff --git a/composer.json b/composer.json
index 1bb5acbb1..d2325ecfe 100644
--- a/composer.json
+++ b/composer.json
@@ -10,7 +10,7 @@
     }
   ],
   "require": {
-    "php": "^5.6.6|^7.0",
+    "php": "^5.6|^7.0|^8.0",
     "psr/log": "~1.0",
     "guzzlehttp/ringphp" : "~1.0"
   },
diff --git a/docs/breaking-changes.asciidoc b/docs/breaking-changes.asciidoc
index aebb599f9..e6028aa58 100644
--- a/docs/breaking-changes.asciidoc
+++ b/docs/breaking-changes.asciidoc
@@ -1,12 +1,21 @@
+== Breaking changes from 2.x
 
-== Breaking changes from 1.x
-
-- The client now requires PHP version 5.4 or higher
-- The entire client configuration and initialization system has changed to a builder pattern.  Please see
-link:_configuration.html[Configuration] for more details
-- Notably, `GuzzleConnection` and `CurlMultiConnection` have been removed.  If your code relied on these classes specifically,
-or configured cURL options explicitly, please see the docs about how the new HTTP handler functions
-- The client no longer ships with a default logger, and Monolog has been moved to "suggest".  Please see
-<<enabling_logger>> for details on how to use Monolog (or equivalent PSR/Log implementation)
-- `custom` parameters are now part of the `client` options (e.g. `['client' => ['custom' => 'abc'] ]`)
-- Exception ignoring is now now part of the `client` options (e.g. `['client' => ['ignore' => 404] ]`)
+- Indices/Analyze Endpoint: `filters` and `char_filters` URI parameters have been renamed to `filter` and `char_filter` respectively
+- SearchExists endpoint has been removed (use `size=0` and `terminate_after=1` instead)
+- Warmers have been removed because they are no longer useful
+- Indices/Optimize Endpoint has been removed (use `_forcemerge` instead)
+- MoreLikeThis (MLT) endpoint has been removed
+- DeleteByQuery endpoint has been removed.
+- Tasks/List and Tasks/Get are now separate endpoints (see: link:http://github.com/elasticsearch/elasticsearch-php/commit/752d5a2[e0cc5f9])
+- Client requires PHP 5.6.6 or higher
+
+=== Deprecations
+
+- Percolator endpoints are deprecated and will be removed in Elasticsearch 6.0
+
+=== Internal BWC Breaks
+
+- Namespace injection has changed slightly.  If you use custom namespaces, you'll need to update your code (see: Add better ability to inject namespaces link:http://github.com/elasticsearch/elasticsearch-php/commit/b1a27b7[b1a27b7])
+- Endpoints no longer use the Transport directly.  If you use custom endpoints, you'll need to do some minor
+refactoring (see: Refactor to remove Transport dependence in endpoints link:http://github.com/elasticsearch/elasticsearch-php/commit/ecd454c[ecd454c])
+- To facilitate testing and other features, the `ConnectionInterface` has expanded to obtain some more methods (link:http://github.com/elasticsearch/elasticsearch-php/commit/8bcf1a8[getPath()], link:http://github.com/elasticsearch/elasticsearch-php/commit/586fbdb[getUserPass()], link:http://github.com/elasticsearch/elasticsearch-php/commit/445fdea[getHost()])
diff --git a/docs/build/Elasticsearch/Client.asciidoc b/docs/build/Elasticsearch/Client.asciidoc
index e7ae18d10..6704ef25a 100644
--- a/docs/build/Elasticsearch/Client.asciidoc
+++ b/docs/build/Elasticsearch/Client.asciidoc
@@ -17,16 +17,13 @@ The class defines the following methods:
 * <<Elasticsearch_Clientget_get,`get()`>>
 * <<Elasticsearch_ClientgetSource_getSource,`getSource()`>>
 * <<Elasticsearch_Clientdelete_delete,`delete()`>>
-* <<Elasticsearch_ClientdeleteByQuery_deleteByQuery,`deleteByQuery()`>>
 * <<Elasticsearch_Clientcount_count,`count()`>>
 * <<Elasticsearch_ClientcountPercolate_countPercolate,`countPercolate()`>>
 * <<Elasticsearch_Clientpercolate_percolate,`percolate()`>>
 * <<Elasticsearch_Clientmpercolate_mpercolate,`mpercolate()`>>
-* <<Elasticsearch_Clienttermvector_termvector,`termvector()`>>
 * <<Elasticsearch_Clienttermvectors_termvectors,`termvectors()`>>
 * <<Elasticsearch_Clientmtermvectors_mtermvectors,`mtermvectors()`>>
 * <<Elasticsearch_Clientexists_exists,`exists()`>>
-* <<Elasticsearch_Clientmlt_mlt,`mlt()`>>
 * <<Elasticsearch_Clientmget_mget,`mget()`>>
 * <<Elasticsearch_Clientmsearch_msearch,`msearch()`>>
 * <<Elasticsearch_Clientcreate_create,`create()`>>
@@ -36,7 +33,6 @@ The class defines the following methods:
 * <<Elasticsearch_Clientsuggest_suggest,`suggest()`>>
 * <<Elasticsearch_Clientexplain_explain,`explain()`>>
 * <<Elasticsearch_Clientsearch_search,`search()`>>
-* <<Elasticsearch_ClientsearchExists_searchExists,`searchExists()`>>
 * <<Elasticsearch_ClientsearchShards_searchShards,`searchShards()`>>
 * <<Elasticsearch_ClientsearchTemplate_searchTemplate,`searchTemplate()`>>
 * <<Elasticsearch_Clientscroll_scroll,`scroll()`>>
@@ -57,6 +53,7 @@ The class defines the following methods:
 * <<Elasticsearch_Clientcat_cat,`cat()`>>
 * <<Elasticsearch_Clientingest_ingest,`ingest()`>>
 * <<Elasticsearch_Clienttasks_tasks,`tasks()`>>
+* <<Elasticsearch_Client-call-_call,`__call()`>>
 * <<Elasticsearch_ClientextractArgument_extractArgument,`extractArgument()`>>
 
 
@@ -192,30 +189,6 @@ $response = $client->delete($params);
 
 
 
-[[Elasticsearch_ClientdeleteByQuery_deleteByQuery]]
-.`deleteByQuery()`
-****
-[source,php]
-----
-/*
-$params[''] @todo finish the rest of these params
-       ['ignore_unavailable'] = (bool) Whether specified concrete indices should be ignored when unavailable (missing or closed)
-       ['allow_no_indices']   = (bool) Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
-       ['expand_wildcards']   = (enum) Whether to expand wildcard expression to concrete indices that are open, closed or both.
-       ['body']  = (array) Request body
-*/
-
-$params = [
-    // ...
-];
-
-$client = ClientBuilder::create()->build();
-$response = $client->deleteByQuery($params);
-----
-****
-
-
-
 [[Elasticsearch_Clientcount_count]]
 .`count()`
 ****
@@ -325,8 +298,8 @@ $response = $client->mpercolate($params);
 
 
 
-[[Elasticsearch_Clienttermvector_termvector]]
-.`termvector()`
+[[Elasticsearch_Clienttermvectors_termvectors]]
+.`termvectors()`
 ****
 [source,php]
 ----
@@ -346,27 +319,6 @@ $params = [
     // ...
 ];
 
-$client = ClientBuilder::create()->build();
-$response = $client->termvector($params);
-----
-****
-
-
-
-[[Elasticsearch_Clienttermvectors_termvectors]]
-.`termvectors()`
-****
-[source,php]
-----
-/*
-Redirect to termvector, this is just a naming difference depending on version
-       ['body']  = (array) Request body
-*/
-
-$params = [
-    // ...
-];
-
 $client = ClientBuilder::create()->build();
 $response = $client->termvectors($params);
 ----
@@ -431,49 +383,6 @@ $response = $client->exists($params);
 
 
 
-[[Elasticsearch_Clientmlt_mlt]]
-.`mlt()`
-****
-[source,php]
-----
-/*
-$params['id']                     = (string) The document ID (Required)
-       ['index']                  = (string) The name of the index (Required)
-       ['type']                   = (string) The type of the document (use `_all` to fetch the first document matching the ID across all types) (Required)
-       ['boost_terms']            = (number) The boost factor
-       ['max_doc_freq']           = (number) The word occurrence frequency as count: words with higher occurrence in the corpus will be ignored
-       ['max_query_terms']        = (number) The maximum query terms to be included in the generated query
-       ['max_word_len']           = (number) The minimum length of the word: longer words will be ignored
-       ['min_doc_freq']           = (number) The word occurrence frequency as count: words with lower occurrence in the corpus will be ignored
-       ['min_term_freq']          = (number) The term frequency as percent: terms with lower occurrence in the source document will be ignored
-       ['min_word_len']           = (number) The minimum length of the word: shorter words will be ignored
-       ['mlt_fields']             = (list) Specific fields to perform the query against
-       ['percent_terms_to_match'] = (number) How many terms have to match in order to consider the document a match (default: 0.3)
-       ['routing']                = (string) Specific routing value
-       ['search_from']            = (number) The offset from which to return results
-       ['search_indices']         = (list) A comma-separated list of indices to perform the query against (default: the index containing the document)
-       ['search_query_hint']      = (string) The search query hint
-       ['search_scroll']          = (string) A scroll search request definition
-       ['search_size']            = (number) The number of documents to return (default: 10)
-       ['search_source']          = (string) A specific search request definition (instead of using the request body)
-       ['search_type']            = (string) Specific search type (eg. `dfs_then_fetch`, `count`, etc)
-       ['search_types']           = (list) A comma-separated list of types to perform the query against (default: the same type as the document)
-       ['stop_words']             = (list) A list of stop words to be ignored
-       ['body']                   = (array) A specific search request definition
-       ['body']  = (array) Request body
-*/
-
-$params = [
-    // ...
-];
-
-$client = ClientBuilder::create()->build();
-$response = $client->mlt($params);
-----
-****
-
-
-
 [[Elasticsearch_Clientmget_mget]]
 .`mget()`
 ****
@@ -538,7 +447,6 @@ $params['index']        = (string) The name of the index (Required)
        ['id']           = (string) Specific document ID (when the POST method is used)
        ['consistency']  = (enum) Explicit write consistency setting for the operation
        ['parent']       = (string) ID of the parent document
-       ['percolate']    = (string) Percolator queries to execute while indexing the document
        ['refresh']      = (boolean) Refresh the index after performing the operation
        ['replication']  = (enum) Specific replication type
        ['routing']      = (string) Specific routing value
@@ -601,7 +509,6 @@ $params['index']        = (string) The name of the index (Required)
        ['consistency']  = (enum) Explicit write consistency setting for the operation
        ['op_type']      = (enum) Explicit operation type
        ['parent']       = (string) ID of the parent document
-       ['percolate']    = (string) Percolator queries to execute while indexing the document
        ['refresh']      = (boolean) Refresh the index after performing the operation
        ['replication']  = (enum) Specific replication type
        ['routing']      = (string) Specific routing value
@@ -770,58 +677,6 @@ $response = $client->search($params);
 
 
 
-[[Elasticsearch_ClientsearchExists_searchExists]]
-.`searchExists()`
-****
-[source,php]
-----
-/*
-$params['index']                    = (list) A comma-separated list of index names to search; use `_all` or empty string to perform the operation on all indices
-       ['type']                     = (list) A comma-separated list of document types to search; leave empty to perform the operation on all types
-       ['analyzer']                 = (string) The analyzer to use for the query string
-       ['analyze_wildcard']         = (boolean) Specify whether wildcard and prefix queries should be analyzed (default: false)
-       ['default_operator']         = (enum) The default operator for query string query (AND or OR)
-       ['df']                       = (string) The field to use as default where no field prefix is given in the query string
-       ['explain']                  = (boolean) Specify whether to return detailed information about score computation as part of a hit
-       ['fields']                   = (list) A comma-separated list of fields to return as part of a hit
-       ['from']                     = (number) Starting offset (default: 0)
-       ['ignore_indices']           = (enum) When performed on multiple indices, allows to ignore `missing` ones
-       ['indices_boost']            = (list) Comma-separated list of index boosts
-       ['lenient']                  = (boolean) Specify whether format-based query failures (such as providing text to a numeric field) should be ignored
-       ['lowercase_expanded_terms'] = (boolean) Specify whether query terms should be lowercased
-       ['preference']               = (string) Specify the node or shard the operation should be performed on (default: random)
-       ['q']                        = (string) Query in the Lucene query string syntax
-       ['routing']                  = (list) A comma-separated list of specific routing values
-       ['scroll']                   = (duration) Specify how long a consistent view of the index should be maintained for scrolled search
-       ['search_type']              = (enum) Search operation type
-       ['size']                     = (number) Number of hits to return (default: 10)
-       ['sort']                     = (list) A comma-separated list of <field>:<direction> pairs
-       ['source']                   = (string) The URL-encoded request definition using the Query DSL (instead of using request body)
-       ['_source']                  = (list) True or false to return the _source field or not, or a list of fields to return
-       ['_source_exclude']          = (list) A list of fields to exclude from the returned _source field
-       ['_source_include']          = (list) A list of fields to extract and return from the _source field
-       ['stats']                    = (list) Specific 'tag' of the request for logging and statistical purposes
-       ['suggest_field']            = (string) Specify which field to use for suggestions
-       ['suggest_mode']             = (enum) Specify suggest mode
-       ['suggest_size']             = (number) How many suggestions to return in response
-       ['suggest_text']             = (text) The source text for which the suggestions should be returned
-       ['timeout']                  = (time) Explicit operation timeout
-       ['version']                  = (boolean) Specify whether to return document version as part of a hit
-       ['body']                     = (array|string) The search definition using the Query DSL
-       ['body']  = (array) Request body
-*/
-
-$params = [
-    // ...
-];
-
-$client = ClientBuilder::create()->build();
-$response = $client->searchExists($params);
-----
-****
-
-
-
 [[Elasticsearch_ClientsearchShards_searchShards]]
 .`searchShards()`
 ****
@@ -931,7 +786,6 @@ $params['id']                = (string) Document ID (Required)
        ['fields']            = (list) A comma-separated list of fields to return in the response
        ['lang']              = (string) The script language (default: mvel)
        ['parent']            = (string) ID of the parent document
-       ['percolate']         = (string) Perform percolation during the operation; use specific registered query name, attribute, or wildcard
        ['refresh']           = (boolean) Refresh the index after performing the operation
        ['replication']       = (enum) Specific replication type
        ['retry_on_conflict'] = (number) Specify how many times should the operation be retried when a conflict occurs (default: 0)
@@ -1279,6 +1133,27 @@ $response = $client->tasks();
 
 
 
+[[Elasticsearch_Client-call-_call]]
+.`__call()`
+****
+[source,php]
+----
+/*
+Catchall for registered namespaces
+       ['body']  = (array) Request body
+*/
+
+$params = [
+    // ...
+];
+
+$client = ClientBuilder::create()->build();
+$response = $client->__call($name,$arguments);
+----
+****
+
+
+
 [[Elasticsearch_ClientextractArgument_extractArgument]]
 .`extractArgument()`
 ****
diff --git a/docs/build/Elasticsearch/ClientBuilder.asciidoc b/docs/build/Elasticsearch/ClientBuilder.asciidoc
index 03d2ed80e..63eacc98e 100644
--- a/docs/build/Elasticsearch/ClientBuilder.asciidoc
+++ b/docs/build/Elasticsearch/ClientBuilder.asciidoc
@@ -21,6 +21,7 @@ The class defines the following methods:
 * <<Elasticsearch_ClientBuildersetConnectionFactory_setConnectionFactory,`setConnectionFactory()`>>
 * <<Elasticsearch_ClientBuildersetConnectionPool_setConnectionPool,`setConnectionPool()`>>
 * <<Elasticsearch_ClientBuildersetEndpoint_setEndpoint,`setEndpoint()`>>
+* <<Elasticsearch_ClientBuilderregisterNamespace_registerNamespace,`registerNamespace()`>>
 * <<Elasticsearch_ClientBuildersetTransport_setTransport,`setTransport()`>>
 * <<Elasticsearch_ClientBuildersetHandler_setHandler,`setHandler()`>>
 * <<Elasticsearch_ClientBuildersetLogger_setLogger,`setLogger()`>>
@@ -158,6 +159,19 @@ corresponds to setConnectionPool().
 
 
 
+[[Elasticsearch_ClientBuilderregisterNamespace_registerNamespace]]
+.`registerNamespace()`
+****
+[source,php]
+----
+/*
+*/
+
+----
+****
+
+
+
 [[Elasticsearch_ClientBuildersetTransport_setTransport]]
 .`setTransport()`
 ****
diff --git a/docs/build/Elasticsearch/Namespaces/IndicesNamespace.asciidoc b/docs/build/Elasticsearch/Namespaces/IndicesNamespace.asciidoc
index 0e03058ea..e46618b2e 100644
--- a/docs/build/Elasticsearch/Namespaces/IndicesNamespace.asciidoc
+++ b/docs/build/Elasticsearch/Namespaces/IndicesNamespace.asciidoc
@@ -16,11 +16,11 @@ The class defines the following methods:
 * <<Elasticsearch_Namespaces_IndicesNamespaceget_get,`get()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacesegments_segments,`segments()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacedeleteTemplate_deleteTemplate,`deleteTemplate()`>>
-* <<Elasticsearch_Namespaces_IndicesNamespacedeleteWarmer_deleteWarmer,`deleteWarmer()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacedelete_delete,`delete()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacestats_stats,`stats()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceputSettings_putSettings,`putSettings()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacesnapshotIndex_snapshotIndex,`snapshotIndex()`>>
+* <<Elasticsearch_Namespaces_IndicesNamespaceshrink_shrink,`shrink()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacegetMapping_getMapping,`getMapping()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacegetFieldMapping_getFieldMapping,`getFieldMapping()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceflush_flush,`flush()`>>
@@ -29,8 +29,6 @@ The class defines the following methods:
 * <<Elasticsearch_Namespaces_IndicesNamespacerecovery_recovery,`recovery()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceexistsType_existsType,`existsType()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceputAlias_putAlias,`putAlias()`>>
-* <<Elasticsearch_Namespaces_IndicesNamespacegetWarmer_getWarmer,`getWarmer()`>>
-* <<Elasticsearch_Namespaces_IndicesNamespaceputWarmer_putWarmer,`putWarmer()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceputTemplate_putTemplate,`putTemplate()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacevalidateQuery_validateQuery,`validateQuery()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacegetAlias_getAlias,`getAlias()`>>
@@ -39,7 +37,6 @@ The class defines the following methods:
 * <<Elasticsearch_Namespaces_IndicesNamespacegetTemplate_getTemplate,`getTemplate()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceexistsTemplate_existsTemplate,`existsTemplate()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacecreate_create,`create()`>>
-* <<Elasticsearch_Namespaces_IndicesNamespaceoptimize_optimize,`optimize()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceforceMerge_forceMerge,`forceMerge()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacedeleteAlias_deleteAlias,`deleteAlias()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceopen_open,`open()`>>
@@ -55,6 +52,7 @@ The class defines the following methods:
 * <<Elasticsearch_Namespaces_IndicesNamespaceupgrade_upgrade,`upgrade()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespacegetUpgrade_getUpgrade,`getUpgrade()`>>
 * <<Elasticsearch_Namespaces_IndicesNamespaceshardStores_shardStores,`shardStores()`>>
+* <<Elasticsearch_Namespaces_IndicesNamespacerollover_rollover,`rollover()`>>
 
 
 
@@ -151,29 +149,6 @@ $response = $client->indices()->deleteTemplate($params);
 
 
 
-[[Elasticsearch_Namespaces_IndicesNamespacedeleteWarmer_deleteWarmer]]
-.`deleteWarmer()`
-****
-[source,php]
-----
-/*
-$params['index'] = (list) A comma-separated list of index names to register warmer for; use `_all` or empty string to perform the operation on all indices (Required)
-       ['name']  = (string) The name of the warmer (supports wildcards); leave empty to delete all warmers
-       ['type']  = (list) A comma-separated list of document types to register warmer for; use `_all` or empty string to perform the operation on all types
-       ['body']  = (array) Request body
-*/
-
-$params = [
-    // ...
-];
-
-$client = ClientBuilder::create()->build();
-$response = $client->indices()->deleteWarmer($params);
-----
-****
-
-
-
 [[Elasticsearch_Namespaces_IndicesNamespacedelete_delete]]
 .`delete()`
 ****
@@ -222,7 +197,6 @@ $params['fields']         = (boolean) A comma-separated list of fields for `fiel
        ['refresh']        = (boolean) Return information about refresh operations
        ['search']         = (boolean) Return information about search operations; use the `groups` parameter to include information for specific search groups
        ['store']          = (boolean) Return information about the size of the index
-       ['warmer']         = (boolean) Return information about warmers
        ['body']  = (array) Request body
 */
 
@@ -283,6 +257,30 @@ $response = $client->indices()->snapshotIndex($params);
 
 
 
+[[Elasticsearch_Namespaces_IndicesNamespaceshrink_shrink]]
+.`shrink()`
+****
+[source,php]
+----
+/*
+$params['index']          = (string) The name of the source index to shrink
+       ['target']         = (string) The name of the target index to shrink into
+       ['timeout']        = (time) Explicit operation timeout
+       ['master_timeout'] = (time) Specify timeout for connection to master
+       ['body']  = (array) Request body
+*/
+
+$params = [
+    // ...
+];
+
+$client = ClientBuilder::create()->build();
+$response = $client->indices()->shrink($params);
+----
+****
+
+
+
 [[Elasticsearch_Namespaces_IndicesNamespacegetMapping_getMapping]]
 .`getMapping()`
 ****
@@ -481,53 +479,6 @@ $response = $client->indices()->putAlias($params);
 
 
 
-[[Elasticsearch_Namespaces_IndicesNamespacegetWarmer_getWarmer]]
-.`getWarmer()`
-****
-[source,php]
-----
-/*
-$params['index'] = (list) A comma-separated list of index names to restrict the operation; use `_all` or empty string to perform the operation on all indices (Required)
-       ['name']  = (string) The name of the warmer (supports wildcards); leave empty to get all warmers
-       ['type']  = (list) A comma-separated list of document types to restrict the operation; leave empty to perform the operation on all types
-       ['body']  = (array) Request body
-*/
-
-$params = [
-    // ...
-];
-
-$client = ClientBuilder::create()->build();
-$response = $client->indices()->getWarmer($params);
-----
-****
-
-
-
-[[Elasticsearch_Namespaces_IndicesNamespaceputWarmer_putWarmer]]
-.`putWarmer()`
-****
-[source,php]
-----
-/*
-$params['index'] = (list) A comma-separated list of index names to register the warmer for; use `_all` or empty string to perform the operation on all indices (Required)
-       ['name']  = (string) The name of the warmer (Required)
-       ['type']  = (list) A comma-separated list of document types to register the warmer for; leave empty to perform the operation on all types
-       ['body']  = (list) A comma-separated list of document types to register the warmer for; leave empty to perform the operation on all types
-       ['body']  = (array) Request body
-*/
-
-$params = [
-    // ...
-];
-
-$client = ClientBuilder::create()->build();
-$response = $client->indices()->putWarmer($params);
-----
-****
-
-
-
 [[Elasticsearch_Namespaces_IndicesNamespaceputTemplate_putTemplate]]
 .`putTemplate()`
 ****
@@ -716,36 +667,6 @@ $response = $client->indices()->create($params);
 
 
 
-[[Elasticsearch_Namespaces_IndicesNamespaceoptimize_optimize]]
-.`optimize()`
-****
-[source,php]
-----
-/*
-$params['index']                = (list) A comma-separated list of index names; use `_all` or empty string to perform the operation on all indices
-       ['flush']                = (boolean) Specify whether the index should be flushed after performing the operation (default: true)
-       ['max_num_segments']     = (number) The number of segments the index should be merged into (default: dynamic)
-       ['only_expunge_deletes'] = (boolean) Specify whether the operation should only expunge deleted documents
-       ['operation_threading']  = () TODO: ?
-       ['refresh']              = (boolean) Specify whether the index should be refreshed after performing the operation (default: true)
-       ['wait_for_merge']       = (boolean) Specify whether the request should block until the merge process is finished (default: true)
-       ['ignore_unavailable']   = (bool) Whether specified concrete indices should be ignored when unavailable (missing or closed)
-       ['allow_no_indices']     = (bool) Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
-       ['expand_wildcards']     = (enum) Whether to expand wildcard expression to concrete indices that are open, closed or both.
-       ['body']  = (array) Request body
-*/
-
-$params = [
-    // ...
-];
-
-$client = ClientBuilder::create()->build();
-$response = $client->indices()->optimize($params);
-----
-****
-
-
-
 [[Elasticsearch_Namespaces_IndicesNamespaceforceMerge_forceMerge]]
 .`forceMerge()`
 ****
@@ -1124,3 +1045,27 @@ $response = $client->indices()->shardStores($params);
 ****
 
 
+
+[[Elasticsearch_Namespaces_IndicesNamespacerollover_rollover]]
+.`rollover()`
+****
+[source,php]
+----
+/*
+$params['newIndex']       = (string) The name of the rollover index
+       ['alias']          = (string) The name of the alias to rollover
+       ['timeout']        = (time) Explicit operation timeout
+       ['master_timeout'] = (time) Specify timeout for connection to master
+       ['body']  = (array) Request body
+*/
+
+$params = [
+    // ...
+];
+
+$client = ClientBuilder::create()->build();
+$response = $client->indices()->rollover($params);
+----
+****
+
+
diff --git a/docs/build/Elasticsearch/Namespaces/TasksNamespace.asciidoc b/docs/build/Elasticsearch/Namespaces/TasksNamespace.asciidoc
index 71e8b52a6..9d51713ae 100644
--- a/docs/build/Elasticsearch/Namespaces/TasksNamespace.asciidoc
+++ b/docs/build/Elasticsearch/Namespaces/TasksNamespace.asciidoc
@@ -13,6 +13,7 @@ Class TasksNamespace
 The class defines the following methods:
 
 * <<Elasticsearch_Namespaces_TasksNamespaceget_get,`get()`>>
+* <<Elasticsearch_Namespaces_TasksNamespacetasksList_tasksList,`tasksList()`>>
 * <<Elasticsearch_Namespaces_TasksNamespacecancel_cancel,`cancel()`>>
 
 
@@ -23,6 +24,27 @@ The class defines the following methods:
 [source,php]
 ----
 /*
+$params['wait_for_completion'] = (bool) Wait for the matching tasks to complete (default: false)
+       ['body']  = (array) Request body
+*/
+
+$params = [
+    // ...
+];
+
+$client = ClientBuilder::create()->build();
+$response = $client->tasks()->get($params);
+----
+****
+
+
+
+[[Elasticsearch_Namespaces_TasksNamespacetasksList_tasksList]]
+.`tasksList()`
+****
+[source,php]
+----
+/*
 $params['node_id'] = (list) A comma-separated list of node IDs or names to limit the returned information; use `_local` to return information from the node you're connecting to, leave empty to get information from all nodes
        ['actions'] = (list) A comma-separated list of actions that should be cancelled. Leave empty to cancel all.
        ['body']  = (array) Request body
@@ -33,7 +55,7 @@ $params = [
 ];
 
 $client = ClientBuilder::create()->build();
-$response = $client->tasks()->get($params);
+$response = $client->tasks()->tasksList($params);
 ----
 ****
 
diff --git a/docs/build/SAMI_VERSION b/docs/build/SAMI_VERSION
index 604a66d86..75a358eed 100644
--- a/docs/build/SAMI_VERSION
+++ b/docs/build/SAMI_VERSION
@@ -1 +1 @@
-3.2.1-DEV
\ No newline at end of file
+3.3.0-DEV
\ No newline at end of file
diff --git a/docs/build/renderer.index b/docs/build/renderer.index
index dba8b12f5..9064cb308 100644
--- a/docs/build/renderer.index
+++ b/docs/build/renderer.index
@@ -1 +1 @@
-C:19:"Sami\Renderer\Index":944:{a:3:{i:0;a:9:{s:20:"Elasticsearch\Client";s:40:"04f5d259604eefa88dc21968baccf069816c5924";s:27:"Elasticsearch\ClientBuilder";s:40:"43909299261f400333c723060331bedf4d90e098";s:37:"Elasticsearch\Namespaces\CatNamespace";s:40:"12e07e6eeeef76765996f6133f85dcb7b4046960";s:41:"Elasticsearch\Namespaces\ClusterNamespace";s:40:"0b6b06bb1d8486e9a4c00e7e8b3da30f10be0a2a";s:41:"Elasticsearch\Namespaces\IndicesNamespace";s:40:"de0be4dddb67b4a52c5cda57a35aca2ee112ad11";s:40:"Elasticsearch\Namespaces\IngestNamespace";s:40:"0d541617b01a75f1e615f35f8202e1747384f5b5";s:39:"Elasticsearch\Namespaces\NodesNamespace";s:40:"fafd30cdb7e0c546217d8bd7aae493ad701f385c";s:42:"Elasticsearch\Namespaces\SnapshotNamespace";s:40:"f2ec6976856d2d06ab29684c982f8e41ac68de5d";s:39:"Elasticsearch\Namespaces\TasksNamespace";s:40:"766f7580c3df06c4369b4bcb82a630ec7d8a2a35";}i:1;a:1:{i:0;s:6:"master";}i:2;a:2:{i:0;s:13:"Elasticsearch";i:1;s:24:"Elasticsearch\Namespaces";}}}
\ No newline at end of file
+C:19:"Sami\Renderer\Index":944:{a:3:{i:0;a:9:{s:20:"Elasticsearch\Client";s:40:"c92166baaf85cb08a91ce4e3cf845b1626ba12f0";s:27:"Elasticsearch\ClientBuilder";s:40:"347f22134a07f53b3355a211264d8e53aa545243";s:37:"Elasticsearch\Namespaces\CatNamespace";s:40:"51d06cd6b8334bcf3a2580f67bbc5c88f8fde761";s:41:"Elasticsearch\Namespaces\ClusterNamespace";s:40:"0934f56b5dfa7978ab1907b6c8a04b0a293ae274";s:41:"Elasticsearch\Namespaces\IndicesNamespace";s:40:"3d23245494af9443c215b31faa4e78dd6ab29750";s:40:"Elasticsearch\Namespaces\IngestNamespace";s:40:"b52adeb7071f16cba79cdcc3dac3fa6e53ed62bd";s:39:"Elasticsearch\Namespaces\NodesNamespace";s:40:"da4e71f9d953d00600920c26fe585b6884e45f94";s:42:"Elasticsearch\Namespaces\SnapshotNamespace";s:40:"e28a1807789b0fcca3fd6b9712ed713650cf7ac2";s:39:"Elasticsearch\Namespaces\TasksNamespace";s:40:"2de86d7ab409a629320725f6444c76d2a9313c72";}i:1;a:1:{i:0;s:6:"master";}i:2;a:2:{i:0;s:13:"Elasticsearch";i:1;s:24:"Elasticsearch\Namespaces";}}}
\ No newline at end of file
diff --git a/docs/community.asciidoc b/docs/community.asciidoc
index c05b4411f..9f286c746 100644
--- a/docs/community.asciidoc
+++ b/docs/community.asciidoc
@@ -45,6 +45,20 @@ Technical goodies:
 __________________________
 
 
+==== FOS Elastica Bundle
+
+https://github.com/FriendsOfSymfony/FOSElasticaBundle[Link: FOS Elastica Bundle]
+
+[quote, FOS Elastica Bundle]
+__________________________
+This bundle provides integration with https://github.com/ruflin/Elastica[Link: Elastica] for Symfony. Features include:
+
+- Integrates the Elastica library into a Symfony environment
+- Automatically generate mappings using a serializer
+- Listeners for Doctrine events for automatic indexing
+__________________________
+
+
 === Drupal
 
 ==== Elasticsearch Connector
@@ -87,3 +101,15 @@ __________________________
 Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch, by providing a fluent syntax for mapping, querying, and storing eloquent models.
 __________________________
 
+=== Helper
+
+==== Index Helper
+
+https://github.com/Nexucis/es-php-index-helper[Link: nexucis/es-php-index-helper]
+
+[quote, Index Helper]
+_____________________
+This helper is a light library which wrap the official client elasticsearch-php. It will help you to manage your ES Indices with no downtime.
+This helper implements the philosophy described in the https://www.elastic.co/guide/en/elasticsearch/guide/master/index-aliases.html[official documentation]
+which can be summarized in a few words : *use alias instead of index directly*
+_____________________
\ No newline at end of file
diff --git a/docs/configuration.asciidoc b/docs/configuration.asciidoc
index ad0ae6cbc..ed6a46f07 100644
--- a/docs/configuration.asciidoc
+++ b/docs/configuration.asciidoc
@@ -58,7 +58,7 @@ methods run into problems with certain edge-cases.  For example, `filter_var()`
 Basic Auth's password contains special characters such as a pound sign (`#`) or question-marks (`?`).
 
 For this reason, the client supports an extended host syntax which provides greater control over host initialization.
-None of the components are validated, so edge-cases like underscores domain names will not cause problems.
+None of the components are validated, so edge-cases like underscores in domain names will not cause problems.
 
 The extended syntax is an array of parameters for each host:
 
@@ -71,7 +71,7 @@ $hosts = [
         'port' => '9200',
         'scheme' => 'https',
         'user' => 'username',
-        'password' => 'password!#$?*abc'
+        'pass' => 'password!#$?*abc'
     ],
 
     // This is equal to "http://localhost:9200/"
@@ -167,7 +167,7 @@ You might have noticed that Monolog was suggested during installation.  To begin
 {
     "require": {
         ...
-        "elasticsearch/elasticsearch" : "~2.0",
+        "elasticsearch/elasticsearch" : "~5.0",
         "monolog/monolog": "~1.0"
     }
 }
@@ -227,7 +227,7 @@ $client = ClientBuilder::create()       // Instantiate a new ClientBuilder
 
 Elasticsearch-PHP uses an interchangeable HTTP transport layer called https://github.com/guzzle/RingPHP/[RingPHP].  This
 allows the client to construct a generic HTTP request, then pass it to the transport layer to execute.  The actual execution
-details are hidden from the client and modular, so that you can choose from several HTTP handlers depending on your needs.
+details are hidden from the client and it is modular, so that you can choose from several HTTP handlers depending on your needs.
 
 The default handler that the client uses is a combination handler.  When executing in synchronous mode, the handler
 uses `CurlHandler`, which executes single curl calls.  These are very fast for single requests.  When asynchronous (future)
diff --git a/docs/connection-pool.asciidoc b/docs/connection-pool.asciidoc
index 192fb3dbd..8999ff60c 100644
--- a/docs/connection-pool.asciidoc
+++ b/docs/connection-pool.asciidoc
@@ -60,7 +60,7 @@ Note that the implementation is specified via a namespace path to the class.
 
 === simpleConnectionPool
 
-The `SimpleConnectionPool` simply returns the next node as specified by the Selector; it does not perform track
+The `SimpleConnectionPool` simply returns the next node as specified by the Selector; it does not track
 the "liveness" of nodes.  This pool will return nodes whether they are alive or dead.  It is just a simple pool of static
 hosts.
 
@@ -81,7 +81,7 @@ Note that the implementation is specified via a namespace path to the class.
 
 Unlike the two previous static connection pools, this one is dynamic.  The user provides a seed list of hosts, which the
 client uses to "sniff" and discover the rest of the cluster.  It achieves this through the Cluster State API.  As new
-nodes are added or removed from the cluster, the client will update it's pool of active connections.
+nodes are added or removed from the cluster, the client will update its pool of active connections.
 
 To use the `SniffingConnectionPool`:
 
@@ -195,7 +195,7 @@ Sniffing is a relatively lightweight operation (one API call to `/_cluster/state
 it may be a non-negligible overhead for certain PHP applications.  The average PHP script will likely load the client,
 execute a few queries and then close.  Imagine this script being called 1000 times per second: the sniffing connection
 pool will perform the sniffing and pinging process 1000 times per second.  The sniffing process will add a large
-amount of overhead
+amount of overhead.
 
 In reality, if your script only executes a few queries, the sniffing concept is _too_ robust.  It tends to be more
 useful in long-lived processes which potentially "out-live" a static list.
diff --git a/docs/crud.asciidoc b/docs/crud.asciidoc
index d778746a8..3d3b54831 100644
--- a/docs/crud.asciidoc
+++ b/docs/crud.asciidoc
@@ -3,7 +3,7 @@
 
 When you add documents to Elasticsearch, you index JSON documents.  This maps naturally to PHP associative arrays, since
 they can easily be encoded in JSON.  Therefore, in Elasticsearch-PHP you create and pass associative arrays to the client
-for indexing.  There are several methods of ingesting data into Elasticsearch, which we will cover here
+for indexing.  There are several methods of ingesting data into Elasticsearch, which we will cover here.
 
 === Single document indexing
 
@@ -133,7 +133,7 @@ if (!empty($params['body'])) {
 
 Elasticsearch provides realtime GETs of documents.  This means that as soon as the document has been indexed and your
 client receives an acknowledgement, you can immediately retrieve the document from any shard.  Get operations are
-performed by requesting a document by it's full `index/type/id` path:
+performed by requesting a document by its full `index/type/id` path:
 
 [source,php]
 ----
@@ -156,7 +156,7 @@ update to just some fields (either changing an existing field, or adding new fie
 === Partial document update
 
 If you want to partially update a document (e.g. change an existing field, or add a new one) you can do so by specifying
-the `doc` in the `body` parameter.  This will merge the fields in `doc` with the existing document
+the `doc` in the `body` parameter.  This will merge the fields in `doc` with the existing document:
 
 
 [source,php]
diff --git a/docs/futures.asciidoc b/docs/futures.asciidoc
index ceee52016..2d6966262 100644
--- a/docs/futures.asciidoc
+++ b/docs/futures.asciidoc
@@ -6,9 +6,9 @@ to the cluster), which can have a dramatic impact on performance and throughput.
 
 PHP is fundamentally single-threaded, however libcurl provides functionality called the "multi interface".  This allows
 languages like PHP to gain concurrency by providing a batch of requests to process.  The batch is executed in a parallel
-by the underlying multithreaded libcurl library, and the batch of responses is then returned to PHP.
+fashion by the underlying multithreaded libcurl library, and the batch of responses is then returned to PHP.
 
-In a single-threaded environment, the time to execute `n` requests is the sum of those `n` request's latencies.  With
+In a single-threaded environment, the time to execute `n` requests is the sum of those `n` requests' latencies.  With
 the multi interface, the time to execute `n` requests is the latency of the slowest request (assuming enough handles
 are available to execute all requests in parallel).
 
@@ -256,4 +256,4 @@ When operated in future mode, unwrapping of the future is left to your applicati
 which means the client can no longer inspect the response and return a simple true/false.  Instead, you'll see the raw
 response from Elasticsearch and will have to take action appropriately.
 
-This also applies to `ping()`.
\ No newline at end of file
+This also applies to `ping()`.
diff --git a/docs/index-operations.asciidoc b/docs/index-operations.asciidoc
index 3108e1429..879c440ed 100644
--- a/docs/index-operations.asciidoc
+++ b/docs/index-operations.asciidoc
@@ -17,7 +17,7 @@ $params = [
 ];
 
 // Create the index
-$response = $client->indices()->create($indexParams);
+$response = $client->indices()->create($params);
 ----
 {zwsp} +
 
@@ -104,28 +104,28 @@ $params = [
             '_default_' => [    <4>
                 'properties' => [
                     'title' => [
-                        'type' => 'string',
+                        'type' => 'text',
                         'analyzer' => 'reuters',
                         'term_vector' => 'yes',
                         'copy_to' => 'combined'
                     ],
                     'body' => [
-                        'type' => 'string',
+                        'type' => 'text',
                         'analyzer' => 'reuters',
                         'term_vector' => 'yes',
                         'copy_to' => 'combined'
                     ],
                     'combined' => [
-                        'type' => 'string',
+                        'type' => 'text',
                         'analyzer' => 'reuters',
                         'term_vector' => 'yes'
                     ],
                     'topics' => [
-                        'type' => 'string',
+                        'type' => 'text',
                         'index' => 'not_analyzed'
                     ],
                     'places' => [
-                        'type' => 'string',
+                        'type' => 'text',
                         'index' => 'not_analyzed'
                     ]
                 ]
@@ -133,7 +133,7 @@ $params = [
             'my_type' => [  <5>
                 'properties' => [
                     'my_field' => [
-                        'type' => 'string'
+                        'type' => 'text'
                     ]
                 ]
             ]
diff --git a/docs/installation.asciidoc b/docs/installation.asciidoc
index ecaefac60..47b80116c 100644
--- a/docs/installation.asciidoc
+++ b/docs/installation.asciidoc
@@ -1,32 +1,33 @@
 == Installation
 
-Elasticsearch-php only has a three requirements that you need to worry about:
+Elasticsearch-php only has four requirements that you need to worry about:
 
-* PHP 5.4.0 or higher
+* PHP 5.6.6 or higher
 * http://getcomposer.org[Composer]
 * http://php.net/manual/en/book.curl.php[ext-curl]: the Libcurl extension for PHP (see note below)
+* Native JSON Extensions (`ext-json`) 1.3.7 or higher
 
-The rest of the dependencies will automatically be downloaded and installed by Composer.  Composer is a package and dependency manager for PHP.  Installing elasticsearch-php with Composer is very easy
+The rest of the dependencies will automatically be downloaded and installed by Composer.  Composer is a package and dependency manager for PHP.  Installing elasticsearch-php with Composer is very easy.
 
 [NOTE]
 .Libcurl can be replaced
 ====
 The default HTTP handlers that ship with Elasticsearch-php require the PHP libcurl extension, but it is not technically
 required for the client to operate.  If you have a host that does not have libcurl installed, you can use an
-alternate HTTP handler based on PHP streams.  Performance _will_ suffer, as the libcurl extension is much faster
+alternate HTTP handler based on PHP streams.  Performance _will_ suffer, as the libcurl extension is much faster.
 ====
 
 === Version Matrix
 
-Since there are breaking changes in Elasticsearch 1.0, you need to match your version of Elasticsearch to the appropriate version of this library.
-If you are using a version older than 1.0, you must install the `0.4` Elasticsearch-PHP branch.  Otherwise, use the `2.0` branch.
+You need to match your version of Elasticsearch to the appropriate version of this library.
 
 The master branch will always track Elasticsearch master, but it is not recommended to use `dev-master` in your production code.
 
 [width="40%",options="header",frame="topbot"]
 |============================
 |Elasticsearch Version | Elasticsearch-PHP Branch
-| >= 1.0                | `1.0`, `2.0`
+| >= 5.0                | `5.0`
+| >= 1.0, <= 5.0        | `1.0`, `2.0`
 | <= 0.90.*             | `0.4`
 |============================
 
@@ -38,12 +39,12 @@ The master branch will always track Elasticsearch master, but it is not recommen
 --------------------------
 {
     "require": {
-        "elasticsearch/elasticsearch": "~2.0@beta"
+        "elasticsearch/elasticsearch": "~5.0"
     }
 }
 --------------------------
 
-* Install the client with composer.  The first command download the `composer.phar` PHP package, and the second command invokes the installation.  Composer will automatically download any required dependencies, store them in a /vendor/ directory and build an autoloader.:
+* Install the client with composer.  The first command downloads the `composer.phar` PHP package, and the second command invokes the installation.  Composer will automatically download any required dependencies, store them in a /vendor/ directory and build an autoloader.
 +
 [source,shell]
 --------------------------
@@ -64,7 +65,7 @@ $client = Elasticsearch\ClientBuilder::create()->build();
 +
 Client instantiation is performed with a static helper function `create()`.  This creates a ClientBuilder object,
 which helps you to set custom configurations.  When you are done configuring, you call the `build()` method to generate
-a `Client` object.  We'll discuss configuration more in the Configuration section
+a `Client` object.  We'll discuss configuration more in the Configuration section.
 
 
 === --no-dev flag
@@ -72,7 +73,7 @@ You'll notice that the installation command specified `--no-dev`.  This prevents
 from installing the various testing and development dependencies.  For average users, there
 is no need to install the test suite.  In particular, the development dependencies include
 a full copy of Elasticsearch so that tests can be run against the REST specifications.  This
-is a rather large download for non-developers, hence the --no-dev flag
+is a rather large download for non-developers, hence the `--no-dev` flag
 
 If you wish to contribute to development of this library, just omit the `--no-dev` flag to
 be able to run tests.
diff --git a/docs/namespaces.asciidoc b/docs/namespaces.asciidoc
index 05a18d1fe..13f093b54 100644
--- a/docs/namespaces.asciidoc
+++ b/docs/namespaces.asciidoc
@@ -43,7 +43,7 @@ As you can see, the same `stats()` call is made through three different
 namespaces.  Sometimes the methods require parameters.  These parameters work
 just like any other method in the library.
 
-For example, we can requests index stats about a specific index, or multiple
+For example, we can request index stats about a specific index, or multiple
 indices:
 
 [source,php]
@@ -79,4 +79,4 @@ $client->indices()->updateAliases($params);
 
 Notice how both the `stats` calls and the updateAlias took a variety of parameters,
 each according to what the particular API requires.  The `stats` API only requires
-an index name(s), while the `updateAlias` requires a body of actions.
\ No newline at end of file
+an index name(s), while the `updateAlias` requires a body of actions.
diff --git a/docs/per-request-configuration.asciidoc b/docs/per-request-configuration.asciidoc
index ad33ca98d..cc74662d8 100644
--- a/docs/per-request-configuration.asciidoc
+++ b/docs/per-request-configuration.asciidoc
@@ -217,7 +217,7 @@ Array
 === Curl Timeouts
 
 It is possible to configure per-request curl timeouts via the `timeout` and `connect_timeout` parameters.  These
-control the client-side, curl timeouts.  The `connect_timeout` paramter controls how long curl should wait for the
+control the client-side, curl timeouts.  The `connect_timeout` parameter controls how long curl should wait for the
 "connect" phase to finish, while the `timeout` parameter controls how long curl should wait for the entire request
 to finish.
 
@@ -268,7 +268,7 @@ $future = $client->get($params);
 $results = $future->wait();       // resolve the future
 ----
 
-Future mode supports two options: `true` or `'lazy'`.  For more details about how asynchronous execution functions, and
+Future mode supports two options: `true` or `lazy`.  For more details about how asynchronous execution functions, and
 how to work with the results, see the dedicated page on <<_future_mode>>.
 
 === SSL Encryption
diff --git a/docs/php-version-requirement.asciidoc b/docs/php-version-requirement.asciidoc
index 3166f07e1..b45fb5aaf 100644
--- a/docs/php-version-requirement.asciidoc
+++ b/docs/php-version-requirement.asciidoc
@@ -1,3 +1,4 @@
 == PHP Version Requirement
 
-Version 2.0 of Elasticsearch-PHP requires PHP version 5.4.0 or higher.
+Version 5.0 of Elasticsearch-PHP requires PHP version 5.6.6 or higher. In addition, it requires the native JSON
+extension to be version 1.3.7 or higher.
diff --git a/docs/php_json_objects.asciidoc b/docs/php_json_objects.asciidoc
index b237bf4fa..8704eab1d 100644
--- a/docs/php_json_objects.asciidoc
+++ b/docs/php_json_objects.asciidoc
@@ -3,7 +3,7 @@
 
 A common source of confusion with the client revolves around JSON arrays and objects, and how to specify them in PHP.
 In particular, problems are caused by empty objects and arrays of objects.  This page will show you some common patterns
-used in Elasticsearch JSON API, and how to convert that to a PHP representation
+used in Elasticsearch JSON API, and how to convert that to a PHP representation.
 
 === Empty Objects
 
@@ -158,4 +158,4 @@ $results = $client->search($params);
 ----
 <1> This encodes the array of objects: `"functions" : []`
 <2> This encodes an object inside the array: `{ "random_score": {} }`
-<3> This encodes the empty JSON object: `"random_score": {}`
\ No newline at end of file
+<3> This encodes the empty JSON object: `"random_score": {}`
diff --git a/docs/quickstart.asciidoc b/docs/quickstart.asciidoc
index fb1537281..740f69895 100644
--- a/docs/quickstart.asciidoc
+++ b/docs/quickstart.asciidoc
@@ -11,7 +11,7 @@ This section will give you a quick overview of the client and how the major func
 ----------------------------
 {
     "require": {
-        "elasticsearch/elasticsearch": "~2.0"
+        "elasticsearch/elasticsearch": "~5.0"
     }
 }
 ----------------------------
@@ -30,6 +30,8 @@ php composer.phar install --no-dev
 ----------------------------
 require 'vendor/autoload.php';
 
+use Elasticsearch\ClientBuilder;
+
 $client = ClientBuilder::create()->build();
 ----------------------------
 
@@ -256,7 +258,7 @@ Array
 
 === Wrap up
 
-That was just a crash-course overview of the client and it's syntax.  If you are familiar with elasticsearch, you'll
+That was just a crash-course overview of the client and its syntax.  If you are familiar with elasticsearch, you'll
 notice that the methods are named just like REST endpoints.
 
 You'll also notice that the client is configured in a manner that facilitates easy discovery via your IDE.  All core
diff --git a/docs/search-operations.asciidoc b/docs/search-operations.asciidoc
index d45ca847b..0607a8527 100644
--- a/docs/search-operations.asciidoc
+++ b/docs/search-operations.asciidoc
@@ -183,7 +183,7 @@ curl -XGET 'localhost:9200/my_index/my_type/_search' -d '{
             "filter" : {
                 "term" : { "my_field" : "abc" }
             },
-            "query" : {
+            "should" : {
                 "match" : { "my_other_field" : "xyz" }
             }
         }
@@ -205,7 +205,7 @@ $params = [
                 'filter' => [
                     'term' => [ 'my_field' => 'abc' ]
                 ],
-                'query' => [
+                'should' => [
                     'match' => [ 'my_other_field' => 'xyz' ]
                 ]
             ]
@@ -219,11 +219,18 @@ $results = $client->search($params);
 {zwsp} +
 
 
-=== Scan/Scroll
+=== Scrolling
 
-The Scan/Scroll functionality of Elasticsearch is similar to search, but different in many ways.  It works by executing a search query with a `search_type` of `scan`.  This initiates a "scan window" which will remain open for the duration of the scan.  This allows proper, consistent pagination.
+The Scrolling functionality of Elasticsearch is used to paginate over many documents in a bulk manner, such as exporting
+all the documents belonging to a single user.  It is more efficient than regular search because it doesn't need to maintain
+an expensive priority queue ordering the documents.
 
-Once a scan window is open, you may start _scrolling) over that window.  This returns results matching your query...but returns them in random order.  This random ordering is important to performance.  Deep pagination is expensive when you need to maintain a sorted, consistent order across shards.  By removing this obligation, Scan/Scroll can efficiently export all the data from your index.
+Scrolling works by maintaining a "point in time" snapshot of the index which is then used to page over.
+This window allows consistent paging even if there is background indexing/updating/deleting.  First, you execute a search
+request with `scroll` enabled.  This returns a "page" of documents, and a scroll_id which is used to continue
+paginating through the hits.
+
+More details about scrolling can be found in the https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-body.html#request-body-search-scroll[Link: reference documentation].
 
 This is an example which can be used as a template for more advanced operations:
 
@@ -231,40 +238,37 @@ This is an example which can be used as a template for more advanced operations:
 ----
 $client = ClientBuilder::create()->build();
 $params = [
-    "search_type" => "scan",    // use search_type=scan
     "scroll" => "30s",          // how long between scroll requests. should be small!
     "size" => 50,               // how many results *per shard* you want back
     "index" => "my_index",
     "body" => [
         "query" => [
-            "match_all" => []
+            "match_all" => new \stdClass() 
         ]
     ]
 ];
 
-$docs = $client->search($params);   // Execute the search
-$scroll_id = $docs['_scroll_id'];   // The response will contain no results, just a _scroll_id
+// Execute the search
+// The response will contain the first batch of documents
+// and a scroll_id
+$response = $client->search($params);
 
 // Now we loop until the scroll "cursors" are exhausted
-while (\true) {
+while (isset($response['hits']['hits']) && count($response['hits']['hits']) > 0) {
+
+    // **
+    // Do your work here, on the $response['hits']['hits'] array
+    // **
+
+    // When done, get the new scroll_id
+    // You must always refresh your _scroll_id!  It can change sometimes
+    $scroll_id = $response['_scroll_id'];
 
-    // Execute a Scroll request
+    // Execute a Scroll request and repeat
     $response = $client->scroll([
             "scroll_id" => $scroll_id,  //...using our previously obtained _scroll_id
             "scroll" => "30s"           // and the same timeout window
         ]
     );
-
-    // Check to see if we got any search hits from the scroll
-    if (count($response['hits']['hits']) > 0) {
-        // If yes, Do Work Here
-
-        // Get new scroll_id
-        // Must always refresh your _scroll_id!  It can change sometimes
-        $scroll_id = $response['_scroll_id'];
-    } else {
-        // No results, scroll cursor is empty.  You've exported all the data
-        break;
-    }
 }
 ----
diff --git a/src/Elasticsearch/Client.php b/src/Elasticsearch/Client.php
index 03993aab6..e22c3a125 100644
--- a/src/Elasticsearch/Client.php
+++ b/src/Elasticsearch/Client.php
@@ -4,15 +4,19 @@
 
 use Elasticsearch\Common\Exceptions\BadMethodCallException;
 use Elasticsearch\Common\Exceptions\InvalidArgumentException;
+use Elasticsearch\Common\Exceptions\NoNodesAvailableException;
+use Elasticsearch\Common\Exceptions\BadRequest400Exception;
 use Elasticsearch\Common\Exceptions\Missing404Exception;
 use Elasticsearch\Common\Exceptions\TransportException;
 use Elasticsearch\Endpoints\AbstractEndpoint;
+use Elasticsearch\Namespaces\AbstractNamespace;
 use Elasticsearch\Namespaces\CatNamespace;
 use Elasticsearch\Namespaces\ClusterNamespace;
 use Elasticsearch\Namespaces\IndicesNamespace;
 use Elasticsearch\Namespaces\IngestNamespace;
 use Elasticsearch\Namespaces\NamespaceBuilderInterface;
 use Elasticsearch\Namespaces\NodesNamespace;
+use Elasticsearch\Namespaces\RemoteNamespace;
 use Elasticsearch\Namespaces\SnapshotNamespace;
 use Elasticsearch\Namespaces\BooleanRequestWrapper;
 use Elasticsearch\Namespaces\TasksNamespace;
@@ -28,6 +32,8 @@
  */
 class Client
 {
+    const VERSION = '5.5.0';
+
     /**
      * @var Transport
      */
@@ -73,6 +79,11 @@ class Client
      */
     protected $tasks;
 
+    /**
+     * @var RemoteNamespace
+     */
+    protected $remote;
+
     /** @var  callback */
     protected $endpoints;
 
@@ -97,6 +108,7 @@ public function __construct(Transport $transport, callable $endpoint, array $reg
         $this->cat       = new CatNamespace($transport, $endpoint);
         $this->ingest    = new IngestNamespace($transport, $endpoint);
         $this->tasks     = new TasksNamespace($transport, $endpoint);
+        $this->remote    = new RemoteNamespace($transport, $endpoint);
         $this->registeredNamespaces = $registeredNamespaces;
     }
 
@@ -136,6 +148,8 @@ public function ping($params = [])
             return false;
         } catch (TransportException $exception) {
             return false;
+        } catch (NoNodesAvailableException $exception) {
+            return false;
         }
 
         return true;
@@ -253,6 +267,66 @@ public function delete($params)
         return $this->performRequest($endpoint);
     }
 
+    /**
+     *
+     * $params['_source'] = (list) True or false to return the _source field or not, or a list of fields to return
+     *        ['_source_exclude'] = (array) A list of fields to exclude from the returned _source field
+     *        ['_source_include'] = (array) A list of fields to extract and return from the _source field
+     *        ['allow_no_indices'] = (bool) Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
+     *        ['analyze_wildcard'] = (bool) Specify whether wildcard and prefix queries should be analyzed (default: false)
+     *        ['analyzer'] = (string) The analyzer to use for the query string
+     *        ['conflicts'] = (enum) What to do when the delete-by-query hits version conflicts?
+     *        ['default_operator'] = (enum) The default operator for query string query (AND or OR)
+     *        ['df'] = (string) The field to use as default where no field prefix is given in the query string
+     *        ['expand_wildcards'] = (enum) Whether to expand wildcard expression to concrete indices that are open, closed or both.
+     *        ['from'] = (number) Starting offset (default: 0)
+     *        ['ignore_unavailable'] = (bool) Whether specified concrete indices should be ignored when unavailable (missing or closed)
+     *        ['lenient'] = (bool) Specify whether format-based query failures (such as providing text to a numeric field) should be ignored
+     *        ['preference'] = (string) Specify the node or shard the operation should be performed on (default: random)
+     *        ['q'] = (string) Query in the Lucene query string syntax
+     *        ['refresh'] = (bool) Should the effected indexes be refreshed?
+     *        ['request_cache'] = (bool) Specify if request cache should be used for this request or not, defaults to index level setting
+     *        ['requests_per_second'] = (number) The throttle for this request in sub-requests per second. -1 means no throttle.
+     *        ['routing'] = (array) A comma-separated list of specific routing values
+     *        ['scroll'] = (number) Specify how long a consistent view of the index should be maintained for scrolled search
+     *        ['scroll_size'] = (number) Size on the scroll request powering the update_by_query
+     *        ['search_timeout'] = (number) Explicit timeout for each search request. Defaults to no timeout.
+     *        ['search_type'] = (enum) Search operation type
+     *        ['size'] = (number) Number of hits to return (default: 10)
+     *        ['slices'] = (integer) The number of slices this task should be divided into. Defaults to 1 meaning the task isn't sliced into subtasks.
+     *        ['sort'] = (array) A comma-separated list of <field>:<direction> pairs
+     *        ['stats'] = (array) Specific 'tag' of the request for logging and statistical purposes
+     *        ['terminate_after'] = (number) The maximum number of documents to collect for each shard, upon reaching which the query execution will terminate early.
+     *        ['timeout'] = (number) Time each individual bulk request should wait for shards that are unavailable.
+     *        ['version'] = (bool) Specify whether to return document version as part of a hit
+     *        ['wait_for_active_shards'] = (string) Sets the number of shard copies that must be active before proceeding with the delete by query operation. Defaults to 1, meaning the primary shard only. Set to `all` for all shard copies, otherwise set to any non-negative value less than or equal to the total number of copies for the shard (number of replicas + 1)
+     *        ['wait_for_completion'] = (bool) Should the request should block until the delete-by-query is complete.
+     *
+     * @param array $params
+     *
+     * @return array
+     */
+    public function deleteByQuery($params = array())
+    {
+        $index = $this->extractArgument($params, 'index');
+
+        $type = $this->extractArgument($params, 'type');
+
+        $body = $this->extractArgument($params, 'body');
+
+        /** @var callback $endpointBuilder */
+        $endpointBuilder = $this->endpoints;
+
+        /** @var \Elasticsearch\Endpoints\DeleteByQuery $endpoint */
+        $endpoint = $endpointBuilder('DeleteByQuery');
+        $endpoint->setIndex($index)
+                ->setType($type)
+                ->setBody($body);
+        $endpoint->setParams($params);
+
+        return $this->performRequest($endpoint);
+    }
+
     /**
      * $params['index']              = (list) A comma-separated list of indices to restrict the results
      *        ['type']               = (list) A comma-separated list of types to restrict the results
@@ -574,6 +648,36 @@ public function msearch($params = array())
         return $this->performRequest($endpoint);
     }
 
+    /**
+     * $params['index']       = (list) A comma-separated list of index names to use as default
+     *        ['type']        = (list) A comma-separated list of document types to use as default
+     *        ['search_type'] = (enum) Search operation type
+     *        ['body']        = (array|string) The request definitions (metadata-search request definition pairs), separated by newlines
+     *        ['max_concurrent_searches'] = (number) Controls the maximum number of concurrent searches the multi search api will execute
+     *
+     * @param $params array Associative array of parameters
+     *
+     * @return array
+     */
+    public function msearchTemplate($params = array())
+    {
+        $index = $this->extractArgument($params, 'index');
+        $type = $this->extractArgument($params, 'type');
+        $body = $this->extractArgument($params, 'body');
+
+        /** @var callback $endpointBuilder */
+        $endpointBuilder = $this->endpoints;
+
+        /** @var \Elasticsearch\Endpoints\MsearchTemplate $endpoint */
+        $endpoint = $endpointBuilder('MsearchTemplate');
+        $endpoint->setIndex($index)
+            ->setType($type)
+            ->setBody($body);
+        $endpoint->setParams($params);
+
+        return $this->performRequest($endpoint);
+    }
+
     /**
      * $params['index']        = (string) The name of the index (Required)
      *        ['type']         = (string) The type of the document (Required)
@@ -823,6 +927,7 @@ public function explain($params)
      *        ['suggest_size']             = (number) How many suggestions to return in response
      *        ['suggest_text']             = (text) The source text for which the suggestions should be returned
      *        ['timeout']                  = (time) Explicit operation timeout
+     *        ['terminate_after']          = (number) The maximum number of documents to collect for each shard, upon reaching which the query execution will terminate early.
      *        ['version']                  = (boolean) Specify whether to return document version as part of a hit
      *        ['body']                     = (array|string) The search definition using the Query DSL
      *
@@ -920,6 +1025,7 @@ public function scroll($params = array())
     {
         $scrollID = $this->extractArgument($params, 'scroll_id');
         $body = $this->extractArgument($params, 'body');
+        $scroll = $this->extractArgument($params, 'scroll');
 
         /** @var callback $endpointBuilder */
         $endpointBuilder = $this->endpoints;
@@ -927,6 +1033,7 @@ public function scroll($params = array())
         /** @var \Elasticsearch\Endpoints\Scroll $endpoint */
         $endpoint = $endpointBuilder('Scroll');
         $endpoint->setScrollID($scrollID)
+                 ->setScroll($scroll)
                  ->setBody($body);
         $endpoint->setParams($params);
 
@@ -950,11 +1057,10 @@ public function clearScroll($params = array())
         /** @var callback $endpointBuilder */
         $endpointBuilder = $this->endpoints;
 
-        /** @var \Elasticsearch\Endpoints\Scroll $endpoint */
-        $endpoint = $endpointBuilder('Scroll');
+        /** @var \Elasticsearch\Endpoints\ClearScroll $endpoint */
+        $endpoint = $endpointBuilder('ClearScroll');
         $endpoint->setScrollID($scrollID)
-                 ->setBody($body)
-                 ->setClearScroll(true);
+                 ->setBody($body);
         $endpoint->setParams($params);
 
         return $this->performRequest($endpoint);
@@ -1004,6 +1110,98 @@ public function update($params)
         return $this->performRequest($endpoint);
     }
 
+    /**
+     * $params['index']                    = (list) A comma-separated list of index names to search; use `_all` or
+     * empty string to perform the operation on all indices (Required)
+     *        ['type']                     = (list) A comma-separated list of document types to search; leave empty to
+     * perform the operation on all types
+     *        ['analyzer']                 = (string) The analyzer to use for the query string
+     *        ['analyze_wildcard']         = (boolean) Specify whether wildcard and prefix queries should be analyzed
+     * (default: false)
+     *        ['default_operator']         = (enum) The default operator for query string query (AND or OR) (AND,OR)
+     * (default: OR)
+     *        ['df']                       = (string) The field to use as default where no field prefix is given in the
+     * query string
+     *        ['explain']                  = (boolean) Specify whether to return detailed information about score
+     * computation as part of a hit
+     *        ['fields']                   = (list) A comma-separated list of fields to return as part of a hit
+     *        ['fielddata_fields']         = (list) A comma-separated list of fields to return as the field data
+     * representation of a field for each hit
+     *        ['from']                     = (number) Starting offset (default: 0)
+     *        ['ignore_unavailable']       = (boolean) Whether specified concrete indices should be ignored when
+     * unavailable (missing or closed)
+     *        ['allow_no_indices']         = (boolean) Whether to ignore if a wildcard indices expression resolves into
+     * no concrete indices. (This includes `_all` string or when no indices have been specified)
+     *        ['conflicts']                = (enum) What to do when the reindex hits version conflicts? (abort,proceed)
+     * (default: abort)
+     *        ['expand_wildcards']         = (enum) Whether to expand wildcard expression to concrete indices that are
+     * open, closed or both. (open,closed,none,all) (default: open)
+     *        ['lenient']                  = (boolean) Specify whether format-based query failures (such as providing
+     * text to a numeric field) should be ignored
+     *        ['lowercase_expanded_terms'] = (boolean) Specify whether query terms should be lowercased
+     *        ['preference']               = (string) Specify the node or shard the operation should be performed on
+     * (default: random)
+     *        ['q']                        = (string) Query in the Lucene query string syntax
+     *        ['routing']                  = (list) A comma-separated list of specific routing values
+     *        ['scroll']                   = (duration) Specify how long a consistent view of the index should be
+     * maintained for scrolled search
+     *        ['search_type']              = (enum) Search operation type (query_then_fetch,dfs_query_then_fetch)
+     *        ['search_timeout']           = (time) Explicit timeout for each search request. Defaults to no timeout.
+     *        ['size']                     = (number) Number of hits to return (default: 10)
+     *        ['sort']                     = (list) A comma-separated list of <field>:<direction> pairs
+     *        ['_source']                  = (list) True or false to return the _source field or not, or a list of
+     * fields to return
+     *        ['_source_exclude']          = (list) A list of fields to exclude from the returned _source field
+     *        ['_source_include']          = (list) A list of fields to extract and return from the _source field
+     *        ['terminate_after']          = (number) The maximum number of documents to collect for each shard, upon
+     * reaching which the query execution will terminate early.
+     *        ['stats']                    = (list) Specific 'tag' of the request for logging and statistical purposes
+     *        ['suggest_field']            = (string) Specify which field to use for suggestions
+     *        ['suggest_mode']             = (enum) Specify suggest mode (missing,popular,always) (default: missing)
+     *        ['suggest_size']             = (number) How many suggestions to return in response
+     *        ['suggest_text']             = (text) The source text for which the suggestions should be returned
+     *        ['timeout']                  = (time) Time each individual bulk request should wait for shards that are
+     * unavailable. (default: 1m)
+     *        ['track_scores']             = (boolean) Whether to calculate and return scores even if they are not used
+     * for sorting
+     *        ['version']                  = (boolean) Specify whether to return document version as part of a hit
+     *        ['version_type']             = (boolean) Should the document increment the version number (internal) on
+     * hit or not (reindex)
+     *        ['request_cache']            = (boolean) Specify if request cache should be used for this request or not,
+     * defaults to index level setting
+     *        ['refresh']                  = (boolean) Should the effected indexes be refreshed?
+     *        ['consistency']              = (enum) Explicit write consistency setting for the operation
+     * (one,quorum,all)
+     *        ['scroll_size']              = (integer) Size on the scroll request powering the update_by_query
+     *        ['wait_for_completion']      = (boolean) Should the request should block until the reindex is complete.
+     * (default: false)
+     *        ['body']                     = The search definition using the Query DSL
+     *
+     * @param array $params
+     *
+     * @return array
+     */
+    public function updateByQuery($params = array())
+    {
+        $index = $this->extractArgument($params, 'index');
+
+        $body = $this->extractArgument($params, 'body');
+
+        $type = $this->extractArgument($params, 'type');
+
+        /** @var callback $endpointBuilder */
+        $endpointBuilder = $this->endpoints;
+
+        /** @var \Elasticsearch\Endpoints\UpdateByQuery $endpoint */
+        $endpoint = $endpointBuilder('UpdateByQuery');
+        $endpoint->setIndex($index)
+            ->setType($type)
+            ->setBody($body);
+        $endpoint->setParams($params);
+
+        return $this->performRequest($endpoint);
+    }
+
     /**
      * $params['id']   = (string) The script ID (Required)
      *        ['lang'] = (string) The script language (Required)
@@ -1178,6 +1376,33 @@ public function fieldStats($params = array())
         return $this->performRequest($endpoint);
     }
 
+    /**
+     * $params['index']              = (list) A comma-separated list of indices to restrict the results
+     *        ['ignore_unavailable'] = (bool) Whether specified concrete indices should be ignored when unavailable (missing or closed)
+     *        ['allow_no_indices']   = (bool) Whether to ignore if a wildcard indices expression resolves into no concrete indices. (This includes `_all` string or when no indices have been specified)
+     *        ['expand_wildcards']   = (enum) Whether to expand wildcard expression to concrete indices that are open, closed or both.
+     *
+     * @param $params array Associative array of parameters
+     *
+     * @return array
+     */
+    public function fieldCaps($params = array())
+    {
+        $index = $this->extractArgument($params, 'index');
+        $body = $this->extractArgument($params, 'body');
+
+        /** @var callback $endpointBuilder */
+        $endpointBuilder = $this->endpoints;
+
+        /** @var \Elasticsearch\Endpoints\FieldCaps $endpoint */
+        $endpoint = $endpointBuilder('FieldCaps');
+        $endpoint->setIndex($index)
+            ->setBody($body)
+            ->setParams($params);
+
+        return $this->performRequest($endpoint);
+    }
+
     /**
      * $params['id']                 = (string) ID of the template to render
      *
@@ -1272,6 +1497,16 @@ public function tasks()
         return $this->tasks;
     }
 
+    /**
+     * Operate on the Remote namespace of commands
+     *
+     * @return RemoteNamespace
+     */
+    public function remote()
+    {
+        return $this->remote;
+    }
+
     /**
      * Catchall for registered namespaces
      *
@@ -1300,7 +1535,7 @@ public function extractArgument(&$params, $arg)
             $params = (array) $params;
         }
 
-        if (isset($params[$arg]) === true) {
+        if (array_key_exists($arg, $params) === true) {
             $val = $params[$arg];
             unset($params[$arg]);
 
@@ -1331,7 +1566,7 @@ private function verifyNotNullOrEmpty($name, $var)
 
     /**
      * @param $endpoint AbstractEndpoint
-     * 
+     *
      * @throws \Exception
      * @return array
      */
diff --git a/src/Elasticsearch/ClientBuilder.php b/src/Elasticsearch/ClientBuilder.php
index 7554e36cb..285e4d48d 100644
--- a/src/Elasticsearch/ClientBuilder.php
+++ b/src/Elasticsearch/ClientBuilder.php
@@ -71,6 +71,9 @@ class ClientBuilder
     /** @var array */
     private $hosts;
 
+    /** @var array */
+    private $connectionParams;
+
     /** @var  int */
     private $retries;
 
@@ -86,6 +89,9 @@ class ClientBuilder
     /** @var null|bool|string */
     private $sslVerification = null;
 
+    /** @var bool  */
+    private $allowBadJSON = false;
+
     /**
      * @return ClientBuilder
      */
@@ -94,6 +100,36 @@ public static function create()
         return new static();
     }
 
+    /**
+     * Can supply first parm to Client::__construct() when invoking manually or with dependency injection
+     * @return this->ransport
+     *
+     */
+    public function getTransport()
+    {
+        return $this->transport;
+    }
+
+    /**
+     * Can supply second parm to Client::__construct() when invoking manually or with dependency injection
+     * @return this->endpoint
+     *
+     */
+    public function getEndpoint()
+    {
+        return $this->endpoint;
+    }
+
+    /**
+     * Can supply third parm to Client::__construct() when invoking manually or with dependency injection
+     * @return this->registeredNamespacesBuilders
+     *
+     */
+    public function getRegisteredNamespacesBuilders()
+    {
+        return $this->registeredNamespacesBuilders;
+    }
+
     /**
      * Build a new client from the provided config.  Hash keys
      * should correspond to the method name e.g. ['connectionPool']
@@ -312,6 +348,17 @@ public function setHosts($hosts)
         return $this;
     }
 
+    /**
+     * @param array $params
+     * @return $this
+     */
+    public function setConnectionParams(array $params)
+    {
+        $this->connectionParams = $params;
+
+        return $this;
+    }
+
     /**
      * @param int $retries
      * @return $this
@@ -381,11 +428,24 @@ public function setSSLVerification($value = true)
         return $this;
     }
 
+    public function allowBadJSONSerialization()
+    {
+        $this->allowBadJSON = true;
+        return $this;
+    }
+
     /**
      * @return Client
      */
     public function build()
     {
+        if(!defined('JSON_PRESERVE_ZERO_FRACTION') && $this->allowBadJSON === false) {
+            throw new RuntimeException("Your version of PHP / json-ext does not support the constant 'JSON_PRESERVE_ZERO_FRACTION',".
+            " which is important for proper type mapping in Elasticsearch. Please upgrade your PHP or json-ext.\n".
+            "If you are unable to upgrade, and are willing to accept the consequences, you may use the allowBadJSONSerialization()".
+            " method on the ClientBuilder to bypass this limitation.");
+        }
+
         $this->buildLoggers();
 
         if (is_null($this->handler)) {
@@ -425,8 +485,27 @@ public function build()
         }
 
         if (is_null($this->connectionFactory)) {
-            $connectionParams = [];
-            $this->connectionFactory = new ConnectionFactory($this->handler, $connectionParams, $this->serializer, $this->logger, $this->tracer);
+            if (is_null($this->connectionParams)) {
+                $this->connectionParams = [];
+            }
+
+            // Make sure we are setting Content-Type and Accept (unless the user has explicitly
+            // overridden it
+            if (isset($this->connectionParams['client']['headers']) === false) {
+                $this->connectionParams['client']['headers'] = [
+                    'Content-Type' => ['application/json'],
+                    'Accept' => ['application/json']
+                ];
+            } else {
+                if (isset($this->connectionParams['client']['headers']['Content-Type']) === false) {
+                    $this->connectionParams['client']['headers']['Content-Type'] = ['application/json'];
+                }
+                if (isset($this->connectionParams['client']['headers']['Accept']) === false) {
+                    $this->connectionParams['client']['headers']['Accept'] = ['application/json'];
+                }
+            }
+
+            $this->connectionFactory = new ConnectionFactory($this->handler, $this->connectionParams, $this->serializer, $this->logger, $this->tracer);
         }
 
         if (is_null($this->hosts)) {
@@ -446,7 +525,7 @@ public function build()
 
             $this->endpoint = function ($class) use ($serializer) {
                 $fullPath = '\\Elasticsearch\\Endpoints\\' . $class;
-                if ($class === 'Bulk' || $class === 'Msearch' || $class === 'MPercolate') {
+                if ($class === 'Bulk' || $class === 'Msearch' || $class === 'MsearchTemplate' || $class === 'MPercolate') {
                     return new $fullPath($serializer);
                 } else {
                     return new $fullPath();
@@ -608,7 +687,7 @@ private function extractURIParts($host)
      */
     private function prependMissingScheme($host)
     {
-        if (!filter_var($host, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED)) {
+        if (!filter_var($host, FILTER_VALIDATE_URL)) {
             $host = 'http://' . $host;
         }
 
diff --git a/src/Elasticsearch/Common/Exceptions/Serializer/JsonErrorException.php b/src/Elasticsearch/Common/Exceptions/Serializer/JsonErrorException.php
index 0ad0a295d..626d4ae47 100644
--- a/src/Elasticsearch/Common/Exceptions/Serializer/JsonErrorException.php
+++ b/src/Elasticsearch/Common/Exceptions/Serializer/JsonErrorException.php
@@ -31,18 +31,19 @@ class JsonErrorException extends \Exception implements ElasticsearchException
         JSON_ERROR_CTRL_CHAR => 'Control character error, possibly incorrectly encoded',
         JSON_ERROR_SYNTAX => 'Syntax error',
         JSON_ERROR_UTF8 => 'Malformed UTF-8 characters, possibly incorrectly encoded',
+        JSON_ERROR_RECURSION => 'One or more recursive references in the value to be encoded',
+        JSON_ERROR_INF_OR_NAN => 'One or more NAN or INF values in the value to be encoded',
+        JSON_ERROR_UNSUPPORTED_TYPE => 'A value of a type that cannot be encoded was given',
 
-        // JSON_ERROR_* constant values that are available on PHP >= 5.5.0
-        6 => 'One or more recursive references in the value to be encoded',
-        7 => 'One or more NAN or INF values in the value to be encoded',
-        8 => 'A value of a type that cannot be encoded was given',
-
+        // JSON_ERROR_* constant values that are available on PHP >= 7.0
+        9 => 'Decoding of value would result in invalid PHP property name', //JSON_ERROR_INVALID_PROPERTY_NAME
+        10 => 'Attempted to decode nonexistent UTF-16 code-point' //JSON_ERROR_UTF16
     );
 
     public function __construct($code, $input, $result, $previous = null)
     {
         if (isset(self::$messages[$code]) !== true) {
-            throw new \InvalidArgumentException(sprintf('%d is not a valid JSON error code.', $code));
+            throw new \InvalidArgumentException(sprintf('Encountered unknown JSON error code: [%d]', $code));
         }
 
         parent::__construct(self::$messages[$code], $code, $previous);
diff --git a/src/Elasticsearch/ConnectionPool/SniffingConnectionPool.php b/src/Elasticsearch/ConnectionPool/SniffingConnectionPool.php
index 89b1f8126..70b63099c 100644
--- a/src/Elasticsearch/ConnectionPool/SniffingConnectionPool.php
+++ b/src/Elasticsearch/ConnectionPool/SniffingConnectionPool.php
@@ -128,13 +128,13 @@ private function sniffConnection(Connection $connection)
 
     private function parseClusterState($transportSchema, $nodeInfo)
     {
-        $pattern       = '/\/([^:]*):([0-9]+)\]/';
+        $pattern       = '/([^:]*):([0-9]+)/';
         $schemaAddress = $transportSchema . '_address';
         $hosts         = array();
 
         foreach ($nodeInfo['nodes'] as $node) {
-            if (isset($node[$schemaAddress]) === true) {
-                if (preg_match($pattern, $node[$schemaAddress], $match) === 1) {
+            if (isset($node['http']) === true && isset($node['http']['publish_address']) === true) {
+                if (preg_match($pattern, $node['http']['publish_address'], $match) === 1) {
                     $hosts[] = array(
                         'host' => $match[1],
                         'port' => (int) $match[2],
diff --git a/src/Elasticsearch/Connections/Connection.php b/src/Elasticsearch/Connections/Connection.php
index 3de7899a5..adb9d7ab0 100644
--- a/src/Elasticsearch/Connections/Connection.php
+++ b/src/Elasticsearch/Connections/Connection.php
@@ -2,6 +2,7 @@
 
 namespace Elasticsearch\Connections;
 
+use Elasticsearch\Client;
 use Elasticsearch\Common\Exceptions\AlreadyExpiredException;
 use Elasticsearch\Common\Exceptions\BadRequest400Exception;
 use Elasticsearch\Common\Exceptions\Conflict409Exception;
@@ -72,6 +73,9 @@ class Connection implements ConnectionInterface
      */
     protected $connectionParams;
 
+    /** @var  array */
+    protected $headers = [];
+
     /** @var bool  */
     protected $isAlive = false;
 
@@ -112,6 +116,20 @@ public function __construct($handler, $hostDetails, $connectionParams,
             $connectionParams['client']['curl'][CURLOPT_USERPWD] = $hostDetails['user'].':'.$hostDetails['pass'];
         }
 
+        if (isset($connectionParams['client']['headers']) === true) {
+            $this->headers = $connectionParams['client']['headers'];
+            unset($connectionParams['client']['headers']);
+        }
+
+        // Add the User-Agent using the format: <client-repo-name>/<client-version> (metadata-values)
+        $this->headers['User-Agent'] = [sprintf(
+            "elasticsearch-php/%s (%s %s, PHP %s)",
+            Client::VERSION,
+            php_uname("s"),
+            php_uname("r"),
+            phpversion()
+        )];
+
         $host = $hostDetails['host'].':'.$hostDetails['port'];
         $path = null;
         if (isset($hostDetails['path']) === true) {
@@ -127,6 +145,16 @@ public function __construct($handler, $hostDetails, $connectionParams,
         $this->handler = $this->wrapHandler($handler, $log, $trace);
     }
 
+    /**
+     * Get the HTTP headers
+     *
+     * @return array
+     */
+    public function getHeaders()
+    {
+        return $this->headers;
+    }
+
     /**
      * @param $method
      * @param $uri
@@ -147,13 +175,17 @@ public function performRequest($method, $uri, $params = null, $body = null, $opt
             'scheme'      => $this->transportSchema,
             'uri'         => $this->getURI($uri, $params),
             'body'        => $body,
-            'headers'     => [
-                'host'  => [$this->host]
-            ]
-
+            'headers'     => array_merge([
+                'Host'  => [$this->host]
+            ], $this->headers)
         ];
-        $request = array_merge_recursive($request, $this->connectionParams, $options);
 
+        $request = array_replace_recursive($request, $this->connectionParams, $options);
+
+        // RingPHP does not like if client is empty
+        if (empty($request['client'])) {
+            unset($request['client']);
+        }
 
         $handler = $this->handler;
         $future = $handler($request, $this, $transport, $options);
@@ -444,7 +476,7 @@ public function sniff()
             ]
         ];
 
-        return $this->performRequest('GET', '/_nodes/_all/clear', null, null, $options);
+        return $this->performRequest('GET', '/_nodes/', null, null, $options);
     }
 
     /**
@@ -594,6 +626,8 @@ private function process4xxError($request, $response, $ignore)
             $exception = new ScriptLangNotSupportedException($responseBody. $statusCode);
         } elseif ($statusCode === 408) {
             $exception = new RequestTimeout408Exception($responseBody, $statusCode);
+        } else {
+            $exception = new BadRequest400Exception($responseBody, $statusCode);
         }
 
         $this->logRequestFail(
@@ -638,6 +672,8 @@ private function process5xxError($request, $response, $ignore)
             $exception = new NoDocumentsToGetException($exception->getMessage(), $statusCode, $exception);
         } elseif ($statusCode === 500 && strpos($responseBody, 'NoShardAvailableActionException') !== false) {
             $exception = new NoShardAvailableException($exception->getMessage(), $statusCode, $exception);
+        } else {
+            $exception = new ServerErrorResponseException($responseBody, $statusCode);
         }
 
         $this->logRequestFail(
@@ -667,22 +703,36 @@ private function tryDeserialize500Error($response)
     private function tryDeserializeError($response, $errorClass)
     {
         $error = $this->serializer->deserialize($response['body'], $response['transfer_stats']);
-        if (is_array($error) === true && isset($error['error']['root_cause']) === true) {
-            // Try to use root cause first (only grabs the first root cause)
-            $root = $error['error']['root_cause'];
-            if (isset($root) && isset($root[0])) {
-                $cause = $root[0]['reason'];
-                $type = $root[0]['type'];
-            } else {
-                $cause = $error['error']['reason'];
-                $type = $error['error']['type'];
+        if (is_array($error) === true) {
+            // 2.0 structured exceptions
+            if (isset($error['error']['reason']) === true) {
+
+                // Try to use root cause first (only grabs the first root cause)
+                $root = $error['error']['root_cause'];
+                if (isset($root) && isset($root[0])) {
+                    $cause = $root[0]['reason'];
+                    $type = $root[0]['type'];
+                } else {
+                    $cause = $error['error']['reason'];
+                    $type = $error['error']['type'];
+                }
+
+                $original = new $errorClass($response['body'], $response['status']);
+
+                return new $errorClass("$type: $cause", $response['status'], $original);
+            } elseif (isset($error['error']) === true) {
+                // <2.0 semi-structured exceptions
+                $original = new $errorClass($response['body'], $response['status']);
+
+                return new $errorClass($error['error'], $response['status'], $original);
             }
 
-            $original = new $errorClass($response['body'], $response['status']);
-            return new $errorClass("$type: $cause", $response['status'], $original);
+            // <2.0 "i just blew up" nonstructured exception
+            // $error is an array but we don't know the format, reuse the response body instead
+            return new $errorClass($response['body'], $response['status']);
         }
 
-        // Response mangled or unexpected, just return the body
+        // <2.0 "i just blew up" nonstructured exception
         return new $errorClass($response['body']);
     }
 }
diff --git a/src/Elasticsearch/Connections/ConnectionInterface.php b/src/Elasticsearch/Connections/ConnectionInterface.php
index 44495dbdc..d6b96d3e8 100644
--- a/src/Elasticsearch/Connections/ConnectionInterface.php
+++ b/src/Elasticsearch/Connections/ConnectionInterface.php
@@ -95,5 +95,5 @@ public function getLastRequestInfo();
      * @param \Elasticsearch\Transport $transport
      * @return mixed
      */
-    public function performRequest($method, $uri, $params = null, $body = null, $options = [], Transport $transport);
+    public function performRequest($method, $uri, $params = null, $body = null, $options = [], Transport $transport = null);
 }
diff --git a/src/Elasticsearch/Endpoints/AbstractEndpoint.php b/src/Elasticsearch/Endpoints/AbstractEndpoint.php
index 0cfb68ea2..3330705bd 100644
--- a/src/Elasticsearch/Endpoints/AbstractEndpoint.php
+++ b/src/Elasticsearch/Endpoints/AbstractEndpoint.php
@@ -95,6 +95,14 @@ public function getOptions()
         return $this->options;
     }
 
+    /**
+     * @return string|null
+     */
+    public function getIndex()
+    {
+        return $this->index;
+    }
+
     /**
      * @param string $index
      *
@@ -116,6 +124,14 @@ public function setIndex($index)
         return $this;
     }
 
+    /**
+     * @return string|null
+     */
+    public function getType()
+    {
+        return $this->type;
+    }
+
     /**
      * @param string $type
      *
@@ -212,16 +228,17 @@ private function checkUserParams($params)
             return; //no params, just return.
         }
 
-        $whitelist = array_merge($this->getParamWhitelist(), array('client', 'custom', 'filter_path'));
-
-        foreach ($params as $key => $value) {
-            if (array_search($key, $whitelist) === false) {
-                throw new UnexpectedValueException(sprintf(
-                    '"%s" is not a valid parameter. Allowed parameters are: "%s"',
-                    $key,
-                    implode('", "', $whitelist)
-                ));
-            }
+        $whitelist = array_merge($this->getParamWhitelist(), array('client', 'custom', 'filter_path', 'human'));
+
+        $invalid = array_diff(array_keys($params), $whitelist);
+        if (count($invalid) > 0) {
+            sort($invalid);
+            sort($whitelist);
+            throw new UnexpectedValueException(sprintf(
+                (count($invalid) > 1 ? '"%s" are not valid parameters.' : '"%s" is not a valid parameter.').' Allowed parameters are "%s"',
+                implode('", "', $invalid),
+                implode('", "', $whitelist)
+            ));
         }
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Aliases.php b/src/Elasticsearch/Endpoints/Cat/Aliases.php
index 959fbaeaf..4fbebccdd 100644
--- a/src/Elasticsearch/Endpoints/Cat/Aliases.php
+++ b/src/Elasticsearch/Endpoints/Cat/Aliases.php
@@ -61,7 +61,8 @@ public function getParamWhitelist()
             'help',
             'v',
             'format',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Allocation.php b/src/Elasticsearch/Endpoints/Cat/Allocation.php
index 532245372..3084385d9 100644
--- a/src/Elasticsearch/Endpoints/Cat/Allocation.php
+++ b/src/Elasticsearch/Endpoints/Cat/Allocation.php
@@ -61,7 +61,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Count.php b/src/Elasticsearch/Endpoints/Cat/Count.php
index 5ec9d6423..de64d3f02 100644
--- a/src/Elasticsearch/Endpoints/Cat/Count.php
+++ b/src/Elasticsearch/Endpoints/Cat/Count.php
@@ -41,7 +41,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Fielddata.php b/src/Elasticsearch/Endpoints/Cat/Fielddata.php
index eff659ec7..61a2303e8 100644
--- a/src/Elasticsearch/Endpoints/Cat/Fielddata.php
+++ b/src/Elasticsearch/Endpoints/Cat/Fielddata.php
@@ -59,7 +59,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Health.php b/src/Elasticsearch/Endpoints/Cat/Health.php
index 6a2cf9710..1dbb5192a 100644
--- a/src/Elasticsearch/Endpoints/Cat/Health.php
+++ b/src/Elasticsearch/Endpoints/Cat/Health.php
@@ -37,7 +37,8 @@ public function getParamWhitelist()
             'help',
             'ts',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Help.php b/src/Elasticsearch/Endpoints/Cat/Help.php
index d959ca826..945db52a4 100644
--- a/src/Elasticsearch/Endpoints/Cat/Help.php
+++ b/src/Elasticsearch/Endpoints/Cat/Help.php
@@ -32,7 +32,8 @@ public function getParamWhitelist()
     {
         return array(
             'help',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Indices.php b/src/Elasticsearch/Endpoints/Cat/Indices.php
index 97d8b1796..595f5aa31 100644
--- a/src/Elasticsearch/Endpoints/Cat/Indices.php
+++ b/src/Elasticsearch/Endpoints/Cat/Indices.php
@@ -45,7 +45,8 @@ public function getParamWhitelist()
             'pri',
             'v',
             'health',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Master.php b/src/Elasticsearch/Endpoints/Cat/Master.php
index e6dbfe178..4fdec3d23 100644
--- a/src/Elasticsearch/Endpoints/Cat/Master.php
+++ b/src/Elasticsearch/Endpoints/Cat/Master.php
@@ -36,7 +36,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/NodeAttrs.php b/src/Elasticsearch/Endpoints/Cat/NodeAttrs.php
index ff0d8fa53..e8e773c33 100644
--- a/src/Elasticsearch/Endpoints/Cat/NodeAttrs.php
+++ b/src/Elasticsearch/Endpoints/Cat/NodeAttrs.php
@@ -36,7 +36,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Nodes.php b/src/Elasticsearch/Endpoints/Cat/Nodes.php
index ffe497d21..4c2b565c5 100644
--- a/src/Elasticsearch/Endpoints/Cat/Nodes.php
+++ b/src/Elasticsearch/Endpoints/Cat/Nodes.php
@@ -36,7 +36,9 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'full_id',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/PendingTasks.php b/src/Elasticsearch/Endpoints/Cat/PendingTasks.php
index 435f208fc..0cc9519d1 100644
--- a/src/Elasticsearch/Endpoints/Cat/PendingTasks.php
+++ b/src/Elasticsearch/Endpoints/Cat/PendingTasks.php
@@ -36,7 +36,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Plugins.php b/src/Elasticsearch/Endpoints/Cat/Plugins.php
index dbdc52a07..39b9b7e5a 100644
--- a/src/Elasticsearch/Endpoints/Cat/Plugins.php
+++ b/src/Elasticsearch/Endpoints/Cat/Plugins.php
@@ -36,7 +36,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Recovery.php b/src/Elasticsearch/Endpoints/Cat/Recovery.php
index 4644e8fa8..1acf6c5d4 100644
--- a/src/Elasticsearch/Endpoints/Cat/Recovery.php
+++ b/src/Elasticsearch/Endpoints/Cat/Recovery.php
@@ -42,7 +42,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Repositories.php b/src/Elasticsearch/Endpoints/Cat/Repositories.php
index 1857cd548..43cc12108 100644
--- a/src/Elasticsearch/Endpoints/Cat/Repositories.php
+++ b/src/Elasticsearch/Endpoints/Cat/Repositories.php
@@ -36,7 +36,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Segments.php b/src/Elasticsearch/Endpoints/Cat/Segments.php
index c7b728e30..ef969fb5c 100644
--- a/src/Elasticsearch/Endpoints/Cat/Segments.php
+++ b/src/Elasticsearch/Endpoints/Cat/Segments.php
@@ -47,7 +47,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Shards.php b/src/Elasticsearch/Endpoints/Cat/Shards.php
index 1107037cd..78d8f3343 100644
--- a/src/Elasticsearch/Endpoints/Cat/Shards.php
+++ b/src/Elasticsearch/Endpoints/Cat/Shards.php
@@ -42,7 +42,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Snapshots.php b/src/Elasticsearch/Endpoints/Cat/Snapshots.php
index 72d544f3f..75de7725f 100644
--- a/src/Elasticsearch/Endpoints/Cat/Snapshots.php
+++ b/src/Elasticsearch/Endpoints/Cat/Snapshots.php
@@ -58,7 +58,8 @@ public function getParamWhitelist()
             'h',
             'help',
             'v',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Cat/Templates.php b/src/Elasticsearch/Endpoints/Cat/Templates.php
new file mode 100644
index 000000000..aee9e61fb
--- /dev/null
+++ b/src/Elasticsearch/Endpoints/Cat/Templates.php
@@ -0,0 +1,70 @@
+<?php
+
+namespace Elasticsearch\Endpoints\Cat;
+
+use Elasticsearch\Endpoints\AbstractEndpoint;
+
+/**
+ * Class Templates
+ *
+ * @category Elasticsearch
+ * @package  Elasticsearch\Endpoints\Cat
+ * @author   Zachary Tong <zach@elastic.co>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link     http://elastic.co
+ */
+class Templates extends AbstractEndpoint
+{
+    private $name;
+
+    /**
+     * @param string $name
+     * @return Templates
+     */
+    public function setName($name)
+    {
+        $this->name = $name;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getURI()
+    {
+        if (isset($this->name)) {
+            return "/_cat/templates/{$this->name}";
+        } else {
+            return "/_cat/templates";
+        }
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getParamWhitelist()
+    {
+        return array(
+            'format',
+            'node_id',
+            'actions',
+            'detailed',
+            'parent_node',
+            'parent_task',
+            'h',
+            'help',
+            'v',
+            's',
+            'local',
+            'master_timeout',
+        );
+    }
+
+    /**
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'GET';
+    }
+}
diff --git a/src/Elasticsearch/Endpoints/Cat/ThreadPool.php b/src/Elasticsearch/Endpoints/Cat/ThreadPool.php
index d2a6e0488..e0f0e8d77 100644
--- a/src/Elasticsearch/Endpoints/Cat/ThreadPool.php
+++ b/src/Elasticsearch/Endpoints/Cat/ThreadPool.php
@@ -40,7 +40,8 @@ public function getParamWhitelist()
             'full_id',
             'size',
             'thread_pool_patterns',
-            's'
+            's',
+            'format',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/ClearScroll.php b/src/Elasticsearch/Endpoints/ClearScroll.php
index e9600171d..68466a7f3 100644
--- a/src/Elasticsearch/Endpoints/ClearScroll.php
+++ b/src/Elasticsearch/Endpoints/ClearScroll.php
@@ -16,20 +16,20 @@
 class ClearScroll extends AbstractEndpoint
 {
     // A comma-separated list of scroll IDs to clear
-    private $scroll_id;
+    private $scrollId;
 
     /**
      * @param $scroll_id
      *
      * @return $this
      */
-    public function setScroll_Id($scroll_id)
+    public function setScrollId($scrollId)
     {
-        if (isset($scroll_id) !== true) {
+        if (isset($scrollId) !== true) {
             return $this;
         }
 
-        $this->scroll_id = $scroll_id;
+        $this->scrollId = $scrollId;
 
         return $this;
     }
@@ -40,19 +40,38 @@ public function setScroll_Id($scroll_id)
      */
     public function getURI()
     {
-        if (isset($this->scroll_id) !== true) {
-            throw new Exceptions\RuntimeException(
-                'scroll_id is required for Clearscroll'
-            );
-        }
-        $scroll_id = $this->scroll_id;
-        $uri   = "/_search/scroll/$scroll_id";
+        return "/_search/scroll/";
+    }
 
-        if (isset($scroll_id) === true) {
-            $uri = "/_search/scroll/$scroll_id";
+    /**
+     * @param array $body
+     *
+     * @throws \Elasticsearch\Common\Exceptions\InvalidArgumentException
+     * @return $this
+     */
+    public function setBody($body)
+    {
+        if (isset($body) !== true) {
+            return $this;
         }
 
-        return $uri;
+        $this->body = $body;
+
+        return $this;
+    }
+
+    /**
+     * @return array
+     */
+    public function getBody()
+    {
+        if (isset($this->body)) {
+            return $this->body;
+        }
+        if (is_array($this->scrollId)) {
+            return ['scroll_id' => $this->scrollId];
+        }
+        return ['scroll_id' => [$this->scrollId]];
     }
 
     /**
diff --git a/src/Elasticsearch/Endpoints/Cluster/AllocationExplain.php b/src/Elasticsearch/Endpoints/Cluster/AllocationExplain.php
index 25014bf02..d38cecd40 100644
--- a/src/Elasticsearch/Endpoints/Cluster/AllocationExplain.php
+++ b/src/Elasticsearch/Endpoints/Cluster/AllocationExplain.php
@@ -57,6 +57,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Cluster/Nodes/Stats.php b/src/Elasticsearch/Endpoints/Cluster/Nodes/Stats.php
index 90da06ca2..94dd6cf34 100644
--- a/src/Elasticsearch/Endpoints/Cluster/Nodes/Stats.php
+++ b/src/Elasticsearch/Endpoints/Cluster/Nodes/Stats.php
@@ -97,6 +97,7 @@ public function getParamWhitelist()
             'human',
             'level',
             'types',
+            'include_segment_file_sizes',
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Count.php b/src/Elasticsearch/Endpoints/Count.php
index 7bedb4b33..dd5d24ced 100644
--- a/src/Elasticsearch/Endpoints/Count.php
+++ b/src/Elasticsearch/Endpoints/Count.php
@@ -72,7 +72,8 @@ public function getParamWhitelist()
             'lowercase_expanded_terms',
             'analyze_wildcard',
             'lenient',
-            'lowercase_expanded_terms'
+            'lowercase_expanded_terms',
+            'terminate_after'
         );
     }
 
@@ -81,6 +82,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/CountPercolate.php b/src/Elasticsearch/Endpoints/CountPercolate.php
index f87d6b5e5..f78b7870d 100644
--- a/src/Elasticsearch/Endpoints/CountPercolate.php
+++ b/src/Elasticsearch/Endpoints/CountPercolate.php
@@ -85,6 +85,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/DeleteByQuery.php b/src/Elasticsearch/Endpoints/DeleteByQuery.php
new file mode 100644
index 000000000..b5c0cf99e
--- /dev/null
+++ b/src/Elasticsearch/Endpoints/DeleteByQuery.php
@@ -0,0 +1,104 @@
+<?php
+
+namespace Elasticsearch\Endpoints;
+
+use Elasticsearch\Common\Exceptions;
+
+/**
+ * Class Deletebyquery
+ *
+ * @category Elasticsearch
+ * @package  Elasticsearch\Endpoints
+ * @author   Zachary Tong <zach@elastic.co>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link     http://elastic.co
+ */
+class DeleteByQuery extends AbstractEndpoint
+{
+    /**
+     * @param array $body
+     *
+     * @throws \Elasticsearch\Common\Exceptions\InvalidArgumentException
+     * @return $this
+     */
+    public function setBody($body)
+    {
+        if (isset($body) !== true) {
+            return $this;
+        }
+
+        $this->body = $body;
+
+        return $this;
+    }
+
+    /**
+     * @throws \Elasticsearch\Common\Exceptions\RuntimeException
+     * @return string
+     */
+    public function getURI()
+    {
+        if (!$this->index) {
+            throw new Exceptions\RuntimeException(
+                'index is required for Deletebyquery'
+            );
+        }
+
+        $uri = "/{$this->index}/_delete_by_query";
+        if ($this->type) {
+            $uri = "/{$this->index}/{$this->type}/_delete_by_query";
+        }
+
+        return $uri;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getParamWhitelist()
+    {
+        return array(
+            '_source',
+            '_source_exclude',
+            '_source_include',
+            'allow_no_indices',
+            'analyze_wildcard',
+            'analyzer',
+            'conflicts',
+            'default_operator',
+            'df',
+            'expand_wildcards',
+            'from',
+            'ignore_unavailable',
+            'lenient',
+            'preference',
+            'query',
+            'q',
+            'refresh',
+            'request_cache',
+            'requests_per_second',
+            'routing',
+            'scroll',
+            'scroll_size',
+            'search_timeout',
+            'search_type',
+            'size',
+            'slices',
+            'sort',
+            'stats',
+            'terminate_after',
+            'timeout',
+            'version',
+            'wait_for_active_shards',
+            'wait_for_completion',
+        );
+    }
+
+    /**
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'POST';
+    }
+}
diff --git a/src/Elasticsearch/Endpoints/Exists.php b/src/Elasticsearch/Endpoints/Exists.php
index 8ab0bedbc..a9333d5dc 100644
--- a/src/Elasticsearch/Endpoints/Exists.php
+++ b/src/Elasticsearch/Endpoints/Exists.php
@@ -59,6 +59,8 @@ public function getParamWhitelist()
             'realtime',
             'refresh',
             'routing',
+            'version',
+            'stored_fields'
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Explain.php b/src/Elasticsearch/Endpoints/Explain.php
index 7d1bb2e81..f359de889 100644
--- a/src/Elasticsearch/Endpoints/Explain.php
+++ b/src/Elasticsearch/Endpoints/Explain.php
@@ -86,6 +86,7 @@ public function getParamWhitelist()
             '_source',
             '_source_exclude',
             '_source_include',
+            'stored_fields'
         );
     }
 
@@ -94,6 +95,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/FieldCaps.php b/src/Elasticsearch/Endpoints/FieldCaps.php
new file mode 100644
index 000000000..494a0297a
--- /dev/null
+++ b/src/Elasticsearch/Endpoints/FieldCaps.php
@@ -0,0 +1,69 @@
+<?php
+
+namespace Elasticsearch\Endpoints;
+
+use Elasticsearch\Common\Exceptions\InvalidArgumentException;
+use Elasticsearch\Common\Exceptions;
+
+/**
+ * Class FieldCaps
+ *
+ * @category Elasticsearch
+ * @package  Elasticsearch\Endpoints
+ * @author   Zachary Tong <zach@elastic.co>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link     http://elastic.co
+ */
+class FieldCaps extends AbstractEndpoint
+{
+    /**
+     * @param array $body
+     *
+     * @throws \Elasticsearch\Common\Exceptions\InvalidArgumentException
+     * @return $this
+     */
+    public function setBody($body)
+    {
+        if (isset($body) !== true) {
+            return $this;
+        }
+
+        $this->body = $body;
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getURI()
+    {
+        $index = $this->index;
+
+        if (isset($index) === true ) {
+            return "/$index/_field_caps";
+        } else {
+            return "/_field_caps";
+        }
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getParamWhitelist()
+    {
+        return array(
+            'fields',
+            'ignore_unavailable',
+            'allow_no_indices',
+            'expand_wildcards'
+        );
+    }
+
+    /**
+     * @return string
+     */
+    public function getMethod()
+    {
+        return isset($this->body) ? 'POST' : 'GET';
+    }
+}
diff --git a/src/Elasticsearch/Endpoints/FieldStats.php b/src/Elasticsearch/Endpoints/FieldStats.php
index 1ca80d83e..a91d43c77 100644
--- a/src/Elasticsearch/Endpoints/FieldStats.php
+++ b/src/Elasticsearch/Endpoints/FieldStats.php
@@ -68,6 +68,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Indices/Analyze.php b/src/Elasticsearch/Endpoints/Indices/Analyze.php
index ac7787948..736464607 100644
--- a/src/Elasticsearch/Endpoints/Indices/Analyze.php
+++ b/src/Elasticsearch/Endpoints/Indices/Analyze.php
@@ -74,6 +74,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Indices/Cache/Clear.php b/src/Elasticsearch/Endpoints/Indices/Cache/Clear.php
index 787072d51..6789d3e91 100644
--- a/src/Elasticsearch/Endpoints/Indices/Cache/Clear.php
+++ b/src/Elasticsearch/Endpoints/Indices/Cache/Clear.php
@@ -48,7 +48,9 @@ public function getParamWhitelist()
             'recycler',
             'ignore_unavailable',
             'allow_no_indices',
-            'expand_wildcards'
+            'expand_wildcards',
+            'request_cache',
+            'request'
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Indices/Stats.php b/src/Elasticsearch/Endpoints/Indices/Stats.php
index 899afc6df..bbdc1d2fc 100644
--- a/src/Elasticsearch/Endpoints/Indices/Stats.php
+++ b/src/Elasticsearch/Endpoints/Indices/Stats.php
@@ -71,7 +71,8 @@ public function getParamWhitelist()
             'human',
             'level',
             'types',
-            'metric'
+            'metric',
+            'include_segment_file_sizes'
         );
     }
 
diff --git a/src/Elasticsearch/Endpoints/Indices/ValidateQuery.php b/src/Elasticsearch/Endpoints/Indices/ValidateQuery.php
index df94c02a9..c17ec235b 100644
--- a/src/Elasticsearch/Endpoints/Indices/ValidateQuery.php
+++ b/src/Elasticsearch/Endpoints/Indices/ValidateQuery.php
@@ -72,6 +72,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Ingest/Simulate.php b/src/Elasticsearch/Endpoints/Ingest/Simulate.php
index f4570bbdf..6c5459d3a 100644
--- a/src/Elasticsearch/Endpoints/Ingest/Simulate.php
+++ b/src/Elasticsearch/Endpoints/Ingest/Simulate.php
@@ -60,6 +60,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/MTermVectors.php b/src/Elasticsearch/Endpoints/MTermVectors.php
index e723920d9..5cc87c49d 100644
--- a/src/Elasticsearch/Endpoints/MTermVectors.php
+++ b/src/Elasticsearch/Endpoints/MTermVectors.php
@@ -65,6 +65,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'POST';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Mget.php b/src/Elasticsearch/Endpoints/Mget.php
index 2d7dd562c..367dcb9bb 100644
--- a/src/Elasticsearch/Endpoints/Mget.php
+++ b/src/Elasticsearch/Endpoints/Mget.php
@@ -88,6 +88,6 @@ public function getBody()
      */
     public function getMethod()
     {
-        return 'POST';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Msearch.php b/src/Elasticsearch/Endpoints/Msearch.php
index b4b4d1e82..4e9c539d2 100644
--- a/src/Elasticsearch/Endpoints/Msearch.php
+++ b/src/Elasticsearch/Endpoints/Msearch.php
@@ -77,6 +77,7 @@ public function getParamWhitelist()
     {
         return array(
             'search_type',
+            'typed_keys',
         );
     }
 
@@ -98,6 +99,6 @@ public function getBody()
      */
     public function getMethod()
     {
-        return 'GET';
+        return 'POST';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/MsearchTemplate.php b/src/Elasticsearch/Endpoints/MsearchTemplate.php
new file mode 100644
index 000000000..d0e07050a
--- /dev/null
+++ b/src/Elasticsearch/Endpoints/MsearchTemplate.php
@@ -0,0 +1,105 @@
+<?php
+
+namespace Elasticsearch\Endpoints;
+
+use Elasticsearch\Common\Exceptions;
+use Elasticsearch\Serializers\SerializerInterface;
+use Elasticsearch\Transport;
+
+/**
+ * Class MsearchTemplate
+ *
+ * @category Elasticsearch
+ * @package  Elasticsearch\Endpoints
+ * @author   Zachary Tong <zach@elastic.co>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link     http://elastic.co
+ */
+class MsearchTemplate extends AbstractEndpoint
+{
+    /**
+     * @param SerializerInterface $serializer
+     */
+    public function __construct(SerializerInterface $serializer)
+    {
+        $this->serializer = $serializer;
+    }
+
+    /**
+     * @param array|string $body
+     *
+     * @throws \Elasticsearch\Common\Exceptions\InvalidArgumentException
+     * @return $this
+     */
+    public function setBody($body)
+    {
+        if (isset($body) !== true) {
+            return $this;
+        }
+
+        if (is_array($body) === true) {
+            $bulkBody = "";
+            foreach ($body as $item) {
+                $bulkBody .= $this->serializer->serialize($item)."\n";
+            }
+            $body = $bulkBody;
+        }
+
+        $this->body = $body;
+
+        return $this;
+    }
+
+    /**
+     * @return string
+     */
+    public function getURI()
+    {
+        $index = $this->index;
+        $type = $this->type;
+        $uri   = "/_msearch/template";
+
+        if (isset($index) === true && isset($type) === true) {
+            $uri = "/$index/$type/_msearch/template";
+        } elseif (isset($index) === true) {
+            $uri = "/$index/_msearch/template";
+        } elseif (isset($type) === true) {
+            $uri = "/_all/$type/_msearch/template";
+        }
+
+        return $uri;
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getParamWhitelist()
+    {
+        return array(
+            'search_type',
+            'typed_keys',
+            'max_concurrent_searches'
+        );
+    }
+
+    /**
+     * @return array
+     * @throws \Elasticsearch\Common\Exceptions\RuntimeException
+     */
+    public function getBody()
+    {
+        if (isset($this->body) !== true) {
+            throw new Exceptions\RuntimeException('Body is required for MSearch');
+        }
+
+        return $this->body;
+    }
+
+    /**
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'POST';
+    }
+}
diff --git a/src/Elasticsearch/Endpoints/Percolate.php b/src/Elasticsearch/Endpoints/Percolate.php
index 4418d7dc4..634f00a51 100644
--- a/src/Elasticsearch/Endpoints/Percolate.php
+++ b/src/Elasticsearch/Endpoints/Percolate.php
@@ -93,6 +93,6 @@ public function getBody()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Reindex.php b/src/Elasticsearch/Endpoints/Reindex.php
index 5f8b97c86..532889beb 100644
--- a/src/Elasticsearch/Endpoints/Reindex.php
+++ b/src/Elasticsearch/Endpoints/Reindex.php
@@ -20,6 +20,7 @@ class Reindex extends AbstractEndpoint
     public function getParamWhitelist()
     {
         return array(
+            'slices',
             'refresh',
             'timeout',
             'consistency',
diff --git a/src/Elasticsearch/Endpoints/Remote/Info.php b/src/Elasticsearch/Endpoints/Remote/Info.php
new file mode 100644
index 000000000..b4e8be300
--- /dev/null
+++ b/src/Elasticsearch/Endpoints/Remote/Info.php
@@ -0,0 +1,40 @@
+<?php
+
+namespace Elasticsearch\Endpoints\Remote;
+use Elasticsearch\Endpoints\AbstractEndpoint;
+
+/**
+ * Class Info
+ *
+ * @category Elasticsearch
+ * @package  Elasticsearch\Endpoints\Cluster\Nodes
+ * @author   Zachary Tong <zach@elastic.co>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link     http://elastic.co
+ */
+class Info extends AbstractEndpoint
+{
+    /**
+     * @return string
+     */
+    public function getURI()
+    {
+        return "/_remote/info";
+    }
+
+    /**
+     * @return string[]
+     */
+    public function getParamWhitelist()
+    {
+        return array();
+    }
+
+    /**
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'GET';
+    }
+}
diff --git a/src/Elasticsearch/Endpoints/RenderSearchTemplate.php b/src/Elasticsearch/Endpoints/RenderSearchTemplate.php
index c31eb7238..f69bddc6f 100644
--- a/src/Elasticsearch/Endpoints/RenderSearchTemplate.php
+++ b/src/Elasticsearch/Endpoints/RenderSearchTemplate.php
@@ -72,6 +72,6 @@ public function getBody()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Scroll.php b/src/Elasticsearch/Endpoints/Scroll.php
index 65aab8ddc..9c62da2cb 100644
--- a/src/Elasticsearch/Endpoints/Scroll.php
+++ b/src/Elasticsearch/Endpoints/Scroll.php
@@ -15,7 +15,6 @@
  */
 class Scroll extends AbstractEndpoint
 {
-    private $clear = false;
 
     /**
      * @param array $body
@@ -42,9 +41,18 @@ public function getBody()
         return $this->body;
     }
 
-    public function setClearScroll($clear)
+    /**
+     * @param $scroll
+     *
+     * @return $this
+     */
+    public function setScroll($scroll)
     {
-        $this->clear = $clear;
+        if (isset($scroll) !== true) {
+            return $this;
+        }
+
+        $this->body['scroll'] = $scroll;
 
         return $this;
     }
@@ -60,7 +68,7 @@ public function setScrollId($scroll_id)
             return $this;
         }
 
-        $this->body = $scroll_id;
+        $this->body['scroll_id'] = $scroll_id;
 
         return $this;
     }
@@ -89,10 +97,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        if ($this->clear == true) {
-            return 'DELETE';
-        }
-
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Search.php b/src/Elasticsearch/Endpoints/Search.php
index caf955ebd..57a539671 100644
--- a/src/Elasticsearch/Endpoints/Search.php
+++ b/src/Elasticsearch/Endpoints/Search.php
@@ -79,6 +79,7 @@ public function getParamWhitelist()
             'scroll',
             'search_type',
             'size',
+            'slice',
             'sort',
             'source',
             '_source',
@@ -93,7 +94,11 @@ public function getParamWhitelist()
             'version',
             'fielddata_fields',
             'docvalue_fields',
-            'filter_path'
+            'filter_path',
+            'terminate_after',
+            'stored_fields',
+            'batched_reduce_size',
+            'typed_keys'
         );
     }
 
@@ -102,6 +107,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/SearchTemplate.php b/src/Elasticsearch/Endpoints/SearchTemplate.php
index 7b5c83048..978caf743 100644
--- a/src/Elasticsearch/Endpoints/SearchTemplate.php
+++ b/src/Elasticsearch/Endpoints/SearchTemplate.php
@@ -74,6 +74,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'GET';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/Snapshot/Status.php b/src/Elasticsearch/Endpoints/Snapshot/Status.php
index b8e6aba83..0784e237b 100644
--- a/src/Elasticsearch/Endpoints/Snapshot/Status.php
+++ b/src/Elasticsearch/Endpoints/Snapshot/Status.php
@@ -70,10 +70,10 @@ public function getURI()
         $snapshot   = $this->snapshot;
         $uri        = "/_snapshot/_status";
 
-        if (isset($repository) === true) {
-            $uri = "/_snapshot/$repository/_status";
-        } elseif (isset($repository) === true && isset($snapshot) === true) {
+        if (isset($repository) === true && isset($snapshot) === true) {
             $uri = "/_snapshot/$repository/$snapshot/_status";
+        } elseif (isset($repository) === true) {
+            $uri = "/_snapshot/$repository/_status";
         }
 
         return $uri;
diff --git a/src/Elasticsearch/Endpoints/Suggest.php b/src/Elasticsearch/Endpoints/Suggest.php
index 658eead29..1afb1f274 100644
--- a/src/Elasticsearch/Endpoints/Suggest.php
+++ b/src/Elasticsearch/Endpoints/Suggest.php
@@ -80,6 +80,6 @@ public function getBody()
      */
     public function getMethod()
     {
-        return 'GET';
+        return 'POST';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/TermVectors.php b/src/Elasticsearch/Endpoints/TermVectors.php
index 5ac9569e3..cc5e99c74 100644
--- a/src/Elasticsearch/Endpoints/TermVectors.php
+++ b/src/Elasticsearch/Endpoints/TermVectors.php
@@ -39,27 +39,31 @@ public function setBody($body)
     public function getURI()
     {
         if (isset($this->index) !== true) {
-            throw new Exceptions\RuntimeException(
-                'index is required for TermVectors'
-            );
-        }
-        if (isset($this->type) !== true) {
-            throw new Exceptions\RuntimeException(
-                'type is required for TermVectors'
-            );
-        }
-        if (isset($this->id) !== true) {
-            throw new Exceptions\RuntimeException(
-                'id is required for TermVectors'
-            );
-        }
+           throw new Exceptions\RuntimeException(
+               'index is required for TermVectors'
+           );
+       }
+       if (isset($this->type) !== true) {
+           throw new Exceptions\RuntimeException(
+               'type is required for TermVectors'
+           );
+       }
+       if (isset($this->id) !== true && isset($this->body['doc']) !== true) {
+           throw new Exceptions\RuntimeException(
+               'id or doc is required for TermVectors'
+           );
+       }
+
+       $index = $this->index;
+       $type  = $this->type;
+       $id    = $this->id;
+       $uri   = "/$index/$type/_termvectors";
 
-        $index = $this->index;
-        $type  = $this->type;
-        $id    = $this->id;
-        $uri   = "/$index/$type/$id/_termvectors";
+       if ($id !== null) {
+           $uri = "/$index/$type/$id/_termvectors";
+       }
 
-        return $uri;
+       return $uri;
     }
 
     /**
@@ -86,6 +90,6 @@ public function getParamWhitelist()
      */
     public function getMethod()
     {
-        return 'POST';
+        return isset($this->body) ? 'POST' : 'GET';
     }
 }
diff --git a/src/Elasticsearch/Endpoints/UpdateByQuery.php b/src/Elasticsearch/Endpoints/UpdateByQuery.php
new file mode 100644
index 000000000..685a5809c
--- /dev/null
+++ b/src/Elasticsearch/Endpoints/UpdateByQuery.php
@@ -0,0 +1,122 @@
+<?php
+
+namespace Elasticsearch\Endpoints;
+
+use Elasticsearch\Common\Exceptions;
+
+/**
+ * Class UpdateByQuery
+ *
+ * @category Elasticsearch
+ * @package Elasticsearch\Endpoints *
+ * @author   Zachary Tong <zachary.tong@elasticsearch.com>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link     http://elasticsearch.org
+ */
+class UpdateByQuery extends AbstractEndpoint
+{
+    /**
+     * @param array $body
+     *
+     * @throws \Elasticsearch\Common\Exceptions\InvalidArgumentException
+     * @return $this
+     */
+    public function setBody($body)
+    {
+        if (isset($body) !== true) {
+            return $this;
+        }
+
+        if (is_array($body) !== true) {
+            throw new Exceptions\InvalidArgumentException(
+                'Body must be an array'
+            );
+        }
+        $this->body = $body;
+
+        return $this;
+    }
+
+
+    /**
+     * @throws \Elasticsearch\Common\Exceptions\BadMethodCallException
+     * @return string
+     */
+    public function getURI()
+    {
+        if (!$this->index) {
+            throw new Exceptions\RuntimeException(
+                'index is required for UpdateByQuery'
+            );
+        }
+
+        $uri = "/{$this->index}/_update_by_query";
+        if ($this->type) {
+            $uri = "/{$this->index}/{$this->type}/_update_by_query";
+        }
+
+        return $uri;
+    }
+
+
+    /**
+     * @return string[]
+     */
+    public function getParamWhitelist()
+    {
+        return [
+            'analyzer',
+            'analyze_wildcard',
+            'default_operator',
+            'df',
+            'explain',
+            'fields',
+            'fielddata_fields',
+            'from',
+            'ignore_unavailable',
+            'allow_no_indices',
+            'conflicts',
+            'expand_wildcards',
+            'lenient',
+            'lowercase_expanded_terms',
+            'pipeline',
+            'preference',
+            'q',
+            'routing',
+            'scroll',
+            'search_type',
+            'search_timeout',
+            'size',
+            'sort',
+            '_source',
+            '_source_exclude',
+            '_source_include',
+            'terminate_after',
+            'stats',
+            'suggest_field',
+            'suggest_mode',
+            'suggest_size',
+            'suggest_text',
+            'timeout',
+            'track_scores',
+            'version',
+            'version_type',
+            'request_cache',
+            'refresh',
+            'consistency',
+            'scroll_size',
+            'wait_for_completion',
+            'wait_for_active_shards',
+            'slices',
+        ];
+    }
+
+
+    /**
+     * @return string
+     */
+    public function getMethod()
+    {
+        return 'POST';
+    }
+}
diff --git a/src/Elasticsearch/Namespaces/AbstractNamespace.php b/src/Elasticsearch/Namespaces/AbstractNamespace.php
index 42a0c7815..13b2e02f6 100644
--- a/src/Elasticsearch/Namespaces/AbstractNamespace.php
+++ b/src/Elasticsearch/Namespaces/AbstractNamespace.php
@@ -46,7 +46,7 @@ public function extractArgument(&$params, $arg)
             $params = (array) $params;
         }
 
-        if (isset($params[$arg]) === true) {
+        if (array_key_exists($arg, $params) === true) {
             $val = $params[$arg];
             unset($params[$arg]);
 
diff --git a/src/Elasticsearch/Namespaces/CatNamespace.php b/src/Elasticsearch/Namespaces/CatNamespace.php
index dac0ff6e1..942983813 100644
--- a/src/Elasticsearch/Namespaces/CatNamespace.php
+++ b/src/Elasticsearch/Namespaces/CatNamespace.php
@@ -490,4 +490,31 @@ public function tasks($params = array())
 
         return $this->performRequest($endpoint);
     }
+
+    /**
+     * $params['local']          = (bool) Return local information, do not retrieve the state from master node (default: false)
+     *        ['master_timeout'] = (time) Explicit operation timeout for connection to master node
+     *        ['h']              = (list) Comma-separated list of column names to display
+     *        ['help']           = (bool) Return help information
+     *        ['v']              = (bool) Verbose mode. Display column headers
+     *        ['bytes']          = (enum) The unit in which to display byte values
+     *
+     * @param $params array Associative array of parameters
+     *
+     * @return array
+     */
+    public function templates($params = array())
+    {
+        $name = $this->extractArgument($params, 'name');
+
+        /** @var callback $endpointBuilder */
+        $endpointBuilder = $this->endpoints;
+
+        /** @var \Elasticsearch\Endpoints\Cat\Templates $endpoint */
+        $endpoint = $endpointBuilder('Cat\Templates');
+        $endpoint->setName($name)
+            ->setParams($params);
+
+        return $this->performRequest($endpoint);
+    }
 }
diff --git a/src/Elasticsearch/Namespaces/IndicesNamespace.php b/src/Elasticsearch/Namespaces/IndicesNamespace.php
index 2ad6b1585..e8e43a87a 100644
--- a/src/Elasticsearch/Namespaces/IndicesNamespace.php
+++ b/src/Elasticsearch/Namespaces/IndicesNamespace.php
@@ -48,7 +48,7 @@ public function exists($params)
      *
      * @param $params array Associative array of parameters
      *
-     * @return bool
+     * @return array
      */
     public function get($params)
     {
@@ -248,6 +248,7 @@ public function shrink($params = array())
     {
         $index = $this->extractArgument($params, 'index');
         $target = $this->extractArgument($params, 'target');
+        $body = $this->extractArgument($params, 'body');
 
         /** @var callback $endpointBuilder */
         $endpointBuilder = $this->endpoints;
@@ -255,7 +256,8 @@ public function shrink($params = array())
         /** @var \Elasticsearch\Endpoints\Indices\Shrink $endpoint */
         $endpoint = $endpointBuilder('Indices\Shrink');
         $endpoint->setIndex($index)
-                 ->setTarget($target);
+                 ->setTarget($target)
+                 ->setBody($body);
 
         return $this->performRequest($endpoint);
     }
diff --git a/src/Elasticsearch/Namespaces/RemoteNamespace.php b/src/Elasticsearch/Namespaces/RemoteNamespace.php
new file mode 100644
index 000000000..270530a54
--- /dev/null
+++ b/src/Elasticsearch/Namespaces/RemoteNamespace.php
@@ -0,0 +1,34 @@
+<?php
+
+namespace Elasticsearch\Namespaces;
+
+use Elasticsearch\Endpoints\Remote\Info;
+
+/**
+ * Class RemoteNamespace
+ *
+ * @category Elasticsearch
+ * @package  Elasticsearch\Namespaces\TasksNamespace
+ * @author   Zachary Tong <zach@elastic.co>
+ * @license  http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link     http://elastic.co
+ */
+class RemoteNamespace extends AbstractNamespace
+{
+    /**
+     * @param $params array Associative array of parameters
+     *
+     * @return array
+     */
+    public function info($params = array())
+    {
+        /** @var callback $endpointBuilder */
+        $endpointBuilder = $this->endpoints;
+
+        /** @var Info $endpoint */
+        $endpoint = $endpointBuilder('Remote\Info');
+        $endpoint->setParams($params);
+
+        return $this->performRequest($endpoint);
+    }
+}
diff --git a/src/Elasticsearch/Serializers/SmartSerializer.php b/src/Elasticsearch/Serializers/SmartSerializer.php
index bdae9f852..3b5181d7b 100644
--- a/src/Elasticsearch/Serializers/SmartSerializer.php
+++ b/src/Elasticsearch/Serializers/SmartSerializer.php
@@ -15,6 +15,13 @@
  */
 class SmartSerializer implements SerializerInterface
 {
+    private $PHP_VERSION;
+
+    public function __construct()
+    {
+        $this->PHP_VERSION = phpversion();
+    }
+
     /**
      * Serialize assoc array into JSON string
      *
@@ -27,7 +34,11 @@ public function serialize($data)
         if (is_string($data) === true) {
             return $data;
         } else {
-            $data = json_encode($data, JSON_PRESERVE_ZERO_FRACTION);
+            if (version_compare($this->PHP_VERSION, '5.6.6', '<') || ! defined('JSON_PRESERVE_ZERO_FRACTION')) {
+                $data = json_encode($data);
+            } else {
+                $data = json_encode($data, JSON_PRESERVE_ZERO_FRACTION);
+            }
             if ($data === '[]') {
                 return '{}';
             } else {
diff --git a/src/Elasticsearch/Transport.php b/src/Elasticsearch/Transport.php
index 07323f786..2354a80f4 100644
--- a/src/Elasticsearch/Transport.php
+++ b/src/Elasticsearch/Transport.php
@@ -113,10 +113,13 @@ function ($response) {
                 // Note, this could be a 4xx or 5xx error
             },
             //onFailure
-            function ($response) {
-                //some kind of real faiure here, like a timeout
-                $this->connectionPool->scheduleCheck();
-                // log stuff
+            function (\Exception $response) {
+                // Ignore 400 level errors, as that means the server responded just fine
+                $code = $response->getCode();
+                if (!(isset($code) && $code >=400 && $code < 500)) {
+                    // Otherwise schedule a check
+                    $this->connectionPool->scheduleCheck();
+                }
             });
 
         return $future;
diff --git a/tests/Elasticsearch/Tests/ClientIntegrationTests.php b/tests/Elasticsearch/Tests/ClientIntegrationTests.php
new file mode 100644
index 000000000..4291044a2
--- /dev/null
+++ b/tests/Elasticsearch/Tests/ClientIntegrationTests.php
@@ -0,0 +1,32 @@
+<?php
+
+/**
+ * Class ClientTest
+ *
+ * @category   Tests
+ * @package    Elasticsearch
+ * @subpackage Tests
+ * @author     Zachary Tong <zachary.tong@elasticsearch.com>
+ * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link       http://elasticsearch.org
+ */
+class ClientIntegrationTests extends \PHPUnit_Framework_TestCase
+{
+    public function testCustomQueryParams()
+    {
+        $params = array();
+
+        $client = Elasticsearch\ClientBuilder::create()->setHosts([$_SERVER['ES_TEST_HOST']])->build();
+
+        $getParams = array(
+            'index' => 'test',
+            'type' => 'test',
+            'id' => 1,
+            'parent' => 'abc',
+            'custom' => array('customToken' => 'abc', 'otherToken' => 123),
+            'client' => ['ignore' => 400]
+        );
+        $exists = $client->exists($getParams);
+    }
+
+}
\ No newline at end of file
diff --git a/tests/Elasticsearch/Tests/ClientTest.php b/tests/Elasticsearch/Tests/ClientTest.php
index da4cc8c17..6f654ecb6 100644
--- a/tests/Elasticsearch/Tests/ClientTest.php
+++ b/tests/Elasticsearch/Tests/ClientTest.php
@@ -32,23 +32,6 @@ public function testConstructorIllegalPort()
         $client = Elasticsearch\ClientBuilder::create()->setHosts(['localhost:abc'])->build();
     }
 
-    public function testCustomQueryParams()
-    {
-        $params = array();
-
-        $client = Elasticsearch\ClientBuilder::create()->setHosts([$_SERVER['ES_TEST_HOST']])->build();
-
-        $getParams = array(
-            'index' => 'test',
-            'type' => 'test',
-            'id' => 1,
-            'parent' => 'abc',
-            'custom' => array('customToken' => 'abc', 'otherToken' => 123),
-            'client' => ['ignore' => 400]
-        );
-        $exists = $client->exists($getParams);
-    }
-
     public function testFromConfig()
     {
         $params = [
diff --git a/tests/Elasticsearch/Tests/ConnectionPool/SniffingConnectionPoolIntegrationTest.php b/tests/Elasticsearch/Tests/ConnectionPool/SniffingConnectionPoolIntegrationTest.php
index e6f3de922..0756c6769 100644
--- a/tests/Elasticsearch/Tests/ConnectionPool/SniffingConnectionPoolIntegrationTest.php
+++ b/tests/Elasticsearch/Tests/ConnectionPool/SniffingConnectionPoolIntegrationTest.php
@@ -13,6 +13,11 @@
  */
 class SniffingConnectionPoolIntegrationTest extends \PHPUnit_Framework_TestCase
 {
+    protected function setUp()
+    {
+        static::markTestSkipped("All of Sniffing unit tests use outdated cluster state format, need to redo");
+    }
+
     public function testSniff()
     {
         $client = ClientBuilder::create()
@@ -20,6 +25,7 @@ public function testSniff()
             ->setConnectionPool('\Elasticsearch\ConnectionPool\SniffingConnectionPool', ['sniffingInterval' => -10])
             ->build();
 
-        $client->ping();
+        $pinged = $client->ping();
+        $this->assertTrue($pinged);
     }
 }
diff --git a/tests/Elasticsearch/Tests/ConnectionPool/SniffingConnectionPoolTest.php b/tests/Elasticsearch/Tests/ConnectionPool/SniffingConnectionPoolTest.php
index 5d38c87a2..d724539af 100644
--- a/tests/Elasticsearch/Tests/ConnectionPool/SniffingConnectionPoolTest.php
+++ b/tests/Elasticsearch/Tests/ConnectionPool/SniffingConnectionPoolTest.php
@@ -16,6 +16,12 @@
  */
 class SniffingConnectionPoolTest extends \PHPUnit_Framework_TestCase
 {
+    protected function setUp()
+    {
+        static::markTestSkipped("All of Sniffing unit tests use outdated cluster state format, need to redo");
+    }
+
+
     public function tearDown()
     {
         m::close();
diff --git a/tests/Elasticsearch/Tests/ConnectionPool/StaticConnectionPoolIntegrationTest.php b/tests/Elasticsearch/Tests/ConnectionPool/StaticConnectionPoolIntegrationTest.php
new file mode 100644
index 000000000..f0ef4df5d
--- /dev/null
+++ b/tests/Elasticsearch/Tests/ConnectionPool/StaticConnectionPoolIntegrationTest.php
@@ -0,0 +1,33 @@
+<?php
+
+/**
+ * Class StaticConnectionPoolIntegrationTest
+ *
+ * @category   Tests
+ * @package    Elasticsearch
+ * @subpackage Tests/StaticConnectionPoolTest
+ * @author     Zachary Tong <zachary.tong@elasticsearch.com>
+ * @license    http://www.apache.org/licenses/LICENSE-2.0 Apache2
+ * @link       http://elasticsearch.org
+ */
+class StaticConnectionPoolIntegrationTest extends \PHPUnit_Framework_TestCase
+{
+    // Issue #636
+    public function test404Liveness() {
+        $client = \Elasticsearch\ClientBuilder::create()
+            ->setHosts([$_SERVER['ES_TEST_HOST']])
+            ->setConnectionPool(\Elasticsearch\ConnectionPool\StaticConnectionPool::class)
+            ->build();
+
+        $connection = $client->transport->getConnection();
+
+        // Ensure connection is dead
+        $connection->markDead();
+
+        // The index doesn't exist, but the server is up so this will return a 404
+        $this->assertFalse($client->indices()->exists(['index' => 'not_existing_index']));
+
+        // But the node should be marked as alive since the server responded
+        $this->assertTrue($connection->isAlive());
+    }
+}
\ No newline at end of file
diff --git a/tests/Elasticsearch/Tests/Connections/ConnectionTest.php b/tests/Elasticsearch/Tests/Connections/ConnectionTest.php
new file mode 100644
index 000000000..61e37f6ff
--- /dev/null
+++ b/tests/Elasticsearch/Tests/Connections/ConnectionTest.php
@@ -0,0 +1,81 @@
+<?php
+namespace Elasticsearch\Tests\Connections;
+
+use Elasticsearch\Client;
+use Elasticsearch\ClientBuilder;
+use Elasticsearch\Connections\Connection;
+use Elasticsearch\Serializers\SerializerInterface;
+use Elasticsearch\Serializers\SmartSerializer;
+use Psr\Log\LoggerInterface;
+
+class ConnectionTest extends \PHPUnit\Framework\TestCase
+{
+    private $logger;
+    private $trace;
+    private $serializer;
+
+    protected function setUp()
+    {
+        $this->logger = $this->createMock(LoggerInterface::class);
+        $this->trace = $this->createMock(LoggerInterface::class);
+        $this->serializer = $this->createMock(SerializerInterface::class);
+    }
+
+    public function testConstructor()
+    {
+        $params = [];
+        $host = [
+            'host' => 'localhost'
+        ];
+
+        $connection = new Connection(
+            function(){},
+            $host,
+            $params,
+            $this->serializer,
+            $this->logger,
+            $this->trace
+        );
+
+        $this->assertInstanceOf(Connection::class, $connection);
+    }
+
+    public function testGetHeadersContainUserAgent()
+    {
+        $params = [];
+        $host = [
+            'host' => 'localhost'
+        ];
+        $connection = new Connection(
+            function(){},
+            $host,
+            $params,
+            $this->serializer,
+            $this->logger,
+            $this->trace
+        );
+        $headers =  $connection->getHeaders();
+        $this->assertArrayHasKey('User-Agent', $headers);
+        $this->assertContains('elasticsearch-php/'. Client::VERSION, $headers['User-Agent'][0]);
+    }
+
+    public function testUserAgentHeaderIsSent()
+    {
+        $params = [];
+        $host = [
+            'host' => 'localhost'
+        ];
+        $connection = new Connection(
+            ClientBuilder::defaultHandler(),
+            $host,
+            $params,
+            $this->serializer,
+            $this->logger,
+            $this->trace
+        );
+        $result = $connection->performRequest('GET', '/');
+        $request = $connection->getLastRequestInfo()['request'];
+        $this->assertArrayHasKey('User-Agent', $request['headers']);
+        $this->assertContains('elasticsearch-php/'. Client::VERSION, $request['headers']['User-Agent'][0]);
+    }
+}
diff --git a/tests/Elasticsearch/Tests/Endpoints/AbstractEndpointTest.php b/tests/Elasticsearch/Tests/Endpoints/AbstractEndpointTest.php
new file mode 100644
index 000000000..51701e37e
--- /dev/null
+++ b/tests/Elasticsearch/Tests/Endpoints/AbstractEndpointTest.php
@@ -0,0 +1,36 @@
+<?php
+
+namespace Elasticsearch\Tests\Endpoints;
+
+use Elasticsearch\Endpoints\AbstractEndpoint;
+
+class AbstractEndpointTest extends \PHPUnit_Framework_TestCase
+{
+    private $endpoint;
+
+    public static function invalidParameters()
+    {
+        return [
+            [['invalid' => 10]],
+            [['invalid' => 10, 'invalid2' => 'another']],
+        ];
+    }
+
+    /**
+     * @dataProvider invalidParameters
+     * @expectedException Elasticsearch\Common\Exceptions\UnexpectedValueException
+     */
+    public function testInvalidParamsCauseErrorsWhenProvidedToSetParams(array $params)
+    {
+        $this->endpoint->expects($this->once())
+            ->method('getParamWhitelist')
+            ->willReturn(['one', 'two']);
+
+        $this->endpoint->setParams($params);
+    }
+
+    protected function setUp()
+    {
+        $this->endpoint = $this->getMockForAbstractClass(AbstractEndpoint::class);
+    }
+}
diff --git a/tests/Elasticsearch/Tests/Endpoints/StatusEndpointTest.php b/tests/Elasticsearch/Tests/Endpoints/StatusEndpointTest.php
new file mode 100644
index 000000000..c1896e578
--- /dev/null
+++ b/tests/Elasticsearch/Tests/Endpoints/StatusEndpointTest.php
@@ -0,0 +1,56 @@
+<?php
+namespace Elasticsearch\Tests\Endpoints;
+
+use Elasticsearch\Endpoints\Snapshot\Status;
+use Elasticsearch\Common\Exceptions;
+
+class StatusEndpointTest extends \PHPUnit\Framework\TestCase
+{
+    private $endpoint;
+
+    protected function setUp()
+    {
+        $this->endpoint = new Status();
+    }
+
+    public static function statusParams()
+    {
+        return [
+            [
+                'repository' => 'my_backup',
+                'snapshot' => null,
+                'expected' => '/_snapshot/my_backup/_status',
+            ],
+            [
+                'repository' => 'my_backup',
+                'snapshot' => 'snapshot_1',
+                'expected' => '/_snapshot/my_backup/snapshot_1/_status',
+            ],
+        ];
+    }
+
+    /**
+     * @dataProvider statusParams
+     */
+    public function testGetUriReturnsAppropriateUri($repository, $snapshot, $expected)
+    {
+        if ($repository) {
+            $this->endpoint->setRepository($repository);
+        }
+
+        if ($snapshot) {
+            $this->endpoint->setSnapshot($snapshot);
+        }
+
+        $this->assertSame($expected, $this->endpoint->getURI());
+    }
+
+    public function testMissingRepositoryThrowsException()
+    {
+
+        $this->expectException(Exceptions\RuntimeException::class);
+
+        $this->endpoint->setSnapshot('should fail');
+        $this->endpoint->getURI();
+    }
+}
diff --git a/tests/Elasticsearch/Tests/YamlRunnerTest.php b/tests/Elasticsearch/Tests/YamlRunnerTest.php
index 29a35318c..36eebd11d 100644
--- a/tests/Elasticsearch/Tests/YamlRunnerTest.php
+++ b/tests/Elasticsearch/Tests/YamlRunnerTest.php
@@ -42,7 +42,7 @@ class YamlRunnerTest extends \PHPUnit_Framework_TestCase
 
     /** @var array A list of supported features */
     private static $supportedFeatures = [
-        'stash_in_path',
+        'stash_in_path', 'warnings', 'headers'
     ];
 
     /** @var array A mapping for endpoint when there is a reserved keywords for the method / namespace name */
@@ -56,13 +56,16 @@ class YamlRunnerTest extends \PHPUnit_Framework_TestCase
     private static $skippedTest = [
         'cat.nodeattrs/10_basic.yaml' => 'Using java regex fails in PHP',
         'cat.repositories/10_basic.yaml' => 'Using java regex fails in PHP',
-        'indices.shrink/10_basic.yaml' => 'Shrink tests seem to require multiple nodes'
+        'indices.shrink/10_basic.yaml' => 'Shrink tests seem to require multiple nodes',
+        'indices.rollover/10_basic.yaml' => 'Rollover test seems buggy atm'
     ];
 
     /** @var array A list of files to skip completely, due to fatal parsing errors */
     private static $skippedFiles = [
         'indices.create/10_basic.yaml' => 'Temporary: Yaml parser doesnt support "inline" empty keys',
         'indices.put_mapping/10_basic.yaml' => 'Temporary: Yaml parser doesnt support "inline" empty keys',
+        'search/110_field_collapsing.yaml' => 'Temporary: parse error, malformed inline yaml',
+        'cat.nodes/10_basic.yaml' => 'Temporary: parse error, something about $body: |'
     ];
 
     /**
@@ -102,7 +105,11 @@ public static function setUpBeforeClass()
     public function setUp()
     {
         $this->clean();
-        $this->client = Elasticsearch\ClientBuilder::create()->setHosts([self::getHost()])->build();
+        $builder = Elasticsearch\ClientBuilder::create()->setHosts([self::getHost()]);
+        if (version_compare(phpversion(), '5.6.6', '<') || ! defined('JSON_PRESERVE_ZERO_FRACTION')) {
+            $builder->allowBadJSONSerialization();
+        }
+        $this->client = $builder->build();
     }
 
     /**
@@ -205,6 +212,14 @@ public function processOperation($operation, $lastOperationResult, &$context, $t
             return $this->operationGreaterThan($operation->{$operationName}, $lastOperationResult, $context, $testName);
         }
 
+        if ('lte' === $operationName) {
+            return $this->operationLessThanOrEqual($operation->{$operationName}, $lastOperationResult, $context, $testName);
+        }
+
+        if ('t' === $operationName) {
+            return $this->operationLessThan($operation->{$operationName}, $lastOperationResult, $context, $testName);
+        }
+
         if ('length' === $operationName) {
             return $this->operationLength($operation->{$operationName}, $lastOperationResult, $context, $testName);
         }
@@ -236,13 +251,27 @@ public function processOperation($operation, $lastOperationResult, &$context, $t
     public function operationDo($operation, $lastOperationResult, &$context, $testName, $async = false)
     {
         $expectedError = null;
+        $expectedWarnings = null;
+        $headers = null;
 
-        // Check if a error must be catched
+        // Check if a error must be caught
         if ('catch' === key($operation)) {
             $expectedError = current($operation);
             next($operation);
         }
 
+        // Check if a warning must be caught
+        if ('warnings' === key($operation)) {
+            $expectedWarnings = current($operation);
+            next($operation);
+        }
+
+        // Any specific headers to add?
+        if ('headers' === key($operation)) {
+            $headers = current($operation);
+            next($operation);
+        }
+
         $endpointInfo = explode('.', key($operation));
         $endpointParams = $this->replaceWithContext(current($operation), $context);
         $caller = $this->client;
@@ -258,7 +287,7 @@ public function operationDo($operation, $lastOperationResult, &$context, $testNa
             $method = Inflector::camelize($endpointInfo[1]);
         }
 
-        if (property_exists($endpointParams, 'ignore')) {
+        if (is_object($endpointParams) === true && property_exists($endpointParams, 'ignore')) {
             $ignore = $endpointParams->ignore;
             unset($endpointParams->ignore);
 
@@ -269,6 +298,10 @@ public function operationDo($operation, $lastOperationResult, &$context, $testNa
             $endpointParams->client['future'] = true;
         }
 
+        if ($headers != null) {
+            $endpointParams->client['headers'] = $headers;
+        }
+
         list($method, $namespace) = $this->mapEndpoint($method, $namespace);
 
         if (null !== $namespace) {
@@ -283,12 +316,19 @@ public function operationDo($operation, $lastOperationResult, &$context, $testNa
             self::markTestIncomplete(sprintf('Method "%s" not implement in "%s"', $method, get_class($caller)));
         }
 
+        // TODO remove this after cat testing situation resolved
+        if ($caller instanceof Elasticsearch\Namespaces\CatNamespace) {
+            if (!isset($endpointParams->format)) {
+                $endpointParams->format = 'text';
+            }
+        }
+
         // Exist* methods have to be manually 'unwrapped' into true/false for async
         if (strpos($method, "exist") !== false && $async === true) {
-            return $this->executeAsyncExistRequest($caller, $method, $endpointParams, $expectedError, $testName);
+            return $this->executeAsyncExistRequest($caller, $method, $endpointParams, $expectedError, $expectedWarnings, $testName);
         }
 
-        return $this->executeRequest($caller, $method, $endpointParams, $expectedError, $testName);
+        return $this->executeRequest($caller, $method, $endpointParams, $expectedError, $expectedWarnings, $testName);
     }
 
     /**
@@ -304,7 +344,7 @@ public function operationDo($operation, $lastOperationResult, &$context, $testNa
      *
      * @return array|mixed
      */
-    public function executeRequest($caller, $method, $endpointParams, $expectedError, $testName)
+    public function executeRequest($caller, $method, $endpointParams, $expectedError, $expectedWarnings, $testName)
     {
         try {
             $response = $caller->$method($endpointParams);
@@ -313,6 +353,8 @@ public function executeRequest($caller, $method, $endpointParams, $expectedError
                 $response = $response->wait();
             }
 
+            $this->checkForWarnings($expectedWarnings);
+
             return $response;
         } catch (\Exception $exception) {
             if (null !== $expectedError) {
@@ -340,7 +382,7 @@ public function executeRequest($caller, $method, $endpointParams, $expectedError
      *
      * @return bool
      */
-    public function executeAsyncExistRequest($caller, $method, $endpointParams, $expectedError, $testName)
+    public function executeAsyncExistRequest($caller, $method, $endpointParams, $expectedError, $expectedWarnings, $testName)
     {
         try {
 
@@ -350,6 +392,8 @@ public function executeAsyncExistRequest($caller, $method, $endpointParams, $exp
                 $response = $response->wait();
             }
 
+            $this->checkForWarnings($expectedWarnings);
+
             if ($response['status'] === 200) {
                 return true;
             } else {
@@ -368,6 +412,45 @@ public function executeAsyncExistRequest($caller, $method, $endpointParams, $exp
         }
     }
 
+    public function checkForWarnings($expectedWarnings) {
+        $last = $this->client->transport->getLastConnection()->getLastRequestInfo();
+
+
+        // We have some warnings to check
+        if ($expectedWarnings !== null) {
+            if (isset($last['response']['headers']['Warning']) === true) {
+                foreach ($last['response']['headers']['Warning'] as $warning) {
+                    //$position = array_search($warning, $expectedWarnings);
+                    $position = false;
+                    foreach ($expectedWarnings as $index => $value) {
+                        if (stristr($warning, $value) !== false) {
+                            $position = $index;
+                            break;
+                        }
+                    }
+                    if ($position !== false) {
+                        // found the warning
+                        unset($expectedWarnings[$position]);
+                    } else {
+                        // didn't find, throw error
+                        //throw new \Exception("Expected to find warning [$warning] but did not.");
+                    }
+                }
+                if (count($expectedWarnings) > 0) {
+                    print_r($last['response']);
+                    throw new \Exception("Expected to find more warnings: ". print_r($expectedWarnings, true));
+                }
+            }
+        }
+
+        // Check to make sure we're adding headers
+        static::assertArrayHasKey('Content-Type', $last['request']['headers'], print_r($last['request']['headers'], true));
+        static::assertEquals('application/json', $last['request']['headers']['Content-Type'][0], print_r($last['request']['headers'], true));
+        static::assertArrayHasKey('Accept', $last['request']['headers'], print_r($last['request']['headers'], true));
+        static::assertEquals('application/json', $last['request']['headers']['Accept'][0], print_r($last['request']['headers'], true));
+
+    }
+
     /**
      * Check if a field in the last operation is false
      *
@@ -478,6 +561,40 @@ public function operationGreaterThan($operation, $lastOperationResult, &$context
         return $lastOperationResult;
     }
 
+    /**
+     * Check if a field in the last operation is less than or equal a value
+     *
+     * @param $operation
+     * @param $lastOperationResult
+     * @param $testName
+     */
+    public function operationLessThanOrEqual($operation, $lastOperationResult, &$context, $testName)
+    {
+        $value = $this->resolveValue($lastOperationResult, key($operation), $context);
+        $expected = current($operation);
+
+        static::assertLessThanOrEqual($expected, $value, 'Failed to lte in test ' . $testName);
+
+        return $lastOperationResult;
+    }
+
+    /**
+     * Check if a field in the last operation is less than a value
+     *
+     * @param $operation
+     * @param $lastOperationResult
+     * @param $testName
+     */
+    public function operationLessThan($operation, $lastOperationResult, &$context, $testName)
+    {
+        $value = $this->resolveValue($lastOperationResult, key($operation), $context);
+        $expected = current($operation);
+
+        static::assertLessThan($expected, $value, 'Failed to lt in test ' . $testName);
+
+        return $lastOperationResult;
+    }
+
     /**
      * Check if a field in the last operation has length of a value
      *
@@ -523,8 +640,20 @@ public function operationSet($operation, $lastOperationResult, &$context, $testN
      */
     public function operationSkip($operation, $lastOperationResult, $testName)
     {
-        if (property_exists($operation, 'features') && !in_array($operation->features, static::$supportedFeatures, true)) {
-            static::markTestSkipped(sprintf('Feature(s) %s not supported in test "%s"', json_encode($operation->features), $testName));
+        if (is_object($operation) !== true ) {
+            return $lastOperationResult;
+        }
+
+        if (property_exists($operation, 'features')) {
+            if (is_array($operation->features)) {
+                if (count(array_intersect($operation->features, static::$supportedFeatures)) != count($operation->features)) {
+                    static::markTestSkipped(sprintf('Feature(s) %s not supported in test "%s"', json_encode($operation->features), $testName));
+                }
+            } else {
+                if (!in_array($operation->features, static::$supportedFeatures, true)) {
+                    static::markTestSkipped(sprintf('Feature(s) %s not supported in test "%s"', json_encode($operation->features), $testName));
+                }
+            }
         }
 
         if (property_exists($operation, 'version')) {
@@ -536,15 +665,15 @@ public function operationSkip($operation, $lastOperationResult, $testName)
                 static::markTestSkipped(sprintf('Skip test "%s", as all versions should be skipped (%s)', $testName, $operation->reason));
             }
 
-            if (!isset($version[0])) {
+            if (!isset($version[0]) || $version[0] === "") {
                 $version[0] = ~PHP_INT_MAX;
             }
 
-            if (!isset($version[1])) {
+            if (!isset($version[1]) || $version[1] === "" ) {
                 $version[1] = PHP_INT_MAX;
             }
 
-            if (version_compare(static::$esVersion, $version[0]) >= 0 && version_compare($version[1], YamlRunnerTest::$esVersion) >= 0) {
+            if (version_compare(static::$esVersion, $version[0], '>=')  && version_compare(static::$esVersion, $version[1], '<=')) {
                 static::markTestSkipped(sprintf('Skip test "%s", as version %s should be skipped (%s)', $testName, static::$esVersion, $operation->reason));
             }
         }
@@ -738,6 +867,9 @@ private function formatRegex($regex)
     private function splitDocument($file, $path, $filter = null)
     {
         $fileContent = file_get_contents($file);
+        // cleanup some bad comments
+        $fileContent = str_replace('"#', '" #', $fileContent);
+
         $documents = explode("---\n", $fileContent);
         $documents = array_filter($documents, function ($item) {
             return trim($item) !== '';
diff --git a/travis/download_and_run_es.sh b/travis/download_and_run_es.sh
index 1ca4c9d29..ad6fec2b1 100755
--- a/travis/download_and_run_es.sh
+++ b/travis/download_and_run_es.sh
@@ -21,6 +21,12 @@ unzip "elasticsearch-latest-SNAPSHOT.zip"
 echo "Adding repo to config..."
 find . -name "elasticsearch.yml" | while read TXT ; do echo 'repositories.url.allowed_urls: ["http://*"]' >> $TXT ; done
 find . -name "elasticsearch.yml" | while read TXT ; do echo 'path.repo: ["/tmp"]' >> $TXT ; done
+find . -name "elasticsearch.yml" | while read TXT ; do echo 'node.max_local_storage_nodes: 1' >> $TXT ; done
+find . -name "elasticsearch.yml" | while read TXT ; do echo 'cluster.routing.allocation.disk.watermark.low: 1b' >> $TXT ; done
+find . -name "elasticsearch.yml" | while read TXT ; do echo 'cluster.routing.allocation.disk.watermark.high: 1b' >> $TXT ; done
+find . -name "elasticsearch.yml" | while read TXT ; do echo 'node.attr.testattr: test' >> $TXT ; done
+find . -name "elasticsearch.yml" | while read TXT ; do echo 'script.max_compilations_per_minute: 2048' >> $TXT ; done
+
 
 echo "Starting Elasticsearch v${ES_VERSION}"
 
diff --git a/util/EnsureClusterAlive.php b/util/EnsureClusterAlive.php
index e3a4b3a91..88d1de6fd 100644
--- a/util/EnsureClusterAlive.php
+++ b/util/EnsureClusterAlive.php
@@ -24,7 +24,22 @@
     $count += 1;
 
     if ($count > 15) {
-        throw new \Exception("Live cluster could not be found in 15s!");
+        echo "Live cluster could not be found in 15s!\nContents of elasticsearch.log:\n\n";
+
+        $dir = new DirectoryIterator(dirname(__DIR__));
+
+        foreach ($dir as $fileinfo) {
+            if ($fileinfo->isDir() && !$fileinfo->isDot()) {
+                if (strpos($fileinfo->getFilename(), "elasticsearch") === 0) {
+                    $log = file_get_contents(dirname(__DIR__)."/$fileinfo/logs/elasticsearch.log");
+                    echo $log;
+                    break;
+                }
+
+            }
+        }
+
+        throw new \Exception();
     }
     sleep(1);
 }
