Squads
Squad rosters, members, aggregate stats, and the bases, vehicles, and containers a squad owns.
Everything about the squads on your server — the list, a single squad, its members (with their stats), aggregate totals, and the bases, vehicles, and containers its members own.
Identifying a squad
Every per-squad endpoint takes a numeric {id} path segment — the SCUM squad 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/squads/5
GET /v1/squads/5/membersOn the list endpoint you can also find a squad by its leader, by either identifier:
?leader_steam_id=76561198000000000?leader_discord_id=123456789012345678
A leader_discord_id resolves to the currently-linked player at request time; an unlinked
id simply matches nothing (an empty page, not a 404). Supplying both leader_steam_id and
leader_discord_id is a 400 validation_error.
Authorization
| Scope | Grants |
|---|---|
squads:read | Every squad endpoint — list, detail, members, summary, bases, vehicles, containers. |
Each member and the squad leader carry a discord_id (null when that player isn't linked).
A key missing the scope gets 403 insufficient_scope.
GET /v1/squads
The squad list, paginated. Optional filters:
| Query | Meaning |
|---|---|
leader_steam_id | Squads led by this Steam64 (digits only). |
leader_discord_id | Squads led by the player linked to this Discord id (digits only). |
min_members / max_members | Bound the member count. |
min_score | Minimum squad score. |
active_within_days | Only squads whose last member login is within the last N days. Positive integer (≥ 1). |
search | Free-text name search. Cannot be combined with any structured filter above (400 validation_error). |
limit | Page size, 10–100 (default 50). |
cursor | Opaque cursor from a previous response's next_cursor. |
Returns a collection envelope. total is the count of squads matching the query (across all
pages):
{
"data": [
{
"id": 5,
"name": "Wolves",
"score": 12.5,
"member_limit": 8,
"member_count": 4,
"leader": { "id": 7, "steam_id": "76561198000000000", "discord_id": "123456789012345678", "name": "Bob" },
"last_active": "2024-01-01 12:00:00"
}
],
"total": 1,
"has_more": false,
"next_cursor": null
}Field notes
score is a fractional number. last_active is the raw server-local timestamp as SCUM
stores it (not ISO-8601). A squad leader's discord_id is null when the leader isn't
Discord-linked.
GET /v1/squads/{id}
A single squad — the same object shape as a list row.
GET /v1/squads/{id}/members
The full roster (bounded by the squad's member limit, so not paginated). Each member carries their combat stats, economy, and Discord link.
{
"data": [
{
"id": 9, "profile_id": 7,
"steam_id": "76561198000000000", "discord_id": "123456789012345678",
"steam_name": "Bob", "char_name": "Bobby",
"rank": 4, "kills": 3, "deaths": 1,
"cash": 500, "bank_money": 1000, "gold": 5, "fame_points": 42,
"online": true, "last_logout": "2024-01-01 09:00:00"
}
]
}rank is 4 = leader, 3 = officer, 2 = member, 1 = recruit.
GET /v1/squads/{id}/summary
Aggregate totals across the squad's members.
{
"squad_id": 5,
"total_kills": 10, "total_deaths": 4,
"total_cash": 5000, "total_bank_money": 20000, "total_gold": 30, "total_fame": 999,
"total_containers": 12, "total_vehicles": 3,
"member_count": 4
}GET /v1/squads/{id}/bases
The bases owned by the squad's members, paginated with limit (1–100) and the cursor.
{
"data": [
{
"flag_id": 1, "base_id": 2,
"owner": { "profile_id": 7, "name": "Bob", "steam_id": "76561198000000000", "discord_id": "123456789012345678" },
"max_elements": 100, "element_count": 40, "avg_health": 87.5,
"position": { "x": 1.5, "y": 2.5, "z": 3.5 }
}
],
"has_more": false,
"next_cursor": null
}GET /v1/squads/{id}/vehicles
The vehicles owned by the squad's members, paginated with limit (1–100) and the cursor.
{
"data": [
{
"entity_id": "99", "class_name": "BPC_Kinglet_Duster", "display_name": "Kinglet Duster",
"owner": { "profile_id": 7, "name": "Bob", "steam_id": "76561198000000000", "discord_id": "123456789012345678" },
"health": 950.5, "max_health": 1000,
"position": { "x": 1, "y": 2, "z": 3 },
"is_locked": true, "lock_type": "DialLock_Item", "lock_hp": 0.85,
"is_functional": true, "last_access_time": "2023-11-14T22:13:20.000Z", "item_count": 12
}
],
"has_more": false,
"next_cursor": null
}GET /v1/squads/{id}/containers
The containers owned by the squad's members, paginated with limit (1–100) and the cursor.
{
"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": false, "lock_type": null, "lock_hp": 0, "is_buried": false,
"last_access_time": null, "item_count": null
}
],
"has_more": false,
"next_cursor": null
}Field notes
Every asset owner is the nested identity object { profile_id, name, steam_id, discord_id };
discord_id is null when that owner isn't linked to Discord. avg_health, health,
max_health, 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. The asset lists
carry no total field — page with next_cursor.
Caching
Every squad 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. Nothing here is no-store.
Errors
Standard error envelope. The ones you're most likely to hit:
| Code | Status | When |
|---|---|---|
insufficient_scope | 403 | The key lacks squads:read. |
not_found | 404 | No squad matches the {id}. |
validation_error | 400 | An {id} that isn't a positive integer without leading zeros (^[1-9]\d*$), ?search= combined with a structured filter, both leader ids together, or a non-digit leader_steam_id/leader_discord_id. |
server_unavailable | 503 | The game server is offline or unreachable. |
gateway_timeout | 504 | The server did not respond in time. |