ServiceList is now a LinkCollection.
diff --git a/openstack/identity/v3/services/requests.go b/openstack/identity/v3/services/requests.go
index c40af7d..8c50054 100644
--- a/openstack/identity/v3/services/requests.go
+++ b/openstack/identity/v3/services/requests.go
@@ -9,11 +9,11 @@
 )
 
 type response struct {
-	Service ServiceResult `json:"service"`
+	Service Service `json:"service"`
 }
 
 // Create adds a new service of the requested type to the catalog.
-func Create(client *gophercloud.ServiceClient, serviceType string) (*ServiceResult, error) {
+func Create(client *gophercloud.ServiceClient, serviceType string) (*Service, error) {
 	type request struct {
 		Type string `json:"type"`
 	}
@@ -42,7 +42,7 @@
 }
 
 // List enumerates the services available to a specific user.
-func List(client *gophercloud.ServiceClient, opts ListOpts) (*ServiceListResult, error) {
+func List(client *gophercloud.ServiceClient, opts ListOpts) (*ServiceList, error) {
 	q := make(map[string]string)
 	if opts.ServiceType != "" {
 		q["type"] = opts.ServiceType
@@ -55,7 +55,7 @@
 	}
 	u := getListURL(client) + utils.BuildQuery(q)
 
-	var resp ServiceListResult
+	var resp ServiceList
 	_, err := perigee.Request("GET", u, perigee.Options{
 		MoreHeaders: client.Provider.AuthenticatedHeaders(),
 		Results:     &resp,
@@ -69,7 +69,7 @@
 }
 
 // Info returns additional information about a service, given its ID.
-func Info(client *gophercloud.ServiceClient, serviceID string) (*ServiceResult, error) {
+func Info(client *gophercloud.ServiceClient, serviceID string) (*Service, error) {
 	var resp response
 	_, err := perigee.Request("GET", getServiceURL(client, serviceID), perigee.Options{
 		MoreHeaders: client.Provider.AuthenticatedHeaders(),
@@ -83,7 +83,7 @@
 }
 
 // Update changes the service type of an existing service.s
-func Update(client *gophercloud.ServiceClient, serviceID string, serviceType string) (*ServiceResult, error) {
+func Update(client *gophercloud.ServiceClient, serviceID string, serviceType string) (*Service, error) {
 	type request struct {
 		Type string `json:"type"`
 	}
diff --git a/openstack/identity/v3/services/requests_test.go b/openstack/identity/v3/services/requests_test.go
index 9cd5232..ef8c481 100644
--- a/openstack/identity/v3/services/requests_test.go
+++ b/openstack/identity/v3/services/requests_test.go
@@ -3,6 +3,7 @@
 import (
 	"fmt"
 	"net/http"
+	"reflect"
 	"testing"
 
 	"github.com/rackspace/gophercloud"
@@ -102,20 +103,28 @@
 		t.Fatalf("Error listing services: %v", err)
 	}
 
-	if result.Pagination.Next != nil {
-		t.Errorf("Unexpected next link: %s", result.Pagination.Next)
+	collection, err := gophercloud.AllPages(result)
+	actual := AsServices(collection)
+
+	desc0 := "Service One"
+	desc1 := "Service Two"
+	expected := []Service{
+		Service{
+			Description: &desc0,
+			ID:          "1234",
+			Name:        "service-one",
+			Type:        "identity",
+		},
+		Service{
+			Description: &desc1,
+			ID:          "9876",
+			Name:        "service-two",
+			Type:        "compute",
+		},
 	}
-	if result.Pagination.Previous != nil {
-		t.Errorf("Unexpected previous link: %s", result.Pagination.Previous)
-	}
-	if len(result.Services) != 2 {
-		t.Errorf("Unexpected number of services: %s", len(result.Services))
-	}
-	if result.Services[0].ID != "1234" {
-		t.Errorf("Unexpected service: %#v", result.Services[0])
-	}
-	if result.Services[1].ID != "9876" {
-		t.Errorf("Unexpected service: %#v", result.Services[1])
+
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("Expected %#v, got %#v", expected, actual)
 	}
 }
 
diff --git a/openstack/identity/v3/services/results.go b/openstack/identity/v3/services/results.go
index aba3aa1..c6ce1b9 100644
--- a/openstack/identity/v3/services/results.go
+++ b/openstack/identity/v3/services/results.go
@@ -1,18 +1,60 @@
 package services
 
-import "github.com/rackspace/gophercloud"
+import (
+	"fmt"
 
-// ServiceResult is the result of a list or information query.
-type ServiceResult struct {
+	"github.com/mitchellh/mapstructure"
+	"github.com/rackspace/gophercloud"
+)
+
+// Service is the result of a list or information query.
+type Service struct {
 	Description *string `json:"description,omitempty"`
 	ID          string  `json:"id"`
 	Name        string  `json:"name"`
 	Type        string  `json:"type"`
 }
 
-// ServiceListResult is a paged collection of Services.
-type ServiceListResult struct {
-	gophercloud.Pagination
+// ServiceList is a collection of Services.
+type ServiceList struct {
+	gophercloud.PaginationLinks `json:"links"`
 
-	Services []ServiceResult `json:"services"`
+	client *gophercloud.ServiceClient
+	Page   []Service `json:"services"`
+}
+
+// Pager indicates that the ServiceList is paginated by next and previous links.
+func (list ServiceList) Pager() gophercloud.Pager {
+	return gophercloud.NewLinkPager(list)
+}
+
+// Service returns the ServiceClient used to acquire this list.
+func (list ServiceList) Service() *gophercloud.ServiceClient {
+	return list.client
+}
+
+// Links accesses pagination information for the current page.
+func (list ServiceList) Links() gophercloud.PaginationLinks {
+	return list.PaginationLinks
+}
+
+// Interpret parses a follow-on JSON response as an additional page.
+func (list ServiceList) Interpret(json interface{}) (gophercloud.LinkCollection, error) {
+	mapped, ok := json.(map[string]interface{})
+	if !ok {
+		return nil, fmt.Errorf("Unexpected JSON response: %#v", json)
+	}
+
+	var result ServiceList
+	err := mapstructure.Decode(mapped, &result)
+	if err != nil {
+		return nil, err
+	}
+	return result, nil
+}
+
+// AsServices extracts a slice of Services from a Collection acquired from List.
+// It panics if the Collection does not actually contain Services.
+func AsServices(results gophercloud.Collection) []Service {
+	return results.(*ServiceList).Page
 }