summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-09-26 22:08:14 +1000
committerMadeline <46743919+MaddyUnderStars@users.noreply.github.com>2022-09-26 22:08:14 +1000
commit849b257db7d43c2f1d13d9620ce7f6ba9dfd3e50 (patch)
tree37c9af175c98116a0f48ca2d5c8b74f291b3ce85 /src
parentFix scripts/benchmark/connections.js (diff)
downloadserver-849b257db7d43c2f1d13d9620ce7f6ba9dfd3e50.tar.xz
Move schemas to /src/util/schemas
Diffstat (limited to 'src')
-rw-r--r--src/api/routes/auth/login.ts11
-rw-r--r--src/api/routes/auth/mfa/totp.ts9
-rw-r--r--src/api/routes/auth/register.ts31
-rw-r--r--src/api/routes/auth/verify/view-backup-codes-challenge.ts6
-rw-r--r--src/api/routes/channels/#channel_id/index.ts33
-rw-r--r--src/api/routes/channels/#channel_id/invites.ts12
-rw-r--r--src/api/routes/channels/#channel_id/messages/#message_id/ack.ts7
-rw-r--r--src/api/routes/channels/#channel_id/messages/#message_id/index.ts6
-rw-r--r--src/api/routes/channels/#channel_id/messages/bulk-delete.ts5
-rw-r--r--src/api/routes/channels/#channel_id/messages/index.ts35
-rw-r--r--src/api/routes/channels/#channel_id/purge.ts14
-rw-r--r--src/api/routes/channels/#channel_id/webhooks.ts11
-rw-r--r--src/api/routes/guilds/#guild_id/audit-logs.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/bans.ts24
-rw-r--r--src/api/routes/guilds/#guild_id/channels.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/emojis.ts14
-rw-r--r--src/api/routes/guilds/#guild_id/index.ts4
-rw-r--r--src/api/routes/guilds/#guild_id/integrations.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/members/#member_id/index.ts8
-rw-r--r--src/api/routes/guilds/#guild_id/members/#member_id/nick.ts4
-rw-r--r--src/api/routes/guilds/#guild_id/prune.ts7
-rw-r--r--src/api/routes/guilds/#guild_id/roles/#role_id/index.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/roles/index.ts15
-rw-r--r--src/api/routes/guilds/#guild_id/stickers.ts20
-rw-r--r--src/api/routes/guilds/#guild_id/templates.ts10
-rw-r--r--src/api/routes/guilds/#guild_id/vanity-url.ts10
-rw-r--r--src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts12
-rw-r--r--src/api/routes/guilds/#guild_id/webhooks.ts3
-rw-r--r--src/api/routes/guilds/#guild_id/welcome-screen.ts13
-rw-r--r--src/api/routes/guilds/#guild_id/widget.ts7
-rw-r--r--src/api/routes/guilds/index.ts16
-rw-r--r--src/api/routes/guilds/templates/index.ts7
-rw-r--r--src/api/routes/users/@me/channels.ts7
-rw-r--r--src/api/routes/users/@me/index.ts22
-rw-r--r--src/api/routes/users/@me/mfa/codes-verification.ts8
-rw-r--r--src/api/routes/users/@me/mfa/codes.ts7
-rw-r--r--src/api/routes/users/@me/mfa/totp/disable.ts6
-rw-r--r--src/api/routes/users/@me/mfa/totp/enable.ts9
-rw-r--r--src/api/routes/users/@me/relationships.ts9
-rw-r--r--src/api/util/handlers/Message.ts2
-rw-r--r--src/gateway/events/Message.ts20
-rw-r--r--src/gateway/opcodes/Identify.ts2
-rw-r--r--src/gateway/opcodes/LazyRequest.ts7
-rw-r--r--src/gateway/opcodes/PresenceUpdate.ts3
-rw-r--r--src/gateway/opcodes/VoiceStateUpdate.ts2
-rw-r--r--src/util/schemas/ActivitySchema.ts (renamed from src/gateway/schema/Activity.ts)2
-rw-r--r--src/util/schemas/BackupCodesChallengeSchema.ts3
-rw-r--r--src/util/schemas/BanCreateSchema.ts4
-rw-r--r--src/util/schemas/BanModeratorSchema.ts7
-rw-r--r--src/util/schemas/BanRegistrySchema.ts8
-rw-r--r--src/util/schemas/BulkDeleteSchema.ts3
-rw-r--r--src/util/schemas/ChannelModifySchema.ts30
-rw-r--r--src/util/schemas/CodesVerificationSchema.ts5
-rw-r--r--src/util/schemas/DmChannelCreateSchema.ts4
-rw-r--r--src/util/schemas/EmojiCreateSchema.ts6
-rw-r--r--src/util/schemas/EmojiModifySchema.ts4
-rw-r--r--src/util/schemas/GuildCreateSchema.ts14
-rw-r--r--src/util/schemas/GuildTemplateCreateSchema.ts4
-rw-r--r--src/util/schemas/GuildUpdateWelcomeScreenSchema.ts10
-rw-r--r--src/util/schemas/IdentifySchema.ts (renamed from src/gateway/schema/Identify.ts)2
-rw-r--r--src/util/schemas/InviteCreateSchema.ts11
-rw-r--r--src/util/schemas/LazyRequestSchema.ts (renamed from src/gateway/schema/LazyRequest.ts)4
-rw-r--r--src/util/schemas/LoginSchema.ts8
-rw-r--r--src/util/schemas/MemberChangeSchema.ts4
-rw-r--r--src/util/schemas/MemberNickChangeSchema.ts3
-rw-r--r--src/util/schemas/MessageAcknowledgeSchema.ts4
-rw-r--r--src/util/schemas/MessageCreateSchema.ts33
-rw-r--r--src/util/schemas/MfaCodesSchema.ts4
-rw-r--r--src/util/schemas/ModifyGuildStickerSchema.ts15
-rw-r--r--src/util/schemas/PruneSchema.ts6
-rw-r--r--src/util/schemas/PurgeSchema.ts4
-rw-r--r--src/util/schemas/RegisterSchema.ts27
-rw-r--r--src/util/schemas/RelationshipPostSchema.ts4
-rw-r--r--src/util/schemas/RelationshipPutSchema.ts5
-rw-r--r--src/util/schemas/RoleModifySchema.ts10
-rw-r--r--src/util/schemas/SelectProtocolSchema.ts19
-rw-r--r--src/util/schemas/TemplateCreateSchema.ts4
-rw-r--r--src/util/schemas/TemplateModifySchema.ts4
-rw-r--r--src/util/schemas/TotpDisableSchema.ts3
-rw-r--r--src/util/schemas/TotpEnableSchema.ts5
-rw-r--r--src/util/schemas/TotpSchema.ts6
-rw-r--r--src/util/schemas/UserModifySchema.ts19
-rw-r--r--src/util/schemas/VanityUrlSchema.ts7
-rw-r--r--src/util/schemas/VoiceIdentifySchema.ts12
-rw-r--r--src/util/schemas/VoiceStateUpdateSchema.ts (renamed from src/gateway/schema/VoiceStateUpdateSchema.ts)25
-rw-r--r--src/util/schemas/VoiceVideoSchema.ts17
-rw-r--r--src/util/schemas/WebhookCreateSchema.ts8
-rw-r--r--src/util/schemas/WidgetModifySchema.ts4
-rw-r--r--src/util/schemas/index.ts41
-rw-r--r--src/util/schemas/voice.ts69
90 files changed, 458 insertions, 503 deletions
diff --git a/src/api/routes/auth/login.ts b/src/api/routes/auth/login.ts
index bcaccb30..9bed5aab 100644
--- a/src/api/routes/auth/login.ts
+++ b/src/api/routes/auth/login.ts
@@ -1,21 +1,12 @@
 import { Request, Response, Router } from "express";
 import { route, getIpAdress, verifyCaptcha } from "@fosscord/api";
 import bcrypt from "bcrypt";
-import { Config, User, generateToken, adjustEmail, FieldErrors } from "@fosscord/util";
+import { Config, User, generateToken, adjustEmail, FieldErrors, LoginSchema } from "@fosscord/util";
 import crypto from "crypto";
 
 const router: Router = Router();
 export default router;
 
