Let's include the / in service endpoints.
diff --git a/openstack/client.go b/openstack/client.go
index e964d07..cbfde10 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -4,6 +4,7 @@
 	"errors"
 	"fmt"
 	"net/url"
+	"strings"
 
 	"github.com/rackspace/gophercloud"
 	tokens3 "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
@@ -65,6 +66,10 @@
 		return err
 	}
 
+	if !strings.HasSuffix(endpoint, "/") {
+		endpoint = endpoint + "/"
+	}
+
 	switch chosen.ID {
 	case v20:
 		return errors.New("Not implemented yet.")
@@ -92,7 +97,7 @@
 
 // NewIdentityV2 creates a ServiceClient that may be used to interact with the v2 identity service.
 func NewIdentityV2(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
-	v2Endpoint := client.IdentityEndpoint + "/v2.0"
+	v2Endpoint := client.IdentityEndpoint + "/v2.0/"
 
 	return &gophercloud.ServiceClient{
 		Provider: client,
@@ -102,7 +107,7 @@
 
 // NewIdentityV3 creates a ServiceClient that may be used to access the v3 identity service.
 func NewIdentityV3(client *gophercloud.ProviderClient) *gophercloud.ServiceClient {
-	v3Endpoint := client.IdentityEndpoint + "/v3"
+	v3Endpoint := client.IdentityEndpoint + "/v3/"
 
 	return &gophercloud.ServiceClient{
 		Provider: client,
diff --git a/service_client.go b/service_client.go
index cca5a74..83ad69b 100644
--- a/service_client.go
+++ b/service_client.go
@@ -9,11 +9,11 @@
 	Provider *ProviderClient
 
 	// Endpoint is the base URL of the service's API, acquired from a service catalog.
-	// It should NOT end with a /.
+	// It MUST end with a /.
 	Endpoint string
 }
 
 // ServiceURL constructs a URL for a resource belonging to this provider.
 func (client *ServiceClient) ServiceURL(parts ...string) string {
-	return client.Endpoint + "/" + strings.Join(parts, "/")
+	return client.Endpoint + strings.Join(parts, "/")
 }