This document defines the cross-team API contracts. These endpoints must be implemented exactly as specified so other teams can call them.
All endpoints return responses in this format:
{
"success": true,
"data": { ... },
"pagination": {
"page": 1,
"pageSize": 20,
"total": 150,
"totalPages": 8
}
}Error responses:
{
"success": false,
"error": {
"code": "ERROR_CODE",
"message": "Human readable message"
}
}Returns approved contacts for an incarcerated person.
Used by: Voice, Video, Messaging
Query: ?incarceratedPersonId=X&familyMemberId=Y
Returns: { approved: boolean, isAttorney: boolean }
Used by: All communication guilds (before connecting)
Returns facility info including announcement text/audio.
Used by: Voice (for announcements)
Returns rules for the unit type (call duration, hours, etc.).
Used by: Voice, Video
Returns user profile (incarcerated or family).
Query: ?phoneNumber=X&facilityId=Y
Returns: { blocked: boolean, scope: 'facility' | 'agency' }
Used by: Voice
Query: ?facilityId=X
Returns list of calls currently in progress.
Query: ?facilityId=X&startDate=Y&endDate=Z&userId=W&page=1&pageSize=20
Returns paginated call history.
Body: { adminId: string }
Terminates an active call.
Query: ?facilityId=X&date=Y
Returns: { activeCalls: number, todayTotal: number }
Query: ?facilityId=X
Returns list of video calls in progress.
Query: ?facilityId=X&startDate=Y&endDate=Z&userId=W&page=1&pageSize=20
Returns paginated video call history.
Query: ?facilityId=X
Returns video call requests awaiting approval.
Body: { adminId: string }
Approves a video call request.
Body: { adminId: string }
Terminates an active video call.
Query: ?facilityId=X&date=Y
Returns: { activeCalls: number, todayTotal: number, pendingRequests: number }
Query: ?facilityId=X&startDate=Y&endDate=Z&userId=W&page=1&pageSize=20
Returns paginated message metadata.
Query: ?facilityId=X
Returns messages flagged for manual review.
Body: { adminId: string }
Approves a pending message.
Body: { adminId: string }
Blocks a conversation.
Query: ?facilityId=X&date=Y
Returns: { todayTotal: number, pendingReview: number }
All endpoints (except public ones) require a valid JWT in the Authorization header:
Authorization: Bearer <token>
Use the middleware from @openconnect/shared:
import { requireAuth, requireRole } from '@openconnect/shared';
router.get('/endpoint', requireAuth, (req, res) => {
// req.user contains the authenticated user
});
router.post('/admin-only', requireAuth, requireRole('facility_admin', 'agency_admin'), (req, res) => {
// Only admins can access
});