objectstorage v1 and orchestration v1 struct tags
diff --git a/openstack/objectstorage/v1/accounts/requests.go b/openstack/objectstorage/v1/accounts/requests.go
index f50cf97..41479a2 100644
--- a/openstack/objectstorage/v1/accounts/requests.go
+++ b/openstack/objectstorage/v1/accounts/requests.go
@@ -24,30 +24,27 @@
 // all the headers that are returned (including the metadata), call the
 // ExtractHeader method on the GetResult.
 func Get(c *gophercloud.ServiceClient, opts GetOptsBuilder) GetResult {
-	var res GetResult
-	h := c.AuthenticatedHeaders()
-
+	var r GetResult
+	h := make(map[string]string)
 	if opts != nil {
 		headers, err := opts.ToAccountGetMap()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
-
 		for k, v := range headers {
 			h[k] = v
 		}
 	}
-
 	resp, err := c.Request("HEAD", getURL(c), &gophercloud.RequestOpts{
 		MoreHeaders: h,
 		OkCodes:     []int{204},
 	})
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
 
 // UpdateOptsBuilder allows extensions to add additional headers to the Update
@@ -81,27 +78,25 @@
 // Update is a function that creates, updates, or deletes an account's metadata.
 // To extract the headers returned, call the Extract method on the UpdateResult.
 func Update(c *gophercloud.ServiceClient, opts UpdateOptsBuilder) UpdateResult {
-	var res UpdateResult
+	var r UpdateResult
 	h := make(map[string]string)
-
 	if opts != nil {
 		headers, err := opts.ToAccountUpdateMap()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
 		for k, v := range headers {
 			h[k] = v
 		}
 	}
-
 	resp, err := c.Request("POST", updateURL(c), &gophercloud.RequestOpts{
 		MoreHeaders: h,
 		OkCodes:     []int{201, 202, 204},
 	})
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
diff --git a/openstack/objectstorage/v1/containers/requests.go b/openstack/objectstorage/v1/containers/requests.go
index b2160c3..f575ea7 100644
--- a/openstack/objectstorage/v1/containers/requests.go
+++ b/openstack/objectstorage/v1/containers/requests.go
@@ -26,10 +26,7 @@
 // representing whether to list complete information for each container.
 func (opts ListOpts) ToContainerListParams() (bool, string, error) {
 	q, err := gophercloud.BuildQueryString(opts)
-	if err != nil {
-		return false, "", err
-	}
-	return opts.Full, q.String(), nil
+	return opts.Full, q.String(), err
 }
 
 // List is a function that retrieves containers associated with the account as
@@ -51,13 +48,11 @@
 		}
 	}
 
-	createPage := func(r pagination.PageResult) pagination.Page {
+	pager := pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
 		p := ContainerPage{pagination.MarkerPageBase{PageResult: r}}
 		p.MarkerPageBase.Owner = p
 		return p
-	}
-
-	pager := pagination.NewPager(c, url, createPage)
+	})
 	pager.Headers = headers
 	return pager
 }
@@ -95,37 +90,34 @@
 
 // Create is a function that creates a new container.
 func Create(c *gophercloud.ServiceClient, containerName string, opts CreateOptsBuilder) CreateResult {
-	var res CreateResult
-	h := c.AuthenticatedHeaders()
-
+	var r CreateResult
+	h := make(map[string]string)
 	if opts != nil {
 		headers, err := opts.ToContainerCreateMap()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
-
 		for k, v := range headers {
 			h[k] = v
 		}
 	}
-
 	resp, err := c.Request("PUT", createURL(c, containerName), &gophercloud.RequestOpts{
 		MoreHeaders: h,
 		OkCodes:     []int{201, 202, 204},
 	})
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
 
 // Delete is a function that deletes a container.
 func Delete(c *gophercloud.ServiceClient, containerName string) DeleteResult {
-	var res DeleteResult
-	_, res.Err = c.Delete(deleteURL(c, containerName), nil)
-	return res
+	var r DeleteResult
+	_, r.Err = c.Delete(deleteURL(c, containerName), nil)
+	return r
 }
 
 // UpdateOptsBuilder allows extensions to add additional parameters to the
@@ -163,43 +155,41 @@
 // Update is a function that creates, updates, or deletes a container's
 // metadata.
 func Update(c *gophercloud.ServiceClient, containerName string, opts UpdateOptsBuilder) UpdateResult {
-	var res UpdateResult
-	h := c.AuthenticatedHeaders()
-
+	var r UpdateResult
+	h := make(map[string]string)
 	if opts != nil {
 		headers, err := opts.ToContainerUpdateMap()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
 
 		for k, v := range headers {
 			h[k] = v
 		}
 	}
-
 	resp, err := c.Request("POST", updateURL(c, containerName), &gophercloud.RequestOpts{
 		MoreHeaders: h,
 		OkCodes:     []int{201, 202, 204},
 	})
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
 
 // Get is a function that retrieves the metadata of a container. To extract just
 // the custom metadata, pass the GetResult response to the ExtractMetadata
 // function.
 func Get(c *gophercloud.ServiceClient, containerName string) GetResult {
-	var res GetResult
+	var r GetResult
 	resp, err := c.Request("HEAD", getURL(c, containerName), &gophercloud.RequestOpts{
 		OkCodes: []int{200, 204},
 	})
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
diff --git a/openstack/objectstorage/v1/objects/requests.go b/openstack/objectstorage/v1/objects/requests.go
index d82aeb2..2505bdb 100644
--- a/openstack/objectstorage/v1/objects/requests.go
+++ b/openstack/objectstorage/v1/objects/requests.go
@@ -1,13 +1,12 @@
 package objects
 
 import (
-	"bufio"
+	"bytes"
 	"crypto/hmac"
 	"crypto/md5"
 	"crypto/sha1"
 	"fmt"
 	"io"
-	"io/ioutil"
 	"strings"
 	"time"
 
@@ -42,10 +41,7 @@
 // representing whether to list complete information for each object.
 func (opts ListOpts) ToObjectListParams() (bool, string, error) {
 	q, err := gophercloud.BuildQueryString(opts)
-	if err != nil {
-		return false, "", err
-	}
-	return opts.Full, q.String(), nil
+	return opts.Full, q.String(), err
 }
 
 // List is a function that retrieves all objects in a container. It also returns the details
@@ -67,13 +63,11 @@
 		}
 	}
 
-	createPage := func(r pagination.PageResult) pagination.Page {
+	pager := pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
 		p := ObjectPage{pagination.MarkerPageBase{PageResult: r}}
 		p.MarkerPageBase.Owner = p
 		return p
-	}
-
-	pager := pagination.NewPager(c, url, createPage)
+	})
 	pager.Headers = headers
 	return pager
 }
