diff --git a/keyserver/src/responders/user-responders.js b/keyserver/src/responders/user-responders.js
--- a/keyserver/src/responders/user-responders.js
+++ b/keyserver/src/responders/user-responders.js
@@ -293,7 +293,18 @@
   return response;
 }
 
-async function siweAuthResponder(): Promise<string> {
+const siweAuthRequestInputValidator = tShape({
+  signature: t.String,
+  message: t.String,
+  calendarQuery: t.maybe(entryQueryInputValidator),
+  deviceTokenUpdateRequest: t.maybe(deviceTokenUpdateRequestInputValidator),
+  platformDetails: tPlatformDetails,
+  watchedIDs: t.list(t.String),
+});
+
+async function siweAuthResponder(viewer: Viewer, input: any): Promise<string> {
+  await validateInput(viewer, siweAuthRequestInputValidator, input);
+
   return 'UNIMPLEMENTED';
 }
 
diff --git a/lib/types/siwe-types.js b/lib/types/siwe-types.js
--- a/lib/types/siwe-types.js
+++ b/lib/types/siwe-types.js
@@ -1,9 +1,24 @@
 // @flow
 
+import {
+  type DeviceTokenUpdateRequest,
+  type PlatformDetails,
+} from './device-types';
+import { type CalendarQuery } from './entry-types';
+
 export type SIWENonceResponse = {
   +nonce: string,
 };
 
+export type SIWEAuthRequest = {
+  +message: string,
+  +signature: string,
+  +calendarQuery?: ?CalendarQuery,
+  +deviceTokenUpdateRequest?: ?DeviceTokenUpdateRequest,
+  +platformDetails: PlatformDetails,
+  +watchedIDs: $ReadOnlyArray<string>,
+};
+
 // This is a message that the rendered webpage (landing/siwe.react.js) uses to
 // communicate back to the React Native WebView that is rendering it
 // (native/account/siwe-panel.react.js)