WardenCoredocs
APIEndpoints

Containers

Storage containers on your server, their owners, inventory, and type counts.

Every storage container on your server — the paginated list, a single container by its entity id, its inventory, and a breakdown of how many of each type exist.

Identifying a container

The detail and inventory endpoints take a numeric {id} path segment — the container's entity id. It must be a positive integer with no leading zeros (pattern ^[1-9]\d*$); values such as 0 and 007 are rejected with 400 validation_error.

GET /v1/containers
GET /v1/containers/5
GET /v1/containers/5/inventory
GET /v1/containers/types

Authorization

ScopeGrants
containers:readEvery container endpoint — list, detail, inventory, type counts.

Each container owner carries a discord_id (null when that owner isn't linked to Discord). A key missing the scope gets 403 insufficient_scope.

GET /v1/containers

The container list, paginated. Optional filters:

QueryMeaning
owner_steam_idContainers owned by this Steam64 (digits only).
owner_discord_idContainers owned by the player linked to this Discord id (digits only). Resolves at request time; an unlinked id matches nothing (empty page, never a 404).
owner_nameExact owner character-name match (no substring operator).
base_idContainers on this base (digits only).
is_lockedtrue or false.
is_buriedtrue or false.
searchFree-text search. Cannot be combined with any structured filter above (400 validation_error).
limitPage size, 10–100 (default 50).
cursorOpaque cursor from a previous response's next_cursor.

Supplying both owner_steam_id and owner_discord_id is a 400 validation_error.

{
  "data": [
    {
      "entity_id": "5", "class_name": "Crate", "display_name": "Crate", "custom_name": "Loot",
      "owner": { "profile_id": 7, "name": "Bob", "steam_id": "76561198000000000", "discord_id": "123456789012345678" },
      "base_id": 2, "base_name": "HQ",
      "position": { "x": 1, "y": 2, "z": 3 },
      "is_locked": true, "lock_type": "DialLock_Item", "lock_hp": 0.5, "is_buried": false,
      "last_access_time": "2023-11-14T22:13:20.000Z", "item_count": 4
    }
  ],
  "has_more": false,
  "next_cursor": null,
  "total": 1
}

Field notes

owner is the nested identity object { profile_id, name, steam_id, discord_id }. lock_hp and every position axis are fractional numbers. last_access_time is ISO-8601 (or null). item_count is null when the mod didn't report it.

GET /v1/containers/{id}

A single container by its entity id. Returns the same object as one list row. 404 not_found when no container carries that entity id.

GET /v1/containers/{id}/inventory

The container's full, nested inventory. Each item may carry contents (recursively). A subtree the mod stopped expanding at its depth cap is flagged contents_truncated: true.

{
  "items": [
    {
      "id": 7, "class": "Rifle", "name": "Rifle", "icon": "…",
      "health": 90, "max_health": 100, "weight": 3, "is_container": false, "is_weapon": true,
      "contents_truncated": false,
      "contents": [ { "id": 8, "class": "Mag", "name": "Mag", "icon": "…", "contents": [], "contents_truncated": true, "health": 1, "max_health": 1, "weight": 0.2, "is_container": true, "is_weapon": false } ]
    }
  ],
  "total": 1
}

GET /v1/containers/types

A read-only aggregation of how many containers of each display name exist. This is a summary, not a filter source — the numbers are keyed by human-readable names, not the raw class_name you'd pass to a filter.

{ "types": { "Crate": 5, "Wooden Locker": 2 } }

Caching

Every container read sends an ETag and Cache-Control: private with a short max-age (10–15 s); send the ETag back as If-None-Match to get a 304 Not Modified.

Errors

Standard error envelope. The ones you're most likely to hit:

CodeStatusWhen
insufficient_scope403The key lacks containers:read.
not_found404No container matches the {id}.
validation_error400An {id} that isn't a positive integer without leading zeros (^[1-9]\d*$), ?search= combined with a structured filter, both owner ids together, or a non-digit owner_steam_id/owner_discord_id/base_id.
server_unavailable503The game server is offline or unreachable.
gateway_timeout504The server did not respond in time.

On this page