diff --git a/.gitignore b/.gitignore
index a0190963..473211c6 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+doc
 tmp
 .rvmrc
 .ruby-version
diff --git a/Gemfile.lock b/Gemfile.lock
index 73364087..8f0f6944 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -57,7 +57,7 @@ GEM
       multipart-post (>= 1.2, < 3)
     ffi (1.9.10)
     gherkin (3.2.0)
-    hashdiff (0.2.3)
+    hashdiff (0.3.7)
     httpclient (2.7.1)
     i18n (0.7.0)
     inch (0.7.0)
@@ -129,7 +129,7 @@ GEM
     tins (1.8.2)
     tzinfo (1.2.2)
       thread_safe (~> 0.1)
-    webmock (1.22.6)
+    webmock (3.3.0)
       addressable (>= 2.3.6)
       crack (>= 0.3.2)
       hashdiff
@@ -154,7 +154,7 @@ DEPENDENCIES
   rspec_api_documentation!
   sinatra (~> 1.4, >= 1.4.4)
   thin (~> 1.6, >= 1.6.3)
-  webmock (~> 1.7)
+  webmock (~> 3.3)
 
 BUNDLED WITH
    1.16.1
diff --git a/lib/rspec_api_documentation/configuration.rb b/lib/rspec_api_documentation/configuration.rb
index c4721674..24845653 100644
--- a/lib/rspec_api_documentation/configuration.rb
+++ b/lib/rspec_api_documentation/configuration.rb
@@ -81,6 +81,9 @@ def self.add_setting(name, opts = {})
     add_setting :response_headers_to_include, :default => nil
     add_setting :html_embedded_css_file, :default => nil
 
+    # sorting
+    add_setting :sort_routes, :default => false
+
     # renamed to request_body_formatter. here for backwards compatibility
     add_setting :post_body_formatter, :default => nil
 
diff --git a/lib/rspec_api_documentation/dsl/endpoint/params.rb b/lib/rspec_api_documentation/dsl/endpoint/params.rb
index 037788b8..c2501b20 100644
--- a/lib/rspec_api_documentation/dsl/endpoint/params.rb
+++ b/lib/rspec_api_documentation/dsl/endpoint/params.rb
@@ -13,11 +13,19 @@ def initialize(example_group, example, extra_params)
         end
 
         def call
-          parameters = example.metadata.fetch(:parameters, {}).inject({}) do |hash, param|
+          set_param = -> hash, param {
             SetParam.new(self, hash, param).call
-          end
-          parameters.deep_merge!(extra_params)
-          parameters
+          }
+
+          example.metadata
+            .fetch(:parameters, {})
+            .inject({}, &set_param)
+            .deep_merge(
+              example.metadata
+                .fetch(:attributes, {})
+                .inject({}, &set_param)
+            )
+            .deep_merge(extra_params)
         end
 
       private
diff --git a/lib/rspec_api_documentation/dsl/resource.rb b/lib/rspec_api_documentation/dsl/resource.rb
index 1e45d4e2..c6569e2e 100644
--- a/lib/rspec_api_documentation/dsl/resource.rb
+++ b/lib/rspec_api_documentation/dsl/resource.rb
@@ -8,15 +8,25 @@ def self.define_action(method)
         define_method method do |*args, &block|
           options = args.extract_options!
           options[:method] = method
+
           if metadata[:route_uri]
             options[:route] = metadata[:route_uri]
             options[:action_name] = args.first
+
           else
             options[:route] = args.first
+            options[:route_uri] = args[0].gsub(/\{.*\}/, "")
+            options[:route_optionals] = (optionals = args[0].match(/(\{.*\})/) and optionals[-1])
+            options[:route_name] = options[:route_name] || options[:route]
+            options[:action_name] = options[:action_name] || method.to_s.upcase
+
           end
+
           options[:api_doc_dsl] = :endpoint
+
           args.push(options)
           args[0] = "#{method.to_s.upcase} #{args[0]}"
+
           context(*args, &block)
         end
       end
@@ -30,7 +40,7 @@ def self.define_action(method)
 
       def callback(*args, &block)
         begin
-          require 'webmock'
+          require 'webmock/rspec'
         rescue LoadError
           raise "Callbacks require webmock to be installed"
         end
@@ -71,7 +81,13 @@ def header(name, value)
       end
 
       def explanation(text)
-        safe_metadata(:resource_explanation, text)
+        if metadata[:method].present?
+          safe_metadata(:method_explanation, text)
+        elsif metadata[:route_uri].present?
+          safe_metadata(:route_explanation, text)
+        else
+          safe_metadata(:resource_explanation, text)
+        end
       end
 
       private
