diff --git a/prisma/migrations/20241217160850_init/migration.sql b/prisma/migrations/20241222165332_init/migration.sql
similarity index 98%
rename from prisma/migrations/20241217160850_init/migration.sql
rename to prisma/migrations/20241222165332_init/migration.sql
index d1cd314..7eed25f 100644
--- a/prisma/migrations/20241217160850_init/migration.sql
+++ b/prisma/migrations/20241222165332_init/migration.sql
@@ -55,6 +55,7 @@ CREATE TABLE `Item` (
     `itemType` ENUM('WEAPON', 'HELMET', 'CHEST', 'LEGS', 'BOOTS', 'GLOVES', 'RING', 'NECKLACE') NOT NULL,
     `stackable` BOOLEAN NOT NULL DEFAULT false,
     `rarity` ENUM('COMMON', 'UNCOMMON', 'RARE', 'EPIC', 'LEGENDARY') NOT NULL DEFAULT 'COMMON',
+    `spriteId` VARCHAR(191) NULL,
     `createdAt` DATETIME(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3),
     `updatedAt` DATETIME(3) NOT NULL,
 
@@ -256,6 +257,9 @@ ALTER TABLE `Chat` ADD CONSTRAINT `Chat_zoneId_fkey` FOREIGN KEY (`zoneId`) REFE
 -- AddForeignKey
 ALTER TABLE `SpriteAction` ADD CONSTRAINT `SpriteAction_spriteId_fkey` FOREIGN KEY (`spriteId`) REFERENCES `Sprite`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
 
+-- AddForeignKey
+ALTER TABLE `Item` ADD CONSTRAINT `Item_spriteId_fkey` FOREIGN KEY (`spriteId`) REFERENCES `Sprite`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
+
 -- AddForeignKey
 ALTER TABLE `PasswordResetToken` ADD CONSTRAINT `PasswordResetToken_userId_fkey` FOREIGN KEY (`userId`) REFERENCES `User`(`id`) ON DELETE CASCADE ON UPDATE CASCADE;
 
diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml
index e5a788a..8a21669 100644
--- a/prisma/migrations/migration_lock.toml
+++ b/prisma/migrations/migration_lock.toml
@@ -1,3 +1,3 @@
 # Please do not edit this file manually
-# It should be added in your version-control system (i.e. Git)
+# It should be added in your version-control system (e.g., Git)
 provider = "mysql"
\ No newline at end of file
diff --git a/prisma/schema/game.prisma b/prisma/schema/game.prisma
index 694547c..576c009 100644
--- a/prisma/schema/game.prisma
+++ b/prisma/schema/game.prisma
@@ -24,6 +24,7 @@ model Sprite {
   spriteActions  SpriteAction[]
   characterTypes CharacterType[]
   characterHairs CharacterHair[]
+  Item           Item[]
 }
 
 model SpriteAction {
@@ -38,7 +39,7 @@ model SpriteAction {
   isLooping   Boolean @default(false)
   frameWidth  Int     @default(0)
   frameHeight Int     @default(0)
-  frameRate  Int     @default(0)
+  frameRate   Int     @default(0)
 }
 
 model Item {
@@ -48,6 +49,8 @@ model Item {
   itemType    ItemType
   stackable   Boolean              @default(false)
   rarity      ItemRarity           @default(COMMON)
+  spriteId    String?
+  sprite      Sprite?              @relation(fields: [spriteId], references: [id], onDelete: Cascade)
   createdAt   DateTime             @default(now())
   updatedAt   DateTime             @updatedAt
   characters  CharacterItem[]
diff --git a/src/repositories/itemRepository.ts b/src/repositories/itemRepository.ts
new file mode 100644
index 0000000..5644459
--- /dev/null
+++ b/src/repositories/itemRepository.ts
@@ -0,0 +1,39 @@
+import prisma from '../utilities/prisma' // Import the global Prisma instance
+import { Tile } from '@prisma/client'
+import zoneRepository from './zoneRepository'
+import { unduplicateArray } from '../utilities/utilities'
+import { FlattenZoneArray } from '../utilities/zone'
+
+class ItemRepository {
+  async getById(id: string) {
+    return prisma.item.findUnique({
+      where: { id },
+      include: {
+        sprite: true
+      }
+    })
+  }
+
+  async getByIds(ids: string[]) {
+    return prisma.item.findMany({
+      where: {
+        id: {
+          in: ids
+        }
+      },
+      include: {
+        sprite: true
+      }
+    })
+  }
+
+  async getAll() {
+    return prisma.item.findMany({
+      include: {
+        sprite: true
+      }
+    })
+  }
+}
+
+export default new ItemRepository()
diff --git a/src/socketEvents/gameMaster/assetManager/item/create.ts b/src/socketEvents/gameMaster/assetManager/item/create.ts
new file mode 100644
index 0000000..dc86dd3
--- /dev/null
+++ b/src/socketEvents/gameMaster/assetManager/item/create.ts
@@ -0,0 +1,41 @@
+import { Server } from 'socket.io'
+import { TSocket } from '../../../../utilities/types'
+import prisma from '../../../../utilities/prisma'
+import characterRepository from '../../../../repositories/characterRepository'
+
+export default class ItemCreateEvent {
+  constructor(
+    private readonly io: Server,
+    private readonly socket: TSocket
+  ) {}
+
+  public listen(): void {
+    this.socket.on('gm:item:create', this.handleEvent.bind(this))
+  }
+
+  private async handleEvent(data: undefined, callback: (response: boolean, item?: any) => void): Promise<void> {
+    try {
+      const character = await characterRepository.getById(this.socket.characterId as number)
+      if (!character) return callback(false)
+
+      if (character.role !== 'gm') {
+        return callback(false)
+      }
+
+      const newItem = await prisma.item.create({
+        data: {
+          name: 'New Item',
+          itemType: 'WEAPON',
+          stackable: false,
+          rarity: 'COMMON',
+          spriteId: null
+        }
+      })
+
+      callback(true, newItem)
+    } catch (error) {
+      console.error('Error creating item:', error)
+      callback(false)
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/socketEvents/gameMaster/assetManager/item/delete.ts b/src/socketEvents/gameMaster/assetManager/item/delete.ts
new file mode 100644
index 0000000..cc78667
--- /dev/null
+++ b/src/socketEvents/gameMaster/assetManager/item/delete.ts
@@ -0,0 +1,40 @@
+import { Server } from 'socket.io'
+import { TSocket } from '../../../../utilities/types'
+import prisma from '../../../../utilities/prisma'
+import characterRepository from '../../../../repositories/characterRepository'
+import { gameMasterLogger } from '../../../../utilities/logger'
+
+interface IPayload {
+  id: string
+}
+
+export default class ItemDeleteEvent {
+  constructor(
+    private readonly io: Server,
+    private readonly socket: TSocket
+  ) {}
+
+  public listen(): void {
+    this.socket.on('gm:item:remove', this.handleEvent.bind(this))
+  }
+
+  private async handleEvent(data: IPayload, callback: (response: boolean) => void): Promise<void> {
+    const character = await characterRepository.getById(this.socket.characterId as number)
+    if (!character) return callback(false)
+
+    if (character.role !== 'gm') {
+      return callback(false)
+    }
+
+    try {
+      await prisma.item.delete({
+        where: { id: data.id }
+      })
+
+      callback(true)
+    } catch (error) {
+      gameMasterLogger.error(`Error deleting item ${data.id}: ${error instanceof Error ? error.message : String(error)}`)
+      callback(false)
+    }
+  }
+}
\ No newline at end of file
diff --git a/src/socketEvents/gameMaster/assetManager/item/list.ts b/src/socketEvents/gameMaster/assetManager/item/list.ts
new file mode 100644
index 0000000..58513a3
--- /dev/null
+++ b/src/socketEvents/gameMaster/assetManager/item/list.ts
@@ -0,0 +1,36 @@
+import { Server } from 'socket.io'
+import { TSocket } from '../../../../utilities/types'
+import { Item } from '@prisma/client'
+import characterRepository from '../../../../repositories/characterRepository'
+import { gameMasterLogger } from '../../../../utilities/logger'
+import itemRepository from '../../../../repositories/itemRepository'
+
+interface IPayload {}
+
+export default class ItemListEvent {
+  constructor(
+    private readonly io: Server,
+    private readonly socket: TSocket
+  ) {}
+
+  public listen(): void {
+    this.socket.on('gm:item:list', this.handleEvent.bind(this))
+  }
+
+  private async handleEvent(data: IPayload, callback: (response: Item[]) => void): Promise<void> {
+    const character = await characterRepository.getById(this.socket.characterId as number)
+    if (!character) {
+      gameMasterLogger.error('gm:item:list error', 'Character not found')
+      return callback([])
+    }
+
+    if (character.role !== 'gm') {
+      gameMasterLogger.info(`User ${character.id} tried to list items but is not a game master.`)
+      return callback([])
+    }
+
+    // get all items
+    const items = await itemRepository.getAll()
+    callback(items)
+  }
+}
\ No newline at end of file
diff --git a/src/socketEvents/gameMaster/assetManager/item/update.ts b/src/socketEvents/gameMaster/assetManager/item/update.ts
new file mode 100644
index 0000000..03d3044
--- /dev/null
+++ b/src/socketEvents/gameMaster/assetManager/item/update.ts
@@ -0,0 +1,55 @@
+import { Server } from 'socket.io'
+import { TSocket } from '../../../../utilities/types'
+import prisma from '../../../../utilities/prisma'
+import characterRepository from '../../../../repositories/characterRepository'
+import { ItemType, ItemRarity } from '@prisma/client'
+import { gameMasterLogger } from '../../../../utilities/logger'
+
+type Payload = {
+  id: string
+  name: string
+  description: string | null
+  itemType: ItemType
+  stackable: boolean
+  rarity: ItemRarity
+  spriteId: string | null
+}
+
+export default class ItemUpdateEvent {
+  constructor(
+    private readonly io: Server,
+    private readonly socket: TSocket
+  ) {}
+
+  public listen(): void {
+    this.socket.on('gm:item:update', this.handleObjectUpdate.bind(this))
+  }
+
+  private async handleObjectUpdate(data: Payload, callback: (success: boolean) => void): Promise<void> {
+    const character = await characterRepository.getById(this.socket.characterId as number)
+    if (!character) return callback(false)
+
+    if (character.role !== 'gm') {
+      return callback(false)
+    }
+
+    try {
+      await prisma.item.update({
+        where: { id: data.id },
+        data: {
+          name: data.name,
+          description: data.description,
+          itemType: data.itemType,
+          stackable: data.stackable,
+          rarity: data.rarity,
+          spriteId: data.spriteId
+        }
+      })
+
+      return callback(true)
+    } catch (error) {
+      gameMasterLogger.error(`Error updating item: ${error instanceof Error ? error.message : String(error)}`)
+      return callback(false)
+    }
+  }
+}
\ No newline at end of file