Item
A unified inventory engine: a designer-managed catalog of item definitions, per-user item instances living in containers, stacking, slots, weight and volume limits, nested bags, atomic move/split/merge, cross-user transfer, reservation holds with fencing tokens, blueprint crafting, durability, and set collections. Every example on this page was executed against a live server.
When to reach for it: game inventories with gear slots and bags, crafting economies, collectible sets with completion bonuses, warehouse or license stock that gets held and then committed.
When not to: currency balances, grants, and payouts belong to Treasury; a checkout flow that prices a basket and captures a purchase belongs to Cart.
Concepts
- Domains partition everything. The domain is a path segment
(
/api/v1/items/{domain}/...) that springs into existence on first use - there is no create-domain call, and nothing crosses domains. - Definition vs instance - an
ItemDefinitionis the catalog template (stacking rules, weight, rarity, durability defaults, salvage outputs); an instance is an owned row minted from it by grant, craft, or salvage. - Two roles - catalog CRUD (definitions, blueprints, collections) and
grantrequire a platform admin token or thedesignercapability. Everything else is owner-scoped: only the item or container owner (or an admin) may act on it. - Containers hold instances:
slottedgrids, unboundedlists, orequipmentloadouts, nestable viaparent_container_id, with optional weight/volume limits and tag-based accept filters. - Stacking - depositing a stackable definition merges into the
container's existing stack up to
max_stack; non-stackable definitions mint one instance per unit. - Reservations hold stock against a container without moving it: available = on hand - reserved. Holds expire on a TTL and every mutation is guarded by a monotonic fencing token.
- Idempotency keys - every inventory mutation accepts one; replaying the same key returns the original result instead of acting twice.
The catalog (designer or admin)
Definitions are created from a JSON body (snug item definitions create
reads it from a file):
cat > iron_ingot.json <<'EOF'
{ "name": "Iron Ingot", "tags": ["metal"], "stackable": true,
"max_stack": 10, "weight": 2, "volume": 1, "rarity": "common" }
EOF
snug item definitions create --domain docs4-forge --file iron_ingot.json
snug item definitions list --domain docs4-forge # supports ?q= name search + pagination
snug item definitions update --domain docs4-forge --id FdtUrUxXVxaAxUqNCLZv --file patch.jsondefinitions batch-create --file imports an array of definitions in one
capped request. Blueprints and collections follow the same
create/get/list/update/delete shape - see
Crafting, durability, and collections.
Deleting a definition does not delete its instances - and because capacity
checks resolve every resident item's definition, deposits into a container
still holding an orphaned instance then fail with
404 definition_not_found (reproduced live). Retire instances first.
Containers
Users create their own containers; kinds are slotted, list, equipment:
snug item containers create --domain docs4-forge --kind slotted --slots 8 --max-weight 100
snug item containers create --domain docs4-forge --kind list # unbounded
snug --output json item containers get --domain docs4-forge --container-id cont_XtmDHBhEAZwK --expand--expand (HTTP: ?expand=contents) returns contents plus recursively
expanded children - containers created with parent_container_id nest
inside their parent, with depth and cycle checks. A container with
accepts: {"tags_none": ["weapon"]} rejects any weapon-tagged deposit with
400 accept_filter_rejected; a deposit that would push total weight or
volume past a limit is 400 capacity_exceeded; reading another user's
container is 403 insufficient_permissions (all reproduced live).
Granting items
grant mints instances from a definition straight into a container - it is
the faucet, so it needs the designer or admin role:
snug item grant --domain docs4-forge --definition FdtUrUxXVxaAxUqNCLZv \
--quantity 6 --container cont_XtmDHBhEAZwK --owner docs-waveOver HTTP, granting 2 more ingots into a container that already holds a
stack of 4 merges into it - same item_id, summed quantity:
{
"status": 201,
"msg": "Created",
"data": {
"items": [
{
"item_id": "item_tgznyZxfemKx",
"definition_id": "FdtUrUxXVxaAxUqNCLZv",
"owner_id": "docs-wave",
"container_id": "cont_XtmDHBhEAZwK",
"quantity": 6,
"state": "normal",
...
}
]
}
}A grant that would push the stack past max_stack fails whole:
400 Stack limit exceeded: stack would reach 13, exceeding max_stack of 10.
Move, split, merge
All owner-scoped, all atomic, all accepting --idempotency-key:
snug item move --domain docs4-forge --item item_tgznyZxfemKx --to-container cont_XtmDHBhEAZwK --to-slot 2
snug item split --domain docs4-forge --item item_tgznyZxfemKx --quantity 2
snug item merge --domain docs4-forge --source item_yWjqffKFDjnp --target item_tgznyZxfemKxsplit returns both the shrunken source and the newly minted created
stack. Merging stacks of different definitions is
400 cannot merge stacks of different definitions; moving onto an occupied
slot is 400 slot 2 is already occupied in this container. Destination
accept filters and capacity limits apply to moves too.
Transfer between users
transfer reassigns ownership and relocates in one atomic step. The
destination container must belong to the recipient:
snug item transfer --domain docs4-forge --item item_tgznyZxfemKx \
--to-user docs4-other --to-container cont_bNJNtWtLhAjnNaming a destination the recipient does not own fails with
400 destination container is not owned by the recipient; another user
touching your item gets
403 only the owner or an admin may act on this inventory (both reproduced
with a second identity).
Reservations
A reservation holds quantity against a source container you own without
moving anything. Each successful mutation increments the fencing token, and
you must present the current token - after create it is 1, after one
refresh 2, and so on:
snug item reservations create --domain docs4-forge --container cont_XtmDHBhEAZwK \
--definition FdtUrUxXVxaAxUqNCLZv --quantity 2 --ttl-seconds 120
snug item reservations refresh --domain docs4-forge --reservation resv_yMsTBqTmDRVG --fencing-token 1 --ttl-seconds 300
snug item reservations shrink --domain docs4-forge --reservation resv_yMsTBqTmDRVG --fencing-token 2 --quantity 1
snug item reservations commit --domain docs4-forge --reservation resv_yMsTBqTmDRVG --fencing-token 3
snug item reservations release --domain docs4-forge --reservation resv_ZWsbNrDYyEuh --fencing-token 1Reserving more than is available fails with
400 only 0 of ... available to reserve; a wrong token is
409 Stale fencing token (expected 1, got 99); commit debits the held
quantity from the container's stacks; an expired hold simply disappears -
later operations on it return 404 reservation_not_found. The default TTL
is 15 minutes, capped at 24 hours.
Crafting, durability, collections
Blueprint crafting (including discovery by contents), wear/repair/salvage, and set collections with tier bonuses have their own page: Crafting, durability, and collections.
Limits and configuration
Container slots (1000), nesting depth (16), reservation TTLs, idempotency
retention, and the batch-create cap (500) are tunable via the ITEM_*
variables in the
Item CONFIG reference.