diff --git a/lib/rspec_api_documentation/views/api_blueprint_index.rb b/lib/rspec_api_documentation/views/api_blueprint_index.rb
index 75e19449..57edaba1 100644
--- a/lib/rspec_api_documentation/views/api_blueprint_index.rb
+++ b/lib/rspec_api_documentation/views/api_blueprint_index.rb
@@ -12,19 +12,25 @@ def sections
             attrs  = fields(:attributes, examples)
             params = fields(:parameters, examples)
 
-            methods = examples.group_by(&:http_method).map do |http_method, examples|
-              {
-                http_method: http_method,
-                description: examples.first.respond_to?(:action_name) && examples.first.action_name,
-                examples: examples
-              }
-            end
+            methods = examples
+              .group_by { |e| "#{e.http_method} - #{e.action_name}" }
+              .map do |group, examples|
+                first_example = examples.first
+
+                {
+                  http_method: first_example.try(:http_method),
+                  description: first_example.try(:action_name),
+                  explanation: first_example.try(:[], :metadata).try(:[], :method_explanation),
+                  examples: examples
+                }
+              end
 
             {
               "has_attributes?".to_sym => attrs.size > 0,
               "has_parameters?".to_sym => params.size > 0,
               route: format_route(examples[0]),
               route_name: examples[0][:route_name],
+              explanation: examples[0][:route_explanation],
               attributes: attrs,
               parameters: params,
               http_methods: methods
@@ -32,7 +38,7 @@ def sections
           end
 
           section.merge({
-            routes: routes
+            routes: @configuration.sort_routes ? routes.sort_by { |r| r[:route_name] } : routes
           })
         end
       end
@@ -60,11 +66,10 @@ def format_route(example)
       # with all of its properties, like name, description, required.
       #   {
       #     required: true,
-      #     example: "1",
       #     type: "string",
       #     name: "id",
       #     description: "The id",
-      #     properties_description: "required, string"
+      #     properties_description: "string, required"
       #   }
       def fields(property_name, examples)
         examples
@@ -74,8 +79,10 @@ def fields(property_name, examples)
           .uniq { |property| property[:name] }
           .map do |property|
             properties = []
-            properties << "required"      if property[:required]
             properties << property[:type] if property[:type]
+            properties << "required"      if property[:required] == true
+            properties << "optional"      if property[:required].blank?
+
             if properties.count > 0
               property[:properties_description] = properties.join(", ")
             else
diff --git a/rspec_api_documentation.gemspec b/rspec_api_documentation.gemspec
index cc975926..8e1ba9ac 100644
--- a/rspec_api_documentation.gemspec
+++ b/rspec_api_documentation.gemspec
@@ -26,7 +26,7 @@ Gem::Specification.new do |s|
   s.add_development_dependency "rake", "~> 10.1"
   s.add_development_dependency "rack-test", "~> 0.6.2"
   s.add_development_dependency "rack-oauth2", "~> 1.2.2", ">= 1.0.7"
-  s.add_development_dependency "webmock", "~> 1.7"
+  s.add_development_dependency "webmock", "~> 3.3"
   s.add_development_dependency "rspec-its", "~> 1.0"
   s.add_development_dependency "faraday", "~> 0.9", ">= 0.9.0"
   s.add_development_dependency "thin", "~> 1.6", ">= 1.6.3"
diff --git a/spec/dsl_spec.rb b/spec/dsl_spec.rb
index 94253414..cd841aad 100644
--- a/spec/dsl_spec.rb
+++ b/spec/dsl_spec.rb
@@ -130,9 +130,12 @@
     parameter :id, 'The ID of the resource.', :required => true, scope: :data
     parameter :note, "Any additional notes about your order."
 
+    attribute :tip, "The amount you want to tip", :required => true
+
     let(:type) { "coffee" }
     let(:size) { "medium" }
     let(:data_id) { 2 }
+    let(:tip) { 20 }
 
     let(:id) { 1 }
 
@@ -157,6 +160,10 @@
         expect(params['data']).to eq({'id' => 2})
       end
 
+      it "should set attributes as well" do
+        expect(params["tip"]).to eq(tip())
+      end
+
       it "should allow extra parameters to be passed in" do
         expect(client).to receive(method).with(path, params.merge("extra" => true), nil)
         do_request(:extra => true)
diff --git a/spec/http_test_client_spec.rb b/spec/http_test_client_spec.rb
index e2282371..9f73bb78 100644
--- a/spec/http_test_client_spec.rb
+++ b/spec/http_test_client_spec.rb
@@ -3,7 +3,7 @@
 require 'capybara'
 require 'capybara/server'
 require 'sinatra/base'
-require 'webmock'
+require 'webmock/rspec'
 require 'support/stub_app'
 
 describe RspecApiDocumentation::HttpTestClient do
@@ -16,7 +16,7 @@
       Rack::Handler::Thin.run(app, :Port => port)
     end
 
-    server = Capybara::Server.new(StubApp.new, 8888)
+    server = Capybara::Server.new(StubApp.new, 29876)
     server.boot
   end
 
@@ -25,7 +25,7 @@
   end
 
   let(:client_context) { |example| double(example: example, app_root: 'nowhere') }
-  let(:target_host) { 'http://localhost:8888' }
+  let(:target_host) { 'http://localhost:29876' }
   let(:test_client) { RspecApiDocumentation::HttpTestClient.new(client_context, {host: target_host}) }
 
   subject { test_client }
diff --git a/spec/views/api_blueprint_index_spec.rb b/spec/views/api_blueprint_index_spec.rb
index 862016c2..039a4833 100644
--- a/spec/views/api_blueprint_index_spec.rb
+++ b/spec/views/api_blueprint_index_spec.rb
@@ -63,7 +63,10 @@
 
   let(:rspec_example_comments) do
     comment_group.route "/comments", "Comments Collection" do
+      explanation "Route explanation"
+
       get("/comments") do
+        explanation "Method explanation"
         example_request 'Get all comments' do
         end
       end
@@ -98,6 +101,8 @@
         post_route = sections[1][:routes][1]
         post_route_with_optionals = sections[1][:routes][2]
 
+        expect(comments_route[:explanation]).to eq "Route explanation"
+
         comments_examples = comments_route[:http_methods].map { |http_method| http_method[:examples] }.flatten
         expect(comments_examples.size).to eq 1
         expect(comments_route[:route]).to eq "/comments"
@@ -118,7 +123,7 @@
           example: "1",
           name: "id",
           description: "The id",
-          properties_description: "required, string"
+          properties_description: "string, required"
         }]
         expect(post_route[:has_attributes?]).to eq true
         expect(post_route[:attributes]).to eq [{
@@ -139,11 +144,11 @@
           example: "1",
           name: "id",
           description: "The id",
-          properties_description: "required, string"
+          properties_description: "string, required"
         }, {
           name: "option",
           description: nil,
-          properties_description: nil
+          properties_description: "optional"
         }]
         expect(post_route_with_optionals[:has_attributes?]).to eq false
         expect(post_route_with_optionals[:attributes]).to eq []
