PulseRoster API
A REST API over your community roster. Read and write members, departments, ranks, duty time, leave, discipline, certifications and documents from your own code.
Available on the Professional plan. Create a key in Community settings → API keys. Machine-readable spec: /api/v1/openapi.json.
Authentication
Send your key as a bearer token. The X-API-Key header works too, for HTTP clients that make setting Authorization awkward.
curl https://roster.mypulsetech.com/api/v1/whoami \
-H "Authorization: Bearer prk_a1b2c3d4_<secret>"GET /api/v1/whoami is the first call to make: it confirms the key is live and shows which community and scopes it carries.
Responses
Every response uses the same envelope, success or failure, so a client can branch on success.
{
"success": true,
"data": [ ... ],
"meta": {
"request_id": "a1b2c3d4",
"pagination": { "page": 1, "limit": 25, "total": 84, "total_pages": 4, "has_more": true }
}
}
{
"success": false,
"error": { "code": "insufficient_scope", "message": "This key lacks the required scope: roster:write" },
"meta": { "request_id": "e5f6a7b8" }
}meta.request_id is also returned as the X-Request-Id header and written to our logs. Quote it in a support message and we can find the exact request.
Rate limits
120 requests per minute and 25,000 per day, per key. A key can be given a lower per-minute limit in settings.
X-RateLimit-Limit: the ceiling for the window closest to exhaustion.X-RateLimit-Remaining: requests left. Present on successes too, so you can back off before you are throttled.X-RateLimit-Reset: unix seconds when the window rolls over.Retry-After: seconds to wait. Sent only with a 429.
Query conventions
Every list endpoint supports the same parameters. Which fields are filterable, sortable or searchable is listed per resource below.
?page=2&limit=50: pagination. Limit caps at 100.?sort=-createdAt: sort,-for descending.?q=smith: case-insensitive search across the resource's search fields.?status=ACTIVE&status=ON_LOA: repeat an enum filter to mean "either".?createdAt.after=2026-01-01T00:00:00Z: date range on any date-time field..beforetoo.?include=member,rank: expand related records.
Scopes
A key carries an explicit scope list. A :write scope implies its :read counterpart. You can only grant scopes you hold the matching staff permission for, so a key is never more powerful than the person who made it.
Roster
roster:readMembers, characters, department and subdivision assignments, roster slots, callsigns.roster:writeCreate, update and remove members; change ranks, assignments and slots.Departments
departments:readDepartments, subdivisions and ranks.departments:writeCreate, update and delete departments, subdivisions and ranks.Duty & activity
timelogs:readDuty sessions, time logs, activity logs and activity requirement status.timelogs:writeOpen and close duty sessions, create, edit and delete time logs.Leave of absence
loa:readLOA requests across the community.loa:writeCreate, approve, deny, extend and cancel LOA requests.Certifications
certifications:readCertification definitions and member certifications.certifications:writeManage certification definitions; award and revoke member certifications.Disciplinary
disciplinary:readDisciplinary records, appeals, probations, commendations and infraction categories.disciplinary:writeIssue, edit and delete disciplinary records; handle appeals and probations.Documents
documents:readDocuments, folders, versions, required reading and acknowledgment status.documents:writeCreate, edit, publish and delete documents and folders.Applications
applications:readApplication forms, submissions and answers.applications:writeReview submissions, change status, and manage application forms.Community
community:readCommunity profile, roles, staff roles, custom field definitions and code tables.community:writeUpdate community settings, roles, custom field definitions and code tables.audit:readThe community audit log.Errors
invalid_api_key401: missing, malformed, unknown, revoked or expired key.insufficient_scope403: the key is valid but lacks the scope this endpoint needs.ip_not_allowed403: the key has an IP allowlist and you are not on it.plan_required403: the community is not on an active Professional plan.not_found404: no such endpoint, or no such record in this community.method_not_allowed405: that verb is not supported for this resource.conflict409: a uniqueness constraint, or the record is still referenced.unprocessable422: well-formed, but a referenced record does not exist.validation_error400: a field or query parameter failed validation. See error.details.bad_request400: malformed JSON or no writable fields supplied.rate_limited429: slow down. Check Retry-After.internal500: our fault. Quote meta.request_id to support.Endpoints
22 resources. All paths are relative to https://roster.mypulsetech.com.
/api/v1/departments
A department within the community, e.g. a police or fire department.
- Filters:
- type, isActive, slug, publicRosterEnabled, rosterMode
- Sortable:
- name, sortOrder, createdAt, publicRosterOrder
- Searchable:
- name, abbreviation
- Expandable:
- ranks, subdivisions
/api/v1/subdivisions
A unit within a department, e.g. Traffic, K9, SWAT.
- Filters:
- departmentId, isActive, hasOwnRoster, publicRosterEnabled
- Sortable:
- name, sortOrder, createdAt
- Searchable:
- name, abbreviation
/api/v1/ranks
A rank within a department. `level` orders seniority, and higher is more senior.
- Filters:
- departmentId, isActive, isCommandStaff, isSupervisor, level
- Sortable:
- level, name, sortOrder, createdAt
- Searchable:
- name, abbreviation
/api/v1/members
A person in the community. Identity lives on the linked user; roster state lives here.
- Filters:
- status, isCommunityStaff, userId, fivemLicense, steamId
- Sortable:
- joinDate, createdAt, lastName, displayName, status
- Searchable:
- displayName, firstName, lastName
- Expandable:
- characters, departmentAssignments
/api/v1/characters
An in-game character belonging to a member.
- Filters:
- memberId, isPrimary
- Sortable:
- name, createdAt
- Searchable:
- name
/api/v1/department-assignments
Places a member in a department at a rank. The core roster row.
- Filters:
- memberId, departmentId, rankId, status, isPrimary, characterId
- Sortable:
- joinDate, createdAt, callsign, badgeNumber
- Searchable:
- callsign, badgeNumber, unitNumber
- Expandable:
- member, rank, department
/api/v1/subdivision-assignments
Places an existing department assignment into a subdivision.
- Filters:
- departmentAssignmentId, subdivisionId
- Sortable:
- joinDate, createdAt
/api/v1/roster-slots
A named position in a slot-based or hybrid roster. A null assignedMemberId means vacant.
- Filters:
- departmentId, subdivisionId, rankId, assignedMemberId, isActive
- Sortable:
- sortOrder, badgeNumber, createdAt
- Searchable:
- badgeNumber, name
/api/v1/member-notes
A staff note attached to a member. Private notes are visible to their author in the UI; see the caveat in the docs.
- Filters:
- memberId, createdById, isPinned, isPrivate, category
- Sortable:
- createdAt, updatedAt
- Searchable:
- content
/api/v1/duty-sessions
A shift. `endedAt` is null while the member is still on duty.
- Filters:
- memberId, departmentAssignmentId, source, activityType
- Sortable:
- startedAt, endedAt, createdAt
- Expandable:
- member
/api/v1/activity-logs
Logged hours against a department assignment. Denied entries are excluded from all totals.
- Filters:
- departmentAssignmentId, activityType, verified, loggedById
- Sortable:
- date, hours, createdAt
- Searchable:
- description
/api/v1/leaves-of-absence
An LOA request. Status drives whether the member shows as on leave.
- Filters:
- memberId, status, type, departmentAssignmentId
- Sortable:
- startDate, endDate, requestedAt, createdAt
- Expandable:
- member
/api/v1/disciplinary-records
A disciplinary action filed against a department assignment.
- Filters:
- departmentAssignmentId, type, isActive, appealStatus, infractionCategoryId
- Sortable:
- issuedAt, expiresAt, createdAt
- Searchable:
- description
/api/v1/disciplinary-appeals
An appeal against a disciplinary record.
- Filters:
- disciplinaryRecordId, appellantId, status, stage
- Sortable:
- submittedAt, reviewedAt, createdAt
/api/v1/probations
A probation period for a member, often triggered by a disciplinary record.
- Filters:
- memberId, status, departmentAssignmentId, disciplinaryRecordId
- Sortable:
- startDate, endDate, createdAt
/api/v1/commendations
An award or recognition given to a department assignment.
- Filters:
- departmentAssignmentId, type, awardedById
- Sortable:
- awardedAt, createdAt
- Searchable:
- type, description
/api/v1/certifications
A certification definition. `departmentId` null means community-wide.
- Filters:
- departmentId, isActive
- Sortable:
- name, createdAt
- Searchable:
- name, abbreviation
/api/v1/member-certifications
A certification awarded to a member.
- Filters:
- memberId, certificationId, tier
- Sortable:
- awardedAt, expiresAt, createdAt
- Expandable:
- certification, member
/api/v1/documents
A document in the documentation CMS. `isDraft` false plus a publishedAt means it is live.
- Filters:
- departmentId, folderId, type, isDraft, isActive, slug, requiresAcknowledgment
- Sortable:
- title, sortOrder, publishedAt, createdAt, updatedAt
- Searchable:
- title
/api/v1/document-folders
A folder in the documentation tree.
- Filters:
- departmentId, parentFolderId, isActive, slug
- Sortable:
- name, sortOrder, createdAt
- Searchable:
- name
/api/v1/announcements
A community or department announcement.
- Filters:
- departmentId, priority, isPinned, isActive
- Sortable:
- publishAt, createdAt, title
- Searchable:
- title, content
/api/v1/audit-logs
The community audit trail. `apiKeyId` is set when the change came through this API.
- Filters:
- actorId, action, targetType, targetId, apiKeyId
- Sortable:
- createdAt