diff --git a/api/lib/control/video-service.ts b/api/lib/control/video-service.ts
index 7060bf15f..b69d3a511 100644
--- a/api/lib/control/video-service.ts
+++ b/api/lib/control/video-service.ts
@@ -3,6 +3,7 @@ import Config from '../config.js';
 import { Type, Static } from '@sinclair/typebox';
 import { VideoLeaseResponse } from '../types.js';
 import fetch from '../fetch.js';
+import TAKAPI, { APIAuthCertificate } from '../tak-api.js';
 
 export const Protocols = Type.Object({
     rtmp: Type.Optional(Type.Object({
@@ -361,6 +362,29 @@ export default class VideoServiceControl {
         return lease;
     }
 
+    async from(
+        leaseid: string,
+        opts: {
+            username: string
+            admin: boolean
+        }
+    ): Promise<Static<typeof VideoLeaseResponse>> {
+        const lease = await this.config.models.VideoLease.from(leaseid);
+
+        if (!opts.admin) {
+            const profile = await this.config.models.Profile.from(opts.username);
+            const api = await TAKAPI.init(new URL(String(this.config.server.api)), new APIAuthCertificate(profile.auth.cert, profile.auth.key));
+            const groups = (await api.Group.list({ useCache: true }))
+                .data.map((group) => group.name);
+
+            if (lease.username !== opts.username && (!lease.channel || !groups.includes(lease.channel))) {
+                throw new Err(400, null, 'You can only access a lease you created or that is assigned to a channel you are in');
+            }
+        }
+
+        return lease;
+    }
+
     async commit(
         leaseid: string,
         body: {
@@ -376,15 +400,7 @@ export default class VideoServiceControl {
         const video = await this.settings();
         if (!video.configured) throw new Err(400, null, 'Media Integration is not configured');
 
-        let lease = await this.config.models.VideoLease.from(leaseid);
-
-        if (opts.admin) {
-            lease = await this.config.models.VideoLease.commit(leaseid, body);
-        } else if (lease.username === opts.username) {
-            lease = await this.config.models.VideoLease.commit(leaseid, body);
-        } else {
-            throw new Err(400, null, 'You can only update a lease you created');
-        }
+        const lease = await this.from(leaseid, opts);
 
         try {
             await this.path(lease.path);
@@ -435,14 +451,20 @@ export default class VideoServiceControl {
         }
     }
 
-    async delete(leaseid: string): Promise<void> {
+    async delete(
+        leaseid: string,
+        opts: {
+            username: string;
+            admin: boolean;
+        }
+    ): Promise<void> {
         const video = await this.settings();
 
         if (!video.configured) throw new Err(400, null, 'Media Integration is not configured');
 
         const headers = this.headers(video.username, video.password);
 
-        const lease = await this.config.models.VideoLease.from(leaseid);
+        const lease = await this.from(leaseid, opts);
 
         await this.config.models.VideoLease.delete(leaseid);
 
diff --git a/api/routes/video-lease.ts b/api/routes/video-lease.ts
index 56f46ecfe..19e55f11b 100644
--- a/api/routes/video-lease.ts
+++ b/api/routes/video-lease.ts
@@ -10,6 +10,7 @@ import { randomUUID } from 'node:crypto';
 import { StandardResponse, VideoLeaseResponse } from '../lib/types.js';
 import ECSVideoControl, { Protocols } from '../lib/control/video-service.js';
 import * as Default from '../lib/limits.js';
+import TAKAPI, { APIAuthCertificate } from '../lib/tak-api.js';
 
 export default async function router(schema: Schema, config: Config) {
     const videoControl = new ECSVideoControl(config);
@@ -55,6 +56,12 @@ export default async function router(schema: Schema, config: Config) {
             } else {
                 const user = await Auth.as_user(config, req);
 
+                const profile = await config.models.Profile.from(user.email);
+                const api = await TAKAPI.init(new URL(String(config.server.api)), new APIAuthCertificate(profile.auth.cert, profile.auth.key));
+
+                const groups = (await api.Group.list({ useCache: true }))
+                    .data.map((group) => group.name);
+
                 res.json(await config.models.VideoLease.list({
                     limit: req.query.limit,
                     page: req.query.page,
@@ -62,7 +69,7 @@ export default async function router(schema: Schema, config: Config) {
                     sort: req.query.sort,
                     where: sql`
                         name ~* ${req.query.filter}
-                        AND username = ${user.email}
+                        AND (username = ${user.email} OR channel IN ${groups})
                         AND ephemeral = ${req.query.ephemeral}
                     `
                 }));
@@ -87,16 +94,10 @@ export default async function router(schema: Schema, config: Config) {
         try {
             const user = await Auth.as_user(config, req);
 
-            let lease;
-            if (user.access === AuthUserAccess.ADMIN) {
-                lease = await config.models.VideoLease.from(req.params.lease);
-            } else {
-                lease = await config.models.VideoLease.from(req.params.lease);
-
-                if (lease.username !== user.email) {
-                    throw new Err(400, null, 'You can only delete a lease you created');
-                }
-            }
+            const lease = await videoControl.from(req.params.lease, {
+                username: user.email,
+                admin: user.access === AuthUserAccess.ADMIN
+            });
 
             res.json({
                 lease,
@@ -233,17 +234,10 @@ export default async function router(schema: Schema, config: Config) {
         try {
             const user = await Auth.as_user(config, req);
 
-            if (user.access === AuthUserAccess.ADMIN) {
-                await videoControl.delete(req.params.lease);
-            } else {
-                const lease = await config.models.VideoLease.from(req.params.lease);
-
-                if (lease.username === user.email) {
-                    await videoControl.delete(req.params.lease);
-                } else {
-                    throw new Err(400, null, 'You can only delete a lease you created');
-                }
-            }
+            await videoControl.delete(req.params.lease, {
+                username: user.email,
+                admin: user.access === AuthUserAccess.ADMIN
+            });
 
             res.json({
                 status: 200,
diff --git a/api/web/src/components/Admin/Videos/AdminVideoLeases.vue b/api/web/src/components/Admin/Videos/AdminVideoLeases.vue
index 52a1cc31d..efbe1b817 100644
--- a/api/web/src/components/Admin/Videos/AdminVideoLeases.vue
+++ b/api/web/src/components/Admin/Videos/AdminVideoLeases.vue
@@ -142,7 +142,7 @@ const list = ref<VideoLeaseList>({
     items: []
 });
 
-watch(paging, async () => {
+watch(paging.value, async () => {
     await fetchList();
 });
 
diff --git a/api/web/src/components/CloudTAK/Menu/Videos.vue b/api/web/src/components/CloudTAK/Menu/Videos.vue
index f7c244735..d7082e4bd 100644
--- a/api/web/src/components/CloudTAK/Menu/Videos.vue
+++ b/api/web/src/components/CloudTAK/Menu/Videos.vue
@@ -86,6 +86,10 @@
                         label='Video Connections'
                         :create='false'
                     />
+                    <TablerAlert
+                        v-else-if='error'
+                        :err='error'
+                    />
                     <template v-else>
                         <div
                             v-for='connection in connections.videoConnections'
@@ -131,6 +135,10 @@
                     label='Video Leases'
                     :create='false'
                 />
+                <TablerAlert
+                    v-else-if='error'
+                    :err='error'
+                />
                 <div
                     v-for='l in leases.items'
                     v-else
@@ -199,6 +207,7 @@ import { useCOTStore } from '../../../stores/cots.ts';
 import { useVideoStore } from '../../../stores/videos.ts';
 import {
     TablerNone,
+    TablerAlert,
     TablerDelete,
     TablerIconButton
 } from '@tak-ps/vue-tabler';
@@ -215,6 +224,7 @@ const cotStore = useCOTStore();
 const videoStore = useVideoStore();
 
 const mode = ref('connections');
+const error = ref<Error | undefined>();
 const loading = ref(true);
 const lease = ref();
 const leases = ref<VideoLeaseList>({ total: 0, items: [] });
@@ -241,16 +251,28 @@ function expired(expiration: string | null): boolean {
 }
 
 async function fetchLeases(): Promise<void> {
-    lease.value = undefined;
-    loading.value = true;
-    leases.value = await std('/api/video/lease') as VideoLeaseList
+    try {
+        lease.value = undefined;
+        loading.value = true;
+        error.value = undefined;
+        leases.value = await std('/api/video/lease') as VideoLeaseList
+    } catch (err) {
+        error.value = err instanceof Error ? err : new Error(String(err));
+    }
+
     loading.value = false;
 }
 
 async function fetchConnections(): Promise<void> {
-    lease.value = undefined;
-    loading.value = true;
-    connections.value = await std('/api/marti/video') as VideoConnectionList;
+    try {
+        lease.value = undefined;
+        loading.value = true;
+        error.value = undefined;
+        connections.value = await std('/api/marti/video') as VideoConnectionList;
+    } catch (err) {
+        error.value = err instanceof Error ? err : new Error(String(err));
+    }
+
     loading.value = false;
 }