diff --git a/config/settings/base.py b/config/settings/base.py
index 55d2b3e61027b57b95e1d048e609fb50e34091c0..a2b76f94e944d33dc6f02349d09c1bdd54d6c378 100644
--- a/config/settings/base.py
+++ b/config/settings/base.py
@@ -301,7 +301,7 @@ INSTALLED_APPS = [
     'django.contrib.messages',
     'maintenance_mode',
     'alerts',
-    'api'
+    'api',
     'events',
     'ligoauth',
     'search',
@@ -332,6 +332,11 @@ SHELL_PLUS_MODEL_ALIASES = {
 
 # Details used by REST API
 REST_FRAMEWORK = {
+    'DEFAULT_VERSIONING_CLASS':
+        'api.versioning.NestedNamespaceVersioning',
+        #'rest_framework.versioning.NamespaceVersioning',
+    'DEFAULT_VERSION': 'default',
+    'ALLOWED_VERSIONS': ['default', 'v1'],
     'DEFAULT_PAGINATION_CLASS':
         'rest_framework.pagination.LimitOffsetPagination',
     'PAGE_SIZE': 1e7,
@@ -340,11 +345,11 @@ REST_FRAMEWORK = {
         'annotation'    : '10/second',
     },
     'DEFAULT_AUTHENTICATION_CLASSES': (
-        'events.api.backends.LigoAuthentication',
+        'api.v1.backends.LigoAuthentication',
     ),
     'COERCE_DECIMAL_TO_STRING': False,
     'EXCEPTION_HANDLER':
-        'superevents.api.exceptions.gracedb_exception_handler',
+        'api.exceptions.gracedb_exception_handler',
     'DEFAULT_PERMISSION_CLASSES': (
         'rest_framework.permissions.IsAuthenticatedOrReadOnly',
     )
@@ -530,6 +535,11 @@ LOGGING = {
             'propagate': True,
             'level': LOG_LEVEL,
         },
+        'api': {
+            'handlers': ['debug_file','error_file'],
+            'propagate': True,
+            'level': LOG_LEVEL,
+        },
         'alerts': {
             'handlers': ['debug_file','error_file'],
             'propagate': True,
diff --git a/config/urls.py b/config/urls.py
index 4ea8f2ff0ddb5f990d87ba2fa98d99b90bb365f9..cbcc91d610aedc79fb7361b100b30ddc71016f83 100644
--- a/config/urls.py
+++ b/config/urls.py
@@ -42,12 +42,10 @@ urlpatterns = [
     url(r'^search/$', search.views.search, name="mainsearch"),
 
     # API URLs
-    url(r'^apibasic/', include('events.api.urls', app_name="api",
-        namespace="basic")),
-    url(r'^apiweb/', include('events.api.urls', app_name="api",
-        namespace="shib")),
-    url(r'^api/', include('events.api.urls', app_name="api",
-        namespace="x509")),
+    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
 
     # Uncomment the admin/doc line below and add 'django.contrib.admindocs'
     # to INSTALLED_APPS to enable admin documentation:
diff --git a/gracedb/alerts/superevent_utils.py b/gracedb/alerts/superevent_utils.py
index 3050afcdee0b6c7399898e64ea3f35bc1b1a1bdc..9579a420da6f11fe926e0b8512ed7ba52e0b10ea 100644
--- a/gracedb/alerts/superevent_utils.py
+++ b/gracedb/alerts/superevent_utils.py
@@ -3,7 +3,7 @@ from rest_framework.renderers import JSONRenderer
 
 from .main import issue_alerts
 from core.urls import build_absolute_uri
-from superevents.api.serializers import SupereventSerializer, \
+from api.v1.superevents.serializers import SupereventSerializer, \
     SupereventLogSerializer, SupereventLabelSerializer, \
     SupereventEMObservationSerializer, SupereventVOEventSerializer, \
     SupereventSignoffSerializer
diff --git a/gracedb/superevents/api/exceptions.py b/gracedb/api/exceptions.py
similarity index 100%
rename from gracedb/superevents/api/exceptions.py
rename to gracedb/api/exceptions.py
diff --git a/gracedb/api/urls.py b/gracedb/api/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..6e8f80038d348ef8e546fb287d4288b2768b8aa8
--- /dev/null
+++ b/gracedb/api/urls.py
@@ -0,0 +1,9 @@
+from django.conf.urls import url, include
+
+app_name = 'api'
+
+urlpatterns = [
+    url(r'^', include('api.v1.urls', namespace='default')),
+    url(r'^v1/', include('api.v1.urls', namespace='v1')),
+    #url(r'^v2/', include('api.v2.urls', namespace='v2')),
+]
diff --git a/gracedb/api/utils.py b/gracedb/api/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..129bec5252e70acdbb25fe49116a508b8b2c604b
--- /dev/null
+++ b/gracedb/api/utils.py
@@ -0,0 +1,86 @@
+import logging
+
+from django.urls import resolve
+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'
+
+
+def api_reverse(viewname, args=None, kwargs=None, request=None, format=None,
+    **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)
+        api_reverse('events:event-list')
+
+    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')
+        api_reverse('api:v1:events:event-list')
+        api_reverse('x509:default:events:event-list')
+        api_reverse('x509:v1:events:event-list')
+    """
+    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:
+        url = build_absolute_uri(url)
+   
+    return url 
diff --git a/gracedb/events/api/backends.py b/gracedb/api/v1/backends.py
similarity index 100%
rename from gracedb/events/api/backends.py
rename to gracedb/api/v1/backends.py
diff --git a/gracedb/events/api/fields.py b/gracedb/api/v1/events/fields.py
similarity index 94%
rename from gracedb/events/api/fields.py
rename to gracedb/api/v1/events/fields.py
index c1a3d0e39ce73f8db27102641dbc322481ffbbe5..9129160fa48c1376da2fb74965c245bd90cab622 100644
--- a/gracedb/events/api/fields.py
+++ b/gracedb/api/v1/events/fields.py
@@ -1,13 +1,19 @@
-from rest_framework import serializers
+from __future__ import absolute_import
+import logging
+
 from django.contrib.auth import get_user_model
 
-from ..models import Event
+from rest_framework import serializers
 
+from events.models import Event
+
+# Set up user model
 UserModel = get_user_model()
 
-import logging
+# Set up logger
 logger = logging.getLogger(__name__)
 
+
 class GenericField(serializers.Field):
     # Field, property, or callable of the object which will be used to
     # generate the representation of the object.
diff --git a/gracedb/events/api/__init__.py b/gracedb/api/v1/events/tests/__init__.py
similarity index 100%
rename from gracedb/events/api/__init__.py
rename to gracedb/api/v1/events/tests/__init__.py
diff --git a/gracedb/events/api/tests/mixins.py b/gracedb/api/v1/events/tests/mixins.py
similarity index 100%
rename from gracedb/events/api/tests/mixins.py
rename to gracedb/api/v1/events/tests/mixins.py
diff --git a/gracedb/events/api/throttles.py b/gracedb/api/v1/events/throttles.py
similarity index 100%
rename from gracedb/events/api/throttles.py
rename to gracedb/api/v1/events/throttles.py
diff --git a/gracedb/api/v1/events/urls.py b/gracedb/api/v1/events/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..e942dae6f68a70353dc36a55f8cb26dbc24cbfe5
--- /dev/null
+++ b/gracedb/api/v1/events/urls.py
@@ -0,0 +1,79 @@
+from django.conf.urls import url, include
+
+from .views import * 
+
+
+urlpatterns = [
+    # Event Resources
+    # events/[{graceid}[/{version}]]
+    url(r'^$', EventList.as_view(), name='event-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)$', EventDetail.as_view(),
+        name='event-detail'),
+
+    # Event Log Resources
+    # events/{graceid}/logs/[{logid}]
+    url(r'^(?P<graceid>[GEHMT]\d+)/log/$', EventLogList.as_view(),
+        name='eventlog-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/log/(?P<n>\d+)$',
+        EventLogDetail.as_view(), name='eventlog-detail'),
+
+    # VOEvent Resources
+    # events/{graceid}/voevent/[{serial_number}]
+    url(r'^(?P<graceid>[GEHMT]\d+)/voevent/$', VOEventList.as_view(),
+        name='voevent-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/voevent/(?P<n>\d+)$',
+        VOEventDetail.as_view(), name='voevent-detail'),
+
+    # EMBB Resources
+    # events/{graceid}/logs/[{logid}]
+    url(r'^(?P<graceid>[GEHMT]\d+)/embb/$', EMBBEventLogList.as_view(),
+        name='embbeventlog-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/embb/(?P<n>\d+)$',
+        EMBBEventLogDetail.as_view(), name='embbeventlog-detail'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/emobservation/$',
+        EMObservationList.as_view(), name='emobservation-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/emobservation/(?P<n>\d+)$',
+        EMObservationDetail.as_view(), name='emobservation-detail'),
+#    url(r'(?P<graceid>[GEHMT]\d+)/emobservation/(?P<n>\d+)/emfootprint/$',
+#        EMFootprintList.as_view(), name='emfootprint-list'),
+#    url(r'(?P<graceid>[GEHMT]\d+)/emobservation/(?P<n>\d+)/emfootprint/(?P<m>\d+)$',
+#        EMFootprintDetail.as_view(), name='emfootprint-detail'),
+
+    # Tag Resources
+    url(r'^(?P<graceid>[GEHMT]\d+)/tag/$', EventTagList.as_view(),
+        name='eventtag-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/tag/(?P<tagname>.+)$',
+        EventTagDetail.as_view(), name='eventtag-detail'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/log/(?P<n>\d+)/tag/$',
+        EventLogTagList.as_view(), name='eventlogtag-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/log/(?P<n>\d+)/tag/(?P<tagname>.+)$',
+        EventLogTagDetail.as_view(), name='eventlogtag-detail'),
+
+    # Permission Resources
+    url(r'^(?P<graceid>[GEHMT]\d+)/perms/$',
+        EventPermissionList.as_view(), name='eventpermission-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/perms/(?P<group_name>.+)/$', 
+        GroupEventPermissionList.as_view(), name='groupeventpermission-list'),
+    url(r'^(?P<graceid>[GEHMT]\d+)/perms/(?P<group_name>.+)/(?P<perm_shortname>\w+)$', 
+        GroupEventPermissionDetail.as_view(), name='groupeventpermission-detail'),
+
+    # Event File Resources
+    # events/{graceid}/files/[{filename}[/{version}]]
+    url(r'^(?P<graceid>\w[\d]+)/files/(?P<filename>.+)?$',
+        Files.as_view(), name="files"),
+
+    # Event Labels
+    # events/{graceid}/labels/[{label}]
+    url(r'^(?P<graceid>\w[\d]+)/labels/(?P<label>.+)?$',
+        EventLabel.as_view(), name="labels"),
+
+    # Event Neighbors
+    # events/{graceid}/neighbors/[?delta=(N|(N,N))]
+    url(r'^(?P<graceid>\w[\d]+)/neighbors/$', EventNeighbors.as_view(),
+        name="neighbors"),
+
+    # Operator Signoff Resources
+    url(r'^(?P<graceid>[GEHMT]\d+)/signoff/$',
+        OperatorSignoffList.as_view(), name='signoff-list'),
+
+]
diff --git a/gracedb/events/api/views.py b/gracedb/api/v1/events/views.py
similarity index 87%
rename from gracedb/events/api/views.py
rename to gracedb/api/v1/events/views.py
index d82b26b5367d50b9e0e8848a500cfa1e27937c64..61850f7680c379b04b26989bd44badb1917a4163 100644
--- a/gracedb/events/api/views.py
+++ b/gracedb/api/v1/events/views.py
@@ -1,93 +1,68 @@
-
-from django.http import HttpResponse, HttpResponseNotFound
-from django.http import HttpResponseForbidden, HttpResponseServerError
-from django.http.request import QueryDict
-from django.urls import reverse as django_reverse
+from __future__ import absolute_import
+import exceptions
+import json
+import logging
+import os
+import shutil
+import StringIO
+import urllib
 
 from django.conf import settings
-from django.utils.functional import wraps
-from django.db import IntegrityError
+from django.contrib.auth.models import User, Permission, Group as AuthGroup
+from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ValidationError
+from django.db import IntegrityError
+from django.http import HttpResponse, HttpResponseForbidden, \
+    HttpResponseNotFound, HttpResponseServerError
+from django.http.request import QueryDict
+from django.utils.functional import wraps
 
-from django.contrib.auth.models import User, Permission
-from django.contrib.auth.models import Group as AuthGroup
-from django.contrib.contenttypes.models import ContentType
+# Stuff for the LigoLwRenderer
+from glue.ligolw import ligolw
+# lsctables MUST be loaded before utils.
+from glue.ligolw import utils
+from glue.ligolw.utils import ligolw_add
+from glue.ligolw.ligolw import LIGOLWContentHandler
+from glue.ligolw.lsctables import use_in
+from guardian.models import GroupObjectPermission
+from rest_framework import authentication, parsers, serializers, status
+from rest_framework.permissions import IsAuthenticated, BasePermission, SAFE_METHODS
+from rest_framework.renderers import BaseRenderer, JSONRenderer, \
+    BrowsableAPIRenderer
+from rest_framework.response import Response
+from rest_framework.views import APIView
 
 from alerts.old_alert import issueAlertForUpdate
-from ..buildVOEvent import buildVOEvent, VOEventBuilderException
-from ..view_utils import BadFARRange, check_query_far_range
-from ..query import parseQuery, ParseException
-from ..models import Event, Group, Search, Pipeline, EventLog, Tag, Label, \
-    EMGroup, EMBBEventLog, EMSPECTRUM, VOEvent
-from ..view_logic import create_label, get_performance_info, delete_label, \
-    _createEventFromForm, create_eel, create_emobservation
-from ..view_utils import eventToDict, eventLogToDict, labelToDict, reverse, \
-    embbEventLogToDict, voeventToDict, emObservationToDict, signoffToDict, \
-    skymapViewerEMObservationToDict
-from ..forms import SimpleSearchForm
-from ..translator import handle_uploaded_data
-from ..forms import CreateEventForm
-from ..permission_utils import user_has_perm, filter_events_for_user, \
-    is_external, check_external_file_access
-
-from .backends import LigoAuthentication
-from .throttles import EventCreationThrottle, AnnotationThrottle
-
-from core.vfile import VersionedFile
 from core.http import check_and_serve_file
-
-from guardian.models import GroupObjectPermission
-
+from core.vfile import VersionedFile
+from events.buildVOEvent import buildVOEvent, VOEventBuilderException
+from events.forms import SimpleSearchForm, CreateEventForm
+from events.query import parseQuery, ParseException
+from events.models import Event, Group, Search, Pipeline, EventLog, Tag, \
+    Label, EMGroup, EMBBEventLog, EMSPECTRUM, VOEvent
+from events.permission_utils import user_has_perm, filter_events_for_user, \
+    is_external, check_external_file_access
+from events.translator import handle_uploaded_data
+from events.view_logic import create_label, get_performance_info, \
+    delete_label, _createEventFromForm, create_eel, create_emobservation
+from events.view_utils import eventToDict, eventLogToDict, labelToDict, \
+    embbEventLogToDict, voeventToDict, emObservationToDict, signoffToDict, \
+    skymapViewerEMObservationToDict, BadFARRange, check_query_far_range
 from superevents.models import Superevent
-from superevents.api.view_templates import construct_api_url_templates
-
-import os
-import urllib
-import shutil
-import exceptions
-import json
-
+from .throttles import EventCreationThrottle, AnnotationThrottle
+from ..backends import LigoAuthentication
+from ...utils import api_reverse
 
-import logging; logger = logging.getLogger(__name__)
-# 
-# for checking queries in the evnet that the user is external
-#
+# Set up logger
+logger = logging.getLogger(__name__)
 
-##################################################################
+# Set up content handler
+use_in(LIGOLWContentHandler)
 
+# For checking queries in the event that the user is external
 REST_FRAMEWORK_SETTINGS = getattr(settings, 'REST_FRAMEWORK', {})
 PAGINATE_BY = REST_FRAMEWORK_SETTINGS.get('PAGINATE_BY', 10)
 
-##################################################################
-# rest_framework
-from rest_framework import serializers, status
-from rest_framework.response import Response
-#from rest_framework.renderers import JSONRenderer, JSONPRenderer
-#from rest_framework.renderers import YAMLRenderer, XMLRenderer
-from rest_framework.renderers import BaseRenderer, JSONRenderer
-from rest_framework.renderers import BrowsableAPIRenderer
-from rest_framework import parsers      # YAMLParser, MultiPartParser
-from rest_framework.parsers import DataAndFiles
-
-from rest_framework.permissions import IsAuthenticated, BasePermission, SAFE_METHODS
-from rest_framework import authentication
-from rest_framework.views import APIView
-
-MAX_FAILED_OPEN_ATTEMPTS = 5
-
-
-
-##################################################################
-# Stuff for the LigoLwRenderer
-from glue.ligolw import ligolw
-# lsctables MUST be loaded before utils.
-from glue.ligolw import utils
-from glue.ligolw.utils import ligolw_add
-from glue.ligolw.ligolw import LIGOLWContentHandler
-from glue.ligolw.lsctables import use_in
-import StringIO
-
-use_in(LIGOLWContentHandler)
 
 #
 # A custom permission class for the EventDetail view. 
@@ -426,7 +401,7 @@ class EventList(APIView):
         rv['links'] = links
         rv['events'] = [eventToDict(e, request=request)
                 for e in events[start:start+count]]
-        baseuri = reverse('event-list', request=request)
+        baseuri = api_reverse('events:event-list', request=request)
 
         links['self'] = request.build_absolute_uri()
 
@@ -506,8 +481,8 @@ class EventList(APIView):
                 rv.update(eventToDict(event, request=request))
                 rv['warnings'] += warnings
                 response = Response(rv, status=status.HTTP_201_CREATED)
-                response["Location"] = reverse(
-                        'event-detail',
+                response["Location"] = api_reverse(
+                        'events:event-detail',
                         args=[event.graceid()],
                         request=request)
                 return response
@@ -531,7 +506,7 @@ class RawdataParser(parsers.BaseParser):
                 self.read = read
         files = { 'upload' : FakeFile("initial.data", stream.read) }
         data = {}
-        return DataAndFiles(data, files)
+        return parsers.DataAndFiles(data, files)
 
 class LigoLwParser(parsers.MultiPartParser):
     # XXX Revisit this.
@@ -678,7 +653,8 @@ class EventNeighbors(APIView):
                 'numRows' : len(neighbors),
                 'links' : {
                     'self': request.build_absolute_uri(),
-                    'event': reverse("event-detail", args=[event.graceid()], request=request),
+                    'event': api_reverse("events:event-detail",
+                        args=[event.graceid()], request=request),
                     }
                 })
 
@@ -707,7 +683,7 @@ class EventLabel(APIView):
             return Response({
                 'links' : [{
                     'self': request.build_absolute_uri(),
-                    'event': reverse("event-detail",
+                    'event': api_reverse("events:event-detail",
                         args=[event.graceid()],
                         request=request),
                     }],
@@ -1066,18 +1042,18 @@ def tagToDict(tag, columns=None, request=None, event=None, n=None):
         if n:
             # We want a link to the self only.  End of the line.
             rv['links'] = {
-                            "self" : reverse("eventlogtag-detail",
+                            "self" : api_reverse("events:eventlogtag-detail",
                                              args=[event.graceid(),n,tag.name],
                                              request=request)
                           }
         else:
             # Links to all log messages of the event with this tag.
             rv['links'] = {
-                            "logs" : [reverse("eventlog-detail", 
+                            "logs" : [api_reverse("events:eventlog-detail", 
                                               args=[event.graceid(),log.N], 
                                               request=request) 
                                       for log in event.getLogsForTag(tag.name)],
-                            "self" : reverse("eventtag-detail",
+                            "self" : api_reverse("events:eventtag-detail",
                                              args=[event.graceid(),tag.name],
                                              request=request)
                           }
@@ -1096,30 +1072,6 @@ def tagToDict(tag, columns=None, request=None, event=None, n=None):
 #                       }
     return rv
 
-class TagList(APIView):
-    """Tag List Resource
-    """
-    authentication_classes = (LigoAuthentication,)
-    permission_classes = (IsAuthenticated,)
-
-    def get(self, request):
-        # Return a list of links to all tag objects.
-        tag_dict = {}
-        for tag in Tag.objects.all():
-            tag_dict[tag.name] = { 
-                'displayName': tag.displayName,
-                'blessed': tag.name in settings.BLESSED_TAGS
-            }
-        rv = {
-#                 'tags' : [ reverse("tag-detail", args=[tag.name],
-#                                    request=request)
-#                            for tag in Tag.objects.all() ]
-#                For now, we just output the tag names, since we don't know what 
-#                tag-detail should look like.
-#                 'tags' : [ tag.name for tag in Tag.objects.all() ]
-                  'tags' : tag_dict,
-             }
-        return Response(rv)
 
 # XXX Unclear what the tag detail resource should be.
 # class TagDetail(APIView):
@@ -1151,8 +1103,8 @@ class EventTagList(APIView):
         rv = {
                 'tags' : [
                     {
-                        'self': reverse("eventtag-detail", args=[
-                            event.graceid(), tag.name], request=request),
+                        'self': api_reverse("events:eventtag-detail",
+                            args=[event.graceid(), tag.name], request=request),
                         'name': tag.name,
                         'displayName': tag.displayName
                     }
@@ -1189,8 +1141,8 @@ class EventLogTagList(APIView):
         rv = {
                 'tags' : [
                     {
-                        'self': reverse("eventlogtag-detail", args=[
-                            event.graceid(), eventlog.N, tag.name],
+                        'self': api_reverse("events:eventlogtag-detail",
+                            args=[event.graceid(), eventlog.N, tag.name],
                             request=request),
                         'name': tag.name,
                         'displayName': tag.displayName
@@ -1314,7 +1266,7 @@ def groupeventpermissionToDict(gop, event, request=None):
     rv['permission'] = perm_shortname
     # We want a link to the self only.  End of the line.
     rv['links'] = {
-                    "self" : reverse("groupeventpermission-detail",
+                    "self" : api_reverse("events:groupeventpermission-detail",
                                      args=[event.graceid(),gop.group.name,perm_shortname],
                                      request=request)
                   }
@@ -1342,7 +1294,7 @@ class EventPermissionList(APIView):
         out_dict = {}
         links['groupeventpermissions'] = out_dict
         for group in groups:
-            out_dict[group.name] = reverse("groupeventpermission-list", 
+            out_dict[group.name] = api_reverse("events:groupeventpermission-list", 
                 args=[event.graceid(),group.name], request=request) 
         return Response(rv, status=status.HTTP_200_OK)            
 
@@ -1501,105 +1453,6 @@ class GroupEventPermissionDetail(APIView):
         rv = {'message': 'Permission successfully deleted.'}
         return Response(rv, status=status.HTTP_200_OK)            
 
-#==================================================================
-# Root Resource
-
-class GracedbRoot(APIView):
-    """
-        Root of the Gracedb REST API
-    """
-    authentication_classes = (LigoAuthentication,)
-    permission_classes = (IsAuthenticated,)
-    parser_classes = ()
-    def get(self, request):
-        # XXX This seems like a scummy way to get a URI template.
-        # Is there better?
-        detail = reverse("event-detail", args=["G1200"], request=request)
-        detail = detail.replace("G1200", "{graceid}")
-        log = reverse("eventlog-list", args=["G1200"], request=request)
-        log = log.replace("G1200", "{graceid}")
-        log_detail = reverse("eventlog-detail", args=["G1200", "3333"],
-            request=request)
-        log_detail = log_detail.replace("G1200", "{graceid}")
-        log_detail = log_detail.replace("3333", "{N}")
-        voevent = reverse("voevent-list", args=["G1200"], request=request)
-        voevent = voevent.replace("G1200", "{graceid}")
-        voevent_detail = reverse("voevent-detail", args=["G1200", "3333"],
-            request=request)
-        voevent_detail = voevent_detail.replace("G1200", "{graceid}")
-        voevent_detail = voevent_detail.replace("3333", "{N}")
-        embb = reverse("embbeventlog-list", args=["G1200"], request=request)
-        embb = embb.replace("G1200", "{graceid}")
-        emo = reverse("emobservation-list", args=["G1200"], request=request)
-        emo = emo.replace("G1200", "{graceid}")
-        emo_detail = reverse("emobservation-detail", args=["G1200", "3333"],
-            request=request)
-        emo_detail= emo_detail.replace("G1200", "{graceid}")
-        emo_detail= emo_detail.replace("3333", "{N}")
-
-        files = reverse("files", args=["G1200", "filename"], request=request)
-        files = files.replace("G1200", "{graceid}")
-        files = files.replace("filename", "{filename}")
-
-        labels = reverse('labels', args=["G1200", "thelabel"], request=request)
-        labels = labels.replace("G1200", "{graceid}")
-        labels = labels.replace("thelabel", "{label}")
-
-        taglist = reverse("eventlogtag-list", args=["G1200", "0"], request=request)
-        taglist = taglist.replace("G1200", "{graceid}")
-        taglist = taglist.replace("0", "{N}")
-
-        tag = reverse("eventlogtag-detail", args=["G1200", "0", "tagname"], request=request)
-        tag = tag.replace("G1200", "{graceid}")
-        tag = tag.replace("0", "{N}")
-        tag = tag.replace("tagname", "{tag_name}")
-
-        signofflist = reverse("signoff-list", args=["G1200"], request=request)
-        signofflist = signofflist.replace("G1200", "{graceid}")
-
-        # XXX Need a template for the tag list?
-
-        templates = {
-                "event-detail-template" : detail,
-                "voevent-list-template" : voevent,
-                "voevent-detail-template" : voevent_detail,
-                "event-log-template" : log,
-                "event-log-detail-template" : log_detail,
-                "emobservation-list-template": emo,
-                "emobservation-detail-template": emo_detail,
-                "embb-event-log-template" : embb,
-                "event-label-template" : labels,
-                "files-template" : files,
-                "tag-template" : tag,
-                "taglist-template" : taglist,
-                "signoff-list-template": signofflist,
-                }
-
-        # Get superevent templates
-        superevent_templates = construct_api_url_templates(request)
-        templates.update(superevent_templates)
-
-        return Response({
-            "links" : {
-                "superevents" : reverse("superevents:superevent-list",
-                    request=request),
-                "events"      : reverse("event-list", request=request),
-                "self"        : reverse("api-root", request=request),
-                "performance" : reverse("performance-info", request=request),
-                },
-            "templates" : templates,
-            "groups"    : [group.name for group in Group.objects.all()],
-            "pipelines" : [pipeline.name for pipeline in Pipeline.objects.all()],
-            "searches"  : [search.name for search in Search.objects.all()],
-            "labels"    : [label.name for label in Label.objects.all()],
-            "em-groups"  : [g.name for g in EMGroup.objects.all()],
-            "wavebands"      : dict(EMSPECTRUM),
-            "eel-statuses"   : dict(EMBBEventLog.EEL_STATUS_CHOICES),
-            "obs-statuses"   : dict(EMBBEventLog.OBS_STATUS_CHOICES),
-            "superevent-categories": dict(Superevent.SUPEREVENT_CATEGORY_CHOICES),
-            "voevent-types"  : dict(VOEvent.VOEVENT_TYPE_CHOICES),
-        })
-
 
 class Files(APIView):
     """Files Resource"""
@@ -1659,10 +1512,10 @@ class Files(APIView):
 
             files = []
             for filename in fnames:
-                rv[filename] = reverse("files", args=[graceid, filename], request=request)
+                rv[filename] = api_reverse("events:files", args=[graceid, filename], request=request)
                 files.append({
                         'name' : filename,
-                        'link' :  reverse("files",
+                        'link' :  api_reverse("events:files",
                             args=[graceid, filename],
                             request=request),
                         })
@@ -1691,8 +1544,8 @@ class Files(APIView):
             # XXX this seems wobbly.
             longname = fdest.name
             shortname = longname[longname.rfind(filename):]
-            rv['permalink'] = reverse(
-                    "files", args=[event.graceid(), shortname], request=request)
+            rv['permalink'] = api_reverse(
+                    "events:files", args=[event.graceid(), shortname], request=request)
             response = Response(rv, status=status.HTTP_201_CREATED)
         except Exception, e:
             # XXX This needs some thought.
@@ -1731,35 +1584,6 @@ class Files(APIView):
 
         return response
 
-class PerformanceInfo(APIView):
-    """
-    Serialized performance information
-    """
-    authentication_classes = (LigoAuthentication,)
-    permission_classes = (IsAuthenticated,)
-    parser_classes = (parsers.MultiPartParser,)
-
-    def get(self, request, *args, **kwargs):
-        user_groups = set(request.user.groups.all())
-        allowed_groups = set([])
-        try:
-            allowed_groups = set([
-                AuthGroup.objects.get(name=settings.LVC_GROUP),
-                AuthGroup.objects.get(name=settings.EXEC_GROUP),
-            ])
-        except:
-            pass
-
-        if not user_groups & allowed_groups:
-            return HttpResponseForbidden("Forbidden")
-
-        try:
-            performance_info = get_performance_info()
-        except Exception, e:
-            return Response(str(e), status=status.HTTP_500_INTERNAL_SERVER_ERROR)
-
-        return Response(performance_info,status=status.HTTP_200_OK)
-
 
 #==================================================================
 # VOEvent Resources
diff --git a/gracedb/superevents/api/fields.py b/gracedb/api/v1/fields.py
similarity index 99%
rename from gracedb/superevents/api/fields.py
rename to gracedb/api/v1/fields.py
index 5f77531a7b75c1341401e47e0f8b446c28c15e54..fb378b95878dc2058e2b66e33e73036a351681aa 100644
--- a/gracedb/superevents/api/fields.py
+++ b/gracedb/api/v1/fields.py
@@ -1,7 +1,9 @@
+import logging
+import six
+
 from rest_framework import fields
 
-import six
-import logging
+# Set up logger
 logger = logging.getLogger(__name__)
 
 
diff --git a/gracedb/events/api/tests/__init__.py b/gracedb/api/v1/main/__init__.py
similarity index 100%
rename from gracedb/events/api/tests/__init__.py
rename to gracedb/api/v1/main/__init__.py
diff --git a/gracedb/api/v1/main/views.py b/gracedb/api/v1/main/views.py
new file mode 100644
index 0000000000000000000000000000000000000000..2a5a54ab6336c9bfc1db242579e7ff716309cf85
--- /dev/null
+++ b/gracedb/api/v1/main/views.py
@@ -0,0 +1,170 @@
+# Needed because our local events and superevents modules (for the API)
+# shadow the names of the events and superevents apps.
+from __future__ import absolute_import
+
+from django.conf import settings
+from django.contrib.auth.models import Group as AuthGroup
+from django.http import HttpResponse, HttpResponseForbidden
+
+from rest_framework import parsers, status
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.response import Response
+from rest_framework.reverse import reverse as drf_reverse
+from rest_framework.views import APIView
+
+from api.utils import api_reverse
+from events.models import Group, Pipeline, Search, Tag, Label, EMGroup, \
+    VOEvent, EMBBEventLog, EMSPECTRUM
+from events.view_logic import get_performance_info
+from superevents.models import Superevent
+from ..backends import LigoAuthentication
+from ..superevents.url_templates import construct_url_templates
+
+
+class TagList(APIView):
+    """Tag List Resource
+    """
+    authentication_classes = (LigoAuthentication,)
+    permission_classes = (IsAuthenticated,)
+
+    def get(self, request):
+        # Return a list of links to all tag objects.
+        tag_dict = {}
+        for tag in Tag.objects.all():
+            tag_dict[tag.name] = { 
+                'displayName': tag.displayName,
+                'blessed': tag.name in settings.BLESSED_TAGS
+            }
+        rv = {'tags' : tag_dict}
+        return Response(rv)
+
+
+class GracedbRoot(APIView):
+    """
+    Root of the Gracedb REST API
+    """
+    authentication_classes = (LigoAuthentication,)
+    permission_classes = (IsAuthenticated,)
+    parser_classes = ()
+
+    def get(self, request):
+        # XXX This seems like a scummy way to get a URI template.
+        # Is there better?
+        detail = api_reverse("events:event-detail", args=["G1200"], request=request)
+        detail = detail.replace("G1200", "{graceid}")
+        log = api_reverse("events:eventlog-list", args=["G1200"], request=request)
+        log = log.replace("G1200", "{graceid}")
+        log_detail = api_reverse("events:eventlog-detail", args=["G1200", "3333"],
+            request=request)
+        log_detail = log_detail.replace("G1200", "{graceid}")
+        log_detail = log_detail.replace("3333", "{N}")
+        voevent = api_reverse("events:voevent-list", args=["G1200"], request=request)
+        voevent = voevent.replace("G1200", "{graceid}")
+        voevent_detail = api_reverse("events:voevent-detail", args=["G1200", "3333"],
+            request=request)
+        voevent_detail = voevent_detail.replace("G1200", "{graceid}")
+        voevent_detail = voevent_detail.replace("3333", "{N}")
+        embb = api_reverse("events:embbeventlog-list", args=["G1200"], request=request)
+        embb = embb.replace("G1200", "{graceid}")
+        emo = api_reverse("events:emobservation-list", args=["G1200"], request=request)
+        emo = emo.replace("G1200", "{graceid}")
+        emo_detail = api_reverse("events:emobservation-detail", args=["G1200", "3333"],
+            request=request)
+        emo_detail= emo_detail.replace("G1200", "{graceid}")
+        emo_detail= emo_detail.replace("3333", "{N}")
+
+        files = api_reverse("events:files", args=["G1200", "filename"], request=request)
+        files = files.replace("G1200", "{graceid}")
+        files = files.replace("filename", "{filename}")
+
+        labels = api_reverse("events:labels", args=["G1200", "thelabel"], request=request)
+        labels = labels.replace("G1200", "{graceid}")
+        labels = labels.replace("thelabel", "{label}")
+
+        taglist = api_reverse("events:eventlogtag-list", args=["G1200", "0"], request=request)
+        taglist = taglist.replace("G1200", "{graceid}")
+        taglist = taglist.replace("0", "{N}")
+
+        tag = api_reverse("events:eventlogtag-detail", args=["G1200", "0", "tagname"], request=request)
+        tag = tag.replace("G1200", "{graceid}")
+        tag = tag.replace("0", "{N}")
+        tag = tag.replace("tagname", "{tag_name}")
+
+        signofflist = api_reverse("events:signoff-list", args=["G1200"], request=request)
+        signofflist = signofflist.replace("G1200", "{graceid}")
+
+        # XXX Need a template for the tag list?
+
+        templates = {
+                "event-detail-template" : detail,
+                "voevent-list-template" : voevent,
+                "voevent-detail-template" : voevent_detail,
+                "event-log-template" : log,
+                "event-log-detail-template" : log_detail,
+                "emobservation-list-template": emo,
+                "emobservation-detail-template": emo_detail,
+                "embb-event-log-template" : embb,
+                "event-label-template" : labels,
+                "files-template" : files,
+                "tag-template" : tag,
+                "taglist-template" : taglist,
+                "signoff-list-template": signofflist,
+                }
+
+        # Get superevent templates
+        superevent_templates = construct_url_templates(request)
+        templates.update(superevent_templates)
+
+        return Response({
+            "links" : {
+                "superevents" : api_reverse("superevents:superevent-list",
+                    request=request),
+                "events"      : api_reverse("events:event-list", request=request),
+                "self"        : api_reverse("root", request=request),
+                "performance" : api_reverse("performance-info", request=request),
+                },
+            "templates" : templates,
+            "groups"    : [group.name for group in Group.objects.all()],
+            "pipelines" : [pipeline.name for pipeline in
+                Pipeline.objects.all()],
+            "searches"  : [search.name for search in Search.objects.all()],
+            "labels"    : [label.name for label in Label.objects.all()],
+            "em-groups"  : [g.name for g in EMGroup.objects.all()],
+            "wavebands"      : dict(EMSPECTRUM),
+            "eel-statuses"   : dict(EMBBEventLog.EEL_STATUS_CHOICES),
+            "obs-statuses"   : dict(EMBBEventLog.OBS_STATUS_CHOICES),
+            "superevent-categories": 
+                dict(Superevent.SUPEREVENT_CATEGORY_CHOICES),
+            "voevent-types"  : dict(VOEvent.VOEVENT_TYPE_CHOICES),
+        })
+
+
+class PerformanceInfo(APIView):
+    """
+    Serialized performance information
+    """
+    authentication_classes = (LigoAuthentication,)
+    permission_classes = (IsAuthenticated,)
+    parser_classes = (parsers.MultiPartParser,)
+
+    def get(self, request, *args, **kwargs):
+        user_groups = set(request.user.groups.all())
+        allowed_groups = set([])
+        try:
+            allowed_groups = set([
+                AuthGroup.objects.get(name=settings.LVC_GROUP),
+                AuthGroup.objects.get(name=settings.EXEC_GROUP),
+            ])
+        except:
+            pass
+
+        if not user_groups & allowed_groups:
+            return HttpResponseForbidden("Forbidden")
+
+        try:
+            performance_info = get_performance_info()
+        except Exception, e:
+            return Response(str(e),
+                status=status.HTTP_500_INTERNAL_SERVER_ERROR)
+
+        return Response(performance_info, status=status.HTTP_200_OK)
diff --git a/gracedb/superevents/api/base_viewsets.py b/gracedb/api/v1/superevents/base_viewsets.py
similarity index 98%
rename from gracedb/superevents/api/base_viewsets.py
rename to gracedb/api/v1/superevents/base_viewsets.py
index d144924b0debb48418298ac20852b6288fe228da..59f13047e44fb709a009bf3f5bbefafa8fa3fca3 100644
--- a/gracedb/superevents/api/base_viewsets.py
+++ b/gracedb/api/v1/superevents/base_viewsets.py
@@ -5,9 +5,9 @@ from django.shortcuts import get_object_or_404
 from guardian.shortcuts import get_objects_for_user
 from rest_framework import viewsets
 
+from superevents.models import Superevent
+from superevents.utils import get_superevent_by_date_id_or_404
 from .settings import SUPEREVENT_LOOKUP_URL_KWARG
-from ..models import Superevent
-from ..utils import get_superevent_by_date_id_or_404
 
 # Set up logger
 logger = logging.getLogger(__name__)
diff --git a/gracedb/superevents/api/filters.py b/gracedb/api/v1/superevents/filters.py
similarity index 97%
rename from gracedb/superevents/api/filters.py
rename to gracedb/api/v1/superevents/filters.py
index 9f71f8e3dda14f7710b52f46b604e0c0f99663b7..85e974487c4783a57771375ca54ba5b364fc29b5 100644
--- a/gracedb/superevents/api/filters.py
+++ b/gracedb/api/v1/superevents/filters.py
@@ -1,13 +1,17 @@
-from rest_framework import filters, exceptions
+from __future__ import absolute_import
+import logging
+from pyparsing import ParseException
 
 from django.http import HttpResponseBadRequest
 
-from ..query import parseSupereventQuery
+from rest_framework import filters, exceptions
+
+from superevents.query import parseSupereventQuery
 
-from pyparsing import ParseException
-import logging
+# Set up logger
 logger = logging.getLogger(__name__)
 
+
 class SupereventSearchFilter(filters.SearchFilter):
     search_param = 'query'
 
diff --git a/gracedb/superevents/api/mixins.py b/gracedb/api/v1/superevents/mixins.py
similarity index 98%
rename from gracedb/superevents/api/mixins.py
rename to gracedb/api/v1/superevents/mixins.py
index bdf91b919926b4bee969207c6f4e23ea782605cd..0b487859983c99022acb87046f9a3a623a9e6129 100644
--- a/gracedb/superevents/api/mixins.py
+++ b/gracedb/api/v1/superevents/mixins.py
@@ -1,3 +1,4 @@
+from __future__ import absolute_import
 import logging
 
 from django.core.exceptions import ValidationError as DjangoValidationError
diff --git a/gracedb/superevents/api/paginators.py b/gracedb/api/v1/superevents/paginators.py
similarity index 99%
rename from gracedb/superevents/api/paginators.py
rename to gracedb/api/v1/superevents/paginators.py
index d30750d00b5986e831559664f1e51ddde61357f5..6fa5e67775bc13b30d876740eaa129d8dac0d330 100644
--- a/gracedb/superevents/api/paginators.py
+++ b/gracedb/api/v1/superevents/paginators.py
@@ -1,10 +1,11 @@
+from collections import OrderedDict
+import logging
+import urllib
+
 from rest_framework import pagination
 from rest_framework.response import Response
 
-import urllib
-from collections import OrderedDict
-
-import logging
+# Set up logger
 logger = logging.getLogger(__name__)
 
 # TP (30 Apr 2018):
diff --git a/gracedb/superevents/api/permissions.py b/gracedb/api/v1/superevents/permissions.py
similarity index 100%
rename from gracedb/superevents/api/permissions.py
rename to gracedb/api/v1/superevents/permissions.py
diff --git a/gracedb/superevents/api/serializers.py b/gracedb/api/v1/superevents/serializers.py
similarity index 95%
rename from gracedb/superevents/api/serializers.py
rename to gracedb/api/v1/superevents/serializers.py
index 9c8c66398b2052d3e3d62530afb8b0669bde1516..ea0c44081afb6b096a94e7212e6aac5d8994021e 100644
--- a/gracedb/superevents/api/serializers.py
+++ b/gracedb/api/v1/superevents/serializers.py
@@ -1,24 +1,28 @@
-from rest_framework import serializers, validators
-from rest_framework.exceptions import ValidationError
+from __future__ import absolute_import
+import functools
+import logging
+import os
+
+from django.conf import settings
 from django.contrib.auth import get_user_model
 from django.utils.translation import ugettext_lazy as _
-from django.conf import settings
-from ..models import Superevent, Labelling, Log, VOEvent, EMObservation, \
-    EMFootprint, Signoff
 
+from rest_framework import serializers, validators
+from rest_framework.exceptions import ValidationError
+
+from events.models import Event, Label, Tag, EMGroup
+from superevents.models import Superevent, Labelling, Log, VOEvent, \
+    EMObservation, EMFootprint, Signoff
 from .fields import ParentObjectDefault, CommaSeparatedOrListField, \
     ChoiceDisplayField
 from .settings import SUPEREVENT_LOOKUP_URL_KWARG
+from ..events.fields import EventGraceidField
+from ...utils import api_reverse
 
-from events.models import Event, Label, Tag, EMGroup
-from events.view_utils import reverse as gracedb_reverse
-from events.api.fields import EventGraceidField
-
+# Set up user model
 UserModel = get_user_model()
 
-import os
-import functools
-import logging
+# Set up logger
 logger = logging.getLogger(__name__)
 
 
@@ -94,7 +98,7 @@ class SupereventSerializer(serializers.ModelSerializer):
 
     def create(self, validated_data):
         # Function-level import to prevent circular import in alerts
-        from ..utils import create_superevent
+        from superevents.utils import create_superevent
         submitter = validated_data.pop('user')
 
         # TODO: 
@@ -110,7 +114,7 @@ class SupereventSerializer(serializers.ModelSerializer):
         return [ev.graceid() for ev in obj.get_external_events()]
 
     def get_links(self, obj):
-        bound_reverse = functools.partial(gracedb_reverse,
+        bound_reverse = functools.partial(api_reverse,
             args=[obj.superevent_id],
             request=self.context.get('request', None))
         link_dict = {
@@ -174,7 +178,7 @@ class SupereventUpdateSerializer(SupereventSerializer):
 
     def update(self, instance, validated_data):
         # Function-level import to prevent circular import in alerts
-        from ..utils import update_superevent
+        from superevents.utils import update_superevent
 
         # CurrentUserDefault doesn't work for PATCH requests since the
         # serializer has self.partial == True, the default function is never
@@ -208,7 +212,7 @@ class SupereventEventSerializer(serializers.ModelSerializer):
         fields = ('self', 'graceid', 'event', 'superevent', 'user')
 
     def get_self(self, obj):
-        return gracedb_reverse('event-detail', args=[obj.graceid()],
+        return api_reverse('events:event-detail', args=[obj.graceid()],
             request=self.context.get('request', None))
 
     def validate(self, data):
@@ -231,7 +235,7 @@ class SupereventEventSerializer(serializers.ModelSerializer):
 
     def create(self, validated_data):
         # Function-level import to prevent circular import in alerts
-        from ..utils import add_event_to_superevent
+        from superevents.utils import add_event_to_superevent
 
         superevent = validated_data.pop('superevent')
         event = validated_data.pop('event')
@@ -264,13 +268,13 @@ class SupereventLabelSerializer(serializers.ModelSerializer):
             'superevent')
 
     def get_self(self, obj):
-        return gracedb_reverse('superevents:superevent-label-detail', args=[
+        return api_reverse('superevents:superevent-label-detail', args=[
             obj.superevent.superevent_id, obj.label.name],
             request=self.context.get('request', None))
 
     def create(self, validated_data):
         # Function-level import to prevent circular import in alerts
-        from ..utils import add_label_to_superevent
+        from superevents.utils import add_label_to_superevent
 
         creator = validated_data.pop('submitter')
         superevent = validated_data.pop('superevent')
@@ -319,14 +323,14 @@ class SupereventLogSerializer(serializers.ModelSerializer):
         self.fields['file_version'].read_only = True
 
     def get_self(self, obj):
-        return gracedb_reverse('superevents:superevent-log-detail',
+        return api_reverse('superevents:superevent-log-detail',
             args=[obj.superevent.superevent_id, obj.N],
             request=self.context.get('request', None))
 
     def get_file(self, obj):
         link = None
         if obj.filename:
-            link = gracedb_reverse('superevents:superevent-file-detail',
+            link = api_reverse('superevents:superevent-file-detail',
                 args=[obj.superevent.superevent_id, obj.versioned_filename],
                 request=self.context.get('request', None))
         return link
@@ -343,7 +347,7 @@ class SupereventLogSerializer(serializers.ModelSerializer):
 
     def create(self, validated_data):
         # Function-level import to prevent circular import in alerts
-        from ..utils import create_log, get_or_create_tags
+        from superevents.utils import create_log, get_or_create_tags
 
         # TODO:
         # Check user permissions here, or somewhere else? Maybe just on viewset
@@ -391,7 +395,7 @@ class SupereventLogTagSerializer(serializers.ModelSerializer):
         superevent_id = self.context['view'].kwargs.get(
             SUPEREVENT_LOOKUP_URL_KWARG)
         log_N = self.context['view'].kwargs.get('N')
-        return gracedb_reverse('superevents:superevent-log-tag-detail',
+        return api_reverse('superevents:superevent-log-tag-detail',
             args=[superevent_id, log_N, obj.name],
             request=self.context.get('request', None))
 
@@ -423,7 +427,7 @@ class SupereventLogTagSerializer(serializers.ModelSerializer):
 
     def create(self, validated_data):
         # Function-level import to prevent circular import in alerts
-        from ..utils import add_tag_to_log, get_or_create_tag
+        from superevents.utils import add_tag_to_log, get_or_create_tag
 
         # Get parent log message
         parent_log = validated_data.pop('parent_log')
@@ -497,12 +501,12 @@ class SupereventVOEventSerializer(serializers.ModelSerializer):
         if obj.filename:
             file_name = "{name},{version}".format(name=obj.filename,
                 version=obj.file_version)
-            file_link = gracedb_reverse('superevents:superevent-file-detail',
+            file_link = api_reverse('superevents:superevent-file-detail',
                 args=[obj.superevent.superevent_id, file_name],
                 request=self.context.get('request', None))
 
         link_dict = {
-            'self': gracedb_reverse('superevents:superevent-voevent-detail',
+            'self': api_reverse('superevents:superevent-voevent-detail',
                 args=[obj.superevent.superevent_id, obj.N],
                 request=self.context.get('request', None)),
             'file': file_link,
@@ -553,8 +557,8 @@ class SupereventVOEventSerializer(serializers.ModelSerializer):
         return data
 
     def create(self, validated_data):
-
-        from ..utils import create_voevent_for_superevent
+        # Function-level import to prevent circular import in alerts
+        from superevents.utils import create_voevent_for_superevent
 
         # Pop some data
         superevent = validated_data.pop('superevent')
@@ -658,7 +662,7 @@ class SupereventEMObservationSerializer(serializers.ModelSerializer):
 
     def create(self, validated_data):
         # Function-level import to prevent circular import in alerts
-        from ..utils import create_emobservation_for_superevent
+        from superevents.utils import create_emobservation_for_superevent
 
         # Create EMObservation and EMFootprint set
         emo = create_emobservation_for_superevent(validated_data['superevent'],
diff --git a/gracedb/api/v1/superevents/settings.py b/gracedb/api/v1/superevents/settings.py
new file mode 100644
index 0000000000000000000000000000000000000000..8cf021f7df867d905b46107ad384dfaaa3102a78
--- /dev/null
+++ b/gracedb/api/v1/superevents/settings.py
@@ -0,0 +1,8 @@
+from __future__ import absolute_import
+
+from superevents.models import Superevent
+
+# Define superevent lookup URL kwarg and regex pattern for
+# use throughout this module
+SUPEREVENT_LOOKUP_URL_KWARG = 'superevent_id'
+SUPEREVENT_LOOKUP_REGEX = Superevent.ID_REGEX
diff --git a/gracedb/superevents/api/__init__.py b/gracedb/api/v1/superevents/tests/__init__.py
similarity index 100%
rename from gracedb/superevents/api/__init__.py
rename to gracedb/api/v1/superevents/tests/__init__.py
diff --git a/gracedb/superevents/api/tests/mixins.py b/gracedb/api/v1/superevents/tests/mixins.py
similarity index 94%
rename from gracedb/superevents/api/tests/mixins.py
rename to gracedb/api/v1/superevents/tests/mixins.py
index 409383e945587971a15fc77ea72a7938a74b69dd..28a4aa5597a515d6cb6ea2dabe4e7b18d536a141 100644
--- a/gracedb/superevents/api/tests/mixins.py
+++ b/gracedb/api/v1/superevents/tests/mixins.py
@@ -3,8 +3,8 @@ import os
 
 from django.contrib.auth import get_user_model
 
-from events.api.tests.mixins import EventCreateMixin
 from superevents.models import Superevent
+from ...events.tests.mixins import EventCreateMixin
 
 UserModel = get_user_model()
 
diff --git a/gracedb/superevents/api/tests/test_access.py b/gracedb/api/v1/superevents/tests/test_access.py
similarity index 90%
rename from gracedb/superevents/api/tests/test_access.py
rename to gracedb/api/v1/superevents/tests/test_access.py
index 06ea476cfa1affea0122886c38227f31ff163187..0650d334d8888a042d468145d5d1ea1f7338f837 100644
--- a/gracedb/superevents/api/tests/test_access.py
+++ b/gracedb/api/v1/superevents/tests/test_access.py
@@ -49,7 +49,7 @@ class TestSupereventListGet(SupereventSetup, GraceDbApiTestBase):
     @classmethod
     def setUpClass(cls):
         super(TestSupereventListGet, cls).setUpClass()
-        cls.url = reverse('api:superevents:superevent-list')
+        cls.url = reverse('api:default:superevents:superevent-list')
 
     def test_internal_user(self):
         """Internal user sees all superevents"""
@@ -132,7 +132,7 @@ class TestSupereventListPost(SupereventManagersGroupAndUserSetup,
     @classmethod
     def setUpClass(cls):
         super(TestSupereventListPost, cls).setUpClass()
-        cls.url = reverse('api:superevents:superevent-list')
+        cls.url = reverse('api:default:superevents:superevent-list')
 
     def test_basic_internal_production(self):
         """Basic internal user can't create a production superevent"""
@@ -257,7 +257,7 @@ class TestSupereventDetail(SupereventSetup, GraceDbApiTestBase):
         """Internal user can get all superevent details"""
         for s in Superevent.objects.all():
             # Set up URL
-            url = reverse('api:superevents:superevent-detail',
+            url = reverse('api:default:superevents:superevent-detail',
                 args=[s.superevent_id])
             # Get response and check code
             response = self.request_as_user(url, "GET",
@@ -272,7 +272,7 @@ class TestSupereventDetail(SupereventSetup, GraceDbApiTestBase):
         have not been added
         """
         # Set up URL
-        url = reverse('api:superevents:superevent-detail',
+        url = reverse('api:default:superevents:superevent-detail',
             args=[self.internal_superevent.superevent_id])
         # Get response and check code
         response = self.request_as_user(url, "GET", self.lvem_user)
@@ -285,7 +285,7 @@ class TestSupereventDetail(SupereventSetup, GraceDbApiTestBase):
         LV-EM user can GET this superevent since permissions have been added
         """
         # Set up URL
-        url = reverse('api:superevents:superevent-detail',
+        url = reverse('api:default:superevents:superevent-detail',
             args=[self.lvem_superevent.superevent_id])
         # Get response and check code
         response = self.request_as_user(url, "GET", self.lvem_user)
@@ -311,7 +311,7 @@ class TestSupereventDetail(SupereventSetup, GraceDbApiTestBase):
     def test_basic_internal_patch_production(self):
         """Basic internal user can't update production superevents"""
         # Define url, make request, and check response
-        url = reverse('api:superevents:superevent-detail',
+        url = reverse('api:default:superevents:superevent-detail',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "PATCH", self.internal_user,
             data={'t_0': 1234})
@@ -323,7 +323,7 @@ class TestSupereventDetail(SupereventSetup, GraceDbApiTestBase):
         s = self.create_superevent(self.internal_user, event_search='MDC',
             category=Superevent.SUPEREVENT_CATEGORY_MDC)
         # Define url, make request, and check response
-        url = reverse('api:superevents:superevent-detail',
+        url = reverse('api:default:superevents:superevent-detail',
             args=[s.superevent_id])
         response = self.request_as_user(url, "PATCH", self.internal_user,
             data={'t_0': 1234})
@@ -335,7 +335,7 @@ class TestSupereventDetail(SupereventSetup, GraceDbApiTestBase):
         s = self.create_superevent(self.internal_user, event_group='Test',
             category=Superevent.SUPEREVENT_CATEGORY_TEST)
         # Define url, make request, and check response
-        url = reverse('api:superevents:superevent-detail',
+        url = reverse('api:default:superevents:superevent-detail',
             args=[s.superevent_id])
         response = self.request_as_user(url, "PATCH", self.internal_user,
             data={'t_0': 1234})
@@ -373,21 +373,21 @@ class TestSupereventConfirmAsGw(SupereventManagersGroupAndUserSetup,
 
     def test_basic_internal_user_confirm_production(self):
         """Basic internal user can't confirm production superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.production_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user)
         self.assertEqual(response.status_code, 403)
 
     def test_basic_internal_user_confirm_mdc(self):
         """Basic internal user can't confirm MDC superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.mdc_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user)
         self.assertEqual(response.status_code, 403)
 
     def test_basic_internal_user_confirm_test(self):
         """Basic internal user can confirm test superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.test_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user)
         self.assertEqual(response.status_code, 200)
@@ -397,7 +397,7 @@ class TestSupereventConfirmAsGw(SupereventManagersGroupAndUserSetup,
 
     def test_privileged_internal_user_confirm_production(self):
         """Privileged internal user can confirm production superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.production_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.sm_user)
         self.assertEqual(response.status_code, 200)
@@ -407,7 +407,7 @@ class TestSupereventConfirmAsGw(SupereventManagersGroupAndUserSetup,
 
     def test_privileged_internal_user_confirm_mdc(self):
         """Privileged internal user can confirm MDC superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.mdc_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.sm_user)
         self.assertEqual(response.status_code, 200)
@@ -417,7 +417,7 @@ class TestSupereventConfirmAsGw(SupereventManagersGroupAndUserSetup,
 
     def test_privileged_internal_user_confirm_test(self):
         """Privileged internal user can confirm test superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.test_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.sm_user)
         self.assertEqual(response.status_code, 200)
@@ -427,7 +427,7 @@ class TestSupereventConfirmAsGw(SupereventManagersGroupAndUserSetup,
 
     def test_lvem_user_confirm_production(self):
         """LV-EM user can't confirm production superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.production_superevent.superevent_id])
 
         # Make request and check response
@@ -442,7 +442,7 @@ class TestSupereventConfirmAsGw(SupereventManagersGroupAndUserSetup,
 
     def test_lvem_user_confirm_mdc(self):
         """LV-EM user can't confirm mdc superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.mdc_superevent.superevent_id])
 
         # Make request and check response
@@ -457,7 +457,7 @@ class TestSupereventConfirmAsGw(SupereventManagersGroupAndUserSetup,
 
     def test_lvem_user_confirm_test(self):
         """LV-EM user can't confirm test superevent as GW"""
-        url = reverse('api:superevents:superevent-confirm-as-gw',
+        url = reverse('api:default:superevents:superevent-confirm-as-gw',
             args=[self.test_superevent.superevent_id])
 
         # Make request and check response
@@ -476,7 +476,7 @@ class TestSupereventConfirmAsGw(SupereventManagersGroupAndUserSetup,
         superevents = [self.production_superevent, self.test_superevent,
             self.mdc_superevent]
         for s in superevents:
-            url = reverse('api:superevents:superevent-confirm-as-gw',
+            url = reverse('api:default:superevents:superevent-confirm-as-gw',
                 args=[s.superevent_id])
             response = self.request_as_user(url, "POST")
             self.assertEqual(response.status_code, 403)
@@ -508,7 +508,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
         """Internal user sees all labels for all superevents"""
         for s in Superevent.objects.all():
             # Set up URL
-            url = reverse('api:superevents:superevent-label-list',
+            url = reverse('api:default:superevents:superevent-label-list',
                 args=[s.superevent_id])
             # Get response and check code
             response = self.request_as_user(url, "GET",
@@ -523,7 +523,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_get_no_view_perms(self):
         """LV-EM user can't see labels for internal-only superevent"""
-        url = reverse('api:superevents:superevent-label-list',
+        url = reverse('api:default:superevents:superevent-label-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         # Should get 404 response - because of filtering, this object
@@ -532,7 +532,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_get_with_view_perms(self):
         """LV-EM user can see labels for exposed superevent"""
-        url = reverse('api:superevents:superevent-label-list',
+        url = reverse('api:default:superevents:superevent-label-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -547,7 +547,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
         """Public user can't see labels for non-public superevents"""
         # TODO: these errors will be 404 in the future
         # Test internal superevent
-        url = reverse('api:superevents:superevent-label-list',
+        url = reverse('api:default:superevents:superevent-label-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET")
         # Should get 404 response - because of filtering, this object
@@ -555,7 +555,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
         self.assertEqual(response.status_code, 403)
 
         # Test LV-EM superevent
-        url = reverse('api:superevents:superevent-label-list',
+        url = reverse('api:default:superevents:superevent-label-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET")
         # Should get 404 response - because of filtering, this object
@@ -571,7 +571,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
         """Internal user can add labels to all superevents"""
         label, _ = Label.objects.get_or_create(name='NEW_LABEL')
         for s in Superevent.objects.all():
-            url = reverse('api:superevents:superevent-label-list',
+            url = reverse('api:default:superevents:superevent-label-list',
                 args=[s.superevent_id])
             data = {'name': label.name}
             response = self.request_as_user(url, "POST", self.internal_user,
@@ -586,7 +586,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
         label, _ = Label.objects.get_or_create(name='NEW_LABEL')
 
         # Internal-only superevent - should get 404
-        url = reverse('api:superevents:superevent-label-list',
+        url = reverse('api:default:superevents:superevent-label-list',
             args=[self.internal_superevent.superevent_id])
         data = {'name': label.name}
         response = self.request_as_user(url, "POST", self.lvem_user,
@@ -594,7 +594,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
         self.assertEqual(response.status_code, 404)
 
         # LV-EM superevent - should get 403
-        url = reverse('api:superevents:superevent-label-list',
+        url = reverse('api:default:superevents:superevent-label-list',
             args=[self.lvem_superevent.superevent_id])
         data = {'name': label.name}
         response = self.request_as_user(url, "POST", self.lvem_user,
@@ -607,7 +607,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
 
         # Internal-only superevent - should get 404
         # TODO: eventually this will be a 404, 403 for now
-        url = reverse('api:superevents:superevent-label-list',
+        url = reverse('api:default:superevents:superevent-label-list',
             args=[self.internal_superevent.superevent_id])
         data = {'name': label.name}
         response = self.request_as_user(url, "POST", data=data)
@@ -615,7 +615,7 @@ class TestSupereventLabelList(SupereventSetup, GraceDbApiTestBase):
 
         # LV-EM superevent - should get 404
         # TODO: eventually this will be a 404, 403 for now
-        url = reverse('api:superevents:superevent-label-list',
+        url = reverse('api:default:superevents:superevent-label-list',
             args=[self.lvem_superevent.superevent_id])
         data = {'name': label.name}
         response = self.request_as_user(url, "POST", data=data)
@@ -649,7 +649,7 @@ class TestSupereventLabelDetail(SupereventSetup, GraceDbApiTestBase):
         for s in Superevent.objects.all():
             for l in s.labels.all():
             # Set up URL
-                url = reverse('api:superevents:superevent-label-detail',
+                url = reverse('api:default:superevents:superevent-label-detail',
                     args=[s.superevent_id, l.name])
                 # Get response and check code
                 response = self.request_as_user(url, "GET",
@@ -661,7 +661,7 @@ class TestSupereventLabelDetail(SupereventSetup, GraceDbApiTestBase):
     def test_lvem_get_no_view_perms(self):
         """LV-EM user can't see labels for internal-only superevent"""
         for l in self.internal_superevent.labels.all():
-            url = reverse('api:superevents:superevent-label-detail',
+            url = reverse('api:default:superevents:superevent-label-detail',
                 args=[self.internal_superevent.superevent_id, l.name])
             response = self.request_as_user(url, "GET", self.lvem_user)
             # Should get 404 response - because of filtering, the superevent
@@ -671,7 +671,7 @@ class TestSupereventLabelDetail(SupereventSetup, GraceDbApiTestBase):
     def test_lvem_get_with_view_perms(self):
         """LV-EM user can see all labels for exposed superevent"""
         for l in self.lvem_superevent.labels.all():
-            url = reverse('api:superevents:superevent-label-detail',
+            url = reverse('api:default:superevents:superevent-label-detail',
                 args=[self.lvem_superevent.superevent_id, l.name])
             response = self.request_as_user(url, "GET", self.lvem_user)
             self.assertEqual(response.status_code, 200)
@@ -683,14 +683,14 @@ class TestSupereventLabelDetail(SupereventSetup, GraceDbApiTestBase):
         # TODO: these errors will be 404 in the future
         # Test internal superevent
         for l in self.internal_superevent.labels.all():
-            url = reverse('api:superevents:superevent-label-detail',
+            url = reverse('api:default:superevents:superevent-label-detail',
                 args=[self.internal_superevent.superevent_id, l.name])
             response = self.request_as_user(url, "GET")
             self.assertEqual(response.status_code, 403)
         
         # Test LV-EM superevent
         for l in self.lvem_superevent.labels.all():
-            url = reverse('api:superevents:superevent-label-detail',
+            url = reverse('api:default:superevents:superevent-label-detail',
                 args=[self.lvem_superevent.superevent_id, l.name])
             response = self.request_as_user(url, "GET")
             self.assertEqual(response.status_code, 403)
@@ -704,7 +704,7 @@ class TestSupereventLabelDetail(SupereventSetup, GraceDbApiTestBase):
         """Internal user can remove labels from all superevents"""
         for s in Superevent.objects.all():
             for l in s.labels.all():
-                url = reverse('api:superevents:superevent-label-detail',
+                url = reverse('api:default:superevents:superevent-label-detail',
                     args=[s.superevent_id, l.name])
                 response = self.request_as_user(url, "DELETE",
                     self.internal_user)
@@ -715,20 +715,20 @@ class TestSupereventLabelDetail(SupereventSetup, GraceDbApiTestBase):
         """LV-EM user cannot remove labels from any superevents"""
         # Internal superevent - should get 404
         for l in self.internal_superevent.labels.all():
-            url = reverse('api:superevents:superevent-label-detail',
+            url = reverse('api:default:superevents:superevent-label-detail',
                 args=[self.internal_superevent.superevent_id, l.name])
             response = self.request_as_user(url, "DELETE", self.lvem_user)
             self.assertEqual(response.status_code, 404)
         # Try to delete a label that doesn't exist to ensure there is no
         # information leaked that way.
-        url = reverse('api:superevents:superevent-label-detail',
+        url = reverse('api:default:superevents:superevent-label-detail',
             args=[self.internal_superevent.superevent_id, 'FAKE_LABEL'])
         response = self.request_as_user(url, "DELETE", self.lvem_user)
         self.assertEqual(response.status_code, 404)
 
         # LV-EM superevent - should get 403
         for l in self.lvem_superevent.labels.all():
-            url = reverse('api:superevents:superevent-label-detail',
+            url = reverse('api:default:superevents:superevent-label-detail',
                 args=[self.lvem_superevent.superevent_id, l.name])
             response = self.request_as_user(url, "DELETE", self.lvem_user)
             self.assertEqual(response.status_code, 403)
@@ -737,21 +737,21 @@ class TestSupereventLabelDetail(SupereventSetup, GraceDbApiTestBase):
         """Public user cannot remove labels from any superevents"""
         # Internal superevent - should get 404 (TODO: 403 for now)
         for l in self.internal_superevent.labels.all():
-            url = reverse('api:superevents:superevent-label-detail',
+            url = reverse('api:default:superevents:superevent-label-detail',
                 args=[self.internal_superevent.superevent_id, l.name])
             response = self.request_as_user(url, "DELETE")
             self.assertEqual(response.status_code, 403)
 
         # Try to delete a label that doesn't exist to ensure there is no
         # information leaked that way. (TODO: 403 for now, will be 404)
-        url = reverse('api:superevents:superevent-label-detail',
+        url = reverse('api:default:superevents:superevent-label-detail',
             args=[self.internal_superevent.superevent_id, 'FAKE_LABEL'])
         response = self.request_as_user(url, "DELETE")
         self.assertEqual(response.status_code, 403)
 
         # LV-EM superevent - should get 404 (TODO: 403 for now)
         for l in self.lvem_superevent.labels.all():
-            url = reverse('api:superevents:superevent-label-detail',
+            url = reverse('api:default:superevents:superevent-label-detail',
                 args=[self.lvem_superevent.superevent_id, l.name])
             response = self.request_as_user(url, "DELETE")
             self.assertEqual(response.status_code, 403)
@@ -784,7 +784,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
         """Internal user sees all events for superevents"""
         for s in Superevent.objects.all():
             # Set up URL
-            url = reverse('api:superevents:superevent-event-list',
+            url = reverse('api:default:superevents:superevent-event-list',
                 args=[s.superevent_id])
             # Get response and check code
             response = self.request_as_user(url, "GET", self.internal_user)
@@ -797,7 +797,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
 
     def test_lvem_get_no_view_perms(self):
         """LV-EM user can't see events for internal-only superevent"""
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         # Should get 404 response - because of filtering, this object
@@ -808,7 +808,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
         """LV-EM user can see events for exposed superevent"""
         # TODO: do we deal with permissions on events too? i.e.,
         #       don't show events in the list if they aren't exposed?
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -823,7 +823,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
     def test_public_get_no_view_perms(self):
         """Public user can't see events for non-public superevents"""
         # Internal superevent
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET")
         # Should get 404 response - because of filtering, this object
@@ -831,7 +831,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
         self.assertEqual(response.status_code, 403)
 
         # LV-EM superevent
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET")
         # Should get 404 response - because of filtering, this object
@@ -851,7 +851,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
             user=self.internal_user)
 
         # Set up URL, make request, check response code
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user,
             data={'event': ev.graceid()})
@@ -866,7 +866,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
             search_name='MDC', user=self.internal_user)
 
         # Set up URL, make request, check response code
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[s.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user,
             data={'event': ev.graceid()})
@@ -881,7 +881,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
             user=self.internal_user)
 
         # Set up URL, make request, check response code and data
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[s.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user,
             data={'event': ev.graceid()})
@@ -895,7 +895,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
             user=self.internal_user)
 
         # Set up URL, make request, check response code
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.sm_user,
             data={'event': ev.graceid()})
@@ -911,7 +911,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
             search_name='MDC', user=self.internal_user)
 
         # Set up URL, make request, check response code
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[s.superevent_id])
         response = self.request_as_user(url, "POST", self.sm_user,
             data={'event': ev.graceid()})
@@ -927,7 +927,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
             user=self.internal_user)
 
         # Set up URL, make request, check response code and data
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[s.superevent_id])
         response = self.request_as_user(url, "POST", self.sm_user,
             data={'event': ev.graceid()})
@@ -942,7 +942,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
 
         # Set up URL, make request, check response code
         # Should be 404 since superevent is not exposed
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data={'event': ev.graceid()})
@@ -963,7 +963,7 @@ class TestSupereventEventList(SupereventManagersGroupAndUserSetup,
 
         # Set up URL, make request, check response code
         # Should be 404 since superevent is not exposed
-        url = reverse('api:superevents:superevent-event-list',
+        url = reverse('api:default:superevents:superevent-event-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST",
             data={'event': ev.graceid()})
@@ -996,7 +996,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         for s in Superevent.objects.all():
             for ev in s.events.all():
                 # Set up URL
-                url = reverse('api:superevents:superevent-event-detail',
+                url = reverse('api:default:superevents:superevent-event-detail',
                     args=[s.superevent_id, ev.graceid()])
                 # Get response and check code
                 response = self.request_as_user(url, "GET", self.internal_user)
@@ -1007,7 +1007,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
     def test_lvem_get_no_view_perms(self):
         """LV-EM user can't see events for internal-only superevent"""
         for ev in self.internal_superevent.events.all():
-            url = reverse('api:superevents:superevent-event-detail',
+            url = reverse('api:default:superevents:superevent-event-detail',
                 args=[self.internal_superevent.superevent_id, ev.graceid()])
             response = self.request_as_user(url, "GET", self.lvem_user)
             # Should get 404 response - because of filtering, this superevent
@@ -1019,7 +1019,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         # TODO: do we deal with permissions on events too? i.e.,
         #       don't show events in the list if they aren't exposed?
         for ev in self.lvem_superevent.events.all():
-            url = reverse('api:superevents:superevent-event-detail',
+            url = reverse('api:default:superevents:superevent-event-detail',
                 args=[self.lvem_superevent.superevent_id, ev.graceid()])
             response = self.request_as_user(url, "GET", self.lvem_user)
             self.assertEqual(response.status_code, 200)
@@ -1030,7 +1030,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         """Public user can't see events for non-public superevents"""
         # Internal superevent
         for ev in self.internal_superevent.events.all():
-            url = reverse('api:superevents:superevent-event-detail',
+            url = reverse('api:default:superevents:superevent-event-detail',
                 args=[self.internal_superevent.superevent_id, ev.graceid()])
             response = self.request_as_user(url, "GET")
             # Should get 404 response - because of filtering, this superevent
@@ -1039,7 +1039,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
             # NOTE: will be a 404 error in the future
 
         for ev in self.lvem_superevent.events.all():
-            url = reverse('api:superevents:superevent-event-detail',
+            url = reverse('api:default:superevents:superevent-event-detail',
                 args=[self.lvem_superevent.superevent_id, ev.graceid()])
             response = self.request_as_user(url, "GET")
             # Should get 404 response - because of filtering, this superevent
@@ -1056,7 +1056,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         """
         Basic internal user can't remove events from production superevents.
         """
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[self.internal_superevent.superevent_id,
             self.event1.graceid()])
         response = self.request_as_user(url, "DELETE", self.internal_user)
@@ -1074,7 +1074,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         s.events.add(ev)
 
         # Set up URL, make request, check response code
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[s.superevent_id, ev.graceid()])
         response = self.request_as_user(url, "DELETE", self.internal_user)
         self.assertEqual(response.status_code, 403)
@@ -1091,7 +1091,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         s.events.add(ev)
 
         # Set up URL, make request, check response code
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[s.superevent_id, ev.graceid()])
         response = self.request_as_user(url, "DELETE", self.internal_user)
         self.assertEqual(response.status_code, 204)
@@ -1100,7 +1100,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         """
         Privileged internal user can remove events from production superevents.
         """
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[self.internal_superevent.superevent_id,
             self.event1.graceid()])
         response = self.request_as_user(url, "DELETE", self.sm_user)
@@ -1118,7 +1118,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         s.events.add(ev)
 
         # Set up URL, make request, check response code
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[s.superevent_id, ev.graceid()])
         response = self.request_as_user(url, "DELETE", self.sm_user)
         self.assertEqual(response.status_code, 204)
@@ -1135,7 +1135,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         s.events.add(ev)
 
         # Set up URL, make request, check response code
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[s.superevent_id, ev.graceid()])
         response = self.request_as_user(url, "DELETE", self.sm_user)
         self.assertEqual(response.status_code, 204)
@@ -1143,14 +1143,14 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
     def test_lvem_user_remove_event_from_superevent(self):
         """LV-EM user can't remove events from hidden or exposed superevents"""
         # Internal superevent
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[self.internal_superevent.superevent_id,
             self.event1.graceid()])
         response = self.request_as_user(url, "DELETE", self.lvem_user)
         self.assertEqual(response.status_code, 404)
 
         # Exposed superevent
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[self.lvem_superevent.superevent_id,
             self.event2.graceid()])
         response = self.request_as_user(url, "DELETE", self.lvem_user)
@@ -1161,7 +1161,7 @@ class TestSupereventEventDetail(SupereventManagersGroupAndUserSetup,
         Public user can't remove events from hidden or exposed superevents
         """
         # Internal superevent
-        url = reverse('api:superevents:superevent-event-detail',
+        url = reverse('api:default:superevents:superevent-event-detail',
             args=[self.internal_superevent.superevent_id,
             self.event1.graceid()])
         response = self.request_as_user(url, "DELETE")
@@ -1195,7 +1195,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
 
     def test_internal_user_get(self):
         """Internal user can see all logs for a superevent"""
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.internal_user)
         self.assertEqual(response.status_code, 200)
@@ -1206,14 +1206,14 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         """LV-EM user can't see any logs for hidden superevent"""
         # Internal superevent even has one log exposed to LV-EM,
         # but still shouldn't be able to see it
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 404)
 
     def test_lvem_user_get_for_exposed_superevent(self):
         """LV-EM user can see only exposed logs for exposed superevent"""
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -1230,7 +1230,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         """Internal user can create logs for all superevents"""
         log_data = {'comment': 'test comment'}
         for s in Superevent.objects.all():
-            url = reverse('api:superevents:superevent-log-list',
+            url = reverse('api:default:superevents:superevent-log-list',
                 args=[s.superevent_id])
             response = self.request_as_user(url, "POST", self.internal_user,
                 data=log_data)
@@ -1245,7 +1245,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
             'tagname': ['tag1', 'tag2']
         }
         for s in Superevent.objects.all():
-            url = reverse('api:superevents:superevent-log-list',
+            url = reverse('api:default:superevents:superevent-log-list',
                 args=[s.superevent_id])
             response = self.request_as_user(url, "POST", self.internal_user,
                 data=log_data)
@@ -1267,7 +1267,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         Tag.objects.create(name=settings.EXTERNAL_ACCESS_TAGNAME)
 
         # Make request
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user,
             data=log_data)
@@ -1287,7 +1287,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         Tag.objects.create(name=settings.PUBLIC_ACCESS_TAGNAME)
 
         # Make request
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user,
             data=log_data)
@@ -1307,7 +1307,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         Tag.objects.create(name=settings.EXTERNAL_ACCESS_TAGNAME)
 
         # Make request
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.am_user,
             data=log_data)
@@ -1330,7 +1330,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         Tag.objects.create(name=settings.EXTERNAL_ACCESS_TAGNAME)
 
         # Make request
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.am_user,
             data=log_data)
@@ -1347,7 +1347,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         log_data = {'comment': 'test comment'}
 
         # Internal-only superevent
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data=log_data)
@@ -1356,7 +1356,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         self.assertEqual(response.status_code, 404)
 
         # LV-EM exposed superevent
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data=log_data)
@@ -1369,7 +1369,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         log_data = {'comment': 'test comment', 'tagname': ['test_tag']}
 
         # Post to hidden superevent, should get 404
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data=log_data)
@@ -1377,7 +1377,7 @@ class TestSupereventLogList(AccessManagersGroupAndUserSetup,
         self.assertEqual(response.status_code, 404)
 
         # Post to exposed superevent
-        url = reverse('api:superevents:superevent-log-list',
+        url = reverse('api:default:superevents:superevent-log-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data=log_data)
@@ -1423,7 +1423,7 @@ class TestSupereventLogDetail(SupereventSetup, GraceDbApiTestBase):
         """Internal user can see all logs for all superevents"""
         for s in Superevent.objects.all():
             for l in s.log_set.all():
-                url = reverse('api:superevents:superevent-log-detail',
+                url = reverse('api:default:superevents:superevent-log-detail',
                     args=[self.internal_superevent.superevent_id, l.N])
                 response = self.request_as_user(url, "GET",
                     self.internal_user)
@@ -1436,7 +1436,7 @@ class TestSupereventLogDetail(SupereventSetup, GraceDbApiTestBase):
         # Internal superevent even has one log exposed to LV-EM,
         # but still shouldn't be able to see it
         for l in self.internal_superevent.log_set.all():
-            url = reverse('api:superevents:superevent-log-detail',
+            url = reverse('api:default:superevents:superevent-log-detail',
                 args=[self.internal_superevent.superevent_id, l.N])
             response = self.request_as_user(url, "GET", self.lvem_user)
             self.assertEqual(response.status_code, 404)
@@ -1444,7 +1444,7 @@ class TestSupereventLogDetail(SupereventSetup, GraceDbApiTestBase):
     def test_lvem_user_get_for_exposed_superevent(self):
         """LV-EM user can see only exposed logs for exposed superevent"""
         for l in self.lvem_superevent.log_set.all():
-            url = reverse('api:superevents:superevent-log-detail',
+            url = reverse('api:default:superevents:superevent-log-detail',
                 args=[self.lvem_superevent.superevent_id, l.N])
             response = self.request_as_user(url, "GET", self.lvem_user)
 
@@ -1461,7 +1461,7 @@ class TestSupereventLogDetail(SupereventSetup, GraceDbApiTestBase):
         """Public user can't get log detail for hidden superevent"""
         # TODO: add public log to superevent
         for l in self.internal_superevent.log_set.all():
-            url = reverse('api:superevents:superevent-log-detail',
+            url = reverse('api:default:superevents:superevent-log-detail',
                 args=[self.internal_superevent.superevent_id, l.N])
             response = self.request_as_user(url, "GET")
             # TODO: will be 404 in the future
@@ -1512,7 +1512,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
         """Internal user can get all tags for all logs for all superevents"""
         for s in Superevent.objects.all():
             for l in s.log_set.all():
-                url = reverse('api:superevents:superevent-log-tag-list',
+                url = reverse('api:default:superevents:superevent-log-tag-list',
                     args=[s.superevent_id, l.N])
                 # Make request
                 response = self.request_as_user(url, "GET", self.internal_user)
@@ -1531,7 +1531,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
     def test_lvem_get_for_hidden_superevent(self):
         """LV-EM user can't get tags for any logs on hidden superevent"""
         for l in self.internal_superevent.log_set.all():
-            url = reverse('api:superevents:superevent-log-tag-list',
+            url = reverse('api:default:superevents:superevent-log-tag-list',
                 args=[self.internal_superevent.superevent_id, l.N])
             # Make request
             response = self.request_as_user(url, "GET", self.lvem_user)
@@ -1543,7 +1543,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
         LV-EM user can only get tags for exposed logs on exposed superevent
         """
         for l in self.lvem_superevent.log_set.all():
-            url = reverse('api:superevents:superevent-log-tag-list',
+            url = reverse('api:default:superevents:superevent-log-tag-list',
                 args=[self.lvem_superevent.superevent_id, l.N])
             # Make request
             response = self.request_as_user(url, "GET", self.lvem_user)
@@ -1561,7 +1561,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
     def test_public_get_for_hidden_superevent(self):
         """Public user can't get tags for any logs on hidden superevent"""
         for l in self.internal_superevent.log_set.all():
-            url = reverse('api:superevents:superevent-log-tag-list',
+            url = reverse('api:default:superevents:superevent-log-tag-list',
                 args=[self.internal_superevent.superevent_id, l.N])
             # Make request
             response = self.request_as_user(url, "GET")
@@ -1581,7 +1581,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
         tag = Tag.objects.create(name='new_tag')
         for s in Superevent.objects.all():
             for l in s.log_set.all():
-                url = reverse('api:superevents:superevent-log-tag-list',
+                url = reverse('api:default:superevents:superevent-log-tag-list',
                     args=[s.superevent_id, l.N])
                 response = self.request_as_user(url, "POST",
                     self.internal_user, data={'name': tag.name})
@@ -1599,7 +1599,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
             superevent=self.internal_superevent, comment='test')
 
         # Make request
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.internal_superevent.superevent_id, log.N])
         response = self.request_as_user(url, "POST", self.internal_user,
             data={'name': settings.EXTERNAL_ACCESS_TAGNAME})
@@ -1619,7 +1619,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
             superevent=self.internal_superevent, comment='test')
 
         # Make request
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.internal_superevent.superevent_id, log.N])
         response = self.request_as_user(url, "POST", self.internal_user,
             data={'name': settings.PUBLIC_ACCESS_TAGNAME})
@@ -1639,7 +1639,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
             superevent=self.internal_superevent, comment='test')
 
         # Make request
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.internal_superevent.superevent_id, log.N])
         response = self.request_as_user(url, "POST", self.am_user,
             data={'name': settings.EXTERNAL_ACCESS_TAGNAME})
@@ -1660,7 +1660,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
             superevent=self.internal_superevent, comment='test')
 
         # Make request
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.internal_superevent.superevent_id, log.N])
         response = self.request_as_user(url, "POST", self.am_user,
             data={'name': settings.PUBLIC_ACCESS_TAGNAME})
@@ -1675,7 +1675,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
         log = Log.objects.create(issuer=self.internal_user,
             superevent=self.internal_superevent, comment='test')
 
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.internal_superevent.superevent_id, log.N])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data={'name': self.tag1.name})
@@ -1686,7 +1686,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
         # Internal-only superevent again, with tag already applied,
         # to make sure error message is what we expect and that nothing
         # leaks out that way.
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.internal_superevent.superevent_id,
             self.internal_superevent_exposed_log.N])
         response = self.request_as_user(url, "POST", self.lvem_user,
@@ -1695,7 +1695,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
         self.assertEqual(response.status_code, 404)
 
         # LV-EM exposed superevent
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.lvem_superevent.superevent_id,
             self.lvem_superevent_exposed_log.N])
         response = self.request_as_user(url, "POST", self.lvem_user,
@@ -1710,7 +1710,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
         log = Log.objects.create(issuer=self.internal_user,
             superevent=self.internal_superevent, comment='test')
 
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.internal_superevent.superevent_id, log.N])
         response = self.request_as_user(url, "POST",
             data={'name': self.tag1.name})
@@ -1722,7 +1722,7 @@ class TestSupereventLogTagList(AccessManagersGroupAndUserSetup,
         # Internal-only superevent again, with tag already applied,
         # to make sure error message is what we expect and that nothing
         # leaks out that way.
-        url = reverse('api:superevents:superevent-log-tag-list',
+        url = reverse('api:default:superevents:superevent-log-tag-list',
             args=[self.internal_superevent.superevent_id,
             self.internal_superevent_exposed_log.N])
         response = self.request_as_user(url, "POST",
@@ -1779,7 +1779,8 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         for s in Superevent.objects.all():
             for l in s.log_set.all():
                 for t in l.tags.all():
-                    url = reverse('api:superevents:superevent-log-tag-detail',
+                    url = reverse(('api:default:superevents:'
+                        'superevent-log-tag-detail'),
                         args=[s.superevent_id, l.N, t.name])
                     response = self.request_as_user(url, "GET",
                         self.internal_user)
@@ -1790,7 +1791,8 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         """LV-EM user can't get tags for any logs on hidden superevent"""
         for l in self.internal_superevent.log_set.all():
             for t in l.tags.all():
-                url = reverse('api:superevents:superevent-log-tag-detail',
+                url = reverse(('api:default:superevents:'
+                    'superevent-log-tag-detail'),
                     args=[self.internal_superevent.superevent_id, l.N, t.name])
                 response = self.request_as_user(url, "GET", self.lvem_user)
                 self.assertEqual(response.status_code, 404)
@@ -1801,7 +1803,8 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         """
         for l in self.lvem_superevent.log_set.all():
             for t in l.tags.all():
-                url = reverse('api:superevents:superevent-log-tag-detail',
+                url = reverse(('api:default:superevents:'
+                    'superevent-log-tag-detail'),
                     args=[self.lvem_superevent.superevent_id, l.N, t.name])
                 response = self.request_as_user(url, "GET", self.lvem_user)
                 if (l == self.lvem_superevent_exposed_log):
@@ -1814,7 +1817,8 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         """Public user can't get tags for any logs for hidden superevent"""
         for l in self.internal_superevent.log_set.all():
             for t in l.tags.all():
-                url = reverse('api:superevents:superevent-log-tag-detail',
+                url = reverse(('api:default:superevents:'
+                    'superevent-log-tag-detail'),
                     args=[self.internal_superevent.superevent_id, l.N, t.name])
                 response = self.request_as_user(url, "GET")
                 self.assertEqual(response.status_code, 403)
@@ -1829,7 +1833,7 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
 
     def test_internal_user_remove_tag(self):
         """Internal user can remove tags from superevent logs"""
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[self.internal_superevent.superevent_id,
             self.internal_superevent_exposed_log.N, self.tag1.name])
         response = self.request_as_user(url, "DELETE", self.internal_user)
@@ -1842,7 +1846,7 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         log.tags.add(self.lvem_tag)
 
         # Make request and check response data
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[log.superevent.superevent_id, log.N, self.lvem_tag.name])
         response = self.request_as_user(url, "DELETE", self.internal_user)
         self.assertEqual(response.status_code, 403)
@@ -1854,7 +1858,7 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         log.tags.add(self.public_tag)
 
         # Make request and check response data
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[log.superevent.superevent_id, log.N, self.public_tag.name])
         response = self.request_as_user(url, "DELETE", self.internal_user)
         self.assertEqual(response.status_code, 403)
@@ -1866,7 +1870,7 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         log.tags.add(self.lvem_tag)
 
         # Make request and check response data
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[log.superevent.superevent_id, log.N, self.lvem_tag.name])
         response = self.request_as_user(url, "DELETE", self.am_user)
         self.assertEqual(response.status_code, 204)
@@ -1878,7 +1882,7 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         log.tags.add(self.public_tag)
 
         # Make request and check response data
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[log.superevent.superevent_id, log.N, self.public_tag.name])
         response = self.request_as_user(url, "DELETE", self.am_user)
         self.assertEqual(response.status_code, 204)
@@ -1886,7 +1890,7 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
     def test_lvem_user_remove_tag_from_log_on_hidden_superevent(self):
         """LV-EM user can't remove tag from logs on hidden superevent"""
         # Make request and check response data
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[self.internal_superevent.superevent_id,
             self.internal_superevent_exposed_log.N, self.tag1.name])
         response = self.request_as_user(url, "DELETE", self.lvem_user)
@@ -1897,20 +1901,20 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
         # Hidden log on exposed superevent, no tags
         log = Log.objects.create(issuer=self.internal_user,
             superevent=self.lvem_superevent, comment='test')
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[self.lvem_superevent.superevent_id, log.N, self.tag1.name])
         response = self.request_as_user(url, "DELETE", self.lvem_user)
         self.assertEqual(response.status_code, 404)
 
         # Add the tag and try again just to make sure
         log.tags.add(self.tag1)
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[self.lvem_superevent.superevent_id, log.N, self.tag1.name])
         response = self.request_as_user(url, "DELETE", self.lvem_user)
         self.assertEqual(response.status_code, 404)
 
         # Exposed log on exposed superevent
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[self.lvem_superevent.superevent_id,
             self.lvem_superevent_exposed_log.N, self.tag1.name])
         response = self.request_as_user(url, "DELETE", self.lvem_user)
@@ -1919,7 +1923,7 @@ class TestSupereventLogTagDetail(AccessManagersGroupAndUserSetup,
     def test_public_user_remove_tag_from_log_on_hidden_superevent(self):
         """Public user can't remove tag from logs on hidden superevent"""
         # Make request and check response data
-        url = reverse('api:superevents:superevent-log-tag-detail',
+        url = reverse('api:default:superevents:superevent-log-tag-detail',
             args=[self.internal_superevent.superevent_id,
             self.internal_superevent_exposed_log.N, self.tag1.name])
         response = self.request_as_user(url, "DELETE")
@@ -1969,7 +1973,7 @@ class TestSupereventVOEventList(SupereventSetup, GraceDbApiTestBase):
     def test_internal_user_get_list(self):
         """Internal user can get all VOEvents for all superevents"""
         for s in Superevent.objects.all():
-            url = reverse('api:superevents:superevent-voevent-list',
+            url = reverse('api:default:superevents:superevent-voevent-list',
                 args=[s.superevent_id])
             response = self.request_as_user(url, "GET", self.internal_user)
             self.assertEqual(response.status_code, 200)
@@ -1983,14 +1987,14 @@ class TestSupereventVOEventList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_user_get_list_for_hidden_superevent(self):
         """LV-EM user can't get any VOEvents for hidden superevents"""
-        url = reverse('api:superevents:superevent-voevent-list',
+        url = reverse('api:default:superevents:superevent-voevent-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 404)
 
     def test_lvem_user_get_list_for_exposed_superevent(self):
         """LV-EM user can get all VOEvents for exposed superevents"""
-        url = reverse('api:superevents:superevent-voevent-list',
+        url = reverse('api:default:superevents:superevent-voevent-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -2003,7 +2007,7 @@ class TestSupereventVOEventList(SupereventSetup, GraceDbApiTestBase):
 
     def test_public_user_get_list_for_hidden_superevent(self):
         """Public user can't get any VOEvents for hidden superevents"""
-        url = reverse('api:superevents:superevent-voevent-list',
+        url = reverse('api:default:superevents:superevent-voevent-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET")
         self.assertEqual(response.status_code, 403)
@@ -2016,7 +2020,7 @@ class TestSupereventVOEventList(SupereventSetup, GraceDbApiTestBase):
 
     def test_internal_user_create_voevent(self):
         """Internal user can create VOEvents for all superevents"""
-        url = reverse('api:superevents:superevent-voevent-list',
+        url = reverse('api:default:superevents:superevent-voevent-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user,
             data=self.voevent_data)
@@ -2026,7 +2030,7 @@ class TestSupereventVOEventList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_user_create_voevent_for_hidden_superevent(self):
         """LV-EM user can't create VOEvents for hidden superevents"""
-        url = reverse('api:superevents:superevent-voevent-list',
+        url = reverse('api:default:superevents:superevent-voevent-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data=self.voevent_data)
@@ -2034,7 +2038,7 @@ class TestSupereventVOEventList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_user_create_voevent_for_exposed_superevent(self):
         """LV-EM user can't create VOEvents for exposed superevents"""
-        url = reverse('api:superevents:superevent-voevent-list',
+        url = reverse('api:default:superevents:superevent-voevent-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data=self.voevent_data)
@@ -2044,7 +2048,7 @@ class TestSupereventVOEventList(SupereventSetup, GraceDbApiTestBase):
 
     def test_public_user_create_voevent_for_hidden_superevent(self):
         """Public user can't create VOEvents for hidden superevents"""
-        url = reverse('api:superevents:superevent-voevent-list',
+        url = reverse('api:default:superevents:superevent-voevent-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", data=self.voevent_data)
         self.assertEqual(response.status_code, 403)
@@ -2076,7 +2080,8 @@ class TestSupereventVOEventDetail(SupereventSetup, GraceDbApiTestBase):
         """Internal user can get all VOEvent details for all superevents"""
         for s in Superevent.objects.all():
             for v in s.voevent_set.all():
-                url = reverse('api:superevents:superevent-voevent-detail',
+                url = reverse(('api:default:superevents:'
+                    'superevent-voevent-detail'),
                     args=[s.superevent_id, v.N])
                 response = self.request_as_user(url, "GET", self.internal_user)
                 self.assertEqual(response.status_code, 200)
@@ -2086,7 +2091,7 @@ class TestSupereventVOEventDetail(SupereventSetup, GraceDbApiTestBase):
     def test_lvem_user_get_detail_for_hidden_superevent(self):
         """LV-EM user can't get VOEvent detail for hidden superevents"""
         voevent = self.internal_superevent.voevent_set.first()
-        url = reverse('api:superevents:superevent-voevent-detail',
+        url = reverse('api:default:superevents:superevent-voevent-detail',
             args=[self.internal_superevent.superevent_id, voevent.N])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 404)
@@ -2094,7 +2099,7 @@ class TestSupereventVOEventDetail(SupereventSetup, GraceDbApiTestBase):
     def test_lvem_user_get_detail_for_exposed_superevent(self):
         """LV-EM user can get all VOEvent details for exposed superevents"""
         for v in self.lvem_superevent.voevent_set.all():
-            url = reverse('api:superevents:superevent-voevent-detail',
+            url = reverse('api:default:superevents:superevent-voevent-detail',
                 args=[self.lvem_superevent.superevent_id, v.N])
             response = self.request_as_user(url, "GET", self.lvem_user)
             self.assertEqual(response.status_code, 200)
@@ -2104,7 +2109,7 @@ class TestSupereventVOEventDetail(SupereventSetup, GraceDbApiTestBase):
     def test_public_user_get_list_for_hidden_superevent(self):
         """Public user can't get any VOEvent details for hidden superevents"""
         v = self.internal_superevent.voevent_set.first()
-        url = reverse('api:superevents:superevent-voevent-detail',
+        url = reverse('api:default:superevents:superevent-voevent-detail',
             args=[self.internal_superevent.superevent_id, v.N])
         response = self.request_as_user(url, "GET")
         self.assertEqual(response.status_code, 403)
@@ -2158,7 +2163,8 @@ class TestSupereventEMObservationList(SupereventSetup, GraceDbApiTestBase):
     def test_internal_user_get_list(self):
         """Internal user can get all EMObservations for all superevents"""
         for s in Superevent.objects.all():
-            url = reverse('api:superevents:superevent-emobservation-list',
+            url = reverse(('api:default:superevents:'
+                'superevent-emobservation-list'),
                 args=[s.superevent_id])
             response = self.request_as_user(url, "GET", self.internal_user)
             self.assertEqual(response.status_code, 200)
@@ -2172,14 +2178,14 @@ class TestSupereventEMObservationList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_user_get_list_for_hidden_superevent(self):
         """LV-EM user can't get any EMObservations for hidden superevents"""
-        url = reverse('api:superevents:superevent-emobservation-list',
+        url = reverse('api:default:superevents:superevent-emobservation-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 404)
 
     def test_lvem_user_get_list_for_exposed_superevent(self):
         """LV-EM user can get all EMObservations for exposed superevents"""
-        url = reverse('api:superevents:superevent-emobservation-list',
+        url = reverse('api:default:superevents:superevent-emobservation-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -2192,7 +2198,7 @@ class TestSupereventEMObservationList(SupereventSetup, GraceDbApiTestBase):
 
     def test_public_user_get_list_for_hidden_superevent(self):
         """Public user can't get any EMObservations for hidden superevents"""
-        url = reverse('api:superevents:superevent-emobservation-list',
+        url = reverse('api:default:superevents:superevent-emobservation-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET")
         self.assertEqual(response.status_code, 403)
@@ -2205,7 +2211,7 @@ class TestSupereventEMObservationList(SupereventSetup, GraceDbApiTestBase):
 
     def test_internal_user_create_emobservation(self):
         """Internal user can create EMObservations for all superevents"""
-        url = reverse('api:superevents:superevent-emobservation-list',
+        url = reverse('api:default:superevents:superevent-emobservation-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.internal_user,
             data=self.emobservation_data)
@@ -2217,7 +2223,7 @@ class TestSupereventEMObservationList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_user_create_emobservation_for_hidden_superevent(self):
         """LV-EM user can't create EMObservations for hidden superevents"""
-        url = reverse('api:superevents:superevent-emobservation-list',
+        url = reverse('api:default:superevents:superevent-emobservation-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data=self.emobservation_data)
@@ -2225,7 +2231,7 @@ class TestSupereventEMObservationList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_user_create_emobservation_for_exposed_superevent(self):
         """LV-EM user can create EMObservations for exposed superevents"""
-        url = reverse('api:superevents:superevent-emobservation-list',
+        url = reverse('api:default:superevents:superevent-emobservation-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "POST", self.lvem_user,
             data=self.emobservation_data)
@@ -2237,7 +2243,7 @@ class TestSupereventEMObservationList(SupereventSetup, GraceDbApiTestBase):
 
     def test_public_user_create_emobservation_for_hidden_superevent(self):
         """Public user can't create EMObservations for hidden superevents"""
-        url = reverse('api:superevents:superevent-emobservation-list',
+        url = reverse('api:default:superevents:superevent-emobservation-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "POST",
             data=self.emobservation_data)
@@ -2273,7 +2279,8 @@ class TestSupereventEMObservationDetail(SupereventSetup, GraceDbApiTestBase):
         """Internal user can get EMObservaion details for all superevents"""
         for s in Superevent.objects.all():
             for emo in s.emobservation_set.all():
-                url = reverse('api:superevents:superevent-emobservation-detail',
+                url = reverse(('api:default:superevents:'
+                    'superevent-emobservation-detail'),
                     args=[s.superevent_id, emo.N])
                 response = self.request_as_user(url, "GET", self.internal_user)
                 self.assertEqual(response.status_code, 200)
@@ -2282,7 +2289,7 @@ class TestSupereventEMObservationDetail(SupereventSetup, GraceDbApiTestBase):
     def test_lvem_user_get_detail_for_hidden_superevent(self):
         """LV-EM user can't get EMObservation detail for hidden superevents"""
         emo = self.internal_superevent.emobservation_set.first()
-        url = reverse('api:superevents:superevent-emobservation-detail',
+        url = reverse('api:default:superevents:superevent-emobservation-detail',
             args=[self.internal_superevent.superevent_id, emo.N])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 404)
@@ -2290,7 +2297,8 @@ class TestSupereventEMObservationDetail(SupereventSetup, GraceDbApiTestBase):
     def test_lvem_user_get_detail_for_exposed_superevent(self):
         """LV-EM user can get EMObservation details for exposed superevents"""
         for emo in self.lvem_superevent.emobservation_set.all():
-            url = reverse('api:superevents:superevent-emobservation-detail',
+            url = reverse(('api:default:superevents:'
+                'superevent-emobservation-detail'),
                 args=[self.lvem_superevent.superevent_id, emo.N])
             response = self.request_as_user(url, "GET", self.lvem_user)
             self.assertEqual(response.status_code, 200)
@@ -2302,7 +2310,8 @@ class TestSupereventEMObservationDetail(SupereventSetup, GraceDbApiTestBase):
         Public user can't get any EMObservation details for hidden superevents
         """
         emo = self.internal_superevent.emobservation_set.first()
-        url = reverse('api:superevents:superevent-emobservation-detail',
+        url = reverse(('api:default:superevents:'
+            'superevent-emobservation-detail'),
             args=[self.internal_superevent.superevent_id, emo.N])
         response = self.request_as_user(url, "GET")
         self.assertEqual(response.status_code, 403)
@@ -2342,7 +2351,7 @@ class TestSupereventFileList(SupereventSetup, GraceDbApiTestBase):
     def test_internal_get_file_list_for_superevent(self):
         """Internal user can see all files for all superevents"""
         for s in Superevent.objects.all():
-            url = reverse('api:superevents:superevent-file-list',
+            url = reverse('api:default:superevents:superevent-file-list',
                 args=[s.superevent_id])
             response = self.request_as_user(url, "GET", self.internal_user)
             self.assertEqual(response.status_code, 200)
@@ -2357,7 +2366,7 @@ class TestSupereventFileList(SupereventSetup, GraceDbApiTestBase):
 
     def test_lvem_get_file_list_for_hidden_superevent(self):
         """LV-EM user can't get file list for hidden superevents"""
-        url = reverse('api:superevents:superevent-file-list',
+        url = reverse('api:default:superevents:superevent-file-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 404)
@@ -2376,7 +2385,7 @@ class TestSupereventFileList(SupereventSetup, GraceDbApiTestBase):
         expose_log_to_lvem(log)
 
         # Make request and check response
-        url = reverse('api:superevents:superevent-file-list',
+        url = reverse('api:default:superevents:superevent-file-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -2395,7 +2404,7 @@ class TestSupereventFileList(SupereventSetup, GraceDbApiTestBase):
         expose_log_to_lvem(log)
 
         # Make request and get response
-        url = reverse('api:superevents:superevent-file-list',
+        url = reverse('api:default:superevents:superevent-file-list',
             args=[self.lvem_superevent.superevent_id])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -2405,7 +2414,7 @@ class TestSupereventFileList(SupereventSetup, GraceDbApiTestBase):
 
     def test_public_get_file_list_for_hidden_superevent(self):
         """Public user can't get file list for hidden superevents"""
-        url = reverse('api:superevents:superevent-file-list',
+        url = reverse('api:default:superevents:superevent-file-list',
             args=[self.internal_superevent.superevent_id])
         response = self.request_as_user(url, "GET")
         self.assertEqual(response.status_code, 403)
@@ -2461,7 +2470,7 @@ class TestSupereventFileDetail(SupereventSetup, GraceDbApiTestBase):
             symlinks = list(set([fl.filename for fl in file_logs]))
             file_list.extend(symlinks)
             for f in file_list:
-                url = reverse('api:superevents:superevent-file-detail',
+                url = reverse('api:default:superevents:superevent-file-detail',
                     args=[s.superevent_id, f])
                 response = self.request_as_user(url, "GET", self.internal_user)
                 self.assertEqual(response.status_code, 200)
@@ -2473,7 +2482,7 @@ class TestSupereventFileDetail(SupereventSetup, GraceDbApiTestBase):
         symlinks = list(set([fl.filename for fl in file_logs]))
         file_list.extend(symlinks)
         for f in file_list:
-            url = reverse('api:superevents:superevent-file-detail',
+            url = reverse('api:default:superevents:superevent-file-detail',
                 args=[self.internal_superevent.superevent_id, f])
             response = self.request_as_user(url, "GET", self.lvem_user)
             self.assertEqual(response.status_code, 404)
@@ -2486,7 +2495,7 @@ class TestSupereventFileDetail(SupereventSetup, GraceDbApiTestBase):
         expose_log_to_lvem(log)
 
         # Make request and check response
-        url = reverse('api:superevents:superevent-file-detail',
+        url = reverse('api:default:superevents:superevent-file-detail',
             args=[self.lvem_superevent.superevent_id, log.versioned_filename])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -2496,7 +2505,7 @@ class TestSupereventFileDetail(SupereventSetup, GraceDbApiTestBase):
         log2 = self.lvem_superevent.log_set.get(filename=
             self.file1['filename'], file_version=0)
         # Make request and check response
-        url = reverse('api:superevents:superevent-file-detail',
+        url = reverse('api:default:superevents:superevent-file-detail',
             args=[self.lvem_superevent.superevent_id, log2.versioned_filename])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 404)
@@ -2512,14 +2521,14 @@ class TestSupereventFileDetail(SupereventSetup, GraceDbApiTestBase):
         expose_log_to_lvem(log)
 
         # Make request and check response
-        url = reverse('api:superevents:superevent-file-detail',
+        url = reverse('api:default:superevents:superevent-file-detail',
             args=[self.lvem_superevent.superevent_id, log.versioned_filename])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
         data1 = response.data
 
         # Repeat with non-versioned filename
-        url = reverse('api:superevents:superevent-file-detail',
+        url = reverse('api:default:superevents:superevent-file-detail',
             args=[self.lvem_superevent.superevent_id, log.filename])
         response = self.request_as_user(url, "GET", self.lvem_user)
         self.assertEqual(response.status_code, 200)
@@ -2532,7 +2541,7 @@ class TestSupereventFileDetail(SupereventSetup, GraceDbApiTestBase):
         symlinks = list(set([fl.filename for fl in file_logs]))
         file_list.extend(symlinks)
         for f in file_list:
-            url = reverse('api:superevents:superevent-file-detail',
+            url = reverse('api:default:superevents:superevent-file-detail',
                 args=[self.internal_superevent.superevent_id, f])
             response = self.request_as_user(url, "GET")
             self.assertEqual(response.status_code, 403)
diff --git a/gracedb/superevents/api/tests/test_methods.py b/gracedb/api/v1/superevents/tests/test_methods.py
similarity index 100%
rename from gracedb/superevents/api/tests/test_methods.py
rename to gracedb/api/v1/superevents/tests/test_methods.py
diff --git a/gracedb/superevents/api/tests/utils.py b/gracedb/api/v1/superevents/tests/utils.py
similarity index 100%
rename from gracedb/superevents/api/tests/utils.py
rename to gracedb/api/v1/superevents/tests/utils.py
diff --git a/gracedb/superevents/api/view_templates.py b/gracedb/api/v1/superevents/url_templates.py
similarity index 91%
rename from gracedb/superevents/api/view_templates.py
rename to gracedb/api/v1/superevents/url_templates.py
index a070f926099091a9f453c7a82c01531169160ba8..ba3f0b609ab3cd22dc52e0200605081e59b9737f 100644
--- a/gracedb/superevents/api/view_templates.py
+++ b/gracedb/api/v1/superevents/url_templates.py
@@ -1,9 +1,10 @@
-from events.view_utils import reverse
+from __future__ import absolute_import
+
 from .views import SupereventViewSet, SupereventEventViewSet, \
     SupereventLabelViewSet, SupereventLogViewSet, SupereventLogTagViewSet, \
     SupereventFileViewSet, SupereventVOEventViewSet, \
     SupereventEMObservationViewSet
-
+from ...utils import api_reverse
 
 # Placeholder parameters for getting URLs with reverse
 PH = {
@@ -19,10 +20,10 @@ PH = {
 }
 
 
-def construct_api_url_templates(request=None):
+def construct_url_templates(request=None):
     # Bind our custom reverse for ease of use
-    sr = lambda view_name, args=[]: reverse('superevents:' + view_name, args=[
-        PH[SupereventViewSet.lookup_url_kwarg]] + args, request=request)
+    sr = lambda view_name, args=[]: api_reverse('superevents:' + view_name,
+        args=[PH[SupereventViewSet.lookup_url_kwarg]] + args, request=request)
 
     # Dict of views and temporary arguments which will be passed to reverse
     views = {
diff --git a/gracedb/superevents/api/urls.py b/gracedb/api/v1/superevents/urls.py
similarity index 100%
rename from gracedb/superevents/api/urls.py
rename to gracedb/api/v1/superevents/urls.py
diff --git a/gracedb/superevents/api/views.py b/gracedb/api/v1/superevents/views.py
similarity index 95%
rename from gracedb/superevents/api/views.py
rename to gracedb/api/v1/superevents/views.py
index c63036fa78f927f80ba8edd995333d48f502dcc6..16602f253080fc8ee874b87da1d521b290540cc4 100644
--- a/gracedb/superevents/api/views.py
+++ b/gracedb/api/v1/superevents/views.py
@@ -1,35 +1,28 @@
+from __future__ import absolute_import
 from collections import OrderedDict
 import logging
 import os
 
 from django.http import HttpResponse
-from django.db.models import QuerySet, Max
+from django.db.models import QuerySet
 from django.shortcuts import get_object_or_404
 
 from guardian.shortcuts import get_objects_for_user
 from rest_framework import mixins, parsers, permissions, serializers, status, \
     viewsets
 from rest_framework.decorators import action
-from rest_framework.renderers import BaseRenderer, JSONRenderer, \
-    BrowsableAPIRenderer
-from rest_framework.permissions import IsAuthenticated
-from rest_framework.views import APIView
 from rest_framework.response import Response
+from rest_framework.views import APIView
 
-
-from ..models import Superevent, Log
-from ..utils import remove_tag_from_log, remove_event_from_superevent, \
-    remove_label_from_superevent, confirm_superevent_as_gw, \
-    get_superevent_by_date_id_or_404
-
-from core.vfile import VersionedFile
 from core.http import check_and_serve_file
+from core.vfile import VersionedFile
 from events.models import Event, Label
 from events.view_utils import reverse as gracedb_reverse
-#from events.api.views import IsAuthorizedForPipeline, LigoLwRenderer
-from events.api.backends import LigoAuthentication
-
-from ..buildVOEvent import VOEventBuilderException
+from superevents.buildVOEvent import VOEventBuilderException
+from superevents.models import Superevent, Log
+from superevents.utils import remove_tag_from_log, \
+    remove_event_from_superevent, remove_label_from_superevent, \
+    confirm_superevent_as_gw, get_superevent_by_date_id_or_404
 from .base_viewsets import SupereventNestedViewSet
 from .filters import SupereventSearchFilter, SupereventOrderingFilter, \
     DjangoObjectAndGlobalPermissionsFilter
@@ -46,7 +39,9 @@ from .serializers import SupereventSerializer, SupereventUpdateSerializer, \
     SupereventLogSerializer, SupereventLogTagSerializer, \
     SupereventVOEventSerializer, SupereventEMObservationSerializer
 from .settings import SUPEREVENT_LOOKUP_URL_KWARG, SUPEREVENT_LOOKUP_REGEX
+from ...utils import api_reverse
 
+# Set up logger
 logger = logging.getLogger(__name__)
 
 
@@ -279,7 +274,7 @@ class SupereventFileViewSet(SupereventNestedViewSet):
 
         # Compile sorted dict of filenames and links
         file_dict = OrderedDict((f,
-            gracedb_reverse('superevents:superevent-file-detail',
+            api_reverse('superevents:superevent-file-detail',
             args=[parent_superevent.superevent_id, f], request=request))
             for f in sorted(file_list))
 
diff --git a/gracedb/api/v1/urls.py b/gracedb/api/v1/urls.py
new file mode 100644
index 0000000000000000000000000000000000000000..b4541713716dbf222a77b5ff54d002b29963f025
--- /dev/null
+++ b/gracedb/api/v1/urls.py
@@ -0,0 +1,26 @@
+from __future__ import absolute_import
+
+from django.conf.urls import url, include
+
+from .main.views import GracedbRoot, PerformanceInfo, TagList
+
+
+urlpatterns = [
+    # Root level API resources ------------------------------------------------
+    # API root
+    url(r'^$', GracedbRoot.as_view(), name="root"),
+
+    # Tags
+    url(r'^tag/', TagList.as_view(), name='tag-list'),
+
+    # Performance stats
+    url(r'^performance/', PerformanceInfo.as_view(), name='performance-info'),
+
+    # Events section of the API -----------------------------------------------
+    url(r'^events/', include('api.v1.events.urls',
+        namespace='events')),
+
+    # Superevents section of the API ------------------------------------------
+    url(r'^superevents/', include('api.v1.superevents.urls',
+        namespace='superevents')),
+]
diff --git a/gracedb/api/versioning.py b/gracedb/api/versioning.py
new file mode 100644
index 0000000000000000000000000000000000000000..a6299221b1e68cf27438b3334a2a3839eed58674
--- /dev/null
+++ b/gracedb/api/versioning.py
@@ -0,0 +1,40 @@
+import logging
+
+from rest_framework import versioning
+
+# Set up logger
+logger = logging.getLogger(__name__)
+
+
+class NestedNamespaceVersioning(versioning.NamespaceVersioning):
+    version_nest_level = 2 # starts with 1
+
+    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)
+        return super(NestedNamespaceVersioning, self).reverse(
+            viewname, args, kwargs, request, format, **extra
+        )
+
+    def get_versioned_viewname(self, viewname, request=None):
+        # Split up viewname parts
+        viewname_parts = viewname.split(':')
+        namespaces = viewname_parts[:-1]
+        viewname_only = viewname_parts[-1]
+
+        # Get version
+        if request and 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:
+            namespaces.insert(self.version_nest_level - 1, version)
+
+        versioned_viewname = ':'.join(namespaces + [viewname_only])
+        return versioned_viewname
+
diff --git a/gracedb/core/middleware/api.py b/gracedb/core/middleware/api.py
index 2d017eb9d7db6c9f483b4afb903799e636bf5338..71411c41dd9b3182522d31a34a279c85afb4e588 100644
--- a/gracedb/core/middleware/api.py
+++ b/gracedb/core/middleware/api.py
@@ -53,6 +53,8 @@ class ClientVersionMiddleware(object):
         #  3. If User-Agent header and not client_string, assume browser
         #     and allow to pass
         request_allowed = True
+        # TODO: can we check the request's resolver match for the api namespace
+        # instead?  That keeps things more DRY.
         if request.path.startswith('/api'):
             if (agent_header is None and not
                 settings.ALLOW_BLANK_USER_AGENT_TO_API):
diff --git a/gracedb/events/api/urls.py b/gracedb/events/api/urls.py
deleted file mode 100644
index 579a58eb780f7024a5c4c7fa5fb975facfd02565..0000000000000000000000000000000000000000
--- a/gracedb/events/api/urls.py
+++ /dev/null
@@ -1,94 +0,0 @@
-# Changed for Django 1.11
-from django.conf.urls import url, include
-
-from .views import * 
-
-urlpatterns = [
-    url(r'^$', GracedbRoot.as_view(), name="api-root"),
-
-    # Event Resources
-    # events/[{graceid}[/{version}]]
-    url(r'^events/$', EventList.as_view(), name='event-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)$', EventDetail.as_view(),
-        name='event-detail'),
-
-    # Event Log Resources
-    # events/{graceid}/logs/[{logid}]
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/log/$', EventLogList.as_view(),
-        name='eventlog-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/log/(?P<n>\d+)$',
-        EventLogDetail.as_view(), name='eventlog-detail'),
-
-    # VOEvent Resources
-    # events/{graceid}/voevent/[{serial_number}]
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/voevent/$', VOEventList.as_view(),
-        name='voevent-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/voevent/(?P<n>\d+)$',
-        VOEventDetail.as_view(), name='voevent-detail'),
-
-    # EMBB Resources
-    # events/{graceid}/logs/[{logid}]
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/embb/$', EMBBEventLogList.as_view(),
-        name='embbeventlog-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/embb/(?P<n>\d+)$',
-        EMBBEventLogDetail.as_view(), name='embbeventlog-detail'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/emobservation/$',
-        EMObservationList.as_view(), name='emobservation-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/emobservation/(?P<n>\d+)$',
-        EMObservationDetail.as_view(), name='emobservation-detail'),
-#    url(r'events/(?P<graceid>[GEHMT]\d+)/emobservation/(?P<n>\d+)/emfootprint/$',
-#        EMFootprintList.as_view(), name='emfootprint-list'),
-#    url(r'events/(?P<graceid>[GEHMT]\d+)/emobservation/(?P<n>\d+)/emfootprint/(?P<m>\d+)$',
-#        EMFootprintDetail.as_view(), name='emfootprint-detail'),
-
-    # Tag Resources
-    url(r'^tag/$', TagList.as_view(), name='tag-list'),
-    # XXX unclear what the tag detail resource should be.
-    #url(r'^tag/(?P<tagname>.+)$', TagDetail.as_view(), name='tag-detail'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/tag/$', EventTagList.as_view(),
-        name='eventtag-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/tag/(?P<tagname>.+)$',
-        EventTagDetail.as_view(), name='eventtag-detail'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/log/(?P<n>\d+)/tag/$',
-        EventLogTagList.as_view(), name='eventlogtag-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/log/(?P<n>\d+)/tag/(?P<tagname>.+)$',
-        EventLogTagDetail.as_view(), name='eventlogtag-detail'),
-
-    # Permission Resources
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/perms/$',
-        EventPermissionList.as_view(), name='eventpermission-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/perms/(?P<group_name>.+)/$', 
-        GroupEventPermissionList.as_view(), name='groupeventpermission-list'),
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/perms/(?P<group_name>.+)/(?P<perm_shortname>\w+)$', 
-        GroupEventPermissionDetail.as_view(), name='groupeventpermission-detail'),
-
-    # Event File Resources
-    # events/{graceid}/files/[{filename}[/{version}]]
-    url(r'^events/(?P<graceid>\w[\d]+)/files/(?P<filename>.+)?$',
-        Files.as_view(), name="files"),
-
-    # Event Labels
-    # events/{graceid}/labels/[{label}]
-    url(r'^events/(?P<graceid>\w[\d]+)/labels/(?P<label>.+)?$',
-        EventLabel.as_view(), name="labels"),
-
-    # Event Neighbors
-    # events/{graceid}/neighbors/[?delta=(N|(N,N))]
-    url(r'^events/(?P<graceid>\w[\d]+)/neighbors/$', EventNeighbors.as_view(),
-        name="neighbors"),
-
-    # Operator Signoff Resources
-    url(r'^events/(?P<graceid>[GEHMT]\d+)/signoff/$',
-        OperatorSignoffList.as_view(), name='signoff-list'),
-
-    # Performance stats
-    url(r'^performance/$', PerformanceInfo.as_view(), name='performance-info'),
-
-    # Legacy
-    url(r'^event/(?P<graceid>\w[\d]+)/files/(?P<filename>.+)?$',
-        Files.as_view(), name="file-download"),
-
-    # Superevents
-    url(r'^superevents/', include('superevents.api.urls',
-        namespace='superevents')),
-]
diff --git a/gracedb/events/buildVOEvent.py b/gracedb/events/buildVOEvent.py
index baa2119270f14ba965a4f99a30ba1d6078c0d0e4..287f4c54205fe5daf56a63f7d3f559c53a52c14f 100644
--- a/gracedb/events/buildVOEvent.py
+++ b/gracedb/events/buildVOEvent.py
@@ -296,14 +296,18 @@ def buildVOEvent(event, serial_number, voevent_type, request=None, skymap_filena
             shib_png_skymap_url  = get_url(request, objid, "file-download", img_name)
 
         # x509 urls. Hafta specify the api namespace.
-        x509_fits_skymap_url = get_url(request, objid, "x509:files", fits_name)
+        x509_fits_skymap_url = get_url(request, objid,
+            "x509:default:events:files", fits_name)
         if img_name:
-            x509_png_skymap_url  = get_url(request, objid, "x509:files", 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:files", fits_name)
+        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:files", img_name)
+            basic_png_skymap_url  = get_url(request, objid,
+                "basic:default:events:files", img_name)
         
 
         # Add parameters to the skymap group
diff --git a/gracedb/events/view_utils.py b/gracedb/events/view_utils.py
index 4e2b9a5f1978a8f360e2f9c222710a1a63da4e46..e8d344de4e5bc07864120da84c246a6cbf168a7f 100644
--- a/gracedb/events/view_utils.py
+++ b/gracedb/events/view_utils.py
@@ -1,4 +1,4 @@
-
+from __future__ import absolute_import
 from django.http import HttpResponse, HttpResponseBadRequest
 from django.urls import reverse as django_reverse
 from django.utils import dateformat
@@ -11,6 +11,7 @@ from .models import SingleInspiral, Event, Search, Group
 from core.urls import build_absolute_uri
 from core.vfile import VersionedFile
 from .permission_utils import is_external
+from api.utils import api_reverse
 from django.db.models import Q
 
 import os
@@ -351,13 +352,13 @@ def eventToDict(event, columns=None, request=None):
 
     # Links
     rv['links'] = {
-          "neighbors" : reverse("neighbors", args=[graceid], request=request),
-          "log"   : reverse("eventlog-list", args=[graceid], request=request),
-          "emobservations"   : reverse("emobservation-list", args=[graceid], request=request),
-          "files" : reverse("files", args=[graceid], request=request),
-          "labels" : reverse("labels", args=[graceid], request=request),
-          "self"  : reverse("event-detail", args=[graceid], request=request),
-          "tags"  : reverse("eventtag-list", args=[graceid], request=request),
+          "neighbors" : api_reverse("events:neighbors", args=[graceid], request=request),
+          "log"   : api_reverse("events:eventlog-list", args=[graceid], request=request),
+          "emobservations"   : api_reverse("events:emobservation-list", args=[graceid], request=request),
+          "files" : api_reverse("events:files", args=[graceid], request=request),
+          "labels" : api_reverse("events:labels", args=[graceid], request=request),
+          "self"  : api_reverse("events:event-detail", args=[graceid], request=request),
+          "tags"  : api_reverse("events:eventtag-list", args=[graceid], request=request),
           }
     return rv
 
@@ -367,10 +368,10 @@ def eventLogToDict(log, request=None):
     file_uri = None
 
     # Get some links
-    uri = reverse("eventlog-detail",
+    uri = api_reverse("events:eventlog-detail",
             args=[log.event.graceid(), log.N],
             request=request)
-    taglist_uri = reverse("eventlogtag-list",
+    taglist_uri = api_reverse("events:eventlogtag-list",
             args=[log.event.graceid(), log.N],
             request=request)
     if log.filename:
@@ -382,7 +383,7 @@ def eventLogToDict(log, request=None):
         # escaping twice results in wrong urls. 
         #filename = urlquote(actual_filename)
         filename = actual_filename
-        file_uri = reverse("files",
+        file_uri = api_reverse("events:files",
             args=[log.event.graceid(), filename],
             request=request)
 
@@ -422,7 +423,7 @@ def labelToDict(labelling, request=None):
             "creator" : labelling.creator.username,
             "created" : labelling.created.strftime(
                       settings.GRACE_STRFTIME_FORMAT),
-            "self" : reverse("labels",
+            "self" : api_reverse("events:labels",
                 args=[labelling.event.graceid(), labelling.label.name],
                 request=request),
            }
@@ -431,7 +432,7 @@ def labelToDict(labelling, request=None):
 def embbEventLogToDict(eel, request=None):
       uri = None
       if request:
-          uri = reverse("embbeventlog-detail",
+          uri = api_reverse("events:embbeventlog-detail",
                   args=[eel.event.graceid(), eel.N],
                   request=request)
       return {
@@ -467,7 +468,7 @@ def embbEventLogToDict(eel, request=None):
 
 # EMObservation serializer.
 def emObservationToDict(emo, request=None):
-      uri = reverse("emobservation-detail",
+      uri = api_reverse("events:emobservation-detail",
           args=[emo.event.graceid(), emo.N],
           request=request)
       
@@ -492,7 +493,7 @@ def emObservationToDict(emo, request=None):
 def emFootprintToDict(emf, request=None):
 #      uri = None
 #      if request:
-#          uri = reverse("emfootprint-detail",
+#          uri = api_reverse("events:emfootprint-detail",
 #                  args=[emf.emobservation.event.graceid(), emf.emobservation.N, emf.N],
 #                  request=request)
       
@@ -513,7 +514,7 @@ def emFootprintToDict(emf, request=None):
 # XXX Eventually hope to remove this
 # EMObservation serializer for the skymap Viewer
 def skymapViewerEMObservationToDict(emo, request=None):
-    uri = reverse("emobservation-detail",
+    uri = api_reverse("events:emobservation-detail",
         args=[emo.event.graceid(), emo.N],
         request=request)
 
@@ -574,10 +575,10 @@ def voeventToDict(voevent, request=None):
     #filename = urlquote('%s,%d' % (voevent.filename, voevent.file_version))
     filename = '%s,%d' % (voevent.filename, voevent.file_version)
 
-    uri = reverse("voevent-detail",
+    uri = api_reverse("events:voevent-detail",
         args=[voevent.event.graceid(), voevent.N],
         request=request)
-    file_uri = reverse("files",
+    file_uri = api_reverse("events:files",
         args=[voevent.event.graceid(), filename],
         request=request)
 
diff --git a/gracedb/superevents/api/settings.py b/gracedb/superevents/api/settings.py
deleted file mode 100644
index 277c5e7e2cd88348f8b2bf53f3e110782db74c03..0000000000000000000000000000000000000000
--- a/gracedb/superevents/api/settings.py
+++ /dev/null
@@ -1,5 +0,0 @@
-from ..models import Superevent
-
-SUPEREVENT_LOOKUP_URL_KWARG = 'superevent_id'
-SUPEREVENT_LOOKUP_REGEX = Superevent.ID_REGEX
-
diff --git a/gracedb/superevents/api/tests/__init__.py b/gracedb/superevents/api/tests/__init__.py
deleted file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000
diff --git a/gracedb/superevents/buildVOEvent.py b/gracedb/superevents/buildVOEvent.py
index 6400e55847359b62dba7211b3d0e6d71bcd830fb..9777b988ade739ecce5e401eace2240abd6f2778 100644
--- a/gracedb/superevents/buildVOEvent.py
+++ b/gracedb/superevents/buildVOEvent.py
@@ -276,12 +276,17 @@ def construct_voevent_file(superevent, voevent, request=None,
         # 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 + ":superevents:superevent-file-detail",
+            reverse(ns + ":default:superevents:superevent-file-detail",
             args=[superevent.superevent_id, file_name]), request)
-        shib_fits_skymap_url = file_abs_reverse('shib', fits_name)
+        shib_fits_skymap_url = build_absolute_uri(
+            reverse("superevents:file-download",
+            args=[superevent.superevent_id, fits_name]), request)
         x509_fits_skymap_url = file_abs_reverse('x509', fits_name)
         basic_fits_skymap_url = file_abs_reverse('basic', fits_name)
         if img_name:
+            shib_fits_skymap_url = build_absolute_uri(
+                reverse("superevents:file-download",
+                args=[superevent.superevent_id, img_name]), request)
             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)
diff --git a/gracedb/templates/gracedb/event_detail_script.js b/gracedb/templates/gracedb/event_detail_script.js
index 8e7ecaf37e4c8e01c02e0109dd21f44ba0439710..7f7268bd6e225d3d48d6e7225ce53fbe5369d79b 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:tag-list" %}';
+var tagListUrl          = '{% url "shib:default:tag-list" %}';
 var tagUrlPattern       = '{% url "taglogentry" object.graceid "000" "temp" %}';
-var eventLogListUrl     = '{% url "shib:eventlog-list" object.graceid %}';
+var eventLogListUrl     = '{% url "shib:default:events:eventlog-list" object.graceid %}';
 var eventLogSaveUrl     = '{% url "logentry" object.graceid "" %}';
-var embbEventLogListUrl = '{% url "shib:embbeventlog-list" object.graceid %}';
-var emObservationListUrl = '{% url "shib:emobservation-list" object.graceid %}';
+var embbEventLogListUrl = '{% url "shib:default:events:embbeventlog-list" object.graceid %}';
+var emObservationListUrl = '{% url "shib:default:events:emobservation-list" object.graceid %}';
 var fileDownloadUrl = '{% url "file-download" object.graceid "FAKE_FILE_NAME" %}';
-var skymapJsonUrl       = '{% url "shib:files" object.graceid "" %}';
+var skymapJsonUrl       = '{% url "shib: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 fe7a0125feb30cbd5b1dea6f97d07c8d919d29ac..f6f2cfd18528f4ee788dc8d99c8184c1055bc9c0 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/DASWG/GraceDB">Project page on wiki.ligo.org</a></li>
-<li><a href="{% url "shib:api-root" %}">Browseable REST API</a>
+<li><a href="{% url "shib: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 fb62b6fa21915aa3a9b8a4b6c748010fd50ec95b..4c5698b389947c3943fba0b8cff7b95f617077c6 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:api-root" %}>REST API</a>.</p>
+<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> Your username is: <b>{{ username }}</b></p>
 {% if has_password %}
diff --git a/gracedb/templates/superevents/superevent_detail_script.js b/gracedb/templates/superevents/superevent_detail_script.js
index 373c2d52c2d30f29884ba11f6e27a04a7252c3ed..89320153f7d10d6f78738484dcb6c4b031aa5467 100644
--- a/gracedb/templates/superevents/superevent_detail_script.js
+++ b/gracedb/templates/superevents/superevent_detail_script.js
@@ -156,12 +156,12 @@ var hasImage = function(object) {
 }
 
 // some URLs. Usage of Django template syntax should be limited to here
-var tagListUrl          = '{% url "shib:tag-list" %}';
-var tagCreateUrlPattern = '{% url "shib:superevents:superevent-log-tag-list" superevent.superevent_id "000" %}';
-var tagDeleteUrlPattern = '{% url "shib:superevents:superevent-log-tag-detail" superevent.superevent_id "000" "FAKE_TAG_NAME" %}';
-var logListUrl     = '{% url "shib:superevents:superevent-log-list" superevent.superevent_id %}';
-var logSaveUrl     = '{% url "shib:superevents:superevent-log-list" superevent.superevent_id %}';
-var emObservationListUrl = '{% url "shib:superevents:superevent-emobservation-list" superevent.superevent_id %}';
+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 "superevents:file-download" superevent.superevent_id "FAKE_FILE_NAME" %}';
 var skymapViewerUrl     = '{{ SKYMAP_VIEWER_SERVICE_URL }}';