diff --git a/gregui/api/serializers/identity.py b/gregui/api/serializers/identity.py
new file mode 100644
index 0000000000000000000000000000000000000000..df8d06b1a9b1bc059696953b1ef5869bfd22b06e
--- /dev/null
+++ b/gregui/api/serializers/identity.py
@@ -0,0 +1,52 @@
+from django.utils import timezone
+from rest_framework import serializers
+
+from greg.models import Identity
+from gregui.models import GregUserProfile
+
+
+class IdentitySerializer(serializers.ModelSerializer):
+    """Serializer for the Identity model with validation of various fields"""
+
+    class Meta:
+        model = Identity
+        fields = "__all__"
+        read_only_fields = [
+            "id",
+            "person",
+            "type",
+            "source",
+            "value",
+            "verified",
+            "verified_by",
+        ]
+
+    def _get_sponsor(self):
+        """
+        Fetch the sponsor doing the request
+
+        Since the ViewSet using this Serializer uses the IsSponsor permission, we know
+        that the user is connect to a GregUserProfile with a sponsor object.
+        """
+        user = None
+        request = self.context.get("request")
+        if request and hasattr(request, "user"):
+            user = request.user
+        return GregUserProfile.objects.get(user=user).sponsor
+
+    def validate(self, attrs):
+        """
+        Set values automatically when updating.
+
+        - All updates are manual from the ui endpoints.
+        - The one verifying must be the logged in user which we know is a sponsor since
+          the user passed the IsSponsor permission in the view using this serializer.
+        - No point leaving setting the verified_at time to anyone other than the
+          server itself.
+
+        Note: Get requests do not use this method, making it safe.
+        """
+        attrs["verified"] = Identity.Verified.MANUAL
+        attrs["verified_by"] = self._get_sponsor()
+        attrs["verified_at"] = timezone.now()
+        return attrs
diff --git a/gregui/api/urls.py b/gregui/api/urls.py
index 6cb9764a4785481399ff927cc176716ea5ef527b..aaa40487cd74bcf78be456e59afb32578bab0abd 100644
--- a/gregui/api/urls.py
+++ b/gregui/api/urls.py
@@ -1,5 +1,6 @@
 from django.urls import re_path, path
 from rest_framework.routers import DefaultRouter
+from gregui.api.views.identity import IdentityViewSet
 
 from gregui.api.views.invitation import (
     CheckInvitationView,
@@ -14,6 +15,7 @@ from gregui.api.views.unit import UnitsViewSet
 
 router = DefaultRouter(trailing_slash=False)
 router.register(r"role", RoleInfoViewSet, basename="role")
+router.register(r"identity", IdentityViewSet, basename="identity")
 
 urlpatterns = router.urls
 urlpatterns += [
diff --git a/gregui/api/views/identity.py b/gregui/api/views/identity.py
new file mode 100644
index 0000000000000000000000000000000000000000..18c88586611af8ad85e7a291b9bb115960d6a9ea
--- /dev/null
+++ b/gregui/api/views/identity.py
@@ -0,0 +1,31 @@
+from rest_framework.authentication import SessionAuthentication, BasicAuthentication
+from rest_framework.permissions import IsAuthenticated
+from rest_framework.viewsets import GenericViewSet
+from rest_framework import mixins
+from rest_framework.exceptions import MethodNotAllowed
+from greg.models import Identity
+from greg.permissions import IsSponsor
+from gregui.api.serializers.identity import IdentitySerializer
+from gregui.models import GregUserProfile
+
+
+class IdentityViewSet(
+    mixins.RetrieveModelMixin,
+    mixins.UpdateModelMixin,
+    GenericViewSet,
+):
+    """
+    Fetch or update identity info for any guest as long as you are a sponsor.
+
+    This is required for when a host(sponsor) needs to verify the identity of a guest
+    so that they are considered "active".
+
+    Limited to GET and PATCH so that we can only update or get a single identity at a
+    time.
+    """
+
+    queryset = Identity.objects.all()
+    authentication_classes = [SessionAuthentication, BasicAuthentication]
+    permission_classes = [IsAuthenticated, IsSponsor]
+    serializer_class = IdentitySerializer
+    http_method_names = ["get", "patch"]