@@ -114,46 +108,42 @@
 // To extract just the content, pass the DownloadResult response to the
 // ExtractContent function.
 func Download(c *gophercloud.ServiceClient, containerName, objectName string, opts DownloadOptsBuilder) DownloadResult {
-	var res DownloadResult
-
+	var r DownloadResult
 	url := downloadURL(c, containerName, objectName)
-	h := c.AuthenticatedHeaders()
-
+	h := make(map[string]string)
 	if opts != nil {
 		headers, query, err := opts.ToObjectDownloadParams()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
-
 		for k, v := range headers {
 			h[k] = v
 		}
-
 		url += query
 	}
 
-	resp, err := c.Request("GET", url, &gophercloud.RequestOpts{
+	resp, err := c.Get(url, nil, &gophercloud.RequestOpts{
 		MoreHeaders: h,
 		OkCodes:     []int{200, 304},
 	})
 	if resp != nil {
-		res.Header = resp.Header
-		res.Body = resp.Body
+		r.Header = resp.Header
+		r.Body = resp.Body
 	}
-	res.Err = err
-
-	return res
+	r.Err = err
+	return r
 }
 
 // CreateOptsBuilder allows extensions to add additional parameters to the
 // Create request.
 type CreateOptsBuilder interface {
-	ToObjectCreateParams() (map[string]string, string, error)
+	ToObjectCreateParams() (io.Reader, map[string]string, string, error)
 }
 
 // CreateOpts is a structure that holds parameters for creating an object.
 type CreateOpts struct {
+	Content            io.Reader
 	Metadata           map[string]string
 	ContentDisposition string `h:"Content-Disposition"`
 	ContentEncoding    string `h:"Content-Encoding"`
@@ -174,81 +164,61 @@
 
 // ToObjectCreateParams formats a CreateOpts into a query string and map of
 // headers.
-func (opts CreateOpts) ToObjectCreateParams() (map[string]string, string, error) {
+func (opts CreateOpts) ToObjectCreateParams() (io.Reader, map[string]string, string, error) {
 	q, err := gophercloud.BuildQueryString(opts)
 	if err != nil {
-		return nil, "", err
+		return nil, nil, "", err
 	}
 	h, err := gophercloud.BuildHeaders(opts)
 	if err != nil {
-		return nil, q.String(), err
+		return nil, nil, "", err
 	}
 
 	for k, v := range opts.Metadata {
 		h["X-Object-Meta-"+k] = v
 	}
 
-	return h, q.String(), nil
+	hash := md5.New()
+	buf := bytes.NewBuffer([]byte{})
+	_, err = io.Copy(io.MultiWriter(hash, buf), opts.Content)
+	if err != nil {
+		return nil, nil, "", err
+	}
+	localChecksum := fmt.Sprintf("%x", hash.Sum(nil))
+	h["ETag"] = localChecksum
+
+	return buf, h, q.String(), nil
 }
 
 // Create is a function that creates a new object or replaces an existing object. If the returned response's ETag
 // header fails to match the local checksum, the failed request will automatically be retried up to a maximum of 3 times.
-func Create(c *gophercloud.ServiceClient, containerName, objectName string, content io.ReadSeeker, opts CreateOptsBuilder) CreateResult {
-	var res CreateResult
-
+func Create(c *gophercloud.ServiceClient, containerName, objectName string, opts CreateOptsBuilder) CreateResult {
+	var r CreateResult
 	url := createURL(c, containerName, objectName)
 	h := make(map[string]string)
-
+	var b io.Reader
 	if opts != nil {
-		headers, query, err := opts.ToObjectCreateParams()
+		tmpB, headers, query, err := opts.ToObjectCreateParams()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
-
 		for k, v := range headers {
 			h[k] = v
 		}
-
 		url += query
+		b = tmpB
 	}
 
-	hash := md5.New()
-	bufioReader := bufio.NewReader(io.TeeReader(content, hash))
-	io.Copy(ioutil.Discard, bufioReader)
-	localChecksum := hash.Sum(nil)
-
-	h["ETag"] = fmt.Sprintf("%x", localChecksum)
-
-	_, err := content.Seek(0, 0)
-	if err != nil {
-		res.Err = err
-		return res
-	}
-
-	ropts := &gophercloud.RequestOpts{
-		RawBody:     content,
+	resp, err := c.Put(url, nil, nil, &gophercloud.RequestOpts{
+		RawBody:     b,
 		MoreHeaders: h,
-	}
-
-	resp, err := c.Request("PUT", url, ropts)
-	if err != nil {
-		res.Err = err
-		return res
-	}
+	})
+	r.Err = err
 	if resp != nil {
-		res.Header = resp.Header
-		if resp.Header.Get("ETag") == fmt.Sprintf("%x", localChecksum) {
-			res.Err = err
-			return res
-		}
-		err := ErrWrongChecksum{}
-		err.Function = "objects.Create"
-		res.Err = err
-
+		r.Header = resp.Header
 	}
-
-	return res
+	return r
 }
 
 // CopyOptsBuilder allows extensions to add additional parameters to the
@@ -264,17 +234,11 @@
 	ContentDisposition string `h:"Content-Disposition"`
 	ContentEncoding    string `h:"Content-Encoding"`
 	ContentType        string `h:"Content-Type"`
-	Destination        string `h:"Destination,required"`
+	Destination        string `h:"Destination" required:"true"`
 }
 
 // ToObjectCopyMap formats a CopyOpts into a map of headers.
 func (opts CopyOpts) ToObjectCopyMap() (map[string]string, error) {
-	if opts.Destination == "" {
-		err := gophercloud.ErrMissingInput{}
-		err.Function = "objects.ToObjectCopyMap"
-		err.Argument = "objects.CopyOpts.Destination"
-		return nil, err
-	}
 	h, err := gophercloud.BuildHeaders(opts)
 	if err != nil {
 		return nil, err
@@ -287,13 +251,12 @@
 
 // Copy is a function that copies one object to another.
 func Copy(c *gophercloud.ServiceClient, containerName, objectName string, opts CopyOptsBuilder) CopyResult {
-	var res CopyResult
-	h := c.AuthenticatedHeaders()
-
+	var r CopyResult
+	h := make(map[string]string)
 	headers, err := opts.ToObjectCopyMap()
 	if err != nil {
-		res.Err = err
-		return res
+		r.Err = err
+		return r
 	}
 
 	for k, v := range headers {
@@ -306,10 +269,10 @@
 		OkCodes:     []int{201},
 	})
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
 
 // DeleteOptsBuilder allows extensions to add additional parameters to the
@@ -326,32 +289,27 @@
 // ToObjectDeleteQuery formats a DeleteOpts into a query string.
 func (opts DeleteOpts) ToObjectDeleteQuery() (string, error) {
 	q, err := gophercloud.BuildQueryString(opts)
-	if err != nil {
-		return "", err
-	}
-	return q.String(), nil
+	return q.String(), err
 }
 
 // Delete is a function that deletes an object.
 func Delete(c *gophercloud.ServiceClient, containerName, objectName string, opts DeleteOptsBuilder) DeleteResult {
-	var res DeleteResult
+	var r DeleteResult
 	url := deleteURL(c, containerName, objectName)
-
 	if opts != nil {
 		query, err := opts.ToObjectDeleteQuery()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
 		url += query
 	}
-
 	resp, err := c.Delete(url, nil)
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
 
 // GetOptsBuilder allows extensions to add additional parameters to the
@@ -369,35 +327,30 @@
 // ToObjectGetQuery formats a GetOpts into a query string.
 func (opts GetOpts) ToObjectGetQuery() (string, error) {
 	q, err := gophercloud.BuildQueryString(opts)
-	if err != nil {
-		return "", err
-	}
-	return q.String(), nil
+	return q.String(), err
 }
 
 // Get is a function that retrieves the metadata of an object. To extract just the custom
 // metadata, pass the GetResult response to the ExtractMetadata function.
 func Get(c *gophercloud.ServiceClient, containerName, objectName string, opts GetOptsBuilder) GetResult {
-	var res GetResult
+	var r GetResult
 	url := getURL(c, containerName, objectName)
-
 	if opts != nil {
 		query, err := opts.ToObjectGetQuery()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
 		url += query
 	}
-
 	resp, err := c.Request("HEAD", url, &gophercloud.RequestOpts{
 		OkCodes: []int{200, 204},
 	})
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
 
 // UpdateOptsBuilder allows extensions to add additional parameters to the
@@ -432,30 +385,28 @@
 
 // Update is a function that creates, updates, or deletes an object's metadata.
 func Update(c *gophercloud.ServiceClient, containerName, objectName string, opts UpdateOptsBuilder) UpdateResult {
-	var res UpdateResult
+	var r UpdateResult
 	h := c.AuthenticatedHeaders()
-
 	if opts != nil {
 		headers, err := opts.ToObjectUpdateMap()
 		if err != nil {
-			res.Err = err
-			return res
+			r.Err = err
+			return r
 		}
 
 		for k, v := range headers {
 			h[k] = v
 		}
 	}
-
 	url := updateURL(c, containerName, objectName)
-	resp, err := c.Request("POST", url, &gophercloud.RequestOpts{
+	resp, err := c.Post(url, nil, nil, &gophercloud.RequestOpts{
 		MoreHeaders: h,
 	})
 	if resp != nil {
-		res.Header = resp.Header
+		r.Header = resp.Header
 	}
-	res.Err = err
-	return res
+	r.Err = err
+	return r
 }
 
 // HTTPMethod represents an HTTP method string (e.g. "GET").
diff --git a/openstack/objectstorage/v1/objects/results.go b/openstack/objectstorage/v1/objects/results.go
index c0d532b..3cfe1f4 100644
--- a/openstack/objectstorage/v1/objects/results.go
+++ b/openstack/objectstorage/v1/objects/results.go
@@ -200,12 +200,16 @@
 
 // CreateResult represents the result of a create operation.
 type CreateResult struct {
+	checksum string
 	gophercloud.HeaderResult
 }
 
 // Extract will return a struct of headers returned from a call to Create. To obtain
 // a map of headers, call the ExtractHeader method on the CreateResult.
 func (r CreateResult) Extract() (*CreateHeader, error) {
+	//if r.Header.Get("ETag") != fmt.Sprintf("%x", localChecksum) {
+	//	return nil, ErrWrongChecksum{}
+	//}
 	var s *CreateHeader
 	err := r.ExtractInto(&s)
 	return s, err
diff --git a/openstack/orchestration/v1/buildinfo/requests.go b/openstack/orchestration/v1/buildinfo/requests.go
index 9d28760..ad12a73 100644
--- a/openstack/orchestration/v1/buildinfo/requests.go
+++ b/openstack/orchestration/v1/buildinfo/requests.go
@@ -4,7 +4,7 @@
 
 // Get retreives data for the given stack template.
 func Get(c *gophercloud.ServiceClient) GetResult {
-	var res GetResult
-	_, res.Err = c.Get(getURL(c), &res.Body, nil)
-	return res
+	var r GetResult
+	_, r.Err = c.Get(getURL(c), &r.Body, nil)
+	return r
 }
diff --git a/openstack/orchestration/v1/stackevents/requests.go b/openstack/orchestration/v1/stackevents/requests.go
index 6112571..794d4c8 100644
--- a/openstack/orchestration/v1/stackevents/requests.go
+++ b/openstack/orchestration/v1/stackevents/requests.go
@@ -7,12 +7,9 @@
 
 // Find retrieves stack events for the given stack name.
 func Find(c *gophercloud.ServiceClient, stackName string) FindResult {
-	var res FindResult
-
-	_, res.Err = c.Request("GET", findURL(c, stackName), &gophercloud.RequestOpts{
-		JSONResponse: &res.Body,
-	})
-	return res
+	var r FindResult
+	_, r.Err = c.Get(findURL(c, stackName), &r.Body, nil)
+	return r
 }
 
 // SortDir is a type for specifying in which direction to sort a list of events.
@@ -102,16 +99,12 @@
 // ToStackEventListQuery formats a ListOpts into a query string.
 func (opts ListOpts) ToStackEventListQuery() (string, error) {
 	q, err := gophercloud.BuildQueryString(opts)
-	if err != nil {
-		return "", err
-	}
-	return q.String(), nil
+	return q.String(), err
 }
 
 // List makes a request against the API to list resources for the given stack.
 func List(client *gophercloud.ServiceClient, stackName, stackID string, opts ListOptsBuilder) pagination.Pager {
 	url := listURL(client, stackName, stackID)
-
 	if opts != nil {
 		query, err := opts.ToStackEventListQuery()
 		if err != nil {
@@ -119,14 +112,11 @@
 		}
 		url += query
 	}
-
-	createPageFn := func(r pagination.PageResult) pagination.Page {
+	return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
 		p := EventPage{pagination.MarkerPageBase{PageResult: r}}
 		p.MarkerPageBase.Owner = p
 		return p
-	}
-
-	return pagination.NewPager(client, url, createPageFn)
+	})
 }
 
 // ListResourceEventsOptsBuilder allows extensions to add additional parameters to the
@@ -166,16 +156,12 @@
 // ToResourceEventListQuery formats a ListResourceEventsOpts into a query string.
 func (opts ListResourceEventsOpts) ToResourceEventListQuery() (string, error) {
 	q, err := gophercloud.BuildQueryString(opts)
-	if err != nil {
-		return "", err
-	}
-	return q.String(), nil
+	return q.String(), err
 }
 
 // ListResourceEvents makes a request against the API to list resources for the given stack.
 func ListResourceEvents(client *gophercloud.ServiceClient, stackName, stackID, resourceName string, opts ListResourceEventsOptsBuilder) pagination.Pager {
 	url := listResourceEventsURL(client, stackName, stackID, resourceName)
-
 	if opts != nil {
 		query, err := opts.ToResourceEventListQuery()
 		if err != nil {
@@ -183,21 +169,18 @@
 		}
 		url += query
 	}
-
-	createPageFn := func(r pagination.PageResult) pagination.Page {
+	return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
 		p := EventPage{pagination.MarkerPageBase{PageResult: r}}
 		p.MarkerPageBase.Owner = p
 		return p
-	}
-
-	return pagination.NewPager(client, url, createPageFn)
+	})
 }
 
 // Get retreives data for the given stack resource.
 func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName, eventID string) GetResult {
-	var res GetResult
-	_, res.Err = c.Get(getURL(c, stackName, stackID, resourceName, eventID), &res.Body, &gophercloud.RequestOpts{
+	var r GetResult
+	_, r.Err = c.Get(getURL(c, stackName, stackID, resourceName, eventID), &r.Body, &gophercloud.RequestOpts{
 		OkCodes: []int{200},
 	})
-	return res
+	return r
 }
diff --git a/openstack/orchestration/v1/stackresources/requests.go b/openstack/orchestration/v1/stackresources/requests.go
index 3ce40eb..f33c170 100644
--- a/openstack/orchestration/v1/stackresources/requests.go
+++ b/openstack/orchestration/v1/stackresources/requests.go
@@ -7,13 +7,9 @@
 
 // Find retrieves stack resources for the given stack name.
 func Find(c *gophercloud.ServiceClient, stackName string) FindResult {
-	var res FindResult
-
-	// Send request to API
-	_, res.Err = c.Request("GET", findURL(c, stackName), &gophercloud.RequestOpts{
-		JSONResponse: &res.Body,
-	})
-	return res
+	var r FindResult
+	_, res.Err = c.Get(findURL(c, stackName), &res.Body, nil)
+	return r
 }
 
 // ListOptsBuilder allows extensions to add additional parameters to the
@@ -32,16 +28,12 @@
 // ToStackResourceListQuery formats a ListOpts into a query string.
 func (opts ListOpts) ToStackResourceListQuery() (string, error) {
 	q, err := gophercloud.BuildQueryString(opts)
-	if err != nil {
-		return "", err
-	}
-	return q.String(), nil
+	return q.String(), err
 }
 
 // List makes a request against the API to list resources for the given stack.
 func List(client *gophercloud.ServiceClient, stackName, stackID string, opts ListOptsBuilder) pagination.Pager {
 	url := listURL(client, stackName, stackID)
-
 	if opts != nil {
 		query, err := opts.ToStackResourceListQuery()
 		if err != nil {
@@ -49,65 +41,42 @@
 		}
 		url += query
 	}
-
-	createPageFn := func(r pagination.PageResult) pagination.Page {
+	return pagination.NewPager(client, url, func(r pagination.PageResult) pagination.Page {
 		return ResourcePage{pagination.SinglePageBase(r)}
-	}
-
-	return pagination.NewPager(client, url, createPageFn)
+	})
 }
 
 // Get retreives data for the given stack resource.
 func Get(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) GetResult {
-	var res GetResult
-
-	// Send request to API
-	_, res.Err = c.Get(getURL(c, stackName, stackID, resourceName), &res.Body, &gophercloud.RequestOpts{
-		OkCodes: []int{200},
-	})
-	return res
+	var r GetResult
+	_, r.Err = c.Get(getURL(c, stackName, stackID, resourceName), &r.Body, nil)
+	return r
 }
 
 // Metadata retreives the metadata for the given stack resource.
 func Metadata(c *gophercloud.ServiceClient, stackName, stackID, resourceName string) MetadataResult {
-	var res MetadataResult
-
-	// Send request to API
-	_, res.Err = c.Get(metadataURL(c, stackName, stackID, resourceName), &res.Body, &gophercloud.RequestOpts{
-		OkCodes: []int{200},
-	})
-	return res
+	var r MetadataResult
+	_, r.Err = c.Get(metadataURL(c, stackName, stackID, resourceName), &r.Body, nil)
+	return r
 }
 
 // ListTypes makes a request against the API to list resource types.
 func ListTypes(client *gophercloud.ServiceClient) pagination.Pager {
-	url := listTypesURL(client)
-
-	createPageFn := func(r pagination.PageResult) pagination.Page {
+	return pagination.NewPager(client, listTypesURL(client), func(r pagination.PageResult) pagination.Page {
 		return ResourceTypePage{pagination.SinglePageBase(r)}
-	}
-
-	return pagination.NewPager(client, url, createPageFn)
+	})
 }
 
 // Schema retreives the schema for the given resource type.
 func Schema(c *gophercloud.ServiceClient, resourceType string) SchemaResult {
-	var res SchemaResult
-
-	// Send request to API
-	_, res.Err = c.Get(schemaURL(c, resourceType), &res.Body, &gophercloud.RequestOpts{
-		OkCodes: []int{200},
-	})
-	return res
+	var r SchemaResult
+	_, r.Err = c.Get(schemaURL(c, resourceType), &r.Body, nil)
+	return r
 }
 
 // Template retreives the template representation for the given resource type.
 func Template(c *gophercloud.ServiceClient, resourceType string) TemplateResult {
-	var res TemplateResult
-
-	// Send request to API
-	_, res.Err = c.Get(templateURL(c, resourceType), &res.Body, &gophercloud.RequestOpts{
-		OkCodes: []int{200},
-	})
-	return res
+	var r TemplateResult
+	_, r.Err = c.Get(templateURL(c, resourceType), &r.Body, nil)
+	return r
 }
diff --git a/openstack/orchestration/v1/stacks/environment.go b/openstack/orchestration/v1/stacks/environment.go
index abaff20..8698918 100644
--- a/openstack/orchestration/v1/stacks/environment.go
+++ b/openstack/orchestration/v1/stacks/environment.go
@@ -1,9 +1,6 @@
 package stacks
 
-import (
-	"fmt"
-	"strings"
-)
+import "strings"
 
 // Environment is a structure that represents stack environments
 type Environment struct {
@@ -26,7 +23,7 @@
 	}
 	for key := range e.Parsed {
 		if _, ok := EnvironmentSections[key]; !ok {
-			return fmt.Errorf("Environment has wrong section: %s", key)
+			return ErrInvalidEnvironment{Section: key}
 		}
 	}
 	return nil
diff --git a/openstack/orchestration/v1/stacks/errors.go b/openstack/orchestration/v1/stacks/errors.go
new file mode 100644
index 0000000..cd6c18f
--- /dev/null
+++ b/openstack/orchestration/v1/stacks/errors.go
@@ -0,0 +1,33 @@
+package stacks
+
+import (
+	"fmt"
+
+	"github.com/gophercloud/gophercloud"
+)
+
+type ErrInvalidEnvironment struct {
+	gophercloud.BaseError
+	Section string
+}
+
+func (e ErrInvalidEnvironment) Error() string {
+	return fmt.Sprintf("Environment has wrong section: %s", e.Section)
+}
+
+type ErrInvalidDataFormat struct {
+	gophercloud.BaseError
+}
+
+func (e ErrInvalidDataFormat) Error() string {
+	return fmt.Sprintf("Data in neither json nor yaml format.")
+}
+
+type ErrInvalidTemplateFormatVersion struct {
+	gophercloud.BaseError
+	Version string
+}
+
+func (e ErrInvalidTemplateFormatVersion) Error() string {
+	return fmt.Sprintf("Template format version not found.")
+}
diff --git a/openstack/orchestration/v1/stacks/requests.go b/openstack/orchestration/v1/stacks/requests.go
index 650763c..47d545e 100644
--- a/openstack/orchestration/v1/stacks/requests.go
+++ b/openstack/orchestration/v1/stacks/requests.go
@@ -7,18 +7,6 @@
 	"github.com/gophercloud/gophercloud/pagination"
 )
 
-// Rollback is used to specify whether or not a stack can be rolled back.
-type Rollback *bool
-
-var (
-	disable = true
-	// Disable is used to specify that a stack cannot be rolled back.
-	Disable Rollback = &disable
-	enable           = false
-	// Enable is used to specify that a stack can be rolled back.
-	Enable Rollback = &enable
-)
-
 // CreateOptsBuilder is the interface options structs have to satisfy in order
 // to be used in the main Create operation in this package. Since many
 // extensions decorate or modify the common logic, it is useful for them to
@@ -30,92 +18,45 @@
 // CreateOpts is the common options struct used in this package's Create
 // operation.
 type CreateOpts struct {
-	// (REQUIRED) The name of the stack. It must start with an alphabetic character.
-	Name string
-	// (REQUIRED) A structure that contains either the template file or url. Call the
+	// The name of the stack. It must start with an alphabetic character.
+	Name string `json:"stack_name" required:"true"`
+	// A structure that contains either the template file or url. Call the
 	// associated methods to extract the information relevant to send in a create request.
-	TemplateOpts *Template
-	// (DEPRECATED): Please use TemplateOpts for providing the template. If
-	// TemplateOpts is provided, TemplateURL will be ignored
-	// (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
-	// This value is ignored if Template is supplied inline.
-	TemplateURL string
-	// (DEPRECATED): Please use TemplateOpts for providing the template. If
-	// TemplateOpts is provided, Template will be ignored
-	// (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
-	// is a stringified version of the JSON/YAML template. Since the template will likely
-	// be located in a file, one way to set this variable is by using ioutil.ReadFile:
-	// import "io/ioutil"
-	// var opts stacks.CreateOpts
-	// b, err := ioutil.ReadFile("path/to/you/template/file.json")
-	// if err != nil {
-	//   // handle error...
-	// }
-	// opts.Template = string(b)
-	Template string
-	// (OPTIONAL) Enables or disables deletion of all stack resources when a stack
+	TemplateOpts *Template `json:"-" required:"true"`
+	// Enables or disables deletion of all stack resources when a stack
 	// creation fails. Default is true, meaning all resources are not deleted when
 	// stack creation fails.
-	DisableRollback Rollback
-	// (OPTIONAL) A structure that contains details for the environment of the stack.
-	EnvironmentOpts *Environment
-	// (DEPRECATED): Please use EnvironmentOpts to provide Environment data
-	// (OPTIONAL) A stringified JSON environment for the stack.
-	Environment string
-	// (DEPRECATED): Files is automatically determined
-	// by parsing the template and environment passed as TemplateOpts and
-	// EnvironmentOpts respectively.
-	// (OPTIONAL) A map that maps file names to file contents. It can also be used
-	// to pass provider template contents. Example:
-	// Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
-	Files map[string]interface{}
-	// (OPTIONAL) User-defined parameters to pass to the template.
-	Parameters map[string]string
-	// (OPTIONAL) The timeout for stack creation in minutes.
-	Timeout int
-	// (OPTIONAL) A list of tags to assosciate with the Stack
-	Tags []string
+	DisableRollback *bool `json:"disable_rollback,omitempty"`
+	// A structure that contains details for the environment of the stack.
+	EnvironmentOpts *Environment `json:"-"`
+	// User-defined parameters to pass to the template.
+	Parameters map[string]string `json:"parameters,omitempty"`
+	// The timeout for stack creation in minutes.
+	Timeout int `json:"timeout_mins,omitempty"`
+	// A list of tags to assosciate with the Stack
+	Tags []string `json:"-"`
 }
 
 // ToStackCreateMap casts a CreateOpts struct to a map.
 func (opts CreateOpts) ToStackCreateMap() (map[string]interface{}, error) {
-	s := make(map[string]interface{})
-
-	if opts.Name == "" {
-		err := gophercloud.ErrMissingInput{}
-		err.Argument = "stacks.CreateOpts.Name"
+	b, err := gophercloud.BuildRequestBody(opts, "")
+	if err != nil {
 		return nil, err
 	}
-	s["stack_name"] = opts.Name
-	Files := make(map[string]string)
-	if opts.TemplateOpts == nil {
-		if opts.Template != "" {
-			s["template"] = opts.Template
-		} else if opts.TemplateURL != "" {
-			s["template_url"] = opts.TemplateURL
-		} else {
-			err := gophercloud.ErrMissingInput{}
-			err.Argument = "stacks.CreateOpts.Template/stacks.CreateOpts.TemplateURL"
-			err.Info = "Either Template or TemplateURL must be provided"
-			return nil, err
-		}
-	} else {
-		if err := opts.TemplateOpts.Parse(); err != nil {
-			return nil, err
-		}
 
-		if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
-			return nil, err
-		}
-		opts.TemplateOpts.fixFileRefs()
-		s["template"] = string(opts.TemplateOpts.Bin)
-
-		for k, v := range opts.TemplateOpts.Files {
-			Files[k] = v
-		}
+	if err := opts.TemplateOpts.Parse(); err != nil {
+		return nil, err
 	}
-	if opts.DisableRollback != nil {
-		s["disable_rollback"] = &opts.DisableRollback
+
+	if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
+		return nil, err
+	}
+	opts.TemplateOpts.fixFileRefs()
+	b["template"] = string(opts.TemplateOpts.Bin)
+
+	files := make(map[string]string)
+	for k, v := range opts.TemplateOpts.Files {
+		files[k] = v
 	}
 
 	if opts.EnvironmentOpts != nil {
@@ -127,50 +68,33 @@
 		}
 		opts.EnvironmentOpts.fixFileRefs()
 		for k, v := range opts.EnvironmentOpts.Files {
-			Files[k] = v
+			files[k] = v
 		}
-		s["environment"] = string(opts.EnvironmentOpts.Bin)
-	} else if opts.Environment != "" {
-		s["environment"] = opts.Environment
+		b["environment"] = string(opts.EnvironmentOpts.Bin)
 	}
 
-	if opts.Files != nil {
-		s["files"] = opts.Files
-	} else {
-		s["files"] = Files
-	}
-
-	if opts.DisableRollback != nil {
-		s["disable_rollback"] = &opts.DisableRollback
-	}
-
-	if opts.Parameters != nil {
-		s["parameters"] = opts.Parameters
-	}
-
-	if opts.Timeout != 0 {
-		s["timeout_mins"] = opts.Timeout
+	if len(files) > 0 {
+		b["files"] = files
 	}
 
 	if opts.Tags != nil {
-		s["tags"] = strings.Join(opts.Tags, ",")
+		b["tags"] = strings.Join(opts.Tags, ",")
 	}
-	return s, nil
+
+	return b, nil
 }
 
 // Create accepts a CreateOpts struct and creates a new stack using the values
 // provided.
 func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
-	var res CreateResult
-
-	reqBody, err := opts.ToStackCreateMap()
+	var r CreateResult
+	b, err := opts.ToStackCreateMap()
 	if err != nil {
-		res.Err = err
-		return res
+		r.Err = err
+		return r
 	}
-
-	_, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
-	return res
+	_, r.Err = c.Post(createURL(c), b, &r.Body, nil)
+	return r
 }
 
 // AdoptOptsBuilder is the interface options structs have to satisfy in order
@@ -184,79 +108,36 @@
 // AdoptOpts is the common options struct used in this package's Adopt
 // operation.
 type AdoptOpts struct {
-	// (REQUIRED) Existing resources data represented as a string to add to the
+	// Existing resources data represented as a string to add to the
 	// new stack. Data returned by Abandon could be provided as AdoptsStackData.
-	AdoptStackData string
-	// (REQUIRED) The name of the stack. It must start with an alphabetic character.
-	Name string
-	// (REQUIRED) The timeout for stack creation in minutes.
-	Timeout int
-	// (REQUIRED) A structure that contains either the template file or url. Call the
+	AdoptStackData string `json:"adopt_stack_data" required:"true"`
+	// The name of the stack. It must start with an alphabetic character.
+	Name string `json:"stack_name" required:"true"`
+	// The timeout for stack creation in minutes.
+	Timeout int `json:"timeout_mins,omitempty"`
+	// A structure that contains either the template file or url. Call the
 	// associated methods to extract the information relevant to send in a create request.
-	TemplateOpts *Template
-	// (DEPRECATED): Please use TemplateOpts for providing the template. If
-	// TemplateOpts is provided, TemplateURL will be ignored
-	// (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
-	// This value is ignored if Template is supplied inline.
-	TemplateURL string
-	// (DEPRECATED): Please use TemplateOpts for providing the template. If
-	// TemplateOpts is provided, Template will be ignored
-	// (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
-	// is a stringified version of the JSON/YAML template. Since the template will likely
-	// be located in a file, one way to set this variable is by using ioutil.ReadFile:
-	// import "io/ioutil"
-	// var opts stacks.CreateOpts
-	// b, err := ioutil.ReadFile("path/to/you/template/file.json")
-	// if err != nil {
-	//   // handle error...
-	// }
-	// opts.Template = string(b)
-	Template string
-	// (OPTIONAL) Enables or disables deletion of all stack resources when a stack
+	//TemplateOpts *Template `json:"-" required:"true"`
+	// Enables or disables deletion of all stack resources when a stack
 	// creation fails. Default is true, meaning all resources are not deleted when
 	// stack creation fails.
-	DisableRollback Rollback
-	// (OPTIONAL) A structure that contains details for the environment of the stack.
-	EnvironmentOpts *Environment
-	// (DEPRECATED): Please use EnvironmentOpts to provide Environment data
-	// (OPTIONAL) A stringified JSON environment for the stack.
-	Environment string
-	// (DEPRECATED): Files is automatically determined
-	// by parsing the template and environment passed as TemplateOpts and
-	// EnvironmentOpts respectively.
-	// (OPTIONAL) A map that maps file names to file contents. It can also be used
-	// to pass provider template contents. Example:
-	// Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
-	Files map[string]interface{}
-	// (OPTIONAL) User-defined parameters to pass to the template.
-	Parameters map[string]string
+	DisableRollback *bool `json:"disable_rollback,omitempty"`
+	// A structure that contains details for the environment of the stack.
+	EnvironmentOpts *Environment `json:"-"`
+	// User-defined parameters to pass to the template.
+	Parameters map[string]string `json:"parameters,omitempty"`
 }
 
 // ToStackAdoptMap casts a CreateOpts struct to a map.
 func (opts AdoptOpts) ToStackAdoptMap() (map[string]interface{}, error) {
-	s := make(map[string]interface{})
-
-	if opts.Name == "" {
-		err := gophercloud.ErrMissingInput{}
-		err.Argument = "stacks.AdoptOpts.Name"
+	b, err := gophercloud.BuildRequestBody(opts, "")
+	if err != nil {
 		return nil, err
 	}
-	s["stack_name"] = opts.Name
-	Files := make(map[string]string)
-	if opts.AdoptStackData != "" {
-		s["adopt_stack_data"] = opts.AdoptStackData
-	} else if opts.TemplateOpts == nil {
-		if opts.Template != "" {
-			s["template"] = opts.Template
-		} else if opts.TemplateURL != "" {
-			s["template_url"] = opts.TemplateURL
-		} else {
-			err := gophercloud.ErrMissingInput{}
-			err.Argument = "stacks.AdoptOpts"
-			err.Info = "One of AdoptStackData, Template, TemplateURL or TemplateOpts must be provided"
-			return nil, err
-		}
-	} else {
+
+	files := make(map[string]string)
+
+	/*
 		if err := opts.TemplateOpts.Parse(); err != nil {
 			return nil, err
 		}
@@ -265,16 +146,12 @@
 			return nil, err
 		}
 		opts.TemplateOpts.fixFileRefs()
-		s["template"] = string(opts.TemplateOpts.Bin)
+		b["template"] = string(opts.TemplateOpts.Bin)
 
 		for k, v := range opts.TemplateOpts.Files {
-			Files[k] = v
+			files[k] = v
 		}
-	}
-
-	if opts.DisableRollback != nil {
-		s["disable_rollback"] = &opts.DisableRollback
-	}
+	*/
 
 	if opts.EnvironmentOpts != nil {
 		if err := opts.EnvironmentOpts.Parse(); err != nil {
@@ -285,44 +162,29 @@
 		}
 		opts.EnvironmentOpts.fixFileRefs()
 		for k, v := range opts.EnvironmentOpts.Files {
-			Files[k] = v
+			files[k] = v
 		}
-		s["environment"] = string(opts.EnvironmentOpts.Bin)
-	} else if opts.Environment != "" {
-		s["environment"] = opts.Environment
+		b["environment"] = string(opts.EnvironmentOpts.Bin)
 	}
 
-	if opts.Files != nil {
-		s["files"] = opts.Files
-	} else {
-		s["files"] = Files
+	if len(files) > 0 {
+		b["files"] = files
 	}
 
-	if opts.Parameters != nil {
-		s["parameters"] = opts.Parameters
-	}
-
-	if opts.Timeout != 0 {
-		s["timeout"] = opts.Timeout
-	}
-	s["timeout_mins"] = opts.Timeout
-
-	return s, nil
+	return b, nil
 }
 
 // Adopt accepts an AdoptOpts struct and creates a new stack using the resources
 // from another stack.
 func Adopt(c *gophercloud.ServiceClient, opts AdoptOptsBuilder) AdoptResult {
-	var res AdoptResult
-
-	reqBody, err := opts.ToStackAdoptMap()
+	var r AdoptResult
+	b, err := opts.ToStackAdoptMap()
 	if err != nil {
-		res.Err = err
-		return res
+		r.Err = err
+		return r
 	}
-
-	_, res.Err = c.Post(adoptURL(c), reqBody, &res.Body, nil)
-	return res
+	_, r.Err = c.Post(adoptURL(c), b, &r.Body, nil)
+	return r
 }
 
 // SortDir is a type for specifying in which direction to sort a list of stacks.
@@ -387,7 +249,6 @@
 		}
 		url += query
 	}
-
 	createPage := func(r pagination.PageResult) pagination.Page {
 		return StackPage{pagination.SinglePageBase(r)}
 	}
@@ -396,9 +257,9 @@
 
 // Get retreives a stack based on the stack name and stack ID.
 func Get(c *gophercloud.ServiceClient, stackName, stackID string) GetResult {
-	var res GetResult
-	_, res.Err = c.Get(getURL(c, stackName, stackID), &res.Body, nil)
-	return res
+	var r GetResult
+	_, r.Err = c.Get(getURL(c, stackName, stackID), &r.Body, nil)
+	return r
 }
 
 // UpdateOptsBuilder is the interface options structs have to satisfy in order
@@ -410,76 +271,39 @@
 // UpdateOpts contains the common options struct used in this package's Update
 // operation.
 type UpdateOpts struct {
-	// (REQUIRED) A structure that contains either the template file or url. Call the
+	// A structure that contains either the template file or url. Call the
 	// associated methods to extract the information relevant to send in a create request.
-	TemplateOpts *Template
-	// (DEPRECATED): Please use TemplateOpts for providing the template. If
-	// TemplateOpts is provided, TemplateURL will be ignored
-	// (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
-	// This value is ignored if Template is supplied inline.
-	TemplateURL string
-	// (DEPRECATED): Please use TemplateOpts for providing the template. If
-	// TemplateOpts is provided, Template will be ignored
-	// (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
-	// is a stringified version of the JSON/YAML template. Since the template will likely
-	// be located in a file, one way to set this variable is by using ioutil.ReadFile:
-	// import "io/ioutil"
-	// var opts stacks.CreateOpts
-	// b, err := ioutil.ReadFile("path/to/you/template/file.json")
-	// if err != nil {
-	//   // handle error...
-	// }
-	// opts.Template = string(b)
-	Template string
-	// (OPTIONAL) A structure that contains details for the environment of the stack.
-	EnvironmentOpts *Environment
-	// (DEPRECATED): Please use EnvironmentOpts to provide Environment data
-	// (OPTIONAL) A stringified JSON environment for the stack.
-	Environment string
-	// (DEPRECATED): Files is automatically determined
-	// by parsing the template and environment passed as TemplateOpts and
-	// EnvironmentOpts respectively.
-	// (OPTIONAL) A map that maps file names to file contents. It can also be used
-	// to pass provider template contents. Example:
-	// Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
-	Files map[string]interface{}
-	// (OPTIONAL) User-defined parameters to pass to the template.
-	Parameters map[string]string
-	// (OPTIONAL) The timeout for stack creation in minutes.
-	Timeout int
-	// (OPTIONAL) A list of tags to assosciate with the Stack
-	Tags []string
+	TemplateOpts *Template `json:"-" required:"true"`
+	// A structure that contains details for the environment of the stack.
+	EnvironmentOpts *Environment `json:"-"`
+	// User-defined parameters to pass to the template.
+	Parameters map[string]string `json:"parameters,omitempty"`
+	// The timeout for stack creation in minutes.
+	Timeout int `json:"timeout_mins,omitempty"`
+	// A list of tags to assosciate with the Stack
+	Tags []string `json:"-"`
 }
 
 // ToStackUpdateMap casts a CreateOpts struct to a map.
 func (opts UpdateOpts) ToStackUpdateMap() (map[string]interface{}, error) {
-	s := make(map[string]interface{})
-	Files := make(map[string]string)
-	if opts.TemplateOpts == nil {
-		if opts.Template != "" {
-			s["template"] = opts.Template
-		} else if opts.TemplateURL != "" {
-			s["template_url"] = opts.TemplateURL
-		} else {
-			err := gophercloud.ErrMissingInput{}
-			err.Argument = "stacks.UpdateOpts"
-			err.Info = "Either Template or TemplateURL must be provided"
-			return nil, err
-		}
-	} else {
-		if err := opts.TemplateOpts.Parse(); err != nil {
-			return nil, err
-		}
+	b, err := gophercloud.BuildRequestBody(opts, "")
+	if err != nil {
+		return nil, err
+	}
 
-		if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
-			return nil, err
-		}
-		opts.TemplateOpts.fixFileRefs()
-		s["template"] = string(opts.TemplateOpts.Bin)
+	if err := opts.TemplateOpts.Parse(); err != nil {
+		return nil, err
+	}
 
-		for k, v := range opts.TemplateOpts.Files {
-			Files[k] = v
-		}
+	if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
+		return nil, err
+	}
+	opts.TemplateOpts.fixFileRefs()
+	b["template"] = string(opts.TemplateOpts.Bin)
+
+	files := make(map[string]string)
+	for k, v := range opts.TemplateOpts.Files {
+		files[k] = v
 	}
 
 	if opts.EnvironmentOpts != nil {
@@ -491,54 +315,40 @@
 		}
 		opts.EnvironmentOpts.fixFileRefs()
 		for k, v := range opts.EnvironmentOpts.Files {
-			Files[k] = v
+			files[k] = v
 		}
-		s["environment"] = string(opts.EnvironmentOpts.Bin)
-	} else if opts.Environment != "" {
-		s["environment"] = opts.Environment
+		b["environment"] = string(opts.EnvironmentOpts.Bin)
 	}
 
-	if opts.Files != nil {
-		s["files"] = opts.Files
-	} else {
-		s["files"] = Files
-	}
-
-	if opts.Parameters != nil {
-		s["parameters"] = opts.Parameters
-	}
-
-	if opts.Timeout != 0 {
-		s["timeout_mins"] = opts.Timeout
+	if len(files) > 0 {
+		b["files"] = files
 	}
 
 	if opts.Tags != nil {
-		s["tags"] = strings.Join(opts.Tags, ",")
+		b["tags"] = strings.Join(opts.Tags, ",")
 	}
 
-	return s, nil
+	return b, nil
 }
 
 // Update accepts an UpdateOpts struct and updates an existing stack using the values
 // provided.
 func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts UpdateOptsBuilder) UpdateResult {
-	var res UpdateResult
-
-	reqBody, err := opts.ToStackUpdateMap()
+	var r UpdateResult
+	b, err := opts.ToStackUpdateMap()
 	if err != nil {
-		res.Err = err
-		return res
+		r.Err = err
+		return r
 	}
-
-	_, res.Err = c.Put(updateURL(c, stackName, stackID), reqBody, nil, nil)
-	return res
+	_, r.Err = c.Put(updateURL(c, stackName, stackID), b, nil, nil)
+	return r
 }
 
 // Delete deletes a stack based on the stack name and stack ID.
 func Delete(c *gophercloud.ServiceClient, stackName, stackID string) DeleteResult {
-	var res DeleteResult
-	_, res.Err = c.Delete(deleteURL(c, stackName, stackID), nil)
-	return res
+	var r DeleteResult
+	_, r.Err = c.Delete(deleteURL(c, stackName, stackID), nil)
+	return r
 }
 
 // PreviewOptsBuilder is the interface options structs have to satisfy in order
@@ -550,90 +360,43 @@
 // PreviewOpts contains the common options struct used in this package's Preview
 // operation.
 type PreviewOpts struct {
-	// (REQUIRED) The name of the stack. It must start with an alphabetic character.
-	Name string
-	// (REQUIRED) The timeout for stack creation in minutes.
-	Timeout int
-	// (REQUIRED) A structure that contains either the template file or url. Call the
+	// The name of the stack. It must start with an alphabetic character.
+	Name string `json:"stack_name" required:"true"`
+	// The timeout for stack creation in minutes.
+	Timeout int `json:"timeout_mins" required:"true"`
+	// A structure that contains either the template file or url. Call the
 	// associated methods to extract the information relevant to send in a create request.
-	TemplateOpts *Template
-	// (DEPRECATED): Please use TemplateOpts for providing the template. If
-	// TemplateOpts is provided, TemplateURL will be ignored
-	// (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
-	// This value is ignored if Template is supplied inline.
-	TemplateURL string
-	// (DEPRECATED): Please use TemplateOpts for providing the template. If
-	// TemplateOpts is provided, Template will be ignored
-	// (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
-	// is a stringified version of the JSON/YAML template. Since the template will likely
-	// be located in a file, one way to set this variable is by using ioutil.ReadFile:
-	// import "io/ioutil"
-	// var opts stacks.CreateOpts
-	// b, err := ioutil.ReadFile("path/to/you/template/file.json")
-	// if err != nil {
-	//   // handle error...
-	// }
-	// opts.Template = string(b)
-	Template string
-	// (OPTIONAL) Enables or disables deletion of all stack resources when a stack
+	TemplateOpts *Template `json:"-" required:"true"`
+	// Enables or disables deletion of all stack resources when a stack
 	// creation fails. Default is true, meaning all resources are not deleted when
 	// stack creation fails.
-	DisableRollback Rollback
-	// (OPTIONAL) A structure that contains details for the environment of the stack.
-	EnvironmentOpts *Environment
-	// (DEPRECATED): Please use EnvironmentOpts to provide Environment data
-	// (OPTIONAL) A stringified JSON environment for the stack.
-	Environment string
-	// (DEPRECATED): Files is automatically determined
-	// by parsing the template and environment passed as TemplateOpts and
-	// EnvironmentOpts respectively.
-	// (OPTIONAL) A map that maps file names to file contents. It can also be used
-	// to pass provider template contents. Example:
-	// Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
-	Files map[string]interface{}
-	// (OPTIONAL) User-defined parameters to pass to the template.
-	Parameters map[string]string
+	DisableRollback *bool `json:"disable_rollback,omitempty"`
+	// A structure that contains details for the environment of the stack.
+	EnvironmentOpts *Environment `json:"-"`
+	// User-defined parameters to pass to the template.
+	Parameters map[string]string `json:"parameters,omitempty"`
 }
 
 // ToStackPreviewMap casts a PreviewOpts struct to a map.
 func (opts PreviewOpts) ToStackPreviewMap() (map[string]interface{}, error) {
-	s := make(map[string]interface{})
-
-	if opts.Name == "" {
-		err := gophercloud.ErrMissingInput{}
-		err.Argument = "stacks.PreviewOpts.Name"
+	b, err := gophercloud.BuildRequestBody(opts, "")
+	if err != nil {
 		return nil, err
 	}
-	s["stack_name"] = opts.Name
-	Files := make(map[string]string)
-	if opts.TemplateOpts == nil {
-		if opts.Template != "" {
-			s["template"] = opts.Template
-		} else if opts.TemplateURL != "" {
-			s["template_url"] = opts.TemplateURL
-		} else {
-			err := gophercloud.ErrMissingInput{}
-			err.Argument = "stacks.PreviewOpts"
-			err.Info = "Either Template or TemplateURL must be provided"
-			return nil, err
-		}
-	} else {
-		if err := opts.TemplateOpts.Parse(); err != nil {
-			return nil, err
-		}
 
-		if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
-			return nil, err
-		}
-		opts.TemplateOpts.fixFileRefs()
-		s["template"] = string(opts.TemplateOpts.Bin)
-
-		for k, v := range opts.TemplateOpts.Files {
-			Files[k] = v
-		}
+	if err := opts.TemplateOpts.Parse(); err != nil {
+		return nil, err
 	}
-	if opts.DisableRollback != nil {
-		s["disable_rollback"] = &opts.DisableRollback
+
+	if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
+		return nil, err
+	}
+	opts.TemplateOpts.fixFileRefs()
+	b["template"] = string(opts.TemplateOpts.Bin)
+
+	files := make(map[string]string)
+	for k, v := range opts.TemplateOpts.Files {
+		files[k] = v
 	}
 
 	if opts.EnvironmentOpts != nil {
@@ -645,55 +408,40 @@
 		}
 		opts.EnvironmentOpts.fixFileRefs()
 		for k, v := range opts.EnvironmentOpts.Files {
-			Files[k] = v
+			files[k] = v
 		}
-		s["environment"] = string(opts.EnvironmentOpts.Bin)
-	} else if opts.Environment != "" {
-		s["environment"] = opts.Environment
+		b["environment"] = string(opts.EnvironmentOpts.Bin)
 	}
 
-	if opts.Files != nil {
-		s["files"] = opts.Files
-	} else {
-		s["files"] = Files
+	if len(files) > 0 {
+		b["files"] = files
 	}
 
-	if opts.Parameters != nil {
-		s["parameters"] = opts.Parameters
-	}
-
-	if opts.Timeout != 0 {
-		s["timeout_mins"] = opts.Timeout
-	}
-
-	return s, nil
+	return b, nil
 }
 
 // Preview accepts a PreviewOptsBuilder interface and creates a preview of a stack using the values
 // provided.
 func Preview(c *gophercloud.ServiceClient, opts PreviewOptsBuilder) PreviewResult {
-	var res PreviewResult
-
-	reqBody, err := opts.ToStackPreviewMap()
+	var r PreviewResult
+	b, err := opts.ToStackPreviewMap()
 	if err != nil {
-		res.Err = err
-		return res
+		r.Err = err
+		return r
 	}
-
-	// Send request to API
-	_, res.Err = c.Post(previewURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{
+	_, r.Err = c.Post(previewURL(c), b, &r.Body, &gophercloud.RequestOpts{
 		OkCodes: []int{200},
 	})
-	return res
+	return r
 }
 
 // Abandon deletes the stack with the provided stackName and stackID, but leaves its
 // resources intact, and returns data describing the stack and its resources.
 func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) AbandonResult {
-	var res AbandonResult
-	_, res.Err = c.Delete(abandonURL(c, stackName, stackID), &gophercloud.RequestOpts{
-		JSONResponse: &res.Body,
+	var r AbandonResult
+	_, r.Err = c.Delete(abandonURL(c, stackName, stackID), &gophercloud.RequestOpts{
+		JSONResponse: &r.Body,
 		OkCodes:      []int{200},
 	})
-	return res
+	return r
 }
diff --git a/openstack/orchestration/v1/stacks/template.go b/openstack/orchestration/v1/stacks/template.go
index c08ac30..4cf5aae 100644
--- a/openstack/orchestration/v1/stacks/template.go
+++ b/openstack/orchestration/v1/stacks/template.go
@@ -2,9 +2,10 @@
 
 import (
 	"fmt"
-	"github.com/gophercloud/gophercloud"
 	"reflect"
 	"strings"
+
+	"github.com/gophercloud/gophercloud"
 )
 
 // Template is a structure that represents OpenStack Heat templates
@@ -27,12 +28,14 @@
 			return err
 		}
 	}
+	var invalid string
 	for key := range t.Parsed {
 		if _, ok := TemplateFormatVersions[key]; ok {
 			return nil
 		}
+		invalid = key
 	}
-	return fmt.Errorf("Template format version not found.")
+	return ErrInvalidTemplateFormatVersion{Version: invalid}
 }
 
 // GetFileContents recursively parses a template to search for urls. These urls
@@ -114,8 +117,7 @@
 	case string, bool, float64, nil, int:
 		return nil
 	default:
-		return fmt.Errorf("%v: Unrecognized type", reflect.TypeOf(te))
-
+		return gophercloud.ErrUnexpectedType{Actual: fmt.Sprintf("%v", reflect.TypeOf(te))}
 	}
 	return nil
 }
diff --git a/openstack/orchestration/v1/stacks/utils.go b/openstack/orchestration/v1/stacks/utils.go
index c210b0d..71d9e35 100644
--- a/openstack/orchestration/v1/stacks/utils.go
+++ b/openstack/orchestration/v1/stacks/utils.go
@@ -113,7 +113,7 @@
 	}
 	if jerr := json.Unmarshal(t.Bin, &t.Parsed); jerr != nil {
 		if yerr := yaml.Unmarshal(t.Bin, &t.Parsed); yerr != nil {
-			return fmt.Errorf("Data in neither json nor yaml format.")
+			return ErrInvalidDataFormat{}
 		}
 	}
 	return t.Validate()
@@ -142,8 +142,7 @@
 		}
 		return typedMap, nil
 	default:
-		return nil, fmt.Errorf("Expected a map of type map[string]interface{} or map[interface{}]interface{}, actual type: %v", reflect.TypeOf(m))
-
+		return nil, gophercloud.ErrUnexpectedType{Expected: "map[string]interface{}/map[interface{}]interface{}", Actual: fmt.Sprintf("%v", reflect.TypeOf(m))}
 	}
 }
 
diff --git a/openstack/orchestration/v1/stacktemplates/requests.go b/openstack/orchestration/v1/stacktemplates/requests.go
index d307fad..9337cae 100644
--- a/openstack/orchestration/v1/stacktemplates/requests.go
+++ b/openstack/orchestration/v1/stacktemplates/requests.go
@@ -4,11 +4,9 @@
 
 // Get retreives data for the given stack template.
 func Get(c *gophercloud.ServiceClient, stackName, stackID string) GetResult {
-	var res GetResult
-	_, res.Err = c.Request("GET", getURL(c, stackName, stackID), &gophercloud.RequestOpts{
-		JSONResponse: &res.Body,
-	})
-	return res
+	var r GetResult
+	_, r.Err = c.Get(getURL(c, stackName, stackID), &r.Body, nil)
+	return r
 }
 
 // ValidateOptsBuilder describes struct types that can be accepted by the Validate call.
@@ -19,39 +17,25 @@
 
 // ValidateOpts specifies the template validation parameters.
 type ValidateOpts struct {
-	Template    string
-	TemplateURL string
+	Template    string `json:"template" or:"TemplateURL"`
+	TemplateURL string `json:"template_url" or:"Template"`
 }
 
 // ToStackTemplateValidateMap assembles a request body based on the contents of a ValidateOpts.
 func (opts ValidateOpts) ToStackTemplateValidateMap() (map[string]interface{}, error) {
-	vo := make(map[string]interface{})
-	if opts.Template != "" {
-		vo["template"] = opts.Template
-		return vo, nil
-	}
-	if opts.TemplateURL != "" {
-		vo["template_url"] = opts.TemplateURL
-		return vo, nil
-	}
-	err := gophercloud.ErrMissingInput{}
-	err.Argument = "stacktemplates.ValidateOpts.Template/stacktemplates.ValidateOpts.TemplateURL"
-	err.Info = "One of Template or TemplateURL is required."
-	return nil, err
+	return gophercloud.BuildRequestBody(opts, "")
 }
 
 // Validate validates the given stack template.
 func Validate(c *gophercloud.ServiceClient, opts ValidateOptsBuilder) ValidateResult {
-	var res ValidateResult
-
-	reqBody, err := opts.ToStackTemplateValidateMap()
+	var r ValidateResult
+	b, err := opts.ToStackTemplateValidateMap()
 	if err != nil {
-		res.Err = err
-		return res
+		r.Err = err
+		return r
 	}
-
-	_, res.Err = c.Post(validateURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{
+	_, r.Err = c.Post(validateURL(c), b, &r.Body, &gophercloud.RequestOpts{
 		OkCodes: []int{200},
 	})
-	return res
+	return r
 }