diff --git a/config/urls.py b/config/urls.py
index 7b6630f1a10e4ba92c97ac78df37a8620b7be79f..1d3db0dc00a4320424cb9b004c1bad8b2c7e7618 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -55,10 +55,10 @@ urlpatterns = [
     url(r'^search/$', search.views.search, name="mainsearch"),
 
     # API URLs
-    url(r'^apibasic/', include('api.urls', namespace="basic")),
-    url(r'^apiweb/', include('api.urls', namespace="shib")),
-    url(r'^api/', include('api.urls', namespace="x509")),
-    #url(r'^apinew/', include('api.urls')), # one place for all auth schemes
+    url(r'^api/', include('api.urls')),
+    # Legacy API URLs: can we get rid of these at some point? (TODO)
+    url(r'^apibasic/', include('api.urls', namespace='legacy_apibasic')),
+    url(r'^apiweb/', include('api.urls', namespace='legacy_apiweb')),
 
     # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
     # to INSTALLED_APPS to enable admin documentation:
diff --git a/docs/user_docs/source/auth.rst b/docs/user_docs/source/auth.rst
index d39e13b7232bb7cfd1d221ae7937044fa976acea..216f05f6fb085e64d749eb521fd3e9f69863eeb7 100644
--- a/docs/user_docs/source/auth.rst
+++ b/docs/user_docs/source/auth.rst
@@ -7,21 +7,17 @@ Authentication and Authorization
 Authentication methods
 ========================================
 
-GraceDB supports three different types of authentication methods depending
-on the entry point:
+GraceDB supports three different types of authentication methods depending on the entry point:
 
-- **Web Interface**: ``gracedb.ligo.org/`` supports Shibboleth with
+- **Web interface**: ``gracedb.ligo.org/`` supports Shibboleth with
   federated identities.
-- **REST API**: The API has three entry points:
-    - **X509**: ``gracedb.ligo.org/api/``
-    - **Shibboleth**: ``gracedb.ligo.org/apiweb/``
-    - **Basic**: ``gracedb.ligo.org/apibasic/``
+- **REST API**: The API has a single entry point which can handle the following types of authentication:
+    - **Shibboleth**
+    - **X509**
+    - **Basic (password-based)**
 
-The X509 URL listed above is the default for the Python client. But users
-with robot Kerberos keytabs will want to point to the Shibboleth URL.
-(The same URL can also be accessed with a web browser to browse the API.)
-Similarly, LV-EM users accessing the API will want to point to the URL
-for basic auth.
+Unauthenticated, read-only access is also available for both the web interface and the API.
+Only a limited set of information is available to unauthenticated users.
 
 GraceDB permissions
 =========================================
@@ -72,11 +68,10 @@ Shibbolized client as follows::
 
     from ligo.gracedb.rest import GraceDb, HTTPError
 
-    SERVICE = "https://gracedb.ligo.org/apiweb/"
+    SERVICE = "https://gracedb.ligo.org/api/"
     SHIB_SESSION_ENDPOINT = "https://gracedb.ligo.org/Shibboleth.sso/Session"
 
     client = GraceDb(SERVICE, SHIB_SESSION_ENDPOINT)
-    client.initialize()
 
     try:
         r = client.ping()
diff --git a/docs/user_docs/source/lvem.rst b/docs/user_docs/source/lvem.rst
index 31c2b8fb51da33dfc2263da2250b19fb6d9a307c..fcce9ce141684ceb97ea69f3e7ca2d04b7db02c4 100644
--- a/docs/user_docs/source/lvem.rst
+++ b/docs/user_docs/source/lvem.rst
@@ -71,7 +71,7 @@ client class is specially formulated for basic auth::
 
     from ligo.gracedb.rest import GraceDbBasic, HTTPError
  
-    service_url = 'https://gracedb.ligo.org/apibasic/'
+    service_url = 'https://gracedb.ligo.org/api/'
     client = GraceDbBasic(service_url)
   
     try:
@@ -108,7 +108,7 @@ This file can be retrieved in the following way::
     out_filename = grace_id + '_' + filename
 
     # Instantiate the GraceDB client
-    service_url = 'https://gracedb.ligo.org/apibasic/'
+    service_url = 'https://gracedb.ligo.org/api/'
     client = GraceDbBasic(service_url)
 
     # Grab the file from the server and write it 
diff --git a/docs/user_docs/source/rest.rst b/docs/user_docs/source/rest.rst
index 6b2c36fa6d2f9d69d3d1414b69b72074737917aa..3afc87075c6122341df09e05865410a830544fa6 100644
--- a/docs/user_docs/source/rest.rst
+++ b/docs/user_docs/source/rest.rst
@@ -83,7 +83,7 @@ response.  If there is an error (such as an authentication failure), the
 status code and a response body in JSON. The ``json`` method on the response
 object simply decodes the JSON content. In this particular case, the response
 code should be 200 (meaning "OK") and the body contains a large dictionary
-of information representing the `API Root resource <https://gracedb.ligo.org/apiweb/>`__.
+of information representing the `API Root resource <https://gracedb.ligo.org/api/>`__.
 Most of the examples below will ignore the error handling shown here for the 
 sake of brevity.
 
@@ -143,9 +143,9 @@ out the chirp mass? The best way is to look at the structure of an example
 event in the *browseable* REST API. Here some example events from the different
 subclasses to demonstrate the structure of the event dictionaries.
 
-- `Test gstlal MDC <https://gracedb.ligo.org/apiweb/events/T125738>`__ (a CBC event)
-- `Test cWB MDC <https://gracedb.ligo.org/apiweb/events/T153811>`__ (a Burst event)
-- `External Swift GRB <https://gracedb.ligo.org/apiweb/events/E160846>`__ (a GRB event)
+- `Test gstlal MDC <https://gracedb.ligo.org/api/events/T125738>`__ (a CBC event)
+- `Test cWB MDC <https://gracedb.ligo.org/api/events/T153811>`__ (a Burst event)
+- `External Swift GRB <https://gracedb.ligo.org/api/events/E160846>`__ (a GRB event)
 
 Creating new events
 ====================================
diff --git a/gracedb/api/backends.py b/gracedb/api/backends.py
index 952c35eb6ef1b9a9029808e4abb78561ea762b17..17d67f6b19ea93ac18e6bd453bd5646b20b05a41 100644
--- a/gracedb/api/backends.py
+++ b/gracedb/api/backends.py
@@ -27,8 +27,8 @@ class GraceDbBasicAuthentication(BasicAuthentication):
         """
         logger.debug("{0}: beginning auth attempt".format(self.__class__.__name__))
 
-        # Make sure this request is directed to the basic auth API
-        if self.api_only and not is_api_request(request.path, 'basic'):
+        # Make sure this request is directed to the API
+        if self.api_only and not is_api_request(request.path):
             logger.debug("{0}: request not directed to basic auth API".format(self.__class__.__name__))
             return None
 
@@ -81,8 +81,8 @@ class GraceDbX509Authentication(BaseAuthentication):
     def authenticate(self, request):
         logger.debug("{0}: beginning auth attempt".format(self.__class__.__name__))
 
-        # Make sure this request is directed to the basic auth API
-        if self.api_only and not is_api_request(request.path, 'x509'):
+        # Make sure this request is directed to the API
+        if self.api_only and not is_api_request(request.path):
             logger.debug("{0}: request not directed to x509 API".format(self.__class__.__name__))
             return None
 
@@ -149,8 +149,7 @@ class GraceDbShibAuthentication(BaseAuthentication):
     def authenticate(self, request):
         logger.debug("{0}: beginning auth attempt".format(self.__class__.__name__))
         if (request._request.user.is_authenticated and
-            is_api_request(request.path, 'shib')):
-
+            is_api_request(request.path)):
             logger.debug("{0}: user {1} already authenticated".format(self.__class__.__name__, request._request.user.username))
             return (request._request.user, None)
         else:
diff --git a/gracedb/api/utils.py b/gracedb/api/utils.py
index 940a04b6e85b7d51c62b707876d6a5ca5fa8de7b..f62d96f7b28b14a3a2b3c56d36fc21b7ea795140 100644
--- a/gracedb/api/utils.py
+++ b/gracedb/api/utils.py
@@ -1,105 +1,76 @@
 import logging
 
-from django.urls import resolve
+from django.urls import resolve, reverse as django_reverse
 from rest_framework.settings import api_settings
-from rest_framework.reverse import reverse as drf_reverse
 
 from core.urls import build_absolute_uri
 
 # Set up logger
 logger = logging.getLogger(__name__)
 
-# some default values
-AUTH_NAMESPACES = ['api', 'x509', 'shib', 'basic']
-DEFAULT_AUTH_NAMESPACE = 'api'
+# Some default values
+API_NAMESPACE = 'api'
 
 
 def api_reverse(viewname, args=None, kwargs=None, request=None, format=None,
-    **extra):
+    absolute_path=True, **extra):
     """
-    Reverse which handles different API auth schemes and versions. If a
-    request is provided, we want to send back URLs which use the same
-    auth type and version as the user was using. If not, we send back
-    the "default" auth scheme (currently 'x509') and version ('default').
-
-    Standard usage:
-        api_reverse('events:event-list', request=request)
+    Usage:
+        # No request and no version in viewname uses default version
+        # Same for case when request points to a non-API url
+        api_reverse('api:events:event-list')
         api_reverse('events:event-list')
+        api_reverse('api:events:event-list', request=request)
+        api_reverse('events:event-list', request=request)
+            /api/events/
 
-    Not sure if we would ever *want* to specify the auth and version
-    namespaces manually when a request is not provided, but if so, we
-    can. The following are OK, too:
-        api_reverse('default:events:event-list')
-        api_reverse('v1:events:event-list')
-        api_reverse('api:default:events:event-list')
+        # No request but with version in viewname uses the specified version
+        # Same for case when request points to a non-API url
         api_reverse('api:v1:events:event-list')
-        api_reverse('x509:default:events:event-list')
-        api_reverse('x509:v1:events:event-list')
+        api_reverse('api:v1:events:event-list', request=request)
+            /api/v1/events/
+        api_reverse('v2:events:event-list')
+        api_reverse('v2:events:event-list', request=request)
+            /api/v2/events/
+
+        # Request pointing to an API URL uses the specified version in the
+        # viewname. If a version is not specified in the viewname, the version
+        # is determined from the request.
+        api_reverse('api:v1:events:event-list, request=request)
+        api_reverse('v1:events:event-list, request=request)
+            /api/v1/events/ (request.path is like /api/(any version)/*)
+
+        api_reverse('api:events:event-list, request=request)
+        api_reverse('events:event-list, request=request)
+            /api/v2/events (request.path is like /api/v2/*)
     """
-    namespaces = []
-    if request:
-        resolver_match = resolve(request.path)
-
-        # We have to be careful here because this function is sometimes used
-        # for requests whose path is not in the API.  I.e., when web views
-        # try to serialize stuff (like EventLogToDict). The 'else' statement
-        # handles that case
-        if resolver_match.namespaces:
-            # We only add the *first* namespace because it specifies the auth
-            # namespace.  The version namespace will be handled by the
-            # versioning class in this case.
-            namespaces.append(resolver_match.namespaces[0])
-        else:
-            namespaces.append(DEFAULT_AUTH_NAMESPACE)
-            namespaces.append(api_settings.DEFAULT_VERSION)
-    else:
-        # Otherwise, we check the viewname and add in the auth and version
-        # namespaces as needed. Note that we have to add version namespaces (if
-        # the code doesn't specify them) because there is no request, so
-        # drf_reverse won't trigger the versioning class.
-
-        # Split provided viewname to determine possible namespaces that are
-        # already included
-        possible_namespaces = viewname.split(':')[:-1]
-
-        # Check if any auth namespaces were provided already; if not,
-        # set to default using app_name
-        if not any([v in possible_namespaces for v in AUTH_NAMESPACES]):
-            namespaces.append(DEFAULT_AUTH_NAMESPACE)
-
-        # Check if any version namespaces were provided already; if not,
-        # set to default
-        if not any([v in possible_namespaces for v in
-            api_settings.ALLOWED_VERSIONS]):
-            namespaces.append(api_settings.DEFAULT_VERSION)
-
-    # Join namespaces to viewname    
-    viewname = ':'.join(namespaces + [viewname])
-
-    # Use rest_framework reverse to get url
-    url = drf_reverse(viewname, args, kwargs, request, format, **extra)
-
-    # Use sites to build absolute url if request is not available
-    if request is None:
+
+    # Prepend 'api:' if viewname doesn't start with it.
+    if not viewname.startswith(API_NAMESPACE + ':'):
+        viewname = API_NAMESPACE + ':' + viewname
+
+    # Handle versioning. Nothing is done by the versioning_class if the
+    # viewname already has a version namespace.
+    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS()
+    viewname = versioning_class.get_versioned_viewname(viewname, request)
+
+    # Get URL
+    url = django_reverse(viewname, args=args, kwargs=kwargs, **extra)
+    if absolute_path:
         url = build_absolute_uri(url)
-   
+
     return url
 
 
-def is_api_request(request_path, namespace='x509'):
+def is_api_request(request_path):
     """
     Returns True/False based on whether the request is directed to the API
-    The namespace variable determines whether we should be testing for the
-    'normal' API (x509 auth), basic auth API, or web API.
-
-    These namespaces are specified in the root urlconf (config/urls.py).
     """
 
     # This is hard-coded because things break if we try to import it from .urls
     api_app_name = 'api'
 
     resolver_match = resolve(request_path)
-    if (resolver_match.app_name == api_app_name and
-        resolver_match.namespace == namespace):
+    if (resolver_match.app_name == api_app_name):
         return True
     return False
diff --git a/gracedb/api/versioning.py b/gracedb/api/versioning.py
index a6299221b1e68cf27438b3334a2a3839eed58674..92fd1ccca6c287d824d857da90939832bb1ccef1 100644
--- a/gracedb/api/versioning.py
+++ b/gracedb/api/versioning.py
@@ -11,8 +11,8 @@ class NestedNamespaceVersioning(versioning.NamespaceVersioning):
 
     def reverse(self, viewname, args=None, kwargs=None, request=None,
         format=None, **extra):
-        if request.version is not None:
-            viewname = self.get_versioned_viewname(viewname, request)
+
+        viewname = self.get_versioned_viewname(viewname, request)
         return super(NestedNamespaceVersioning, self).reverse(
             viewname, args, kwargs, request, format, **extra
         )
@@ -24,17 +24,22 @@ class NestedNamespaceVersioning(versioning.NamespaceVersioning):
         viewname_only = viewname_parts[-1]
 
         # Get version
-        if request and request.version:
+        if request and hasattr(request, 'version'):
             version = request.version
         else:
             # The 'default_version' attribute is set by the BaseVersioning
             # class
             version = self.default_version
 
-        # Add version into namespaces
-        if version not in namespaces:
+        # Insert the version unless there are at least (version_nest_level)
+        # namespaces and the one at the (version_nest_level - 1)th index is
+        # an allowed version.
+        insert_version_namespace = True
+        if (len(namespaces) >= self.version_nest_level and
+            self.is_allowed_version(namespaces[self.version_nest_level - 1])):
+            insert_version_namespace = False
+        if insert_version_namespace:
             namespaces.insert(self.version_nest_level - 1, version)
 
         versioned_viewname = ':'.join(namespaces + [viewname_only])
         return versioned_viewname
-
diff --git a/gracedb/events/buildVOEvent.py b/gracedb/events/buildVOEvent.py
index 1721f8f88c7bdd51ca7e9aa9d9f9e2f3a8323228..511bf048443d62271da46fc363a414d04e7d07a7 100644
--- a/gracedb/events/buildVOEvent.py
+++ b/gracedb/events/buildVOEvent.py
@@ -291,24 +291,22 @@ def buildVOEvent(event, serial_number, voevent_type, request=None, skymap_filena
         g = Group('GW_SKYMAP', skymap_type)
 
         # shib urls.
+        # For some reason we use the web URL rather than the API.
+        # TODO: fix it.
         shib_fits_skymap_url = get_url(request, objid, "file-download", fits_name)
         if img_name:
             shib_png_skymap_url  = get_url(request, objid, "file-download", img_name)
 
-        # x509 urls. Hafta specify the api namespace.
+        # API urls: even though we only have one API endpoint now, we still
+        # populate all of these different URLs. Maybe we can change this in the
+        # future (TODO).
         x509_fits_skymap_url = get_url(request, objid,
-            "x509:default:events:files", fits_name)
+            "api:default:events:files", fits_name)
+        basic_fits_skymap_url = x509_fits_skymap_url
         if img_name:
-            x509_png_skymap_url  = get_url(request, objid,
-                "x509:default:events:files", img_name)
-
-        # basic urls. Hafta specify the api namespace.
-        basic_fits_skymap_url = get_url(request, objid,
-            "basic:default:events:files", fits_name)
-        if img_name:
-            basic_png_skymap_url  = get_url(request, objid,
-                "basic:default:events:files", img_name)
-        
+            x509_png_skymap_url = get_url(request, objid,
+                "api:default:events:files", img_name)
+            basic_png_skymap_url = x509_png_skymap_url
 
         # Add parameters to the skymap group
         g.add_Param(Param(name="skymap_fits_shib", 
diff --git a/gracedb/events/permission_utils.py b/gracedb/events/permission_utils.py
index aade21c6d35235e5fceb1b0706d54a10c70c3f46..8fc80065d997bc78902276a9f54acb8da887506d 100644
--- a/gracedb/events/permission_utils.py
+++ b/gracedb/events/permission_utils.py
@@ -143,15 +143,6 @@ def is_external(user):
     else:
         return True
 
-#-------------------------------------------------------------------------------
-# A utility for determining whether a user is accessing the API through the
-# basic auth entry point.
-#-------------------------------------------------------------------------------
-def is_basicapi_request(request):
-   if request.path.startswith("/apibasic/"):
-       return True
-   else:
-       return False
 
 #-------------------------------------------------------------------------------
 # A utility for determining whether an external user should have access to a 
diff --git a/gracedb/events/views.py b/gracedb/events/views.py
index 9b459f452f1cab043a0240b86960646b417044e2..3c9da215f8dd4e82e84d7ff872a7a370347f7893 100644
--- a/gracedb/events/views.py
+++ b/gracedb/events/views.py
@@ -466,7 +466,7 @@ def view(request, event):
 #-----------------------------------------------------------------------------------
 # For tags.  A new view function.  We need this because the API one would want users
 # to have certs stored in their browser.
-# XXX Get rid of this and use apiweb views instead?
+# XXX Get rid of this and use api views instead?
 #-----------------------------------------------------------------------------------
 
 @event_and_auth_required
diff --git a/gracedb/superevents/buildVOEvent.py b/gracedb/superevents/buildVOEvent.py
index 5220d144b61de08d232bca784cbec1142333978a..5247c2592d94ae1f89b3c2d5544f2f6989378137 100644
--- a/gracedb/superevents/buildVOEvent.py
+++ b/gracedb/superevents/buildVOEvent.py
@@ -273,18 +273,21 @@ def construct_voevent_file(superevent, voevent, request=None,
         # Skymaps. Create group and set particular fits and image file names
         g = Group('GW_SKYMAP', skymap_type)
 
+        # We have only one API now for all authorization types.
+        # But the VOEvents are still expected to contain
         # shib, x509, and basic API urls for fits skymap file
-        # Temp function for reversing superevent file detail API resource
-        file_abs_reverse = lambda ns, file_name: build_absolute_uri(
-            reverse(ns + ":default:superevents:superevent-file-detail",
-            args=[superevent.superevent_id, file_name]), request)
-        shib_fits_skymap_url = file_abs_reverse('shib', fits_name)
-        x509_fits_skymap_url = file_abs_reverse('x509', fits_name)
-        basic_fits_skymap_url = file_abs_reverse('basic', fits_name)
+        # TODO: figure out if we can change this functionality going forward
+        shib_fits_skymap_url = build_absolute_uri(reverse(
+            "api:default:superevents:superevent-file-detail",
+            args=[superevent.superevent_id, fits_name]), request)
+        x509_fits_skymap_url = shib_fits_skymap_url
+        basic_fits_skymap_url = shib_fits_skymap_url
         if img_name:
-            shib_png_skymap_url = file_abs_reverse('shib', img_name)
-            x509_png_skymap_url = file_abs_reverse('x509', img_name)
-            basic_png_skymap_url = file_abs_reverse('basic', img_name)
+            shib_png_skymap_url = build_absolute_uri(reverse(
+                "api:default:superevents:superevent-file-detail",
+                args=[superevent.superevent_id, img_name]), request)
+            x509_png_skymap_url = shib_png_skymap_url
+            basic_png_skymap_url = shib_png_skymap_url
 
         # Add parameters to the skymap group
         g.add_Param(Param(name="skymap_fits_shib", 
diff --git a/gracedb/superevents/mixins.py b/gracedb/superevents/mixins.py
index 44cbd84c9fac2c24c73fa4eeab47e2226c9b8830..319a9a72b85ac21e7356661b1b53a1782ab6d159 100644
--- a/gracedb/superevents/mixins.py
+++ b/gracedb/superevents/mixins.py
@@ -165,7 +165,7 @@ class AdvocateSignoffMixin(ContextMixin):
 class ExposeHideMixin(ContextMixin):
     expose_perm_name = 'superevents.expose_superevent'
     hide_perm_name = 'superevents.hide_superevent'
-    form_url_view_name = 'shib:default:superevents:superevent-permissions'
+    form_url_view_name = 'api:default:superevents:superevent-permissions'
 
     def get_context_data(self, **kwargs):
 
diff --git a/gracedb/superevents/models.py b/gracedb/superevents/models.py
index bdd1c6f7075279eedeea3e99112cb7ada80fc1ce..9e396fbb3a1e91f6738a205027e55b2868ce4be8 100644
--- a/gracedb/superevents/models.py
+++ b/gracedb/superevents/models.py
@@ -462,7 +462,7 @@ class Log(CleanSaveModel, LogBase, AutoIncrementModel):
         return os.path.join(self.superevent.datadir, self.versioned_filename)
 
     def fileurl(self):
-        return reverse("shib:default:superevents:superevent-file-detail",
+        return reverse("api:default:superevents:superevent-file-detail",
             args=[self.superevent.superevent_id, self.versioned_filename])
 
 
diff --git a/gracedb/templates/gracedb/event_detail_script.js b/gracedb/templates/gracedb/event_detail_script.js
index 7f7268bd6e225d3d48d6e7225ce53fbe5369d79b..862465156f34ed1d82cfdcedfbf4a86a8c576308 100644
--- a/gracedb/templates/gracedb/event_detail_script.js
+++ b/gracedb/templates/gracedb/event_detail_script.js
@@ -156,14 +156,14 @@ var hasImage = function(object) {
 }
 
 // some URLs. Usage of Django template syntax should be limited to here
-var tagListUrl          = '{% url "shib:default:tag-list" %}';
+var tagListUrl          = '{% url "api:default:tag-list" %}';
 var tagUrlPattern       = '{% url "taglogentry" object.graceid "000" "temp" %}';
-var eventLogListUrl     = '{% url "shib:default:events:eventlog-list" object.graceid %}';
+var eventLogListUrl     = '{% url "api:default:events:eventlog-list" object.graceid %}';
 var eventLogSaveUrl     = '{% url "logentry" object.graceid "" %}';
-var embbEventLogListUrl = '{% url "shib:default:events:embbeventlog-list" object.graceid %}';
-var emObservationListUrl = '{% url "shib:default:events:emobservation-list" object.graceid %}';
+var embbEventLogListUrl = '{% url "api:default:events:embbeventlog-list" object.graceid %}';
+var emObservationListUrl = '{% url "api:default:events:emobservation-list" object.graceid %}';
 var fileDownloadUrl = '{% url "file-download" object.graceid "FAKE_FILE_NAME" %}';
-var skymapJsonUrl       = '{% url "shib:default:events:files" object.graceid "" %}';
+var skymapJsonUrl       = '{% url "api:default:events:files" object.graceid "" %}';
 var skymapViewerUrl     = '{{ SKYMAP_VIEWER_SERVICE_URL }}';
 
 // This little list determines the priority ordering of the digest sections.
diff --git a/gracedb/templates/gracedb/index.html b/gracedb/templates/gracedb/index.html
index 52b8380a1984cd228f74fbd506d5c83ceeb6a6f0..3fa7618f6cf83a9392d4d5b1048af73bee1d8798 100644
--- a/gracedb/templates/gracedb/index.html
+++ b/gracedb/templates/gracedb/index.html
@@ -81,7 +81,7 @@ follow-ups. </p>
 <!-- <li><a href="https://www.lsc-group.phys.uwm.edu/daswg/wiki/GraceDBER6">Recent changes</a> <font color="red">(IMPORTANT!) </font></li> -->
 <!-- <li><a href="https://gw-astronomy.org/wiki/LV_EM/ElectroMagneticBulletinBoard">Prototype EMBB description</a></li> -->
 <li><a href="https://wiki.ligo.org/Computing/DASWG/GraceDB">Project page on wiki.ligo.org</a></li>
-<li><a href="{% url "shib:default:root" %}">Browseable REST API</a>
+<li><a href="{% url "api:default:root" %}">Browseable REST API</a>
 <li><a href="https://gw-astronomy.org/wiki/LV_EM/TechInfo">LV-EM Technical Info</a></li>
 <li><a href="https://dcc.ligo.org/G1501296">Tutorial for operators and detector engineers</a></li>
 
diff --git a/gracedb/templates/profile/manage_password.html b/gracedb/templates/profile/manage_password.html
index 4c5698b389947c3943fba0b8cff7b95f617077c6..d4098a3b6df61c4f6e6151fa69c966d1271e281c 100644
--- a/gracedb/templates/profile/manage_password.html
+++ b/gracedb/templates/profile/manage_password.html
@@ -6,7 +6,7 @@
 
 {% block content %}
 
-<p>Passwords generated here are intended only for scripted access to GraceDB by LV-EM users. Your password allows access to the <a href={% url "basic:default:root" %}>REST API</a>.</p>
+<p>Passwords generated here are intended only for scripted access to the GraceDB <a href={% url "api:default:root" %}>REST API</a> by LV-EM users.</p>
 
 <p> Your username is: <b>{{ username }}</b></p>
 {% if has_password %}
diff --git a/gracedb/templates/superevents/detail.html b/gracedb/templates/superevents/detail.html
index c55f32ac20ee8e8e6ddbcae14510dd1c8d401d11..088eb6714ba140f6bbad791e473600b1f8c7dee6 100644
--- a/gracedb/templates/superevents/detail.html
+++ b/gracedb/templates/superevents/detail.html
@@ -57,7 +57,7 @@
 
 {% if show_gw_status_form %}
 <div class="content-area">
-<form action="{% url "shib:default:superevents:superevent-confirm-as-gw" superevent.superevent_id %}" method="POST" id="confirm_as_gw_form">
+<form action="{% url "api:default:superevents:superevent-confirm-as-gw" superevent.superevent_id %}" method="POST" id="confirm_as_gw_form">
     <input type="submit" value="Confirm this superevent as a GW" class="permButtonClass" disabled>
 </form>
 <div><b>Note:</b> this action is irreversible without manual intervention by an admin.</div>
@@ -70,7 +70,7 @@
 {#-- XXX This next bit is super hacky. #}
 {% if can_modify_permissions %}
 <div class="content-area">
-<form action="{% url "shib:default:superevents:superevent-permission-modify" superevent.superevent_id %}" method="POST" id="permissions_form">
+<form action="{% url "api:default:superevents:superevent-permission-modify" superevent.superevent_id %}" method="POST" id="permissions_form">
     <input type="hidden" name="action" value="{{ permissions_action }}">
     <input type="submit" value="{{ permissions_form_button_text }}" class="permButtonClass" disabled>
 </form>
@@ -95,11 +95,11 @@
             {# inputs are disabled here, enabled by jquery code on page load. Otherwise users who click quickly can activate the form before the jquery is fully loaded #}
             {% if operator_signoff_exists %}
             {% with operator_signoff_type|add:operator_signoff_instrument as typeinst %}
-                <input type="submit" formaction="{% url "shib:default:superevents:superevent-signoff-detail" superevent.superevent_id typeinst %}" value="Update signoff" class="searchButtonClass" id="update" disabled>
-                <input type="submit" formaction="{% url "shib:default:superevents:superevent-signoff-detail" superevent.superevent_id typeinst %}" value="Delete signoff" class="searchButtonClass" id="delete" disabled>
+                <input type="submit" formaction="{% url "api:default:superevents:superevent-signoff-detail" superevent.superevent_id typeinst %}" value="Update signoff" class="searchButtonClass" id="update" disabled>
+                <input type="submit" formaction="{% url "api:default:superevents:superevent-signoff-detail" superevent.superevent_id typeinst %}" value="Delete signoff" class="searchButtonClass" id="delete" disabled>
             {% endwith %}
             {% else %}
-            <input type="submit" value="Create signoff" class="searchButtonClass" formaction={% url "shib:default:superevents:superevent-signoff-list" superevent.superevent_id %} disabled>
+            <input type="submit" value="Create signoff" class="searchButtonClass" formaction={% url "api:default:superevents:superevent-signoff-list" superevent.superevent_id %} disabled>
             {% endif %}
             </td>
         </tr>
@@ -129,11 +129,11 @@
             {# inputs are disabled here, enabled by jquery code on page load. Otherwise users who click quickly can activate the form before the jquery is fully loaded #}
             {% if advocate_signoff_exists %}
             {% with advocate_signoff_type|add:advocate_signoff_instrument as typeinst %}
-                <input type="submit" formaction="{% url "shib:default:superevents:superevent-signoff-detail" superevent.superevent_id typeinst %}" value="Update signoff" class="searchButtonClass" id="update" disabled>
-                <input type="submit" formaction="{% url "shib:default:superevents:superevent-signoff-detail" superevent.superevent_id typeinst %}" value="Delete signoff" class="searchButtonClass" id="delete" disabled>
+                <input type="submit" formaction="{% url "api:default:superevents:superevent-signoff-detail" superevent.superevent_id typeinst %}" value="Update signoff" class="searchButtonClass" id="update" disabled>
+                <input type="submit" formaction="{% url "api:default:superevents:superevent-signoff-detail" superevent.superevent_id typeinst %}" value="Delete signoff" class="searchButtonClass" id="delete" disabled>
             {% endwith %}
             {% else %}
-            <input type="submit" value="Create signoff" class="searchButtonClass" formaction={% url "shib:default:superevents:superevent-signoff-list" superevent.superevent_id %} disabled>
+            <input type="submit" value="Create signoff" class="searchButtonClass" formaction={% url "api:default:superevents:superevent-signoff-list" superevent.superevent_id %} disabled>
             {% endif %}
             </td>
         </tr>
diff --git a/gracedb/templates/superevents/file_list.html b/gracedb/templates/superevents/file_list.html
index 5a71cd49a7947fe2752702d22d7f75c914464a43..c34b8fab8c9924d219db1ae99afd1a4c1c326e84 100644
--- a/gracedb/templates/superevents/file_list.html
+++ b/gracedb/templates/superevents/file_list.html
@@ -8,7 +8,7 @@
 
 <ul>
 {% for filename in file_list %}
-<li><a href="{% url "shib:default:superevents:superevent-file-detail" object.superevent_id filename %}">{{ filename }}</a></li>
+<li><a href="{% url "api:default:superevents:superevent-file-detail" object.superevent_id filename %}">{{ filename }}</a></li>
 {% endfor %}
 </ul>
 
diff --git a/gracedb/templates/superevents/superevent_detail_script.js b/gracedb/templates/superevents/superevent_detail_script.js
index 283af7e305007bf5782efbf421bfddc08ec5a112..84c12f70e1dc351f67257d785259a54e441972ad 100644
--- a/gracedb/templates/superevents/superevent_detail_script.js
+++ b/gracedb/templates/superevents/superevent_detail_script.js
@@ -156,13 +156,13 @@ var hasImage = function(object) {
 }
 
 // some URLs. Usage of Django template syntax should be limited to here
-var tagListUrl          = '{% url "shib:default:tag-list" %}';
-var tagCreateUrlPattern = '{% url "shib:default:superevents:superevent-log-tag-list" superevent.superevent_id "000" %}';
-var tagDeleteUrlPattern = '{% url "shib:default:superevents:superevent-log-tag-detail" superevent.superevent_id "000" "FAKE_TAG_NAME" %}';
-var logListUrl     = '{% url "shib:default:superevents:superevent-log-list" superevent.superevent_id %}';
-var logSaveUrl     = '{% url "shib:default:superevents:superevent-log-list" superevent.superevent_id %}';
-var emObservationListUrl = '{% url "shib:default:superevents:superevent-emobservation-list" superevent.superevent_id %}';
-var fileDownloadUrl     = '{% url "shib:default:superevents:superevent-file-detail" superevent.superevent_id "FAKE_FILE_NAME" %}';
+var tagListUrl          = '{% url "api:default:tag-list" %}';
+var tagCreateUrlPattern = '{% url "api:default:superevents:superevent-log-tag-list" superevent.superevent_id "000" %}';
+var tagDeleteUrlPattern = '{% url "api:default:superevents:superevent-log-tag-detail" superevent.superevent_id "000" "FAKE_TAG_NAME" %}';
+var logListUrl     = '{% url "api:default:superevents:superevent-log-list" superevent.superevent_id %}';
+var logSaveUrl     = '{% url "api:default:superevents:superevent-log-list" superevent.superevent_id %}';
+var emObservationListUrl = '{% url "api:default:superevents:superevent-emobservation-list" superevent.superevent_id %}';
+var fileDownloadUrl     = '{% url "api:default:superevents:superevent-file-detail" superevent.superevent_id "FAKE_FILE_NAME" %}';
 var skymapViewerUrl     = '{{ SKYMAP_VIEWER_SERVICE_URL }}';
 
 // This little list determines the priority ordering of the digest sections.