Build custom integrations, bots, and tools with the FiveRoster REST API. Manage rosters, track shifts, and automate player management from your own applications.
Base URL
https://fiveroster.com/api/v1
All API v1 endpoints require an API key passed via the X-API-KEY header.
X-API-KEY: your_api_key_here
Free for All Users — Every FiveRoster user can generate API keys and use the full API, regardless of subscription tier.
All v1 endpoints are rate-limited to 50 requests per minute per IP address. Exceeding this limit will return a 429 Too Many Requests response.
All errors follow a standard format:
{
"error": {
"code": "error_code_string",
"message": "Human-readable description of the error"
}
}
| Status | Code | Description |
|---|---|---|
| 400 | missing_* | A required parameter is missing |
| 401 | missing_api_key | No API key was provided |
| 401 | invalid_api_key | The API key does not exist |
| 401 | expired_api_key | The API key has expired |
| 403 | premium_required | The API key creator no longer has premium |
| 404 | roster_not_found | Roster not found for this guild |
| 404 | rank_not_found | Rank not found for this roster |
| 404 | player_not_found | Player not found on this roster |
| 429 | — | Rate limit exceeded |
| 500 | — | Internal server error |
/api/v1/rosters
Retrieve all rosters for your guild.
Response
200 OK{
"data": [
{
"roster_uuid": "abc-123-def",
"name": "Los Santos Police Department",
"guild_id": "123456789"
}
]
}
/api/v1/rosters/{roster_uuid}
Retrieve detailed information about a single roster, including its ranks and flags.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
Response
200 OK{
"data": {
"roster_uuid": "abc-123-def",
"name": "Los Santos Police Department",
"guild_id": "123456789",
"ranks": [...],
"flags": [...]
}
}
/api/v1/rosters/{roster_uuid}/players
Retrieve all players on a roster, sorted by rank position.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
Response
200 OK{
"data": [
{
"id": "discord_user_id",
"roster_uuid": "abc-123-def",
"rank_uuid": "rank-uuid-here",
"callsign": "A-01",
"flags": [1, 3],
"promoted_at": "2025-06-15T12:00:00Z"
}
]
}
/api/v1/rosters/{roster_uuid}/ranks
Retrieve all ranks for a roster, ordered by position. Ranks where is_section is true are section headers and cannot be used as promotion/demotion targets.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
Response
200 OK{
"ranks": [
{
"rank_uuid": "rank-uuid-1",
"name": "Chief of Police",
"position": 1,
"is_section": false,
"shortcode": "COP"
}
]
}
/api/v1/rosters/{roster_uuid}/ranks/{rank_uuid}/enroll
Add a new player to a roster at a specific rank.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
| rank_uuid | string | URL | The UUID of the target rank |
| member_id | string | Body | Discord user ID of the player to enroll |
Request Body
{ "member_id": "123456789012345678" }
Response
200 OK{
"message": "Player promoted successfully with dynamic callsign.",
"callsign": "A-01",
"new_rank_name": "Officer"
}
/api/v1/rosters/{roster_uuid}/players/{member_id}
Remove a player from a roster entirely. This will remove their Discord roles and reset their nickname if applicable.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
| member_id | string | URL | Discord user ID of the player |
Response
200 OK{ "message": "Player cleared from roster successfully" }
/api/v1/rosters/{roster_uuid}/members/{member_id}/promote
Promote a player to a higher rank. This will update their Discord roles, assign a new callsign, and post an announcement to configured channels.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
| member_id | string | URL | Discord user ID of the player |
| rank_uuid | string | Body | The UUID of the target rank (must be higher than current) |
| clear_player_data | boolean | Body | Optional. Clears strikes, flags, and notes. Default: false |
Request Body
{ "rank_uuid": "target-rank-uuid", "clear_player_data": false }
Response
200 OK{
"message": "Player promoted successfully with dynamic callsign.",
"callsign": "A-03",
"new_rank_name": "Sergeant"
}
/api/v1/rosters/{roster_uuid}/members/{member_id}/demote
Demote a player to a lower rank. This will update their Discord roles, assign a new callsign, and post an announcement to configured demotion channels.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
| member_id | string | URL | Discord user ID of the player |
| rank_uuid | string | Body | The UUID of the target rank (must be lower than current) |
| clear_player_data | boolean | Body | Optional. Clears strikes, flags, and notes. Default: false |
Request Body
{ "rank_uuid": "target-rank-uuid", "clear_player_data": false }
Response
200 OK{
"message": "Player demoted successfully with dynamic callsign.",
"callsign": "C-12",
"new_rank_name": "Officer"
}
/api/v1/rosters/{roster_uuid}/flags
Retrieve all flags (divisions) for a roster.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
Response
200 OK{
"flags": [
{ "id": 1, "name": "Patrol Division", "position": 1 },
{ "id": 2, "name": "Detective Bureau", "position": 2 }
]
}
/api/v1/rosters/{roster_uuid}/members/{member_id}/flags
Retrieve all flags assigned to a specific member on a roster.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
| member_id | string | URL | Discord user ID of the player |
Response
200 OK{
"member_id": "123456789012345678",
"flags": [
{ "id": 1, "name": "Patrol Division", "position": 1 }
]
}
/api/v1/rosters/{roster_uuid}/members/{member_id}/flags
Add a flag (division) to a member.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
| member_id | string | URL | Discord user ID of the player |
| flag_id | integer | Body | The ID of the flag to assign |
Request Body
{ "flag_id": 1 }
Response
200 OK{
"message": "Flag added to player successfully",
"member_id": "123456789012345678",
"flag": { "id": 1, "name": "Patrol Division" }
}
/api/v1/rosters/{roster_uuid}/members/{member_id}/flags/{flag_id}
Remove a flag (division) from a member.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
| member_id | string | URL | Discord user ID of the player |
| flag_id | integer | URL | The ID of the flag to remove |
Response
200 OK{
"message": "Flag removed from player successfully",
"member_id": "123456789012345678",
"flag": { "id": 1, "name": "Patrol Division" }
}
All shift endpoints support authentication via either X-API-KEY header or X-BOT-TOKEN header. When using X-BOT-TOKEN, a guild_id parameter is required.
/api/v1/shifts/start
Start a new shift for a player.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | Body | UUID of the roster |
| player_id | string | Body | Discord user ID |
| flag_id | integer | Body | Optional. Division/flag ID to track shift under |
Request Body
{ "roster_uuid": "abc-123-def", "player_id": "123456789012345678", "flag_id": 1 }
Response
201 Created{
"message": "Shift started successfully",
"shift": {
"id": 42,
"roster_uuid": "abc-123-def",
"roster_name": "Los Santos Police Department",
"player_id": "123456789012345678",
"flag_id": 1,
"flag_name": "Patrol Division",
"started_at": "2025-06-15T18:30:00+00:00"
}
}
/api/v1/shifts/end
End the currently active shift for a player.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| player_id | string | Body | Discord user ID |
Request Body
{ "player_id": "123456789012345678" }
Response
200 OK{
"message": "Shift ended successfully",
"shift": {
"id": 42,
"started_at": "2025-06-15T18:30:00+00:00",
"ended_at": "2025-06-15T20:45:00+00:00",
"duration_seconds": 8100,
"formatted_duration": "2h 15m"
}
}
/api/v1/shifts/status?player_id={player_id}
Check if a player is currently on shift.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| player_id | string | Query | Discord user ID |
Response
200 OK{
"on_shift": true,
"shift": {
"id": 42,
"roster_uuid": "abc-123-def",
"roster_name": "Los Santos Police Department",
"started_at": "2025-06-15T18:30:00+00:00",
"duration_seconds": 3600,
"formatted_duration": "1h 0m"
}
}
/api/v1/shifts/active
Retrieve all currently active shifts for your guild. Optionally filter by roster or division.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | Query | Optional. Filter by roster |
| flag_id | integer | Query | Optional. Filter by division/flag |
Response
200 OK{
"count": 3,
"shifts": [
{
"player_id": "123456789012345678",
"roster_name": "Los Santos Police Department",
"flag_name": "Patrol Division",
"started_at": "2025-06-15T18:30:00+00:00",
"duration_seconds": 3600,
"formatted_duration": "1h 0m"
}
]
}
/api/v1/shifts/leaderboard
Get the top shift contributors for your guild.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| period | string | Query | Optional. week (default), month, or all-time |
| roster_uuid | string | Query | Optional. Filter by roster |
| flag_id | integer | Query | Optional. Filter by division/flag |
| limit | integer | Query | Optional. Number of results (default: 10, max: 25) |
Response
200 OK{
"period": "week",
"leaderboard": [
{
"rank": 1,
"player_id": "123456789012345678",
"total_hours": 10.0,
"formatted_time": "10h 0m",
"shift_count": 5
}
]
}
/api/v1/shifts/hours
Get shift hour statistics for a specific player. Set include_breakdown=true for division breakdown.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| player_id | string | Query | Discord user ID |
| roster_uuid | string | Query | Optional. Filter by roster |
| flag_id | integer | Query | Optional. Filter by division/flag |
| include_breakdown | boolean | Query | Optional. Include breakdown by division |
Response
200 OK{
"player_id": "123456789012345678",
"weekly": { "hours": 5.0, "formatted": "5h", "shift_count": 3 },
"monthly": { "hours": 20.0, "formatted": "20h", "shift_count": 12 },
"total": { "hours": 100.0, "formatted": "100h", "shift_count": 50 }
}
/api/v1/shifts/quota-progress
Get a player's progress toward active shift quotas.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| player_id | string | Query | Discord user ID |
| roster_uuid | string | Query | Optional. Filter by roster |
Response
200 OK{
"has_active_quotas": true,
"quotas": [
{
"quota_name": "Weekly Minimum",
"required_formatted": "4h",
"completed_formatted": "3h",
"percentage": 75.0,
"is_met": false,
"time_remaining": "2 days 4 hours"
}
]
}
/api/v1/rosters/{roster_uuid}/shifts/analytics
Get comprehensive shift analytics for a specific roster.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | URL | The UUID of the roster |
Response
200 OK{
"active_shifts_count": 3,
"weekly_hours": 45.5,
"monthly_hours": 180.0,
"average_shift_hours": 2.3,
"daily_breakdown": [
{ "date": "2025-06-09", "day": "Mon", "hours": 8.5 }
],
"top_contributors": [
{ "player_id": "123456789012345678", "total_hours": 10.5 }
]
}
/api/v1/shifts/division-stats?roster_uuid={roster_uuid}
Get shift statistics broken down by division/flag for a roster.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_uuid | string | Query | UUID of the roster |
Response
200 OK{
"roster_name": "Los Santos Police Department",
"divisions": [
{
"flag_name": "Patrol Division",
"active_count": 3,
"weekly_formatted": "45h 30m",
"member_count": 12
}
]
}
/api/v1/shifts/guild-rosters
Retrieve all rosters in your guild that have shift tracking enabled.
Response
200 OK{
"rosters": [
{ "roster_uuid": "abc-123-def", "name": "Los Santos Police Department" }
]
}
/api/v1/shifts/rosters?player_id={player_id}
Retrieve rosters where a specific player is enrolled and shift tracking is enabled.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| player_id | string | Query | Discord user ID |
Response
200 OK{
"rosters": [
{ "roster_uuid": "abc-123-def", "name": "Los Santos Police Department" }
]
}
/api/v1/shifts/player-flags?player_id={player_id}&roster_uuid={roster_uuid}
Retrieve a player's assigned flags/divisions for a roster. Useful for determining which division to start a shift under.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| player_id | string | Query | Discord user ID |
| roster_uuid | string | Query | UUID of the roster |
Response
200 OK{
"flags": [
{ "id": 1, "name": "Patrol Division" },
{ "id": 2, "name": "Detective Bureau" }
]
}
/api/v1/rosters/{roster_id}/loa
Get all LOA requests for a roster. Optionally filter by status.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
| status | string | query | Filter by status: pending, approved, denied, cancelled, expired |
Response
200{
"data": [
{
"id": 1,
"player_id": "123456789",
"player_name": "Senior Officer | C-12 - Ryneide",
"start_date": "2026-04-13",
"end_date": "2026-04-17",
"reason": "Vacation",
"status": "approved",
"approved_by": "987654321",
"approved_at": "2026-04-12T18:30:00Z"
}
]
}
/api/v1/rosters/{roster_id}/loa
Submit a new LOA request for a player. The request will be created with pending status.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
Request Body
{
"player_id": "123456789",
"start_date": "2026-04-13",
"end_date": "2026-04-17",
"reason": "Vacation"
}
Response
201{
"success": true,
"message": "LOA request created.",
"data": {
"id": 1,
"status": "pending"
}
}
/api/v1/rosters/{roster_id}/loa/{loa_id}/approve
Approve a pending LOA request. This will apply the configured status or flag to the player.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
| loa_id | integer | path | The LOA request ID |
Response
200{
"success": true,
"message": "LOA request approved."
}
/api/v1/rosters/{roster_id}/loa/{loa_id}/deny
Deny a pending LOA request with an optional reason. The player will be notified via DM.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
| loa_id | integer | path | The LOA request ID |
Request Body
{
"denial_reason": "Insufficient notice period"
}
Response
200{
"success": true,
"message": "LOA request denied."
}
/api/v1/rosters/{roster_id}/loa/{loa_id}/cancel
Cancel a pending or approved LOA. If the LOA was approved, the player's status/flag will be reverted.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
| loa_id | integer | path | The LOA request ID |
Response
200{
"success": true,
"message": "LOA request cancelled."
}
/api/v1/rosters/{roster_id}/members/{member_id}/strikes
Get all strikes for a specific player on a roster.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
| member_id | string | path | The Discord user ID of the player |
Response
200{
"data": [
{
"id": 1,
"player_id": "123456789",
"strike_info": "Failure to follow SOP",
"issued_by": "987654321",
"expires_at": null,
"created_at": "2026-04-10T14:00:00Z"
}
],
"total": 1,
"max_strikes": 4
}
/api/v1/rosters/{roster_id}/members/{member_id}/strikes
Add a strike to a player. If the player reaches a strike threshold with automated actions configured, those actions will be triggered.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
| member_id | string | path | The Discord user ID of the player |
Request Body
{
"reason": "Failure to follow SOP",
"expires_at": "2026-05-10"
}
Response
201{
"success": true,
"message": "Strike added.",
"data": {
"id": 2,
"total_strikes": 2,
"max_strikes": 4
}
}
/api/v1/rosters/{roster_id}/strikes/{strike_id}
Remove a specific strike from a player.
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
| strike_id | integer | path | The strike ID to remove |
Response
200{
"success": true,
"message": "Strike removed."
}
/api/v1/rosters/{roster_id}/strike-actions
Get the configured automated strike actions for a roster (thresholds and action types).
Parameters
| Name | Type | In | Description |
|---|---|---|---|
| roster_id | string | path | The roster UUID |
Response
200{
"data": [
{
"threshold": 3,
"action_type": "demote"
},
{
"threshold": 5,
"action_type": "remove"
}
]
}