Unit tests for Endpoint CRUD operations.
diff --git a/openstack/identity/v3/endpoints/requests.go b/openstack/identity/v3/endpoints/requests.go
index a29b68f..e3d0eb2 100644
--- a/openstack/identity/v3/endpoints/requests.go
+++ b/openstack/identity/v3/endpoints/requests.go
@@ -1 +1,59 @@
 package endpoints
+
+import (
+	"errors"
+
+	"github.com/rackspace/gophercloud"
+)
+
+// Interface describes the availability of a specific service endpoint.
+type Interface string
+
+const (
+	// InterfaceAdmin makes an endpoint only available to administrators.
+	InterfaceAdmin Interface = "admin"
+
+	// InterfacePublic makes an endpoint available to everyone.
+	InterfacePublic Interface = "public"
+
+	// InterfaceInternal makes an endpoint only available within the cluster.
+	InterfaceInternal Interface = "internal"
+)
+
+// EndpointOpts contains the subset of Endpoint attributes that should be used to create or update an Endpoint.
+type EndpointOpts struct {
+	Interface Interface
+	Name      string
+	Region    string
+	URL       string
+	ServiceID string
+}
+
+// Create inserts a new Endpoint into the service catalog.
+func Create(client *gophercloud.ServiceClient, opts EndpointOpts) (*Endpoint, error) {
+	return nil, errors.New("Not implemented")
+}
+
+// ListOpts allows finer control over the the endpoints returned by a List call.
+// All fields are optional.
+type ListOpts struct {
+	Interface Interface
+	ServiceID string
+	Page      int
+	PerPage   int
+}
+
+// List enumerates endpoints in a paginated collection, optionally filtered by ListOpts criteria.
+func List(client *gophercloud.ServiceClient, opts ListOpts) (*EndpointList, error) {
+	return nil, errors.New("Not implemented")
+}
+
+// Update changes an existing endpoint with new data.
+func Update(client *gophercloud.ServiceClient, endpointID string, opts EndpointOpts) (*Endpoint, error) {
+	return nil, errors.New("Not implemented")
+}
+
+// Delete removes an endpoint from the service catalog.
+func Delete(client *gophercloud.ServiceClient, endpointID string) error {
+	return errors.New("Not implemented")
+}
diff --git a/openstack/identity/v3/endpoints/requests_test.go b/openstack/identity/v3/endpoints/requests_test.go
new file mode 100644
index 0000000..77a2292
--- /dev/null
+++ b/openstack/identity/v3/endpoints/requests_test.go
@@ -0,0 +1,224 @@
+package endpoints
+
+import (
+	"fmt"
+	"net/http"
+	"reflect"
+	"testing"
+
+	"github.com/rackspace/gophercloud"
+	"github.com/rackspace/gophercloud/testhelper"
+)
+
+const tokenID = "abcabcabcabc"
+
+func serviceClient() *gophercloud.ServiceClient {
+	return &gophercloud.ServiceClient{
+		Provider: &gophercloud.ProviderClient{TokenID: tokenID},
+		Endpoint: testhelper.Endpoint(),
+	}
+}
+
+func TestCreateSuccessful(t *testing.T) {
+	testhelper.SetupHTTP()
+	defer testhelper.TeardownHTTP()
+
+	testhelper.Mux.HandleFunc("/endpoints", func(w http.ResponseWriter, r *http.Request) {
+		testhelper.TestMethod(t, r, "POST")
+		testhelper.TestHeader(t, r, "X-Auth-Token", tokenID)
+		testhelper.TestJSONRequest(t, r, `
+      {
+        "endpoint": {
+          "interface": "public",
+          "name": "the-endiest-of-points",
+          "region": "underground",
+          "url": "https://1.2.3.4:9000/",
+          "service_id": "asdfasdfasdfasdf"
+        }
+      }
+    `)
+
+		fmt.Fprintf(w, `
+      {
+        "endpoint": {
+          "id": "12",
+          "interface": "public",
+          "links": {
+            "self": "https://localhost:5000/v3/endpoints/12"
+          },
+          "name": "the-endiest-of-points",
+          "region": "underground",
+          "service_id": "asdfasdfasdfasdf",
+          "url": "https://1.2.3.4:9000/"
+        }
+      }
+    `)
+	})
+
+	client := serviceClient()
+
+	result, err := Create(client, EndpointOpts{
+		Interface: InterfacePublic,
+		Name:      "the-endiest-of-points",
+		Region:    "underground",
+		URL:       "https://1.2.3.4:9000/",
+		ServiceID: "asdfasdfasdfasdf",
+	})
+	if err != nil {
+		t.Fatalf("Unable to create an endpoint: %v", err)
+	}
+
+	expected := Endpoint{
+		ID:        "12",
+		Interface: InterfacePublic,
+		Name:      "the-endiest-of-points",
+		Region:    "underground",
+		ServiceID: "asdfasdfasdfasdf",
+		URL:       "https://1.2.3.4:9000/",
+	}
+
+	if !reflect.DeepEqual(result, expected) {
+		t.Errorf("Expected %#v, was %#v", expected, result)
+	}
+}
+
+func TestListEndpoints(t *testing.T) {
+	testhelper.SetupHTTP()
+	defer testhelper.TeardownHTTP()
+
+	testhelper.Mux.HandleFunc("/endpoints", func(w http.ResponseWriter, r *http.Request) {
+		testhelper.TestMethod(t, r, "GET")
+		testhelper.TestHeader(t, r, "X-Auth-Token", tokenID)
+
+		fmt.Fprintf(w, `
+			[
+				{
+					"id": "12",
+					"interface": "public",
+					"links": {
+						"self": "https://localhost:5000/v3/endpoints/12"
+					},
+					"name": "the-endiest-of-points",
+					"region": "underground",
+					"service_id": "asdfasdfasdfasdf",
+					"url": "https://1.2.3.4:9000/"
+				},
+				{
+					"id": "13",
+					"interface": "internal",
+					"links": {
+						"self": "https://localhost:5000/v3/endpoints/13"
+					},
+					"name": "shhhh",
+					"region": "underground",
+					"service_id": "asdfasdfasdfasdf",
+					"url": "https://1.2.3.4:9001/"
+				}
+			]
+		`)
+	})
+
+	client := serviceClient()
+
+	actual, err := List(client, ListOpts{})
+	if err != nil {
+		t.Fatalf("Unexpected error listing endpoints: %v", err)
+	}
+
+	expected := []Endpoint{
+		Endpoint{
+			ID:        "12",
+			Interface: InterfacePublic,
+			Name:      "the-endiest-of-points",
+			Region:    "underground",
+			ServiceID: "asdfasdfasdfasdf",
+			URL:       "https://1.2.3.4:9000/",
+		},
+		Endpoint{
+			ID:        "13",
+			Interface: InterfaceInternal,
+			Name:      "shhhh",
+			Region:    "underground",
+			ServiceID: "asdfasdfasdfasdf",
+			URL:       "https://1.2.3.4:9001/",
+		},
+	}
+
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("Expected %#v, got %#v", expected, actual)
+	}
+}
+
+func TestUpdateEndpoint(t *testing.T) {
+	testhelper.SetupHTTP()
+	defer testhelper.TeardownHTTP()
+
+	testhelper.Mux.HandleFunc("/endpoints/12", func(w http.ResponseWriter, r *http.Request) {
+		testhelper.TestMethod(t, r, "GET")
+		testhelper.TestHeader(t, r, "X-Auth-Token", tokenID)
+		testhelper.TestJSONRequest(t, r, `
+		{
+	    "endpoint": {
+	      "name": "renamed",
+				"region": "somewhere-else"
+	    }
+		}
+	`)
+
+		fmt.Fprintf(w, `
+		{
+			"endpoint": {
+				"id": "12",
+				"interface": "public",
+				"links": {
+					"self": "https://localhost:5000/v3/endpoints/12"
+				},
+				"name": "renamed",
+				"region": "somewhere-else",
+				"service_id": "asdfasdfasdfasdf",
+				"url": "https://1.2.3.4:9000/"
+			}
+		}
+	`)
+	})
+
+	client := serviceClient()
+	actual, err := Update(client, "12", EndpointOpts{
+		Name:   "renamed",
+		Region: "somewhere-else",
+	})
+	if err != nil {
+		t.Fatalf("Unexpected error from Update: %v", err)
+	}
+
+	expected := Endpoint{
+		ID:        "12",
+		Interface: InterfacePublic,
+		Name:      "renamed",
+		Region:    "somewhere-else",
+		ServiceID: "asdfasdfasdfasdf",
+		URL:       "https://1.2.3.4:9000/",
+	}
+	if !reflect.DeepEqual(expected, actual) {
+		t.Errorf("Expected %#v, was %#v", expected, actual)
+	}
+}
+
+func TestDeleteEndpoint(t *testing.T) {
+	testhelper.SetupHTTP()
+	defer testhelper.TeardownHTTP()
+
+	testhelper.Mux.HandleFunc("/endpoints/34", func(w http.ResponseWriter, r *http.Request) {
+		testhelper.TestMethod(t, r, "DELETE")
+		testhelper.TestHeader(t, r, "X-Auth-Token", tokenID)
+
+		w.WriteHeader(http.StatusNoContent)
+	})
+
+	client := serviceClient()
+
+	err := Delete(client, "34")
+	if err != nil {
+		t.Fatalf("Unexpected error from Delete: %v", err)
+	}
+}
diff --git a/openstack/identity/v3/endpoints/results.go b/openstack/identity/v3/endpoints/results.go
new file mode 100644
index 0000000..b7074df
--- /dev/null
+++ b/openstack/identity/v3/endpoints/results.go
@@ -0,0 +1,19 @@
+package endpoints
+
+import "github.com/rackspace/gophercloud"
+
+// Endpoint describes the entry point for another service's API.
+type Endpoint struct {
+	ID        string    `json:"id"`
+	Interface Interface `json:"interface"`
+	Name      string    `json:"name"`
+	Region    string    `json:"region"`
+	ServiceID string    `json:"service_id"`
+	URL       string    `json:"url"`
+}
+
+// EndpointList contains a page of Endpoint results.
+type EndpointList struct {
+	gophercloud.Pagination
+	Endpoints []Endpoint
+}