diff --git a/keyserver/src/responders/handlers.js b/keyserver/src/responders/handlers.js
--- a/keyserver/src/responders/handlers.js
+++ b/keyserver/src/responders/handlers.js
@@ -15,6 +15,7 @@
 } from '../session/cookies';
 import type { Viewer } from '../session/viewer';
 import { type AppURLFacts, getAppURLFactsFromRequestURL } from '../utils/urls';
+import { policiesValidator } from '../utils/validation-utils.js';
 import { getMessageForException } from './utils';
 
 export type JSONResponder = {
@@ -42,6 +43,7 @@
       }
       const { input } = req.body;
       viewer = await fetchViewerForJSONRequest(req);
+      await policiesValidator(viewer, responder.requiredPolicies);
       const responderResult = await responder.responder(viewer, input);
       if (res.headersSent) {
         return;
diff --git a/keyserver/src/socket/socket.js b/keyserver/src/socket/socket.js
--- a/keyserver/src/socket/socket.js
+++ b/keyserver/src/socket/socket.js
@@ -75,6 +75,7 @@
 import {
   checkInputValidator,
   checkClientSupported,
+  policiesValidator,
 } from '../utils/validation-utils';
 import { RedisSubscriber } from './redis';
 import {
@@ -628,6 +629,7 @@
     const { viewer } = this;
     invariant(viewer, 'should be set');
     const responder = jsonEndpoints[message.payload.endpoint];
+    await policiesValidator(viewer, responder.requiredPolicies);
     const response = await responder.responder(viewer, message.payload.input);
     return [
       {
diff --git a/keyserver/src/utils/validation-utils.js b/keyserver/src/utils/validation-utils.js
--- a/keyserver/src/utils/validation-utils.js
+++ b/keyserver/src/utils/validation-utils.js
@@ -1,5 +1,7 @@
 // @flow
 
+import type { PolicyType } from 'lib/facts/policies.js';
+import { hasMinCodeVersion } from 'lib/shared/version-utils.js';
 import { ServerError } from 'lib/utils/errors';
 import {
   tCookie,
@@ -8,6 +10,7 @@
   tPlatformDetails,
 } from 'lib/utils/validation-utils';
 
+import { fetchPolicyAcknowledgments } from '../fetchers/policy-acknowledgment-fetchers.js';
 import { verifyClientSupported } from '../session/version';
 import type { Viewer } from '../session/viewer';
 
@@ -153,4 +156,38 @@
   return null;
 }
 
-export { validateInput, checkInputValidator, checkClientSupported };
+async function policiesValidator(
+  viewer: Viewer,
+  policies: $ReadOnlyArray<PolicyType>,
+) {
+  if (!policies.length) {
+    return;
+  }
+  if (!hasMinCodeVersion(viewer.platformDetails, 1000)) {
+    return;
+  }
+
+  const viewerAcknowledgments = await fetchPolicyAcknowledgments(
+    viewer,
+    policies,
+  );
+  const notAcknowledgedPolicies = policies.filter(policy => {
+    const policyAcknowledgment = viewerAcknowledgments.find(
+      viewerAcknowledgment => viewerAcknowledgment.policy === policy,
+    );
+    return !policyAcknowledgment?.confirmed;
+  });
+
+  if (notAcknowledgedPolicies.length) {
+    throw new ServerError('policies_not_accepted', {
+      notAcknowledgedPolicies,
+    });
+  }
+}
+
+export {
+  validateInput,
+  checkInputValidator,
+  checkClientSupported,
+  policiesValidator,
+};