-export interface LoginSchema {
-	login: string;
-	password: string;
-	undelete?: boolean;
-	captcha_key?: string;
-	login_source?: string;
-	gift_code_sku_id?: string;
-}
-
 router.post("/", route({ body: "LoginSchema" }), async (req: Request, res: Response) => {
 	const { login, password, captcha_key, undelete } = req.body as LoginSchema;
 	const email = adjustEmail(login);
diff --git a/src/api/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts
index 50b9e9c8..96a48b66 100644
--- a/src/api/routes/auth/mfa/totp.ts
+++ b/src/api/routes/auth/mfa/totp.ts
@@ -1,17 +1,10 @@
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { BackupCode, FieldErrors, generateToken, User } from "@fosscord/util";
+import { BackupCode, generateToken, User, TotpSchema } from "@fosscord/util";
 import { verifyToken } from "node-2fa";
 import { HTTPError } from "lambert-server";
 const router = Router();
 
-export interface TotpSchema {
-	code: string,
-	ticket: string,
-	gift_code_sku_id?: string | null,
-	login_source?: string | null,
-}
-
 router.post("/", route({ body: "TotpSchema" }), async (req: Request, res: Response) => {
 	const { code, ticket, gift_code_sku_id, login_source } = req.body as TotpSchema;
 
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index b7122dad..84f8f838 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -1,40 +1,11 @@
 import { Request, Response, Router } from "express";
-import { Config, generateToken, Invite, FieldErrors, User, adjustEmail } from "@fosscord/util";
+import { Config, generateToken, Invite, FieldErrors, User, adjustEmail, RegisterSchema } from "@fosscord/util";
 import { route, getIpAdress, IPAnalysis, isProxy, verifyCaptcha } from "@fosscord/api";
-import "missing-native-js-functions";
 import bcrypt from "bcrypt";
 import { HTTPError } from "lambert-server";
 
 const router: Router = Router();
 
-export interface RegisterSchema {
-	/**
-	 * @minLength 2
-	 * @maxLength 32
-	 */
-	username: string;
-	/**
-	 * @minLength 1
-	 * @maxLength 72
-	 */
-	password?: string;
-	consent: boolean;
-	/**
-	 * @TJS-format email
-	 */
-	email?: string;
-	fingerprint?: string;
-	invite?: string;
-	/**
-	 * @TJS-type string
-	 */
-	date_of_birth?: Date; // "2000-04-03"
-	gift_code_sku_id?: string;
-	captcha_key?: string;
-
-	promotional_email_opt_in?: boolean;
-}
-
 router.post("/", route({ body: "RegisterSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as RegisterSchema;
 	const { register, security } = Config.get();
diff --git a/src/api/routes/auth/verify/view-backup-codes-challenge.ts b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
index 36bfeb0c..24de8ec5 100644
--- a/src/api/routes/auth/verify/view-backup-codes-challenge.ts
+++ b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
@@ -1,13 +1,9 @@
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { FieldErrors, User } from "@fosscord/util";
+import { FieldErrors, User, BackupCodesChallengeSchema } from "@fosscord/util";
 import bcrypt from "bcrypt";
 const router = Router();
 
-export interface BackupCodesChallengeSchema {
-	password: string;
-}
-
 router.post("/", route({ body: "BackupCodesChallengeSchema" }), async (req: Request, res: Response) => {
 	const { password } = req.body as BackupCodesChallengeSchema;
 
diff --git a/src/api/routes/channels/#channel_id/index.ts b/src/api/routes/channels/#channel_id/index.ts
index 0340a616..8dbefe1b 100644
--- a/src/api/routes/channels/#channel_id/index.ts
+++ b/src/api/routes/channels/#channel_id/index.ts
@@ -1,12 +1,12 @@
 import {
 	Channel,
 	ChannelDeleteEvent,
-	ChannelPermissionOverwriteType,
 	ChannelType,
 	ChannelUpdateEvent,
 	emitEvent,
 	Recipient,
-	handleFile
+	handleFile,
+	ChannelModifySchema
 } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import { route } from "@fosscord/api";
@@ -47,35 +47,6 @@ router.delete("/", route({ permission: "MANAGE_CHANNELS" }), async (req: Request
 	res.send(channel);
 });
 
-export interface ChannelModifySchema {
-	/**
-	 * @maxLength 100
-	 */
-	name?: string;
-	type?: ChannelType;
-	topic?: string;
-	icon?: string | null;
-	bitrate?: number;
-	user_limit?: number;
-	rate_limit_per_user?: number;
-	position?: number;
-	permission_overwrites?: {
-		id: string;
-		type: ChannelPermissionOverwriteType;
-		allow: string;
-		deny: string;
-	}[];
-	parent_id?: string;
-	id?: string; // is not used (only for guild create)
-	nsfw?: boolean;
-	rtc_region?: string;
-	default_auto_archive_duration?: number;
-	default_reaction_emoji?: string | null;
-	flags?: number;
-	default_thread_rate_limit_per_user?: number;
-	video_quality_mode?: number;
-}
-
 router.patch("/", route({ body: "ChannelModifySchema", permission: "MANAGE_CHANNELS" }), async (req: Request, res: Response) => {
 	var payload = req.body as ChannelModifySchema;
 	const { channel_id } = req.params;
diff --git a/src/api/routes/channels/#channel_id/invites.ts b/src/api/routes/channels/#channel_id/invites.ts
index fd8339ad..246a2c69 100644
--- a/src/api/routes/channels/#channel_id/invites.ts
+++ b/src/api/routes/channels/#channel_id/invites.ts
@@ -7,18 +7,6 @@ import { isTextChannel } from "./messages";
 
 const router: Router = Router();
 
-export interface InviteCreateSchema {
-	target_user_id?: string;
-	target_type?: string;
-	validate?: string; // ? what is this
-	max_age?: number;
-	max_uses?: number;
-	temporary?: boolean;
-	unique?: boolean;
-	target_user?: string;
-	target_user_type?: number;
-}
-
 router.post("/", route({ body: "InviteCreateSchema", permission: "CREATE_INSTANT_INVITE", right: "CREATE_INVITES" }),
 	async (req: Request, res: Response) => {
 		const { user_id } = req;
diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts b/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts
index 3abae7ce..bedd453c 100644
--- a/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/ack.ts
@@ -1,4 +1,4 @@
-import { emitEvent, getPermission, MessageAckEvent, ReadState, Snowflake } from "@fosscord/util";
+import { emitEvent, getPermission, MessageAckEvent, ReadState } from "@fosscord/util";
 import { Request, Response, Router } from "express";
 import { route } from "@fosscord/api";
 
@@ -8,11 +8,6 @@ const router = Router();
 // TODO: send read state event to all channel members
 // TODO: advance-only notification cursor
 
-export interface MessageAcknowledgeSchema {
-	manual?: boolean;
-	mention_count?: number;
-}
-
 router.post("/", route({ body: "MessageAcknowledgeSchema" }), async (req: Request, res: Response) => {
 	const { channel_id, message_id } = req.params;
 
diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
index a02a9abe..46b0d6bd 100644
--- a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts
@@ -1,8 +1,6 @@
 import {
 	Attachment,
 	Channel,
-	Embed,
-	DiscordApiErrors,
 	emitEvent,
 	FosscordApiErrors,
 	getPermission,
@@ -12,13 +10,13 @@ import {
 	MessageDeleteEvent,
 	MessageUpdateEvent,
 	Snowflake,
-	uploadFile
+	uploadFile,
+	MessageCreateSchema,
 } from "@fosscord/util";
 import { Router, Response, Request } from "express";
 import multer from "multer";
 import { route } from "@fosscord/api";
 import { handleMessage, postHandleMessage } from "@fosscord/api";
-import { MessageCreateSchema } from "../index";
 import { HTTPError } from "lambert-server";
 
 const router = Router();
diff --git a/src/api/routes/channels/#channel_id/messages/bulk-delete.ts b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
index b6fd37f4..6493c16a 100644
--- a/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
+++ b/src/api/routes/channels/#channel_id/messages/bulk-delete.ts
@@ -2,16 +2,11 @@ import { Router, Response, Request } from "express";
 import { Channel, Config, emitEvent, getPermission, getRights, MessageDeleteBulkEvent, Message } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { In } from "typeorm";
 
 const router: Router = Router();
 
 export default router;
 
-export interface BulkDeleteSchema {
-	messages: string[];
-}
-
 // should users be able to bulk delete messages or only bots? ANSWER: all users
 // should this request fail, if you provide messages older than 14 days/invalid ids? ANSWER: NO
 // https://discord.com/developers/docs/resources/channel#bulk-delete-messages
diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts
index 154dc8ed..bee93e80 100644
--- a/src/api/routes/channels/#channel_id/messages/index.ts
+++ b/src/api/routes/channels/#channel_id/messages/index.ts
@@ -5,16 +5,15 @@ import {
 	ChannelType,
 	Config,
 	DmChannelDTO,
-	Embed,
 	emitEvent,
 	getPermission,
-	getRights,
 	Message,
 	MessageCreateEvent,
 	Snowflake,
 	uploadFile,
 	Member,
 	Role,
+	MessageCreateSchema,
 } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { handleMessage, postHandleMessage, route } from "@fosscord/api";
@@ -50,38 +49,6 @@ export function isTextChannel(type: ChannelType): boolean {
 	}
 }
 
-export interface MessageCreateSchema {
-	type?: number;
-	content?: string;
-	nonce?: string;
-	channel_id?: string;
-	tts?: boolean;
-	flags?: string;
-	embeds?: Embed[];
-	embed?: Embed;
-	// TODO: ^ embed is deprecated in favor of embeds (https://discord.com/developers/docs/resources/channel#message-object)
-	allowed_mentions?: {
-		parse?: string[];
-		roles?: string[];
-		users?: string[];
-		replied_user?: boolean;
-	};
-	message_reference?: {
-		message_id: string;
-		channel_id: string;
-		guild_id?: string;
-		fail_if_not_exists?: boolean;
-	};
-	payload_json?: string;
-	file?: any;
-	/**
-	TODO: we should create an interface for attachments
-	TODO: OpenWAAO<-->attachment-style metadata conversion
-	**/
-	attachments?: any[];
-	sticker_ids?: string[];
-}
-
 // https://discord.com/developers/docs/resources/channel#create-message
 // get messages
 router.get("/", async (req: Request, res: Response) => {
diff --git a/src/api/routes/channels/#channel_id/purge.ts b/src/api/routes/channels/#channel_id/purge.ts
index bfac27ee..9fe6b658 100644
--- a/src/api/routes/channels/#channel_id/purge.ts
+++ b/src/api/routes/channels/#channel_id/purge.ts
@@ -3,33 +3,21 @@ import { route } from "@fosscord/api";
 import { isTextChannel } from "./messages";
 import { FindManyOptions, Between, Not } from "typeorm";
 import {
-	Attachment,
 	Channel,
 	Config,
-	Embed,
-	DiscordApiErrors,
 	emitEvent,
-	FosscordApiErrors,
 	getPermission,
 	getRights,
 	Message,
 	MessageDeleteBulkEvent,
-	Snowflake,
-	uploadFile
+	PurgeSchema,
 } from "@fosscord/util";
 import { Router, Response, Request } from "express";
-import multer from "multer";
-import { handleMessage, postHandleMessage } from "@fosscord/api";
 
 const router: Router = Router();
 
 export default router;
 
-export interface PurgeSchema {
-	before: string;
-	after: string;
-}
-
 /**
 TODO: apply the delete bit by bit to prevent client and database stress
 **/
diff --git a/src/api/routes/channels/#channel_id/webhooks.ts b/src/api/routes/channels/#channel_id/webhooks.ts
index 93f70a41..99c104ca 100644
--- a/src/api/routes/channels/#channel_id/webhooks.ts
+++ b/src/api/routes/channels/#channel_id/webhooks.ts
@@ -1,19 +1,12 @@
 import { Router, Response, Request } from "express";
 import { route } from "@fosscord/api";
-import { Channel, Config, getPermission, trimSpecial, Webhook } from "@fosscord/util";
+import { Channel, Config, trimSpecial, Webhook } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { isTextChannel } from "./messages/index";
 import { DiscordApiErrors } from "@fosscord/util";
 
 const router: Router = Router();
-// TODO: webhooks
-export interface WebhookCreateSchema {
-	/**
-	 * @maxLength 80
-	 */
-	name: string;
-	avatar: string;
-}
+
 //TODO: implement webhooks
 router.get("/", route({}), async (req: Request, res: Response) => {
 	res.json([]);
diff --git a/src/api/routes/guilds/#guild_id/audit-logs.ts b/src/api/routes/guilds/#guild_id/audit-logs.ts
index a4f2f800..b54835fc 100644
--- a/src/api/routes/guilds/#guild_id/audit-logs.ts
+++ b/src/api/routes/guilds/#guild_id/audit-logs.ts
@@ -1,8 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
 const router = Router();
 
 //TODO: implement audit logs
diff --git a/src/api/routes/guilds/#guild_id/bans.ts b/src/api/routes/guilds/#guild_id/bans.ts
index 51d3ca67..ed00f9c0 100644
--- a/src/api/routes/guilds/#guild_id/bans.ts
+++ b/src/api/routes/guilds/#guild_id/bans.ts
@@ -1,30 +1,8 @@
 import { Request, Response, Router } from "express";
-import { DiscordApiErrors, emitEvent, GuildBanAddEvent, GuildBanRemoveEvent, Ban, User, Member } from "@fosscord/util";
+import { DiscordApiErrors, emitEvent, GuildBanAddEvent, GuildBanRemoveEvent, Ban, User, Member, BanRegistrySchema, BanModeratorSchema } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { getIpAdress, route } from "@fosscord/api";
 
-export interface BanCreateSchema {
-	delete_message_days?: string;
-	reason?: string;
-};
-
-export interface BanRegistrySchema {
-	id: string;
-	user_id: string;
-	guild_id: string;
-	executor_id: string;
-	ip?: string;
-	reason?: string | undefined;
-};
-
-export interface BanModeratorSchema {
-	id: string;
-	user_id: string;
-	guild_id: string;
-	executor_id: string;
-	reason?: string | undefined;
-};
-
 const router: Router = Router();
 
 /* TODO: Deleting the secrets is just a temporary go-around. Views should be implemented for both safety and better handling. */
diff --git a/src/api/routes/guilds/#guild_id/channels.ts b/src/api/routes/guilds/#guild_id/channels.ts
index 11f727fc..7a5b50d1 100644
--- a/src/api/routes/guilds/#guild_id/channels.ts
+++ b/src/api/routes/guilds/#guild_id/channels.ts
@@ -1,8 +1,7 @@
 import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
+import { Channel, ChannelUpdateEvent, emitEvent, ChannelModifySchema } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
 const router = Router();
 
 router.get("/", route({}), async (req: Request, res: Response) => {
diff --git a/src/api/routes/guilds/#guild_id/emojis.ts b/src/api/routes/guilds/#guild_id/emojis.ts
index 75998e04..cf9d742a 100644
--- a/src/api/routes/guilds/#guild_id/emojis.ts
+++ b/src/api/routes/guilds/#guild_id/emojis.ts
@@ -1,21 +1,9 @@
 import { Router, Request, Response } from "express";
-import { Config, DiscordApiErrors, emitEvent, Emoji, GuildEmojisUpdateEvent, handleFile, Member, Snowflake, User } from "@fosscord/util";
+import { Config, DiscordApiErrors, emitEvent, Emoji, GuildEmojisUpdateEvent, handleFile, Member, Snowflake, User, EmojiCreateSchema, EmojiModifySchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 
 const router = Router();
 
-export interface EmojiCreateSchema {
-	name?: string;
-	image: string;
-	require_colons?: boolean | null;
-	roles?: string[];
-}
-
-export interface EmojiModifySchema {
-	name?: string;
-	roles?: string[];
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
 
diff --git a/src/api/routes/guilds/#guild_id/index.ts b/src/api/routes/guilds/#guild_id/index.ts
index 45bbe348..afeb0938 100644
--- a/src/api/routes/guilds/#guild_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/index.ts
@@ -1,9 +1,7 @@
 import { Request, Response, Router } from "express";
-import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpdateEvent, handleFile, Member } from "@fosscord/util";
+import { DiscordApiErrors, emitEvent, getPermission, getRights, Guild, GuildUpdateEvent, handleFile, Member, GuildCreateSchema } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import "missing-native-js-functions";
-import { GuildCreateSchema } from "../index";
 
 const router = Router();
 
diff --git a/src/api/routes/guilds/#guild_id/integrations.ts b/src/api/routes/guilds/#guild_id/integrations.ts
index abf997c9..a8e78062 100644
--- a/src/api/routes/guilds/#guild_id/integrations.ts
+++ b/src/api/routes/guilds/#guild_id/integrations.ts
@@ -1,8 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
 const router = Router();
 
 //TODO: implement integrations list
diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
index d785eb00..407619d3 100644
--- a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts
@@ -1,15 +1,9 @@
 import { Request, Response, Router } from "express";
-import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Rights, Guild } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
+import { Member, getPermission, getRights, Role, GuildMemberUpdateEvent, emitEvent, Sticker, Emoji, Guild, MemberChangeSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 
 const router = Router();
 
-export interface MemberChangeSchema {
-	roles?: string[];
-	nick?: string;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id, member_id } = req.params;
 	await Member.IsInGuildOrFail(req.user_id, guild_id);
diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts b/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
index 27f7f65d..edd47605 100644
--- a/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
+++ b/src/api/routes/guilds/#guild_id/members/#member_id/nick.ts
@@ -4,10 +4,6 @@ import { Request, Response, Router } from "express";
 
 const router = Router();
 
-export interface MemberNickChangeSchema {
-	nick: string;
-}
-
 router.patch("/", route({ body: "MemberNickChangeSchema" }), async (req: Request, res: Response) => {
 	var { guild_id, member_id } = req.params;
 	var permissionString: PermissionResolvable = "MANAGE_NICKNAMES";
diff --git a/src/api/routes/guilds/#guild_id/prune.ts b/src/api/routes/guilds/#guild_id/prune.ts
index cf3466f1..2e674349 100644
--- a/src/api/routes/guilds/#guild_id/prune.ts
+++ b/src/api/routes/guilds/#guild_id/prune.ts
@@ -62,13 +62,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
 	res.send({ pruned: members.length });
 });
 
-export interface PruneSchema {
-	/**
-	 * @min 0
-	 */
-	days: number;
-}
-
 router.post("/", route({ permission: "KICK_MEMBERS", right: "KICK_BAN_MEMBERS" }), async (req: Request, res: Response) => {
 	const days = parseInt(req.body.days);
 
diff --git a/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
index a01068c0..87cf5261 100644
--- a/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts
@@ -1,8 +1,7 @@
 import { Router, Request, Response } from "express";
-import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile } from "@fosscord/util";
+import { Role, Member, GuildRoleUpdateEvent, GuildRoleDeleteEvent, emitEvent, handleFile, RoleModifySchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import { HTTPError } from "lambert-server";
-import { RoleModifySchema } from "../";
 
 const router = Router();
 
diff --git a/src/api/routes/guilds/#guild_id/roles/index.ts b/src/api/routes/guilds/#guild_id/roles/index.ts
index 7e839f08..c5a86400 100644
--- a/src/api/routes/guilds/#guild_id/roles/index.ts
+++ b/src/api/routes/guilds/#guild_id/roles/index.ts
@@ -5,28 +5,15 @@ import {
 	Member,
 	GuildRoleCreateEvent,
 	GuildRoleUpdateEvent,
-	GuildRoleDeleteEvent,
 	emitEvent,
 	Config,
 	DiscordApiErrors,
-	handleFile
+	RoleModifySchema,
 } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
 
 const router: Router = Router();
 
-export interface RoleModifySchema {
-	name?: string;
-	permissions?: string;
-	color?: number;
-	hoist?: boolean; // whether the role should be displayed separately in the sidebar
-	mentionable?: boolean; // whether the role should be mentionable
-	position?: number;
-	icon?: string;
-	unicode_emoji?: string;
-}
-
 export type RolePositionUpdateSchema = {
 	id: string;
 	position: number;
diff --git a/src/api/routes/guilds/#guild_id/stickers.ts b/src/api/routes/guilds/#guild_id/stickers.ts
index 7a4e71ee..fc0f49ab 100644
--- a/src/api/routes/guilds/#guild_id/stickers.ts
+++ b/src/api/routes/guilds/#guild_id/stickers.ts
@@ -1,13 +1,13 @@
 import {
 	emitEvent,
 	GuildStickersUpdateEvent,
-	handleFile,
 	Member,
 	Snowflake,
 	Sticker,
 	StickerFormatType,
 	StickerType,
-	uploadFile
+	uploadFile,
+	ModifyGuildStickerSchema,
 } from "@fosscord/util";
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
@@ -82,22 +82,6 @@ router.get("/:sticker_id", route({}), async (req: Request, res: Response) => {
 	res.json(await Sticker.findOneOrFail({ where: { guild_id, id: sticker_id } }));
 });
 
-export interface ModifyGuildStickerSchema {
-	/**
-	 * @minLength 2
-	 * @maxLength 30
-	 */
-	name: string;
-	/**
-	 * @maxLength 100
-	 */
-	description?: string;
-	/**
-	 * @maxLength 200
-	 */
-	tags: string;
-}
-
 router.patch(
 	"/:sticker_id",
 	route({ body: "ModifyGuildStickerSchema", permission: "MANAGE_EMOJIS_AND_STICKERS" }),
diff --git a/src/api/routes/guilds/#guild_id/templates.ts b/src/api/routes/guilds/#guild_id/templates.ts
index 0444c402..628321f5 100644
--- a/src/api/routes/guilds/#guild_id/templates.ts
+++ b/src/api/routes/guilds/#guild_id/templates.ts
@@ -23,16 +23,6 @@ const TemplateGuildProjection: (keyof Guild)[] = [
 	"icon"
 ];
 
-export interface TemplateCreateSchema {
-	name: string;
-	description?: string;
-}
-
-export interface TemplateModifySchema {
-	name: string;
-	description?: string;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
 
diff --git a/src/api/routes/guilds/#guild_id/vanity-url.ts b/src/api/routes/guilds/#guild_id/vanity-url.ts
index 040bc1fd..d1fe4726 100644
--- a/src/api/routes/guilds/#guild_id/vanity-url.ts
+++ b/src/api/routes/guilds/#guild_id/vanity-url.ts
@@ -1,4 +1,4 @@
-import { Channel, ChannelType, getPermission, Guild, Invite, trimSpecial } from "@fosscord/util";
+import { Channel, ChannelType, Guild, Invite, VanityUrlSchema } from "@fosscord/util";
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
 import { HTTPError } from "lambert-server";
@@ -24,14 +24,6 @@ router.get("/", route({ permission: "MANAGE_GUILD" }), async (req: Request, res:
 	}
 });
 
-export interface VanityUrlSchema {
-	/**
-	 * @minLength 1
-	 * @maxLength 20
-	 */
-	code?: string;
-}
-
 router.patch("/", route({ body: "VanityUrlSchema", permission: "MANAGE_GUILD" }), async (req: Request, res: Response) => {
 	const { guild_id } = req.params;
 	const body = req.body as VanityUrlSchema;
diff --git a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
index b7fdfecd..006e997f 100644
--- a/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
+++ b/src/api/routes/guilds/#guild_id/voice-states/#user_id/index.ts
@@ -1,20 +1,10 @@
-import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent } from "@fosscord/util";
+import { Channel, ChannelType, DiscordApiErrors, emitEvent, getPermission, VoiceState, VoiceStateUpdateEvent, VoiceStateUpdateSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import { Request, Response, Router } from "express";
 
 const router = Router();
 //TODO need more testing when community guild and voice stage channel are working
 
-export interface VoiceStateUpdateSchema {
-	channel_id: string;
-	guild_id?: string;
-	suppress?: boolean;
-	request_to_speak_timestamp?: Date;
-	self_mute?: boolean;
-	self_deaf?: boolean;
-	self_video?: boolean;
-}
-
 router.patch("/", route({ body: "VoiceStateUpdateSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as VoiceStateUpdateSchema;
 	var { guild_id, user_id } = req.params;
diff --git a/src/api/routes/guilds/#guild_id/webhooks.ts b/src/api/routes/guilds/#guild_id/webhooks.ts
index 8b2febea..9c4e8a8d 100644
--- a/src/api/routes/guilds/#guild_id/webhooks.ts
+++ b/src/api/routes/guilds/#guild_id/webhooks.ts
@@ -1,8 +1,5 @@
 import { Router, Response, Request } from "express";
-import { Channel, ChannelUpdateEvent, getPermission, emitEvent } from "@fosscord/util";
-import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../../channels/#channel_id";
 const router = Router();
 
 //TODO: implement webhooks
diff --git a/src/api/routes/guilds/#guild_id/welcome-screen.ts b/src/api/routes/guilds/#guild_id/welcome-screen.ts
index a57255f0..57da062d 100644
--- a/src/api/routes/guilds/#guild_id/welcome-screen.ts
+++ b/src/api/routes/guilds/#guild_id/welcome-screen.ts
@@ -1,21 +1,10 @@
 import { Request, Response, Router } from "express";
-import { Guild, getPermission, Snowflake, Member } from "@fosscord/util";
+import { Guild, Member, GuildUpdateWelcomeScreenSchema } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import { route } from "@fosscord/api";
 
 const router: Router = Router();
 
-export interface GuildUpdateWelcomeScreenSchema {
-	welcome_channels?: {
-		channel_id: string;
-		description: string;
-		emoji_id?: string;
-		emoji_name?: string;
-	}[];
-	enabled?: boolean;
-	description?: string;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	const guild_id = req.params.guild_id;
 
diff --git a/src/api/routes/guilds/#guild_id/widget.ts b/src/api/routes/guilds/#guild_id/widget.ts
index 103f84a3..dbb4cc0c 100644
--- a/src/api/routes/guilds/#guild_id/widget.ts
+++ b/src/api/routes/guilds/#guild_id/widget.ts
@@ -1,12 +1,7 @@
 import { Request, Response, Router } from "express";
-import { Guild } from "@fosscord/util";
+import { Guild, WidgetModifySchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 
-export interface WidgetModifySchema {
-	enabled: boolean; // whether the widget is enabled
-	channel_id: string; // the widget channel id
-}
-
 const router: Router = Router();
 
 // https://discord.com/developers/docs/resources/guild#get-guild-widget-settings
diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts
index d44cd735..0807cb96 100644
--- a/src/api/routes/guilds/index.ts
+++ b/src/api/routes/guilds/index.ts
@@ -1,23 +1,9 @@
 import { Router, Request, Response } from "express";
-import { Role, Guild, Snowflake, Config, getRights, Member, Channel, DiscordApiErrors, handleFile } from "@fosscord/util";
+import { Role, Guild, Config, getRights, Member, DiscordApiErrors, GuildCreateSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
-import { ChannelModifySchema } from "../channels/#channel_id";
 
 const router: Router = Router();
 
-export interface GuildCreateSchema {
-	/**
-	 * @maxLength 100
-	 */
-	name?: string;
-	region?: string;
-	icon?: string | null;
-	channels?: ChannelModifySchema[];
-	guild_template_code?: string;
-	system_channel_id?: string;
-	rules_channel_id?: string;
-}
-
 //TODO: create default channel
 
 router.post("/", route({ body: "GuildCreateSchema", right: "CREATE_GUILDS" }), async (req: Request, res: Response) => {
diff --git a/src/api/routes/guilds/templates/index.ts b/src/api/routes/guilds/templates/index.ts
index e281214f..4e7abcc5 100644
--- a/src/api/routes/guilds/templates/index.ts
+++ b/src/api/routes/guilds/templates/index.ts
@@ -1,15 +1,10 @@
 import { Request, Response, Router } from "express";
-import { Template, Guild, Role, Snowflake, Config, User, Member } from "@fosscord/util";
+import { Template, Guild, Role, Snowflake, Config, Member, GuildTemplateCreateSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import { DiscordApiErrors } from "@fosscord/util";
 import fetch from "node-fetch";
 const router: Router = Router();
 
-export interface GuildTemplateCreateSchema {
-	name: string;
-	avatar?: string | null;
-}
-
 router.get("/:code", route({}), async (req: Request, res: Response) => {
 	const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates;
 	if (!enabled) res.json({ code: 403, message: "Template creation & usage is disabled on this instance." }).sendStatus(403);
diff --git a/src/api/routes/users/@me/channels.ts b/src/api/routes/users/@me/channels.ts
index 78f531e1..ad483529 100644
--- a/src/api/routes/users/@me/channels.ts
+++ b/src/api/routes/users/@me/channels.ts
@@ -1,5 +1,5 @@
 import { Request, Response, Router } from "express";
-import { Recipient, DmChannelDTO, Channel } from "@fosscord/util";
+import { Recipient, DmChannelDTO, Channel, DmChannelCreateSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 
 const router: Router = Router();
@@ -12,11 +12,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
 	res.json(await Promise.all(recipients.map((r) => DmChannelDTO.from(r.channel, [req.user_id]))));
 });
 
-export interface DmChannelCreateSchema {
-	name?: string;
-	recipients: string[];
-}
-
 router.post("/", route({ body: "DmChannelCreateSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as DmChannelCreateSchema;
 	res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name));
diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index 36b62b55..e849b72a 100644
--- a/src/api/routes/users/@me/index.ts
+++ b/src/api/routes/users/@me/index.ts
@@ -1,31 +1,11 @@
 import { Router, Request, Response } from "express";
-import { User, PrivateUserProjection, emitEvent, UserUpdateEvent, handleFile, FieldErrors, adjustEmail, Config } from "@fosscord/util";
+import { User, PrivateUserProjection, emitEvent, UserUpdateEvent, handleFile, FieldErrors, adjustEmail, Config, UserModifySchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import bcrypt from "bcrypt";
 import { HTTPError } from "lambert-server";
 
 const router: Router = Router();
 
-export interface UserModifySchema {
-	/**
-	 * @minLength 1
-	 * @maxLength 100
-	 */
-	username?: string;
-	avatar?: string | null;
-	/**
-	 * @maxLength 1024
-	 */
-	bio?: string;
-	accent_color?: number;
-	banner?: string | null;
-	password?: string;
-	new_password?: string;
-	code?: string;
-	email?: string;
-	discriminator?: string;
-}
-
 router.get("/", route({}), async (req: Request, res: Response) => {
 	res.json(await User.findOne({ select: PrivateUserProjection, where: { id: req.user_id } }));
 });
diff --git a/src/api/routes/users/@me/mfa/codes-verification.ts b/src/api/routes/users/@me/mfa/codes-verification.ts
index 09000d07..071c71fa 100644
--- a/src/api/routes/users/@me/mfa/codes-verification.ts
+++ b/src/api/routes/users/@me/mfa/codes-verification.ts
@@ -1,15 +1,9 @@
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { BackupCode, generateMfaBackupCodes, User } from "@fosscord/util";
+import { BackupCode, generateMfaBackupCodes, User, CodesVerificationSchema } from "@fosscord/util";
 
 const router = Router();
 
-export interface CodesVerificationSchema {
-	key: string;
-	nonce: string;
-	regenerate?: boolean;
-}
-
 router.post("/", route({ body: "CodesVerificationSchema" }), async (req: Request, res: Response) => {
 	const { key, nonce, regenerate } = req.body as CodesVerificationSchema;
 
diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index 67bd3d5b..58466b9c 100644
--- a/src/api/routes/users/@me/mfa/codes.ts
+++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -1,15 +1,10 @@
 import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
-import { BackupCode, FieldErrors, generateMfaBackupCodes, User } from "@fosscord/util";
+import { BackupCode, FieldErrors, generateMfaBackupCodes, User, MfaCodesSchema } from "@fosscord/util";
 import bcrypt from "bcrypt";
 
 const router = Router();
 
-export interface MfaCodesSchema {
-	password: string;
-	regenerate?: boolean;
-}
-
 // TODO: This route is replaced with users/@me/mfa/codes-verification in newer clients
 
 router.post("/", route({ body: "MfaCodesSchema" }), async (req: Request, res: Response) => {
diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index 2d385fda..2fe9355c 100644
--- a/src/api/routes/users/@me/mfa/totp/disable.ts
+++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -2,14 +2,10 @@ import { Router, Request, Response } from "express";
 import { route } from "@fosscord/api";
 import { verifyToken } from 'node-2fa';
 import { HTTPError } from "lambert-server";
-import { User, generateToken, BackupCode } from "@fosscord/util";
+import { User, generateToken, BackupCode, TotpDisableSchema } from "@fosscord/util";
 
 const router = Router();
 
-export interface TotpDisableSchema {
-	code: string;
-}
-
 router.post("/", route({ body: "TotpDisableSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as TotpDisableSchema;
 
diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index e4ce9ce0..adafe180 100644
--- a/src/api/routes/users/@me/mfa/totp/enable.ts
+++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -1,19 +1,12 @@
 import { Router, Request, Response } from "express";
-import { User, generateToken, BackupCode, generateMfaBackupCodes } from "@fosscord/util";
+import { User, generateToken, generateMfaBackupCodes, TotpEnableSchema } from "@fosscord/util";
 import { route } from "@fosscord/api";
 import bcrypt from "bcrypt";
 import { HTTPError } from "lambert-server";
 import { verifyToken } from 'node-2fa';
-import crypto from "crypto";
 
 const router = Router();
 
-export interface TotpEnableSchema {
-	password: string;
-	code?: string;
-	secret?: string;
-}
-
 router.post("/", route({ body: "TotpEnableSchema" }), async (req: Request, res: Response) => {
 	const body = req.body as TotpEnableSchema;
 
diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts
index 00d4da0b..cd33704d 100644
--- a/src/api/routes/users/@me/relationships.ts
+++ b/src/api/routes/users/@me/relationships.ts
@@ -37,10 +37,6 @@ router.get("/", route({}), async (req: Request, res: Response) => {
 	return res.json(related_users);
 });
 
-export interface RelationshipPutSchema {
-	type?: RelationshipType;
-}
-
 router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request, res: Response) => {
 	return await updateRelationship(
 		req,
@@ -50,11 +46,6 @@ router.put("/:id", route({ body: "RelationshipPutSchema" }), async (req: Request
 	);
 });
 
-export interface RelationshipPostSchema {
-	discriminator: string;
-	username: string;
-}
-
 router.post("/", route({ body: "RelationshipPostSchema" }), async (req: Request, res: Response) => {
 	return await updateRelationship(
 		req,
diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 7e91fb7b..0d29c2e6 100644
--- a/src/api/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -22,11 +22,11 @@ import {
 	Attachment,
 	Config,
 	Sticker,
+	MessageCreateSchema,
 } from "@fosscord/util";
 import { HTTPError } from "lambert-server";
 import fetch from "node-fetch";
 import cheerio from "cheerio";
-import { MessageCreateSchema } from "../../routes/channels/#channel_id/messages";
 import { In } from "typeorm";
 const allow_empty = false;
 // TODO: check webhook, application, system author, stickers
diff --git a/src/gateway/events/Message.ts b/src/gateway/events/Message.ts
index db7dbad2..4699f1af 100644
--- a/src/gateway/events/Message.ts
+++ b/src/gateway/events/Message.ts
@@ -36,7 +36,7 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
 		data = bigIntJson.parse(buffer as string);
 	}
 	else if (typeof buffer == "string") {
-		data = bigIntJson.parse(buffer as string)
+		data = bigIntJson.parse(buffer as string);
 	}
 	else return;
 
@@ -51,14 +51,14 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
 		return;
 	}
 
-	// const transaction = Sentry.startTransaction({
-	// 	op: OPCODES[data.op],
-	// 	name: `GATEWAY ${OPCODES[data.op]}`,
-	// 	data: {
-	// 		...data.d,
-	// 		token: data?.d?.token ? "[Redacted]" : undefined,
-	// 	},
-	// });
+	const transaction = Sentry.startTransaction({
+		op: OPCODES[data.op],
+		name: `GATEWAY ${OPCODES[data.op]}`,
+		data: {
+			...data.d,
+			token: data?.d?.token ? "[Redacted]" : undefined,
+		},
+	});
 
 	try {
 		var ret = await OPCodeHandler.call(this, data);
@@ -66,7 +66,7 @@ export async function Message(this: WebSocket, buffer: WS.Data) {
 		return ret;
 	} catch (error) {
 		Sentry.captureException(error);
-		// transaction.finish();
+		transaction.finish();
 		console.error(`Error: Op ${data.op}`, error);
 		// if (!this.CLOSED && this.CLOSING)
 		return this.close(CLOSECODES.Unknown_error);
diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts
index 3c40962c..b4b36075 100644
--- a/src/gateway/opcodes/Identify.ts
+++ b/src/gateway/opcodes/Identify.ts
@@ -20,12 +20,12 @@ import {
 	PresenceUpdateEvent,
 	DefaultUserGuildSettings,
 	UserGuildSettings,
+	IdentifySchema,
 } from "@fosscord/util";
 import { Send } from "../util/Send";
 import { CLOSECODES, OPCODES } from "../util/Constants";
 import { genSessionId } from "../util/SessionUtils";
 import { setupListener } from "../listener/listener";
-import { IdentifySchema } from "../schema/Identify";
 // import experiments from "./experiments.json";
 const experiments: any = [];
 import { check } from "./instanceOf";
diff --git a/src/gateway/opcodes/LazyRequest.ts b/src/gateway/opcodes/LazyRequest.ts
index 82342224..0f21d087 100644
--- a/src/gateway/opcodes/LazyRequest.ts
+++ b/src/gateway/opcodes/LazyRequest.ts
@@ -1,6 +1,5 @@
-import { getDatabase, getPermission, listenEvent, Member, Role, Session } from "@fosscord/util";
+import { getDatabase, getPermission, listenEvent, Member, Role, Session, LazyRequestSchema } from "@fosscord/util";
 import { WebSocket, Payload, handlePresenceUpdate, OPCODES, Send } from "@fosscord/gateway";
-import { LazyRequest } from "../schema/LazyRequest";
 import { check } from "./instanceOf";
 
 // TODO: only show roles/members that have access to this channel
@@ -137,8 +136,8 @@ async function getMembers(guild_id: string, range: [number, number]) {
 
 export async function onLazyRequest(this: WebSocket, { d }: Payload) {
 	// TODO: check data
-	check.call(this, LazyRequest, d);
-	const { guild_id, typing, channels, activities } = d as LazyRequest;
+	check.call(this, LazyRequestSchema, d);
+	const { guild_id, typing, channels, activities } = d as LazyRequestSchema;
 
 	const channel_id = Object.keys(channels || {}).first();
 	if (!channel_id) return;
diff --git a/src/gateway/opcodes/PresenceUpdate.ts b/src/gateway/opcodes/PresenceUpdate.ts
index 415df6ee..d17b7dd7 100644
--- a/src/gateway/opcodes/PresenceUpdate.ts
+++ b/src/gateway/opcodes/PresenceUpdate.ts
@@ -1,6 +1,5 @@
 import { WebSocket, Payload } from "@fosscord/gateway";
-import { emitEvent, PresenceUpdateEvent, Session, User } from "@fosscord/util";
-import { ActivitySchema } from "../schema/Activity";
+import { emitEvent, PresenceUpdateEvent, Session, User, ActivitySchema } from "@fosscord/util";
 import { check } from "./instanceOf";
 
 export async function onPresenceUpdate(this: WebSocket, { d }: Payload) {
diff --git a/src/gateway/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts
index fa63f7fc..8e1585ec 100644
--- a/src/gateway/opcodes/VoiceStateUpdate.ts
+++ b/src/gateway/opcodes/VoiceStateUpdate.ts
@@ -1,4 +1,3 @@
-import { VoiceStateUpdateSchema } from "../schema/VoiceStateUpdateSchema";
 import { Payload, WebSocket } from "@fosscord/gateway";
 import { genVoiceToken } from "../util/SessionUtils";
 import { check } from "./instanceOf";
@@ -11,6 +10,7 @@ import {
 	VoiceServerUpdateEvent,
 	VoiceState,
 	VoiceStateUpdateEvent,
+	VoiceStateUpdateSchema,
 } from "@fosscord/util";
 // TODO: check if a voice server is setup
 // Notice: Bot users respect the voice channel's user limit, if set. When the voice channel is full, you will not receive the Voice State Update or Voice Server Update events in response to your own Voice State Update. Having MANAGE_CHANNELS permission bypasses this limit and allows you to join regardless of the channel being full or not.
diff --git a/src/gateway/schema/Activity.ts b/src/util/schemas/ActivitySchema.ts
index f58b0fa9..d316420e 100644
--- a/src/gateway/schema/Activity.ts
+++ b/src/util/schemas/ActivitySchema.ts
@@ -57,4 +57,4 @@ export interface ActivitySchema {
 	status: Status;
 	activities?: Activity[];
 	since?: number; // unix time (in milliseconds) of when the client went idle, or null if the client is not idle
-}
+}
\ No newline at end of file
diff --git a/src/util/schemas/BackupCodesChallengeSchema.ts b/src/util/schemas/BackupCodesChallengeSchema.ts
new file mode 100644
index 00000000..d6b519b7
--- /dev/null
+++ b/src/util/schemas/BackupCodesChallengeSchema.ts
@@ -0,0 +1,3 @@
+export interface BackupCodesChallengeSchema {
+	password: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/BanCreateSchema.ts b/src/util/schemas/BanCreateSchema.ts
new file mode 100644
index 00000000..876b2a89
--- /dev/null
+++ b/src/util/schemas/BanCreateSchema.ts
@@ -0,0 +1,4 @@
+export interface BanCreateSchema {
+	delete_message_days?: string;
+	reason?: string;
+};
\ No newline at end of file
diff --git a/src/util/schemas/BanModeratorSchema.ts b/src/util/schemas/BanModeratorSchema.ts
new file mode 100644
index 00000000..8efa2402
--- /dev/null
+++ b/src/util/schemas/BanModeratorSchema.ts
@@ -0,0 +1,7 @@
+export interface BanModeratorSchema {
+	id: string;
+	user_id: string;
+	guild_id: string;
+	executor_id: string;
+	reason?: string | undefined;
+};
\ No newline at end of file
diff --git a/src/util/schemas/BanRegistrySchema.ts b/src/util/schemas/BanRegistrySchema.ts
new file mode 100644
index 00000000..8680d3db
--- /dev/null
+++ b/src/util/schemas/BanRegistrySchema.ts
@@ -0,0 +1,8 @@
+export interface BanRegistrySchema {
+	id: string;
+	user_id: string;
+	guild_id: string;
+	executor_id: string;
+	ip?: string;
+	reason?: string | undefined;
+};
\ No newline at end of file
diff --git a/src/util/schemas/BulkDeleteSchema.ts b/src/util/schemas/BulkDeleteSchema.ts
new file mode 100644
index 00000000..6a71e052
--- /dev/null
+++ b/src/util/schemas/BulkDeleteSchema.ts
@@ -0,0 +1,3 @@
+export interface BulkDeleteSchema {
+	messages: string[];
+}
\ No newline at end of file
diff --git a/src/util/schemas/ChannelModifySchema.ts b/src/util/schemas/ChannelModifySchema.ts
new file mode 100644
index 00000000..835ea2d7
--- /dev/null
+++ b/src/util/schemas/ChannelModifySchema.ts
@@ -0,0 +1,30 @@
+import { ChannelPermissionOverwriteType, ChannelType } from "@fosscord/util";
+
+export interface ChannelModifySchema {
+	/**
+	 * @maxLength 100
+	 */
+	name?: string;
+	type?: ChannelType;
+	topic?: string;
+	icon?: string | null;
+	bitrate?: number;
+	user_limit?: number;
+	rate_limit_per_user?: number;
+	position?: number;
+	permission_overwrites?: {
+		id: string;
+		type: ChannelPermissionOverwriteType;
+		allow: string;
+		deny: string;
+	}[];
+	parent_id?: string;
+	id?: string; // is not used (only for guild create)
+	nsfw?: boolean;
+	rtc_region?: string;
+	default_auto_archive_duration?: number;
+	default_reaction_emoji?: string | null;
+	flags?: number;
+	default_thread_rate_limit_per_user?: number;
+	video_quality_mode?: number;
+}
\ No newline at end of file
diff --git a/src/util/schemas/CodesVerificationSchema.ts b/src/util/schemas/CodesVerificationSchema.ts
new file mode 100644
index 00000000..e8e2e7b4
--- /dev/null
+++ b/src/util/schemas/CodesVerificationSchema.ts
@@ -0,0 +1,5 @@
+export interface CodesVerificationSchema {
+	key: string;
+	nonce: string;
+	regenerate?: boolean;
+}
\ No newline at end of file
diff --git a/src/util/schemas/DmChannelCreateSchema.ts b/src/util/schemas/DmChannelCreateSchema.ts
new file mode 100644
index 00000000..04b8ff69
--- /dev/null
+++ b/src/util/schemas/DmChannelCreateSchema.ts
@@ -0,0 +1,4 @@
+export interface DmChannelCreateSchema {
+	name?: string;
+	recipients: string[];
+}
\ No newline at end of file
diff --git a/src/util/schemas/EmojiCreateSchema.ts b/src/util/schemas/EmojiCreateSchema.ts
new file mode 100644
index 00000000..8e2a2307
--- /dev/null
+++ b/src/util/schemas/EmojiCreateSchema.ts
@@ -0,0 +1,6 @@
+export interface EmojiCreateSchema {
+	name?: string;
+	image: string;
+	require_colons?: boolean | null;
+	roles?: string[];
+}
\ No newline at end of file
diff --git a/src/util/schemas/EmojiModifySchema.ts b/src/util/schemas/EmojiModifySchema.ts
new file mode 100644
index 00000000..cd5b7e3e
--- /dev/null
+++ b/src/util/schemas/EmojiModifySchema.ts
@@ -0,0 +1,4 @@
+export interface EmojiModifySchema {
+	name?: string;
+	roles?: string[];
+}
\ No newline at end of file
diff --git a/src/util/schemas/GuildCreateSchema.ts b/src/util/schemas/GuildCreateSchema.ts
new file mode 100644
index 00000000..9b5f7dc2
--- /dev/null
+++ b/src/util/schemas/GuildCreateSchema.ts
@@ -0,0 +1,14 @@
+import { ChannelModifySchema } from ".";
+
+export interface GuildCreateSchema {
+	/**
+	 * @maxLength 100
+	 */
+	name?: string;
+	region?: string;
+	icon?: string | null;
+	channels?: ChannelModifySchema[];
+	guild_template_code?: string;
+	system_channel_id?: string;
+	rules_channel_id?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/GuildTemplateCreateSchema.ts b/src/util/schemas/GuildTemplateCreateSchema.ts
new file mode 100644
index 00000000..7caefcb8
--- /dev/null
+++ b/src/util/schemas/GuildTemplateCreateSchema.ts
@@ -0,0 +1,4 @@
+export interface GuildTemplateCreateSchema {
+	name: string;
+	avatar?: string | null;
+}
\ No newline at end of file
diff --git a/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts b/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts
new file mode 100644
index 00000000..0022da6e
--- /dev/null
+++ b/src/util/schemas/GuildUpdateWelcomeScreenSchema.ts
@@ -0,0 +1,10 @@
+export interface GuildUpdateWelcomeScreenSchema {
+	welcome_channels?: {
+		channel_id: string;
+		description: string;
+		emoji_id?: string;
+		emoji_name?: string;
+	}[];
+	enabled?: boolean;
+	description?: string;
+}
\ No newline at end of file
diff --git a/src/gateway/schema/Identify.ts b/src/util/schemas/IdentifySchema.ts
index 6f68b515..409a03da 100644
--- a/src/gateway/schema/Identify.ts
+++ b/src/util/schemas/IdentifySchema.ts
@@ -1,4 +1,4 @@
-import { ActivitySchema } from "./Activity";
+import { ActivitySchema } from "@fosscord/util";
 
 export const IdentifySchema = {
 	token: String,
diff --git a/src/util/schemas/InviteCreateSchema.ts b/src/util/schemas/InviteCreateSchema.ts
new file mode 100644
index 00000000..83ae22dd
--- /dev/null
+++ b/src/util/schemas/InviteCreateSchema.ts
@@ -0,0 +1,11 @@
+export interface InviteCreateSchema {
+	target_user_id?: string;
+	target_type?: string;
+	validate?: string; // ? what is this
+	max_age?: number;
+	max_uses?: number;
+	temporary?: boolean;
+	unique?: boolean;
+	target_user?: string;
+	target_user_type?: number;
+}
\ No newline at end of file
diff --git a/src/gateway/schema/LazyRequest.ts b/src/util/schemas/LazyRequestSchema.ts
index 1fe658bb..e9f2df20 100644
--- a/src/gateway/schema/LazyRequest.ts
+++ b/src/util/schemas/LazyRequestSchema.ts
@@ -1,4 +1,4 @@
-export interface LazyRequest {
+export interface LazyRequestSchema {
 	guild_id: string;
 	channels?: Record<string, [number, number][]>;
 	activities?: boolean;
@@ -8,7 +8,7 @@ export interface LazyRequest {
 	thread_member_lists?: any[];
 }
 
-export const LazyRequest = {
+export const LazyRequestSchema = {
 	guild_id: String,
 	$activities: Boolean,
 	$channels: Object,
diff --git a/src/util/schemas/LoginSchema.ts b/src/util/schemas/LoginSchema.ts
new file mode 100644
index 00000000..543d236c
--- /dev/null
+++ b/src/util/schemas/LoginSchema.ts
@@ -0,0 +1,8 @@
+export interface LoginSchema {
+	login: string;
+	password: string;
+	undelete?: boolean;
+	captcha_key?: string;
+	login_source?: string;
+	gift_code_sku_id?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/MemberChangeSchema.ts b/src/util/schemas/MemberChangeSchema.ts
new file mode 100644
index 00000000..566d7e20
--- /dev/null
+++ b/src/util/schemas/MemberChangeSchema.ts
@@ -0,0 +1,4 @@
+export interface MemberChangeSchema {
+	roles?: string[];
+	nick?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/MemberNickChangeSchema.ts b/src/util/schemas/MemberNickChangeSchema.ts
new file mode 100644
index 00000000..ed9fdb7b
--- /dev/null
+++ b/src/util/schemas/MemberNickChangeSchema.ts
@@ -0,0 +1,3 @@
+export interface MemberNickChangeSchema {
+	nick: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/MessageAcknowledgeSchema.ts b/src/util/schemas/MessageAcknowledgeSchema.ts
new file mode 100644
index 00000000..1e7fb80d
--- /dev/null
+++ b/src/util/schemas/MessageAcknowledgeSchema.ts
@@ -0,0 +1,4 @@
+export interface MessageAcknowledgeSchema {
+	manual?: boolean;
+	mention_count?: number;
+}
\ No newline at end of file
diff --git a/src/util/schemas/MessageCreateSchema.ts b/src/util/schemas/MessageCreateSchema.ts
new file mode 100644
index 00000000..9d77c485
--- /dev/null
+++ b/src/util/schemas/MessageCreateSchema.ts
@@ -0,0 +1,33 @@
+import { Embed } from "@fosscord/util";
+
+export interface MessageCreateSchema {
+	type?: number;
+	content?: string;
+	nonce?: string;
+	channel_id?: string;
+	tts?: boolean;
+	flags?: string;
+	embeds?: Embed[];
+	embed?: Embed;
+	// TODO: ^ embed is deprecated in favor of embeds (https://discord.com/developers/docs/resources/channel#message-object)
+	allowed_mentions?: {
+		parse?: string[];
+		roles?: string[];
+		users?: string[];
+		replied_user?: boolean;
+	};
+	message_reference?: {
+		message_id: string;
+		channel_id: string;
+		guild_id?: string;
+		fail_if_not_exists?: boolean;
+	};
+	payload_json?: string;
+	file?: any;
+	/**
+	TODO: we should create an interface for attachments
+	TODO: OpenWAAO<-->attachment-style metadata conversion
+	**/
+	attachments?: any[];
+	sticker_ids?: string[];
+}
\ No newline at end of file
diff --git a/src/util/schemas/MfaCodesSchema.ts b/src/util/schemas/MfaCodesSchema.ts
new file mode 100644
index 00000000..226c43f1
--- /dev/null
+++ b/src/util/schemas/MfaCodesSchema.ts
@@ -0,0 +1,4 @@
+export interface MfaCodesSchema {
+	password: string;
+	regenerate?: boolean;
+}
\ No newline at end of file
diff --git a/src/util/schemas/ModifyGuildStickerSchema.ts b/src/util/schemas/ModifyGuildStickerSchema.ts
new file mode 100644
index 00000000..06bf4ffe
--- /dev/null
+++ b/src/util/schemas/ModifyGuildStickerSchema.ts
@@ -0,0 +1,15 @@
+export interface ModifyGuildStickerSchema {
+	/**
+	 * @minLength 2
+	 * @maxLength 30
+	 */
+	name: string;
+	/**
+	 * @maxLength 100
+	 */
+	description?: string;
+	/**
+	 * @maxLength 200
+	 */
+	tags: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/PruneSchema.ts b/src/util/schemas/PruneSchema.ts
new file mode 100644
index 00000000..60601d81
--- /dev/null
+++ b/src/util/schemas/PruneSchema.ts
@@ -0,0 +1,6 @@
+export interface PruneSchema {
+	/**
+	 * @min 0
+	 */
+	days: number;
+}
\ No newline at end of file
diff --git a/src/util/schemas/PurgeSchema.ts b/src/util/schemas/PurgeSchema.ts
new file mode 100644
index 00000000..8916be92
--- /dev/null
+++ b/src/util/schemas/PurgeSchema.ts
@@ -0,0 +1,4 @@
+export interface PurgeSchema {
+	before: string;
+	after: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/RegisterSchema.ts b/src/util/schemas/RegisterSchema.ts
new file mode 100644
index 00000000..c0cc3805
--- /dev/null
+++ b/src/util/schemas/RegisterSchema.ts
@@ -0,0 +1,27 @@
+export interface RegisterSchema {
+	/**
+	 * @minLength 2
+	 * @maxLength 32
+	 */
+	username: string;
+	/**
+	 * @minLength 1
+	 * @maxLength 72
+	 */
+	password?: string;
+	consent: boolean;
+	/**
+	 * @TJS-format email
+	 */
+	email?: string;
+	fingerprint?: string;
+	invite?: string;
+	/**
+	 * @TJS-type string
+	 */
+	date_of_birth?: Date; // "2000-04-03"
+	gift_code_sku_id?: string;
+	captcha_key?: string;
+
+	promotional_email_opt_in?: boolean;
+}
\ No newline at end of file
diff --git a/src/util/schemas/RelationshipPostSchema.ts b/src/util/schemas/RelationshipPostSchema.ts
new file mode 100644
index 00000000..3ff6eade
--- /dev/null
+++ b/src/util/schemas/RelationshipPostSchema.ts
@@ -0,0 +1,4 @@
+export interface RelationshipPostSchema {
+	discriminator: string;
+	username: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/RelationshipPutSchema.ts b/src/util/schemas/RelationshipPutSchema.ts
new file mode 100644
index 00000000..455f854e
--- /dev/null
+++ b/src/util/schemas/RelationshipPutSchema.ts
@@ -0,0 +1,5 @@
+import { RelationshipType } from "@fosscord/util";
+
+export interface RelationshipPutSchema {
+	type?: RelationshipType;
+}
\ No newline at end of file
diff --git a/src/util/schemas/RoleModifySchema.ts b/src/util/schemas/RoleModifySchema.ts
new file mode 100644
index 00000000..adb0c1a6
--- /dev/null
+++ b/src/util/schemas/RoleModifySchema.ts
@@ -0,0 +1,10 @@
+export interface RoleModifySchema {
+	name?: string;
+	permissions?: string;
+	color?: number;
+	hoist?: boolean; // whether the role should be displayed separately in the sidebar
+	mentionable?: boolean; // whether the role should be mentionable
+	position?: number;
+	icon?: string;
+	unicode_emoji?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/SelectProtocolSchema.ts b/src/util/schemas/SelectProtocolSchema.ts
new file mode 100644
index 00000000..92958e97
--- /dev/null
+++ b/src/util/schemas/SelectProtocolSchema.ts
@@ -0,0 +1,19 @@
+export interface SelectProtocolSchema {
+	protocol: "webrtc" | "udp";
+	data:
+	| string
+	| {
+		address: string;
+		port: number;
+		mode: string;
+	};
+	sdp?: string;
+	codecs?: {
+		name: "opus" | "VP8" | "VP9" | "H264";
+		type: "audio" | "video";
+		priority: number;
+		payload_type: number;
+		rtx_payload_type?: number | null;
+	}[];
+	rtc_connection_id?: string; // uuid
+}
\ No newline at end of file
diff --git a/src/util/schemas/TemplateCreateSchema.ts b/src/util/schemas/TemplateCreateSchema.ts
new file mode 100644
index 00000000..3f98f692
--- /dev/null
+++ b/src/util/schemas/TemplateCreateSchema.ts
@@ -0,0 +1,4 @@
+export interface TemplateCreateSchema {
+	name: string;
+	description?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/TemplateModifySchema.ts b/src/util/schemas/TemplateModifySchema.ts
new file mode 100644
index 00000000..3e6efb74
--- /dev/null
+++ b/src/util/schemas/TemplateModifySchema.ts
@@ -0,0 +1,4 @@
+export interface TemplateModifySchema {
+	name: string;
+	description?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/TotpDisableSchema.ts b/src/util/schemas/TotpDisableSchema.ts
new file mode 100644
index 00000000..05192bfa
--- /dev/null
+++ b/src/util/schemas/TotpDisableSchema.ts
@@ -0,0 +1,3 @@
+export interface TotpDisableSchema {
+	code: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/TotpEnableSchema.ts b/src/util/schemas/TotpEnableSchema.ts
new file mode 100644
index 00000000..7f6fb5a9
--- /dev/null
+++ b/src/util/schemas/TotpEnableSchema.ts
@@ -0,0 +1,5 @@
+export interface TotpEnableSchema {
+	password: string;
+	code?: string;
+	secret?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/TotpSchema.ts b/src/util/schemas/TotpSchema.ts
new file mode 100644
index 00000000..889cb443
--- /dev/null
+++ b/src/util/schemas/TotpSchema.ts
@@ -0,0 +1,6 @@
+export interface TotpSchema {
+	code: string,
+	ticket: string,
+	gift_code_sku_id?: string | null,
+	login_source?: string | null,
+}
\ No newline at end of file
diff --git a/src/util/schemas/UserModifySchema.ts b/src/util/schemas/UserModifySchema.ts
new file mode 100644
index 00000000..34e0f135
--- /dev/null
+++ b/src/util/schemas/UserModifySchema.ts
@@ -0,0 +1,19 @@
+export interface UserModifySchema {
+	/**
+	 * @minLength 1
+	 * @maxLength 100
+	 */
+	username?: string;
+	avatar?: string | null;
+	/**
+	 * @maxLength 1024
+	 */
+	bio?: string;
+	accent_color?: number;
+	banner?: string | null;
+	password?: string;
+	new_password?: string;
+	code?: string;
+	email?: string;
+	discriminator?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/VanityUrlSchema.ts b/src/util/schemas/VanityUrlSchema.ts
new file mode 100644
index 00000000..28bf7f2b
--- /dev/null
+++ b/src/util/schemas/VanityUrlSchema.ts
@@ -0,0 +1,7 @@
+export interface VanityUrlSchema {
+	/**
+	 * @minLength 1
+	 * @maxLength 20
+	 */
+	code?: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/VoiceIdentifySchema.ts b/src/util/schemas/VoiceIdentifySchema.ts
new file mode 100644
index 00000000..d48de347
--- /dev/null
+++ b/src/util/schemas/VoiceIdentifySchema.ts
@@ -0,0 +1,12 @@
+export interface VoiceIdentifySchema {
+	server_id: string;
+	user_id: string;
+	session_id: string;
+	token: string;
+	video?: boolean;
+	streams?: {
+		type: string;
+		rid: string;
+		quality: number;
+	}[];
+}
\ No newline at end of file
diff --git a/src/gateway/schema/VoiceStateUpdateSchema.ts b/src/util/schemas/VoiceStateUpdateSchema.ts
index f6480414..5f805f4d 100644
--- a/src/gateway/schema/VoiceStateUpdateSchema.ts
+++ b/src/util/schemas/VoiceStateUpdateSchema.ts
@@ -1,12 +1,4 @@
-export const VoiceStateUpdateSchema = {
-	$guild_id: String,
-	$channel_id: String,
-	self_mute: Boolean,
-	self_deaf: Boolean,
-	$self_video: Boolean,	//required in docs but bots don't always send it
-	$preferred_region: String,
-};
-
+//TODO need more testing when community guild and voice stage channel are working
 export interface VoiceStateUpdateSchema {
 	guild_id?: string;
 	channel_id?: string;
@@ -14,4 +6,17 @@ export interface VoiceStateUpdateSchema {
 	self_deaf: boolean;
 	self_video?: boolean;
 	preferred_region?: string;
-}
\ No newline at end of file
+	request_to_speak_timestamp?: Date;
+	suppress?: boolean;
+}
+
+export const VoiceStateUpdateSchema = {
+	$guild_id: String,
+	$channel_id: String,
+	self_mute: Boolean,
+	self_deaf: Boolean,
+	$self_video: Boolean,	//required in docs but bots don't always send it
+	$preferred_region: String,
+	$request_to_speak_timestamp: Date,
+	$suppress: Boolean,
+};
\ No newline at end of file
diff --git a/src/util/schemas/VoiceVideoSchema.ts b/src/util/schemas/VoiceVideoSchema.ts
new file mode 100644
index 00000000..837ee1e7
--- /dev/null
+++ b/src/util/schemas/VoiceVideoSchema.ts
@@ -0,0 +1,17 @@
+export interface VoiceVideoSchema {
+	audio_ssrc: number;
+	video_ssrc: number;
+	rtx_ssrc?: number;
+	user_id?: string;
+	streams?: {
+		type: "video" | "audio";
+		rid: string;
+		ssrc: number;
+		active: boolean;
+		quality: number;
+		rtx_ssrc: number;
+		max_bitrate: number;
+		max_framerate: number;
+		max_resolution: { type: string; width: number; height: number; };
+	}[];
+}
\ No newline at end of file
diff --git a/src/util/schemas/WebhookCreateSchema.ts b/src/util/schemas/WebhookCreateSchema.ts
new file mode 100644
index 00000000..c32b642d
--- /dev/null
+++ b/src/util/schemas/WebhookCreateSchema.ts
@@ -0,0 +1,8 @@
+// TODO: webhooks
+export interface WebhookCreateSchema {
+	/**
+	 * @maxLength 80
+	 */
+	name: string;
+	avatar: string;
+}
\ No newline at end of file
diff --git a/src/util/schemas/WidgetModifySchema.ts b/src/util/schemas/WidgetModifySchema.ts
new file mode 100644
index 00000000..3c84b3a1
--- /dev/null
+++ b/src/util/schemas/WidgetModifySchema.ts
@@ -0,0 +1,4 @@
+export interface WidgetModifySchema {
+	enabled: boolean; // whether the widget is enabled
+	channel_id: string; // the widget channel id
+}
\ No newline at end of file
diff --git a/src/util/schemas/index.ts b/src/util/schemas/index.ts
index 662152dc..f86552f3 100644
--- a/src/util/schemas/index.ts
+++ b/src/util/schemas/index.ts
@@ -1,2 +1,41 @@
 export * from "./Validator";
-export * from "./voice";
\ No newline at end of file
+export * from "./SelectProtocolSchema";
+export * from "./LoginSchema";
+export * from "./RegisterSchema";
+export * from "./TotpSchema";
+export * from "./BackupCodesChallengeSchema";
+export * from "./ChannelModifySchema";
+export * from "./InviteCreateSchema";
+export * from "./PurgeSchema";
+export * from "./WebhookCreateSchema";
+export * from "./MessageCreateSchema";
+export * from "./MessageAcknowledgeSchema";
+export * from "./GuildCreateSchema";
+export * from "./BanCreateSchema";
+export * from "./BanModeratorSchema";
+export * from "./BanRegistrySchema";
+export * from "./EmojiCreateSchema";
+export * from "./EmojiModifySchema";
+export * from "./ModifyGuildStickerSchema";
+export * from "./TemplateCreateSchema";
+export * from "./TemplateModifySchema";
+export * from "./VanityUrlSchema";
+export * from "./GuildUpdateWelcomeScreenSchema";
+export * from "./WidgetModifySchema";
+export * from "./MemberChangeSchema";
+export * from "./RoleModifySchema";
+export * from "./GuildTemplateCreateSchema";
+export * from "./DmChannelCreateSchema";
+export * from "./UserModifySchema";
+export * from "./RelationshipPostSchema";
+export * from "./RelationshipPutSchema";
+export * from "./CodesVerificationSchema";
+export * from "./MfaCodesSchema";
+export * from "./TotpDisableSchema";
+export * from "./TotpEnableSchema";
+export * from "./VoiceIdentifySchema";
+export * from "./VoiceStateUpdateSchema";
+export * from "./VoiceVideoSchema";
+export * from "./IdentifySchema";
+export * from "./ActivitySchema";
+export * from "./LazyRequestSchema";
\ No newline at end of file
diff --git a/src/util/schemas/voice.ts b/src/util/schemas/voice.ts
deleted file mode 100644
index 61c12f92..00000000
--- a/src/util/schemas/voice.ts
+++ /dev/null
@@ -1,69 +0,0 @@
-export interface VoiceVideoSchema {
-	audio_ssrc: number;
-	video_ssrc: number;
-	rtx_ssrc?: number;
-	user_id?: string;
-	streams?: {
-		type: "video" | "audio";
-		rid: string;
-		ssrc: number;
-		active: boolean;
-		quality: number;
-		rtx_ssrc: number;
-		max_bitrate: number;
-		max_framerate: number;
-		max_resolution: { type: string; width: number; height: number; };
-	}[];
-}
-
-export const VoiceStateUpdateSchema = {
-	$guild_id: String,
-	$channel_id: String,
-	self_mute: Boolean,
-	self_deaf: Boolean,
-	self_video: Boolean
-};
-
-//TODO need more testing when community guild and voice stage channel are working
-export interface VoiceStateUpdateSchema {
-	channel_id: string;
-	guild_id?: string;
-	suppress?: boolean;
-	request_to_speak_timestamp?: Date;
-	self_mute?: boolean;
-	self_deaf?: boolean;
-	self_video?: boolean;
-}
-
-export interface VoiceIdentifySchema {
-	server_id: string;
-	user_id: string;
-	session_id: string;
-	token: string;
-	video?: boolean;
-	streams?: {
-		type: string;
-		rid: string;
-		quality: number;
-	}[];
-}
-
-export interface SelectProtocolSchema {
-	protocol: "webrtc" | "udp";
-	data:
-	| string
-	| {
-		address: string;
-		port: number;
-		mode: string;
-	};
-	sdp?: string;
-	codecs?: {
-		name: "opus" | "VP8" | "VP9" | "H264";
-		type: "audio" | "video";
-		priority: number;
-		payload_type: number;
-		rtx_payload_type?: number | null;
-	}[];
-	rtc_connection_id?: string; // uuid
-}
\ No newline at end of file