diff --git a/src/routes/admin/admin/+server.ts b/src/routes/admin/admin/+server.ts
index d99a432..ac480ea 100644
--- a/src/routes/admin/admin/+server.ts
+++ b/src/routes/admin/admin/+server.ts
@@ -2,64 +2,47 @@ import type { RequestHandler } from '@sveltejs/kit';
 import { Permissions } from '$lib/permissions';
 import { deleteAllUserSessions, getSession, updateAllUserSessions } from '$lib/server/session';
 import { Admin } from '$lib/server/database';
+import { AdminDeleteSchema, AdminEditSchema, AdminListSchema } from './schema';
 
 export const POST = (async ({ request, cookies }) => {
 	if (getSession(cookies, { permissions: [Permissions.AdminWrite] }) == null) {
-		return new Response(null, {
-			status: 401
-		});
+		return new Response(null, { status: 401 });
 	}
 
-	const data = await request.json();
-	const username = data['username'] as string | null;
-	const password = data['password'] as string | null;
-	const permissions = data['permissions'] as number | null;
+	const parseResult = await AdminListSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) return new Response(null, { status: 400 });
+	const data = parseResult.data;
 
-	if (username == null || password == null || permissions == null) {
-		return new Response(null, {
-			status: 400
-		});
+	if (data.username == null || data.password == null || data.permissions == null) {
+		return new Response(null, { status: 400 });
 	}
 
 	const admin = await Admin.create({
-		username: username,
-		password: password,
-		permissions: new Permissions(permissions)
+		username: data.username,
+		password: data.password,
+		permissions: new Permissions(data.permissions)
 	});
 
 	delete admin.dataValues.password;
 
-	return new Response(JSON.stringify(admin), {
-		status: 201
-	});
+	return new Response(JSON.stringify(admin), { status: 201 });
 }) satisfies RequestHandler;
 
 export const PATCH = (async ({ request, cookies }) => {
 	if (getSession(cookies, { permissions: [Permissions.AdminWrite] }) == null) {
-		return new Response(null, {
-			status: 401
-		});
+		return new Response(null, { status: 401 });
 	}
 
-	const data = await request.json();
-	const id = data['id'] as string | null;
+	const parseResult = await AdminEditSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) return new Response(null, { status: 400 });
+	const data = parseResult.data;
 
-	if (id == null) {
-		return new Response(null, {
-			status: 400
-		});
-	}
+	const user = await Admin.findOne({ where: { id: data.id } });
+	if (!user) return new Response(null, { status: 400 });
 
-	const user = await Admin.findOne({ where: { id: id } });
-	if (!user) {
-		return new Response(null, {
-			status: 400
-		});
-	}
-
-	if (data['username']) user.username = data['username'];
-	if (data['password']) user.password = data['password'];
-	if (data['permissions']) user.permissions = new Permissions(data['permissions']);
+	if (data.username) user.username = data.username;
+	if (data.password) user.password = data.password;
+	if (data.permissions) user.permissions = new Permissions(data.permissions);
 	await user.save();
 
 	updateAllUserSessions(user.id, { permissions: user.permissions });
@@ -69,22 +52,15 @@ export const PATCH = (async ({ request, cookies }) => {
 
 export const DELETE = (async ({ request, cookies }) => {
 	if (getSession(cookies, { permissions: [Permissions.AdminWrite] }) == null) {
-		return new Response(null, {
-			status: 401
-		});
+		return new Response(null, { status: 401 });
 	}
 
-	const data = await request.json();
-	const id = data['id'] as number | null;
+	const parseResult = await AdminDeleteSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) return new Response(null, { status: 400 });
+	const data = parseResult.data;
 
-	if (id == null) {
-		return new Response(null, {
-			status: 400
-		});
-	}
-
-	await Admin.destroy({ where: { id: id } });
-	deleteAllUserSessions(id);
+	await Admin.destroy({ where: { id: data.id } });
+	deleteAllUserSessions(data.id);
 
 	return new Response();
 }) satisfies RequestHandler;
diff --git a/src/routes/admin/admin/schema.ts b/src/routes/admin/admin/schema.ts
new file mode 100644
index 0000000..6f59664
--- /dev/null
+++ b/src/routes/admin/admin/schema.ts
@@ -0,0 +1,19 @@
+import { z } from 'zod';
+
+export const AdminListSchema = z.object({
+	username: z.string(),
+	password: z.string(),
+	permissions: z.number()
+});
+
+export const AdminEditSchema = z.object({
+	id: z.number(),
+
+	username: z.string().nullish(),
+	password: z.string().nullish(),
+	permissions: z.number().nullish()
+});
+
+export const AdminDeleteSchema = z.object({
+	id: z.number()
+});
diff --git a/src/routes/admin/login/+server.ts b/src/routes/admin/login/+server.ts
index 2ac4efa..9687638 100644
--- a/src/routes/admin/login/+server.ts
+++ b/src/routes/admin/login/+server.ts
@@ -4,23 +4,20 @@ import { env as publicEnv } from '$env/dynamic/public';
 import { env } from '$env/dynamic/private';
 import { addSession, sessionCookieName } from '$lib/server/session';
 import { Permissions } from '$lib/permissions';
+import { LoginSchema } from './schema';
 
 export const POST = (async ({ request, cookies }) => {
-	const data = await request.formData();
-	const username = data.get('username') as string | null;
-	const password = data.get('password') as string | null;
-
-	if (username == null || password == null) {
-		return new Response(null, {
-			status: 401
-		});
+	const parseResult = await LoginSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
+		return new Response(null, { status: 400 });
 	}
+	const data = parseResult.data;
 
 	if (
 		env.ADMIN_USER &&
 		env.ADMIN_PASSWORD &&
-		username == env.ADMIN_USER &&
-		password == env.ADMIN_PASSWORD
+		data.username == env.ADMIN_USER &&
+		data.password == env.ADMIN_PASSWORD
 	) {
 		cookies.set(
 			sessionCookieName,
@@ -35,8 +32,8 @@ export const POST = (async ({ request, cookies }) => {
 		return new Response();
 	}
 
-	const user = await Admin.findOne({ where: { username: username } });
-	if (user && user.validatePassword(password)) {
+	const user = await Admin.findOne({ where: { username: data.username } });
+	if (user && user.validatePassword(data.password)) {
 		cookies.set(sessionCookieName, addSession(user), {
 			path: `${publicEnv.PUBLIC_BASE_PATH}/admin`,
 			maxAge: 60 * 60 * 24 * 90,
@@ -45,7 +42,7 @@ export const POST = (async ({ request, cookies }) => {
 		});
 		return new Response();
 	} else {
-		console.log(`failed login attempt for user ${username}`);
+		console.log(`failed login attempt for user ${data.username}`);
 		return new Response(null, {
 			status: 401
 		});
diff --git a/src/routes/admin/login/schema.ts b/src/routes/admin/login/schema.ts
new file mode 100644
index 0000000..c6d4c4e
--- /dev/null
+++ b/src/routes/admin/login/schema.ts
@@ -0,0 +1,6 @@
+import { z } from 'zod';
+
+export const LoginSchema = z.object({
+	username: z.string(),
+	password: z.string()
+});
diff --git a/src/routes/admin/logout/+server.ts b/src/routes/admin/logout/+server.ts
index 4787fbb..dad389d 100644
--- a/src/routes/admin/logout/+server.ts
+++ b/src/routes/admin/logout/+server.ts
@@ -1,5 +1,6 @@
 import type { RequestHandler } from '@sveltejs/kit';
 import { deleteSession, getSession, sessionCookieName } from '$lib/server/session';
+import { env as publicEnv } from '$env/dynamic/public';
 
 export const POST = (async ({ cookies }) => {
 	if (getSession(cookies) == null) {
@@ -9,7 +10,7 @@ export const POST = (async ({ cookies }) => {
 	}
 
 	deleteSession(cookies);
-	cookies.delete(sessionCookieName);
+	cookies.delete(sessionCookieName, { path: `${publicEnv.PUBLIC_BASE_PATH}/admin` });
 
 	return new Response();
 }) satisfies RequestHandler;
diff --git a/src/routes/admin/reports/+server.ts b/src/routes/admin/reports/+server.ts
index 3745ee1..0897c42 100644
--- a/src/routes/admin/reports/+server.ts
+++ b/src/routes/admin/reports/+server.ts
@@ -7,6 +7,7 @@ import { Op } from 'sequelize';
 import { env } from '$env/dynamic/private';
 import crypto from 'crypto';
 import { webhookUserReported } from '$lib/server/webhook';
+import { ReportAddSchema, ReportEditSchema, ReportListSchema } from './schema';
 
 export const POST = (async ({ request, cookies }) => {
 	if (getSession(cookies, { permissions: [Permissions.ReportRead] }) == null) {
@@ -15,21 +16,18 @@ export const POST = (async ({ request, cookies }) => {
 		});
 	}
 
-	const data: {
-		limit: number | null;
-		from: number | null;
-
-		draft: boolean | null;
-		status: 'none' | 'review' | 'reviewed' | null;
-		reporter: string | null;
-		reported: string | null;
-
-		hash: string | null;
-	} = await request.json();
+	const parseResult = await ReportListSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
+		console.log(parseResult.error);
+		return new Response(null, {
+			status: 400
+		});
+	}
+	const data = parseResult.data;
 
 	let reportFindOptions: Attributes<Report> = {};
-	if (data.draft != null) reportFindOptions.draft = data.draft;
-	reportFindOptions.status = data.status == null ? ['none', 'review'] : data.status;
+	reportFindOptions.draft = data.draft;
+	reportFindOptions.status = data.status ?? ['none', 'review'];
 	if (data.reporter != null) {
 		const reporter_ids = await User.findAll({
 			attributes: ['id'],
@@ -97,17 +95,13 @@ export const PATCH = (async ({ request, cookies }) => {
 		});
 	}
 
-	const data: {
-		id: number;
-		reported: string | null;
-		auditor: number;
-		notice: string | null;
-		statement: string | null;
-		status: 'none' | 'review' | 'reviewed' | null;
-		strike_reason: number | null;
-	} = await request.json();
-
-	if (data.id === null || data.auditor === null) return new Response(null, { status: 400 });
+	const parseResult = await ReportEditSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
+		return new Response(null, {
+			status: 400
+		});
+	}
+	const data = parseResult.data;
 
 	const report = await Report.findOne({ where: { id: data.id } });
 	const admin = await Admin.findOne({ where: { id: data.auditor } });
@@ -175,15 +169,13 @@ export const PUT = (async ({ request, cookies }) => {
 		});
 	}
 
-	const data: {
-		reporter: string;
-		reported: string | null;
-		reason: string;
-		body: string | null;
-	} = await request.json();
-
-	if (data.reporter == null || data.reason == null || data.body === undefined)
-		return new Response(null, { status: 400 });
+	const parseResult = await ReportAddSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
+		return new Response(null, {
+			status: 400
+		});
+	}
+	const data = parseResult.data;
 
 	const reporter = await User.findOne({ where: { uuid: data.reporter } });
 	const reported = data.reported ? await User.findOne({ where: { uuid: data.reported } }) : null;
diff --git a/src/routes/admin/reports/HeaderBar.svelte b/src/routes/admin/reports/HeaderBar.svelte
index d3ebbfe..d2f9b52 100644
--- a/src/routes/admin/reports/HeaderBar.svelte
+++ b/src/routes/admin/reports/HeaderBar.svelte
@@ -26,6 +26,5 @@
 	<Select label="Reportstatus" size="sm" bind:value={reportFilter.draft}>
 		<option value={false}>Erstellt</option>
 		<option value={true}>Entwurf</option>
-		<option value={null}>Erstellt & Entwurf</option>
 	</Select>
 </form>
diff --git a/src/routes/admin/reports/schema.ts b/src/routes/admin/reports/schema.ts
new file mode 100644
index 0000000..48a690b
--- /dev/null
+++ b/src/routes/admin/reports/schema.ts
@@ -0,0 +1,30 @@
+import { z } from 'zod';
+
+export const ReportListSchema = z.object({
+	limit: z.number().nullish(),
+	from: z.number().nullish(),
+
+	status: z.enum(['none', 'review', 'reviewed']).nullish(),
+	reporter: z.string().nullish(),
+	reported: z.string().nullish(),
+	draft: z.boolean().nullish(),
+
+	hash: z.string().nullish()
+});
+
+export const ReportEditSchema = z.object({
+	id: z.number(),
+	reported: z.string().nullish(),
+	auditor: z.number(),
+	notice: z.string().nullish(),
+	statement: z.string().nullish(),
+	status: z.enum(['none', 'review', 'reviewed']).nullish(),
+	strike_reason: z.number().nullish()
+});
+
+export const ReportAddSchema = z.object({
+	reporter: z.string(),
+	reported: z.string().nullish(),
+	reason: z.string(),
+	body: z.string().nullish()
+});
diff --git a/src/routes/admin/users/+server.ts b/src/routes/admin/users/+server.ts
index 6f996de..7784724 100644
--- a/src/routes/admin/users/+server.ts
+++ b/src/routes/admin/users/+server.ts
@@ -4,6 +4,7 @@ import { error, type RequestHandler } from '@sveltejs/kit';
 import { User } from '$lib/server/database';
 import { type Attributes, Op } from 'sequelize';
 import { ApiError, getJavaUuid, getNoAuthUuid, UserNotFoundError } from '$lib/server/minecraft';
+import { UserAddSchema, UserDeleteSchema, UserEditSchema, UserListSchema } from './schema';
 
 export const POST = (async ({ request, cookies }) => {
 	if (getSession(cookies, { permissions: [Permissions.UserRead] }) == null) {
@@ -12,16 +13,11 @@ export const POST = (async ({ request, cookies }) => {
 		});
 	}
 
-	const data: {
-		limit: number | null;
-		from: number | null;
-
-		name: string | null;
-		playertype: 'java' | 'bedrock' | 'noauth' | null;
-
-		search: string | null;
-		slim: boolean | null;
-	} = await request.json();
+	const parseResult = await UserListSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
+		return new Response(null, { status: 400 });
+	}
+	const data = parseResult.data;
 
 	const usersFindOptions: Attributes<User> = {};
 	if (data.name) {
@@ -60,30 +56,26 @@ export const PATCH = (async ({ request, cookies }) => {
 		});
 	}
 
-	const data = await request.json();
-	const id = data['id'] as string | null;
-
-	if (id == null) {
-		return new Response(null, {
-			status: 400
-		});
+	const parseResult = await UserEditSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
+		return new Response(null, { status: 400 });
 	}
+	const data = parseResult.data;
 
-	const user = await User.findOne({ where: { id: id } });
+	const user = await User.findOne({ where: { id: data.id } });
 	if (!user) {
 		return new Response(null, {
 			status: 400
 		});
 	}
 
-	if (data['firstname']) user.firstname = data['firstname'];
-	if (data['lastname']) user.lastname = data['lastname'];
-	if (data['birthday']) user.birthday = data['birthday'];
-	if (data['telephone']) user.telephone = data['telephone'];
-	if (data['username']) user.username = data['username'];
-	if (data['playertype']) user.playertype = data['playertype'];
-	if (data['password']) user.password = data['password'];
-	if (data['uuid']) user.uuid = data['uuid'];
+	if (data.firstname) user.firstname = data.firstname;
+	if (data.lastname) user.lastname = data.lastname;
+	if (data.birthday) user.birthday = data.birthday;
+	if (data.telephone) user.telephone = data.telephone;
+	if (data.username) user.username = data.username;
+	if (data.playertype) user.playertype = data.playertype;
+	if (data.uuid) user.uuid = data.uuid;
 	await user.save();
 
 	return new Response();
@@ -96,26 +88,11 @@ export const PUT = (async ({ request, cookies }) => {
 		});
 	}
 
-	const data: {
-		firstname: string;
-		lastname: string;
-
-		birthday: string;
-		telephone: string;
-
-		username: string;
-		playertype: string;
-	} = await request.json();
-
-	if (
-		data.firstname == null ||
-		data.lastname == null ||
-		data.birthday == null ||
-		data.username == null ||
-		data.playertype == null
-	) {
+	const parseResult = await UserAddSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
 		return new Response(null, { status: 400 });
 	}
+	const data = parseResult.data;
 
 	let uuid: string | null;
 	try {
@@ -180,16 +157,13 @@ export const DELETE = (async ({ request, cookies }) => {
 		});
 	}
 
-	const data = await request.json();
-	const id = (data['id'] as number) || null;
-
-	if (id == null) {
-		return new Response(null, {
-			status: 400
-		});
+	const parseResult = await UserDeleteSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
+		return new Response(null, { status: 400 });
 	}
+	const data = parseResult.data;
 
-	await User.destroy({ where: { id: id } });
+	await User.destroy({ where: { id: data.id } });
 
 	return new Response();
 }) satisfies RequestHandler;
diff --git a/src/routes/admin/users/schema.ts b/src/routes/admin/users/schema.ts
new file mode 100644
index 0000000..a97fa6a
--- /dev/null
+++ b/src/routes/admin/users/schema.ts
@@ -0,0 +1,36 @@
+import { z } from 'zod';
+
+export const UserListSchema = z.object({
+	limit: z.number().nullish(),
+	from: z.number().nullish(),
+
+	name: z.string().nullish(),
+	playertype: z.enum(['java', 'bedrock', 'noauth']).nullish(),
+
+	search: z.string().nullish(),
+	slim: z.boolean().nullish()
+});
+
+export const UserEditSchema = z.object({
+	id: z.number(),
+	firstname: z.string().nullish(),
+	lastname: z.string().nullish(),
+	birthday: z.coerce.date().nullish(),
+	telephone: z.string().nullish(),
+	username: z.string().nullish(),
+	playertype: z.enum(['java', 'bedrock', 'noauth']).nullish(),
+	uuid: z.string().nullish()
+});
+
+export const UserAddSchema = z.object({
+	firstname: z.string(),
+	lastname: z.string(),
+	birthday: z.coerce.date(),
+	telephone: z.string().nullish(),
+	username: z.string(),
+	playertype: z.enum(['java', 'bedrock', 'noauth'])
+});
+
+export const UserDeleteSchema = z.object({
+	id: z.number()
+});
diff --git a/src/routes/api/report/+server.ts b/src/routes/api/report/+server.ts
index 4b1a104..60ec654 100644
--- a/src/routes/api/report/+server.ts
+++ b/src/routes/api/report/+server.ts
@@ -3,14 +3,17 @@ import { Report, User } from '$lib/server/database';
 import * as crypto from 'crypto';
 import { env as public_env } from '$env/dynamic/public';
 import { env } from '$env/dynamic/private';
+import { ReportAddSchema } from './schema';
 
 export const POST = (async ({ request, url }) => {
 	if (env.REPORT_SECRET && url.searchParams.get('secret') !== env.REPORT_SECRET)
 		return new Response(null, { status: 401 });
 
-	const data: { reporter: string; reported: string | null; reason: string } = await request.json();
-
-	if (data.reporter == null || data.reason == null) return new Response(null, { status: 400 });
+	const parseResult = await ReportAddSchema.safeParseAsync(await request.json());
+	if (!parseResult.success) {
+		return new Response(null, { status: 400 });
+	}
+	const data = parseResult.data;
 
 	const reporter = await User.findOne({ where: { uuid: data.reporter } });
 	const reported = data.reported
diff --git a/src/routes/api/report/schema.ts b/src/routes/api/report/schema.ts
new file mode 100644
index 0000000..278d3cb
--- /dev/null
+++ b/src/routes/api/report/schema.ts
@@ -0,0 +1,7 @@
+import { z } from 'zod';
+
+export const ReportAddSchema = z.object({
+	reporter: z.string(),
+	reported: z.string().nullish(),
+	reason: z.string()
+});