InventoryApi
Purpose
Owns item-instance state.
This service should answer:
- what item records currently belong to a character, location, or other container owner
- where each item currently is
- whether an item move, split, merge, equip, or consume action is valid
- which specific item instance is being traded, auctioned, or transferred
This service should not own:
- auth/token issuance
- character identity creation
- location generation
- auction bidding logic
Ownership model
- every inventory record has an
ownerTypeandownerId USERcan read and mutate items owned by their own charactersUSERcan read and mutate location/container items only when gameplay rules allow itSUPERcan read and mutate any inventory item- access should be resolved through the current owner, not from the item id alone
Initial design
Use one MongoDB document per inventory item record.
Practical interpretation:
- non-stackable items: one document per item instance
- stackable items: one document per stack
Reasons:
- every item or stack gets a stable UUID, which is useful for auctions, trade, mail, and auditing
- ownership transfer is explicit and cheap: update
ownerType,ownerId, and slot fields - future item metadata like durability, rarity rolls, or provenance can live on the item document
- auction listings can point to specific item ids instead of vague stack descriptions
Tradeoffs:
- inventory reads are queries over many documents instead of one aggregate read
- stack merging and slot enforcement need careful indexes and mutation logic
- transfers should use transactions when they touch multiple item documents
Suggested endpoints
GET /api/inventory/by-owner/{ownerType}/{ownerId}Return all item records currently owned by that container owner.POST /api/inventory/by-owner/{ownerType}/{ownerId}/grantCreate a new item record or add quantity into an existing compatible stack.POST /api/inventory/by-owner/{ownerType}/{ownerId}/moveMove an item or stack within the same owner inventory.POST /api/inventory/transferMove quantity from one owner inventory to another.POST /api/inventory/items/{itemId}/consumeConsume quantity from a specific item record.POST /api/inventory/items/{itemId}/equipEquip a specific item into a character equipment slot.POST /api/inventory/items/{itemId}/unequipReturn an equipped item to a character inventory slot.
Notes:
equipandunequiponly make sense for character-owned itemstransferis the core world interaction primitive for looting, dropping, trading, chest interaction, and auction handoff- a future AuctionApi can reserve or re-own specific item ids without redesigning InventoryApi
Item identity
Every inventory record should have a stable UUID string such as:
a8d4218b-5e20-4e47-8b5f-0f0f0b9d7e10
Each record also carries an itemKey such as:
woodstonepistolsmall_health_potion
Recommended distinction:
id: unique item-record identifier used for ownership changes, auctions, and referencesitemKey: item definition identifier used to decide stackability and gameplay behavior
Recommended stored shape
Each item document should include:
iditemKeyquantityownerTypeownerIdslotequippedSlotownerUserIdwhen applicablecreatedUtcupdatedUtc
Optional future fields:
durabilityrarityinstanceDatalistingIdreservedUntilUtc
MVP rules
- an item record must belong to exactly one owner at a time
- stackable items may share
itemKeybut should still be represented by one stack record per occupied slot - non-stackable items must always have
quantity = 1 - equipped items should set
equippedSlotand clearslot - unequipped bag items should set
slotand clearequippedSlot - slot occupancy must be unique per
(ownerType, ownerId, slot) - all mutating endpoints should be idempotent where practical
Client shape
The Godot client should fetch all items for the currently relevant owner and group them into a bag view locally.
Good pattern:
- login/select character
GET /api/inventory/by-owner/character/{characterId}- when opening a stash or world container:
GET /api/inventory/by-owner/location/{locationId} - cache the returned item records locally
- call transfer/equip/consume endpoints using specific
itemIdvalues - replace local state with the server response after each mutation