diff --git a/src/routes/admin/api/[slug]/+server.js b/src/routes/admin/api/[slug]/+server.js
index 7825b588ec87741a5fe4d50b96acb1b692d561ba..31c3242267070bb3b6b0086fc0cefe6477db6584 100644
--- a/src/routes/admin/api/[slug]/+server.js
+++ b/src/routes/admin/api/[slug]/+server.js
@@ -1,6 +1,7 @@
 import { restockArticle, createArticle } from "../articles";
 import { createUser } from "../users";
 import { deleteItemTransaction } from "../transactions";
+import { deleteNotificationChannel } from "../notificationChannels";
 
 export const POST = async ({request, params}) => {
 	switch(params.slug){
@@ -74,6 +75,23 @@ export const DELETE = async ({request, params}) => {
 					const transaction = await deleteItemTransaction(data.id);
 					return new Response(JSON.stringify({success: true, transaction}), {status: 200});
 				}catch(error){
+					console.error(error);
+					return new Response(JSON.stringify({error: "Internal server error"}), {status: 500});
+				}
+			}catch(e){
+				return new Response(JSON.stringify({message: "Invalid data"}), {headers: {'content-type': 'application/json', 'status': 400}});
+			}
+		}
+		case "notificationchannel": {
+			try {
+				const data = await request.json();
+				if(!data.id) return new Response(JSON.stringify({message: "Missing required fields"}), {status: 400});
+				if(!Number.isInteger(data.id) || data.id <= 0) return new Response(JSON.stringify({message: "Invalid data"}), {status: 400});
+				try{
+					const channel = await deleteNotificationChannel(data.id);
+					return new Response(JSON.stringify({success: true, channel}), {status: 200});
+				}catch(error){
+					console.error(error);
 					return new Response(JSON.stringify({error: "Internal server error"}), {status: 500});
 				}
 			}catch(e){
diff --git a/src/routes/admin/api/notificationChannels.js b/src/routes/admin/api/notificationChannels.js
new file mode 100644
index 0000000000000000000000000000000000000000..c91aee1fe095a8f81e8b77de3fd168366cae687e
--- /dev/null
+++ b/src/routes/admin/api/notificationChannels.js
@@ -0,0 +1,29 @@
+import { db } from "$lib/server/database";
+
+export async function createNotificationChannel(userId, channelType, notificationTypes, recipient){
+	return db.notificationChannel.create({
+		data: {
+			userId,
+			channelType,
+			notificationTypes,
+			recipient
+		}
+	});
+}
+
+export async function deleteNotificationChannel(id){
+	return db.notificationChannel.delete({
+		where: { id }
+	});
+}
+
+export async function updateNotificationChannel(id, channelType, notificationTypes, recipient){
+	return db.notificationChannel.update({
+		where: { id },
+		data: {
+			channelType,
+			notificationTypes,
+			recipient
+		}
+	});
+}
diff --git a/src/routes/admin/api/users.js b/src/routes/admin/api/users.js
index ced7bab77de93fdc6f677aee6d419afd9c849d11..d8e27f6e2e19b6106406383d8ca90bed96198a07 100644
--- a/src/routes/admin/api/users.js
+++ b/src/routes/admin/api/users.js
@@ -21,10 +21,13 @@ export async function getUsers(){
 	return db.user.findMany();
 }
 
-export async function getUser(id, includeCards=false){
+export async function getUser(id, includeCards=false, includeNotificationChannels=false){
+	let include = includeCards || includeNotificationChannels ? {} : undefined;
+	if(includeCards) include.cards = true;
+	if(includeNotificationChannels) include.notificationChannels = true;
 	return db.user.findUnique({
 		where: { id },
-		include: includeCards ? { cards: true } : undefined
+		include
 	});
 }
 
diff --git a/src/routes/admin/user/[id]/+page.server.js b/src/routes/admin/user/[id]/+page.server.js
index 280c70122cfdab584eb1650857c3fdaaa0f3e690..c7fb2b4d025f7b7465c56d42e0160bfff13f49fe 100644
--- a/src/routes/admin/user/[id]/+page.server.js
+++ b/src/routes/admin/user/[id]/+page.server.js
@@ -1,10 +1,12 @@
 import { addUserCard, getUser, updateCard } from "../../api/users";
 import { fail } from "@sveltejs/kit";
 import { createTransaction } from "../../api/transactions";
+import { ChannelType } from "$lib/notifications/channelTypes";
+import { createNotificationChannel, updateNotificationChannel } from "../../api/notificationChannels";
 
 export const load = async ({ params }) => {
 	const { id } = params;
-	const user = await getUser(parseInt(id), true);
+	const user = await getUser(parseInt(id), true, true);
 	return { user };
 }
 
@@ -39,5 +41,30 @@ export const actions = {
 		delete user.createdAt;
 		delete user.updatedAt;
 		return { success: !!user, user };
+	},
+	createNotificationChannel: async event => {
+		const userId = parseInt(event.params.id);
+		const data = await event.request.formData();
+		const channelType = parseInt(data.get('channelType'));
+		const notificationTypes = parseInt(data.get('notificationTypes'));
+		const recipient = data.get('recipient');
+		if(!Object.values(ChannelType).some(type => type.key === channelType)) return fail(400, { error: "Invalid form data" });
+		if(isNaN(notificationTypes) || !Number.isInteger(notificationTypes) || notificationTypes < 0) return fail(400, { error: "Invalid form data" });
+		if(typeof recipient !== "string" || !recipient.length) return fail(400, { error: "Invalid form data" });
+		const channel = await createNotificationChannel(userId, channelType, notificationTypes, recipient);
+		return { success: !!channel, channel };
+	},
+	updateNotificationChannel: async event => {
+		const data = await event.request.formData();
+		const id = parseInt(data.get('id'));
+		const channelType = parseInt(data.get('channelType'));
+		const notificationTypes = parseInt(data.get('notificationTypes'));
+		const recipient = data.get('recipient');
+		if(Number.isNaN(id) || !Number.isInteger(id) || id < 0) return fail(400, { error: "Invalid form data" });
+		if(!Object.values(ChannelType).some(type => type.key === channelType)) return fail(400, { error: "Invalid form data" });
+		if(isNaN(notificationTypes) || !Number.isInteger(notificationTypes) || notificationTypes < 0) return fail(400, { error: "Invalid form data" });
+		if(typeof recipient !== "string" || !recipient.length) return fail(400, { error: "Invalid form data" });
+		const channel = await updateNotificationChannel(id, channelType, notificationTypes, recipient);
+		return { success: !!channel, channel };
 	}
 }
diff --git a/src/routes/admin/user/[id]/+page.svelte b/src/routes/admin/user/[id]/+page.svelte
index 6d01637263d21e4014f4433b846fbf11aa77c29d..869bd2c38e2ba50816d147e839eeeb6dfde3baf8 100644
--- a/src/routes/admin/user/[id]/+page.svelte
+++ b/src/routes/admin/user/[id]/+page.svelte
@@ -2,10 +2,12 @@
 import CardList from "./CardList.svelte";
 import { enhance } from "$app/forms";
 import { addMessage, MessageType } from "$lib/messages";
+	import NotificationChannelList from "./NotificationChannelList.svelte";
 
 	export let data;
 	let cards = data.user.cards;
 	let balance = data.user.balance;
+	let notificationChannels = data.user.notificationChannels;
 </script>
 
 <a href="/admin/user">Zurück</a>
@@ -36,3 +38,6 @@ import { addMessage, MessageType } from "$lib/messages";
 	<label title="positiv: Nutzer zahl Geld ein, negativ: Nutzer hebt Geld ab">Betrag: <input name="amount" value="0" /></label>
 	<input type="submit" value="Speichern" />
 </form>
+
+<h2>Benachrichtigungen</h2>
+<NotificationChannelList bind:notificationChannels />
diff --git a/src/routes/admin/user/[id]/NotificationChannelItem.svelte b/src/routes/admin/user/[id]/NotificationChannelItem.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..6b9dc20fec9629870dcdf613fbdc070d0afd8f69
--- /dev/null
+++ b/src/routes/admin/user/[id]/NotificationChannelItem.svelte
@@ -0,0 +1,29 @@
+<script>
+	import { ChannelType } from "$lib/notifications/channelTypes";
+	import { NotificationType } from "$lib/notifications/notificationTypes";
+	import BitfieldSelector from "../../../../components/BitfieldSelector.svelte";
+
+	export let id, channelType, notificationTypes, recipient, edit, deleteChannel;
+</script>
+
+{#if edit}
+<tr>
+	<td>
+		<select name="channelType" form="notif-form{id}" required>
+			{#each Object.entries(ChannelType) as [name, {key}]}
+				<option value={key} selected={key==channelType}>{name}</option>
+			{/each}
+		</select>
+	</td>
+	<td><BitfieldSelector value={notificationTypes} fields={Object.values(NotificationType).map(type=>({name: type.name, value: type.key}))} formName="notif-form{id}" formFieldName="notificationTypes" /></td>
+	<td><input type="text" name="recipient" form="notif-form{id}" value={recipient} /></td>
+	<td><button type="submit" form="notif-form{id}">Speichern</button><button on:click={()=>edit=false}>Abbrechen</button></td>
+</tr>
+{:else}
+<tr>
+	<td>{Object.entries(ChannelType).find(([,type])=>type.key==channelType)?.[0]}</td>
+	<td><span title={Object.values(NotificationType).filter(t=>t.key&notificationTypes).map(t=>t.name).join(", ")}>{notificationTypes}</span></td>
+	<td>{recipient}</td>
+	<td><button type="button" on:click={() => edit = true}>Bearbeiten</button><button on:click={deleteChannel}>Löschen</button></td>
+</tr>
+{/if}
diff --git a/src/routes/admin/user/[id]/NotificationChannelList.svelte b/src/routes/admin/user/[id]/NotificationChannelList.svelte
new file mode 100644
index 0000000000000000000000000000000000000000..cce8af454d0cab5eab7a554bed375a78eac4d3f3
--- /dev/null
+++ b/src/routes/admin/user/[id]/NotificationChannelList.svelte
@@ -0,0 +1,89 @@
+<script>
+	import { enhance } from "$app/forms";
+	import { MessageType, addMessage } from "$lib/messages";
+	import { ChannelType } from "$lib/notifications/channelTypes";
+	import { NotificationType } from "$lib/notifications/notificationTypes";
+	import BitfieldSelector from "../../../../components/BitfieldSelector.svelte";
+	import NotificationChannelItem from "./NotificationChannelItem.svelte";
+
+	/** @type {import("$lib/notifications/types").NotificationChannel[]} */
+	export let notificationChannels;
+	let edit = notificationChannels.map(() => false);
+	
+	function deleteChannel(id){
+		fetch("/admin/api/notificationchannel", {
+			method: "DELETE",
+			body: JSON.stringify({id}),
+			headers: {
+				"Content-Type": "application/json"
+			}
+		}).then(res => {
+			if(res.ok){
+				notificationChannels = notificationChannels.filter(channel=>channel.id!==id);
+				edit = edit.filter((_,i)=>i!==id);
+				addMessage(MessageType.SUCCESS, "Benachrichtigungskanal wurde gelöscht");
+			}else{
+				addMessage(MessageType.ERROR, "Benachrichtigungskanal konnte nicht gelöscht werden");
+				console.error(res);
+			}
+		}).catch(err=>{
+			addMessage(MessageType.ERROR, "Benachrichtigungskanal konnte nicht gelöscht werden");
+			console.error(err);
+		});
+	}
+</script>
+
+<table>
+	<tr>
+		<th>Typ</th>
+		<th>Events</th>
+		<th>Empfänger</th>
+		<th></th>
+	</tr>
+	{#each notificationChannels as channel, i}
+		<NotificationChannelItem {...channel} bind:edit={edit[i]} deleteChannel={()=>deleteChannel(channel.id)} />
+	{/each}
+	<tr>
+		<td>
+			<select name="channelType" form="notif-form-new" required>
+				{#each Object.entries(ChannelType) as [name, {key}]}
+					<option value={key}>{name}</option>
+				{/each}
+			</select>
+		</td>
+		<td><BitfieldSelector value={0} fields={Object.values(NotificationType).map(type=>({name: type.name, value: type.key}))} formName="notif-form-new" formFieldName="notificationTypes" /></td>
+		<td><input type="text" name="recipient" form="notif-form-new" /></td>
+		<td><button type="submit" form="notif-form-new">Erstellen</button></td>
+	</tr>
+</table>
+
+{#each notificationChannels as channel, i}
+	<form method="post" action="?/updateNotificationChannel" id="notif-form{channel.id}" use:enhance={({form, data, cancel})=>{
+		return async ({result})=>{
+			if(result.type === "success"){
+				notificationChannels[i] = result.data.channel;
+				edit[i] = false;
+				form.reset();
+				addMessage(MessageType.SUCCESS, "Benachrichtigungskanal wurde bearbeitet");
+			}else{
+				addMessage(MessageType.ERROR, "Benachrichtigungskanal konnte nicht bearbeitet werden");
+				console.error(result);
+			}
+		};
+	}}>
+		<input type="hidden" name="id" value={channel.id} />
+	</form>
+{/each}
+<form method="post" action="?/createNotificationChannel" id="notif-form-new" use:enhance={({form, data, cancel})=>{
+	return async ({result})=>{
+		if(result.type === "success"){
+			edit = [...edit, false];
+			notificationChannels = [...notificationChannels, result.data.channel];
+			form.reset();
+			addMessage(MessageType.SUCCESS, "Benachrichtigungskanal wurde erstellt");
+		}else{
+			addMessage(MessageType.ERROR, "Benachrichtigungskanal konnte nicht erstellt werden");
+			console.error(result);
+		}
+	};
+}}></form>