@@ -159,7 +164,7 @@
           required: false,
           name: "description",
           description: nil,
-          properties_description: nil
+          properties_description: "optional"
         }]
       end
     end
diff --git a/templates/rspec_api_documentation/api_blueprint_index.mustache b/templates/rspec_api_documentation/api_blueprint_index.mustache
index 865f24a3..cbdae894 100644
--- a/templates/rspec_api_documentation/api_blueprint_index.mustache
+++ b/templates/rspec_api_documentation/api_blueprint_index.mustache
@@ -1,5 +1,8 @@
 FORMAT: 1A
+
 # {{ api_name }}
+{{{ api_explanation }}}
+
 {{# sections }}
 
 # Group {{ resource_name }}
@@ -16,34 +19,57 @@ FORMAT: 1A
 ## {{ route_name }} [{{ route }}]
 {{# description }}
 
-description: {{ description }}
+{{ description }}
 {{/ description }}
 {{# explanation }}
 
-explanation: {{ explanation }}
+{{{ explanation }}}
 {{/ explanation }}
 {{# has_parameters? }}
 
 + Parameters
+
 {{# parameters }}
-  + {{ name }}{{# example }}: {{ example }}{{/ example }}{{# properties_description }} ({{ properties_description }}){{/ properties_description }}{{# description }} - {{ description }}{{/ description }}
+    + {{ name }}{{# properties_description }} ({{ properties_description }}){{/ properties_description }}
+{{# description }}
+
+        {{ description }}
+{{/ description }}
 {{/ parameters }}
 {{/ has_parameters? }}
-{{# has_attributes? }}
-
-+ Attributes (object)
-{{# attributes }}
-  + {{ name }}{{# example }}: {{ example }}{{/ example }}{{# properties_description }} ({{ properties_description }}){{/ properties_description }}{{# description }} - {{ description }}{{/ description }}
-{{/ attributes }}
-{{/ has_attributes? }}
 {{# http_methods }}
 
 ### {{ description }} [{{ http_method }}]
+{{# explanation }}
+
+{{{ explanation }}}
+{{/ explanation }}
+
 {{# examples }}
 {{# requests }}
+{{# has_attributes? }}
+
++ Parameters
+
+{{# attributes }}
+    + {{ name }}{{# value }}: {{ value }}{{/ value }}{{# properties_description }} ({{ properties_description }}){{/ properties_description }}
+{{# description }}
+
+        {{ description }}
+{{/ description }}
+{{# default }}
+
+        + Default: {{ default }}
+{{/ default }}
+{{/ attributes }}
+{{/ has_attributes? }}
 {{# has_request? }}
 
 + Request {{ description }}{{# request_content_type }} ({{ request_content_type }}){{/ request_content_type }}
+
+    {{# explanation }}
+    {{{ explanation }}}
+    {{/ explanation }}
 {{/ has_request? }}
 {{# request_headers_text }}