# HRIStudio API Routes Documentation ## Overview HRIStudio uses tRPC for type-safe API communication between client and server. All routes are organized into routers by feature area and composed into a single app router. Authentication is handled by NextAuth.js v5. ## Base Configuration ```typescript // All routes are prefixed with /api/trpc/ // Example: POST /api/trpc/auth.login ``` ## Authentication Routes (`auth`) ### `auth.login` - **Description**: Authenticate user with email/password or OAuth - **Type**: Mutation - **Input**: ```typescript { email?: string password?: string provider?: 'google' | 'github' | 'microsoft' callbackUrl?: string } ``` - **Output**: Session object with user details - **Auth Required**: No - **Notes**: Handled primarily by NextAuth.js ### `auth.logout` - **Description**: End user session - **Type**: Mutation - **Input**: None - **Output**: `{ success: boolean }` - **Auth Required**: Yes ### `auth.register` - **Description**: Create new user account - **Type**: Mutation - **Input**: ```typescript { email: string password: string name: string institution?: string } ``` - **Output**: User object - **Auth Required**: No ### `auth.me` - **Description**: Get current user profile - **Type**: Query - **Input**: None - **Output**: User object with roles - **Auth Required**: Yes ## User Management Routes (`users`) ### `users.list` - **Description**: List all users (admin only) - **Type**: Query - **Input**: ```typescript { page?: number limit?: number search?: string role?: SystemRole } ``` - **Output**: Paginated user list - **Auth Required**: Yes (Administrator) ### `users.get` - **Description**: Get user by ID - **Type**: Query - **Input**: `{ id: string }` - **Output**: User object - **Auth Required**: Yes ### `users.update` - **Description**: Update user profile - **Type**: Mutation - **Input**: ```typescript { id: string name?: string email?: string image?: string } ``` - **Output**: Updated user object - **Auth Required**: Yes (Self or Administrator) ### `users.assignRole` - **Description**: Assign system role to user - **Type**: Mutation - **Input**: ```typescript { userId: string role: SystemRole } ``` - **Output**: Updated user roles - **Auth Required**: Yes (Administrator) ### `users.delete` - **Description**: Soft delete user account - **Type**: Mutation - **Input**: `{ id: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Administrator) ## Study Management Routes (`studies`) ### `studies.list` - **Description**: List studies accessible to user - **Type**: Query - **Input**: ```typescript { page?: number limit?: number status?: StudyStatus search?: string myStudiesOnly?: boolean } ``` - **Output**: Paginated study list with member counts - **Auth Required**: Yes ### `studies.get` - **Description**: Get study details - **Type**: Query - **Input**: `{ id: string }` - **Output**: Complete study object with metadata - **Auth Required**: Yes (Study member) ### `studies.create` - **Description**: Create new study - **Type**: Mutation - **Input**: ```typescript { name: string description?: string institution?: string irbProtocol?: string metadata?: Record } ``` - **Output**: Created study object - **Auth Required**: Yes (Researcher) ### `studies.update` - **Description**: Update study details - **Type**: Mutation - **Input**: ```typescript { id: string name?: string description?: string status?: StudyStatus metadata?: Record settings?: Record } ``` - **Output**: Updated study object - **Auth Required**: Yes (Study owner/researcher) ### `studies.delete` - **Description**: Archive study (soft delete) - **Type**: Mutation - **Input**: `{ id: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study owner) ### `studies.addMember` - **Description**: Add member to study team - **Type**: Mutation - **Input**: ```typescript { studyId: string userId: string role: StudyRole permissions?: string[] } ``` - **Output**: Study member object - **Auth Required**: Yes (Study owner/researcher) ### `studies.removeMember` - **Description**: Remove member from study - **Type**: Mutation - **Input**: ```typescript { studyId: string userId: string } ``` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study owner) ### `studies.getMembers` - **Description**: List study team members - **Type**: Query - **Input**: `{ studyId: string }` - **Output**: Array of member objects with roles - **Auth Required**: Yes (Study member) ### `studies.getActivity` - **Description**: Get study activity log - **Type**: Query - **Input**: ```typescript { studyId: string page?: number limit?: number startDate?: Date endDate?: Date } ``` - **Output**: Paginated activity log - **Auth Required**: Yes (Study member) ## Experiment Design Routes (`experiments`) ### `experiments.list` - **Description**: List experiments in a study - **Type**: Query - **Input**: ```typescript { studyId: string status?: ExperimentStatus } ``` - **Output**: Array of experiment objects - **Auth Required**: Yes (Study member) ### `experiments.get` - **Description**: Get experiment details with steps - **Type**: Query - **Input**: `{ id: string }` - **Output**: Experiment object with nested steps and actions - **Auth Required**: Yes (Study member) ### `experiments.create` - **Description**: Create new experiment - **Type**: Mutation - **Input**: ```typescript { studyId: string name: string description?: string robotId?: string estimatedDuration?: number metadata?: Record } ``` - **Output**: Created experiment object - **Auth Required**: Yes (Study researcher) ### `experiments.update` - **Description**: Update experiment details - **Type**: Mutation - **Input**: ```typescript { id: string name?: string description?: string status?: ExperimentStatus estimatedDuration?: number metadata?: Record } ``` - **Output**: Updated experiment object - **Auth Required**: Yes (Study researcher) ### `experiments.duplicate` - **Description**: Create copy of experiment - **Type**: Mutation - **Input**: ```typescript { experimentId: string newName: string includeSteps?: boolean } ``` - **Output**: New experiment object - **Auth Required**: Yes (Study researcher) ### `experiments.delete` - **Description**: Delete experiment - **Type**: Mutation - **Input**: `{ id: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study researcher) ### `experiments.addStep` - **Description**: Add step to experiment - **Type**: Mutation - **Input**: ```typescript { experimentId: string name: string description?: string type: StepType orderIndex: number durationEstimate?: number required?: boolean conditions?: Record } ``` - **Output**: Created step object - **Auth Required**: Yes (Study researcher) ### `experiments.updateStep` - **Description**: Update step details - **Type**: Mutation - **Input**: Step object with id - **Output**: Updated step object - **Auth Required**: Yes (Study researcher) ### `experiments.deleteStep` - **Description**: Remove step from experiment - **Type**: Mutation - **Input**: `{ id: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study researcher) ### `experiments.reorderSteps` - **Description**: Change step order - **Type**: Mutation - **Input**: ```typescript { experimentId: string stepIds: string[] // in new order } ``` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study researcher) ### `experiments.addAction` - **Description**: Add action to step - **Type**: Mutation - **Input**: ```typescript { stepId: string name: string description?: string type: string orderIndex: number parameters?: Record validationSchema?: Record timeout?: number } ``` - **Output**: Created action object - **Auth Required**: Yes (Study researcher) ### `experiments.updateAction` - **Description**: Update action details - **Type**: Mutation - **Input**: Action object with id - **Output**: Updated action object - **Auth Required**: Yes (Study researcher) ### `experiments.deleteAction` - **Description**: Remove action from step - **Type**: Mutation - **Input**: `{ id: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study researcher) ### `experiments.validate` - **Description**: Validate experiment configuration - **Type**: Query - **Input**: `{ experimentId: string }` - **Output**: ```typescript { valid: boolean errors?: ValidationError[] warnings?: ValidationWarning[] } ``` - **Auth Required**: Yes (Study member) ## Trial Execution Routes (`trials`) ### `trials.list` - **Description**: List trials for experiment - **Type**: Query - **Input**: ```typescript { experimentId?: string studyId?: string status?: TrialStatus participantId?: string wizardId?: string page?: number limit?: number } ``` - **Output**: Paginated trial list - **Auth Required**: Yes (Study member) ### `trials.get` - **Description**: Get trial details - **Type**: Query - **Input**: `{ id: string }` - **Output**: Trial object with events - **Auth Required**: Yes (Study member) ### `trials.create` - **Description**: Schedule new trial - **Type**: Mutation - **Input**: ```typescript { experimentId: string participantId?: string wizardId?: string scheduledAt?: Date parameters?: Record } ``` - **Output**: Created trial object - **Auth Required**: Yes (Study researcher) ### `trials.update` - **Description**: Update trial details - **Type**: Mutation - **Input**: ```typescript { id: string participantId?: string wizardId?: string scheduledAt?: Date status?: TrialStatus notes?: string } ``` - **Output**: Updated trial object - **Auth Required**: Yes (Study researcher/wizard) ### `trials.start` - **Description**: Begin trial execution - **Type**: Mutation - **Input**: `{ trialId: string }` - **Output**: ```typescript { success: boolean sessionToken: string websocketUrl: string } ``` - **Auth Required**: Yes (Assigned wizard) ### `trials.complete` - **Description**: Mark trial as completed - **Type**: Mutation - **Input**: ```typescript { trialId: string notes?: string } ``` - **Output**: Updated trial object - **Auth Required**: Yes (Assigned wizard) ### `trials.abort` - **Description**: Abort trial execution - **Type**: Mutation - **Input**: ```typescript { trialId: string reason: string } ``` - **Output**: Updated trial object - **Auth Required**: Yes (Assigned wizard) ### `trials.logEvent` - **Description**: Log trial event - **Type**: Mutation - **Input**: ```typescript { trialId: string eventType: string actionId?: string data?: Record } ``` - **Output**: Event object - **Auth Required**: Yes (Assigned wizard) ### `trials.addIntervention` - **Description**: Record wizard intervention - **Type**: Mutation - **Input**: ```typescript { trialId: string interventionType: string description?: string parameters?: Record reason?: string } ``` - **Output**: Intervention object - **Auth Required**: Yes (Assigned wizard) ### `trials.getEvents` - **Description**: Get trial event timeline - **Type**: Query - **Input**: ```typescript { trialId: string eventType?: string startTime?: Date endTime?: Date } ``` - **Output**: Array of event objects - **Auth Required**: Yes (Study member) ## Participant Management Routes (`participants`) ### `participants.list` - **Description**: List participants in a study - **Type**: Query - **Input**: ```typescript { studyId: string page?: number limit?: number search?: string } ``` - **Output**: Paginated participant list. Each participant object in this response includes a computed `trialCount` field (number of linked trials) plus derived consent metadata; sensitive fields like `demographics` and `notes` are omitted in this list view. - **Auth Required**: Yes (Study member) ### `participants.get` - **Description**: Get participant details - **Type**: Query - **Input**: `{ id: string }` - **Output**: Participant object (sensitive data based on permissions) - **Auth Required**: Yes (Study member) ### `participants.create` - **Description**: Register new participant - **Type**: Mutation - **Input**: ```typescript { studyId: string participantCode: string email?: string name?: string demographics?: Record } ``` - **Output**: Created participant object (does NOT include `notes` or `trialCount`; `trialCount` is computed and only appears in list output as an aggregate) - **Auth Required**: Yes (Study researcher) ### `participants.update` - **Description**: Update participant information - **Type**: Mutation - **Input**: Participant object with id - **Output**: Updated participant object - **Auth Required**: Yes (Study researcher) ### `participants.delete` - **Description**: Remove participant data - **Type**: Mutation - **Input**: `{ id: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study researcher) ### `participants.recordConsent` - **Description**: Record participant consent - **Type**: Mutation - **Input**: ```typescript { participantId: string consentFormId: string signatureData?: string ipAddress?: string } ``` - **Output**: Consent record object - **Auth Required**: Yes (Study researcher/wizard) ## Robot and Plugin Routes (`robots`) ### `robots.list` - **Description**: List available robots - **Type**: Query - **Input**: None - **Output**: Array of robot objects - **Auth Required**: Yes ### `robots.get` - **Description**: Get robot details - **Type**: Query - **Input**: `{ id: string }` - **Output**: Robot object with capabilities - **Auth Required**: Yes ### `robots.testConnection` - **Description**: Test robot connectivity - **Type**: Mutation - **Input**: ```typescript { robotId: string configuration: Record } ``` - **Output**: ```typescript { connected: boolean latency?: number error?: string } ``` - **Auth Required**: Yes (Study researcher) ### `plugins.list` - **Description**: List available plugins - **Type**: Query - **Input**: ```typescript { robotId?: string trustLevel?: PluginTrustLevel } ``` - **Output**: Array of plugin objects - **Auth Required**: Yes ### `plugins.get` - **Description**: Get plugin details - **Type**: Query - **Input**: `{ id: string }` - **Output**: Plugin object with action definitions - **Auth Required**: Yes ### `plugins.install` - **Description**: Install plugin for study - **Type**: Mutation - **Input**: ```typescript { studyId: string pluginId: string configuration?: Record } ``` - **Output**: Installation record - **Auth Required**: Yes (Study researcher) ### `plugins.uninstall` - **Description**: Remove plugin from study - **Type**: Mutation - **Input**: ```typescript { studyId: string pluginId: string } ``` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study researcher) ### `plugins.getActions` - **Description**: Get available actions for robot - **Type**: Query - **Input**: ```typescript { studyId: string robotId: string } ``` - **Output**: Array of action definitions - **Auth Required**: Yes (Study member) ## Media and Data Routes (`media`) ### `media.uploadVideo` - **Description**: Upload video file - **Type**: Mutation - **Input**: ```typescript { trialId: string file: File startTimestamp: Date endTimestamp?: Date } ``` - **Output**: Media capture object - **Auth Required**: Yes (Study member) ### `media.uploadAudio` - **Description**: Upload audio file - **Type**: Mutation - **Input**: Similar to uploadVideo - **Output**: Media capture object - **Auth Required**: Yes (Study member) ### `media.list` - **Description**: List media files for trial - **Type**: Query - **Input**: ```typescript { trialId: string mediaType?: MediaType } ``` - **Output**: Array of media objects - **Auth Required**: Yes (Study member) ### `media.getUrl` - **Description**: Get presigned URL for media - **Type**: Query - **Input**: `{ mediaId: string }` - **Output**: ```typescript { url: string expiresAt: Date } ``` - **Auth Required**: Yes (Study member) ### `media.delete` - **Description**: Delete media file - **Type**: Mutation - **Input**: `{ mediaId: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Study researcher) ### `sensorData.record` - **Description**: Record sensor data batch - **Type**: Mutation - **Input**: ```typescript { trialId: string sensorType: string data: Array<{ timestamp: Date values: Record robotState?: Record }> } ``` - **Output**: `{ recordedCount: number }` - **Auth Required**: Yes (System/Robot) ### `sensorData.query` - **Description**: Query sensor data - **Type**: Query - **Input**: ```typescript { trialId: string sensorType?: string startTime: Date endTime: Date limit?: number } ``` - **Output**: Array of sensor readings - **Auth Required**: Yes (Study member) ## Analysis Routes (`analysis`) ### `analysis.createAnnotation` - **Description**: Add annotation to trial - **Type**: Mutation - **Input**: ```typescript { trialId: string timestampStart: Date timestampEnd?: Date category?: string description: string tags?: string[] } ``` - **Output**: Annotation object - **Auth Required**: Yes (Study member) ### `analysis.updateAnnotation` - **Description**: Update existing annotation - **Type**: Mutation - **Input**: Annotation object with id - **Output**: Updated annotation - **Auth Required**: Yes (Annotation creator) ### `analysis.deleteAnnotation` - **Description**: Remove annotation - **Type**: Mutation - **Input**: `{ id: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Annotation creator) ### `analysis.getAnnotations` - **Description**: Get annotations for trial - **Type**: Query - **Input**: ```typescript { trialId: string category?: string annotatorId?: string } ``` - **Output**: Array of annotations - **Auth Required**: Yes (Study member) ### `analysis.exportData` - **Description**: Export study data - **Type**: Mutation - **Input**: ```typescript { studyId: string exportType: ExportType format: ExportFormat filters?: { experiments?: string[] trials?: string[] dateRange?: { start: Date end: Date } includeMedia?: boolean } } ``` - **Output**: Export job object - **Auth Required**: Yes (Study researcher) ### `analysis.getExportStatus` - **Description**: Check export job status - **Type**: Query - **Input**: `{ jobId: string }` - **Output**: ```typescript { status: JobStatus progress?: number downloadUrl?: string error?: string } ``` - **Auth Required**: Yes (Job creator) ## Collaboration Routes (`collaboration`) ### `collaboration.createComment` - **Description**: Add comment to resource - **Type**: Mutation - **Input**: ```typescript { resourceType: "study" | "experiment" | "trial" resourceId: string content: string parentId?: string metadata?: any } ``` - **Output**: Comment object - **Auth Required**: Yes (Study member) ### `collaboration.getComments` - **Description**: Get comments for resource - **Type**: Query - **Input**: ```typescript { resourceType: "study" | "experiment" | "trial" resourceId: string parentId?: string includeReplies?: boolean limit?: number offset?: number } ``` - **Output**: Array of comments - **Auth Required**: Yes (Study member) ### `collaboration.deleteComment` - **Description**: Delete comment (soft) - **Type**: Mutation - **Input**: `{ id: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Comment author) ### `collaboration.uploadAttachment` - **Description**: Upload file attachment - **Type**: Mutation - **Input**: ```typescript { resourceType: "study" | "experiment" | "trial" resourceId: string fileName: string fileSize: number contentType: string description?: string } ``` - **Output**: ```typescript { attachment: AttachmentObject uploadUrl: string } ``` - **Auth Required**: Yes (Study member) ### `collaboration.createShareLink` - **Description**: Create token-based shareable link for a resource - **Type**: Mutation - **Input**: ```typescript { resourceType: "study" | "experiment" | "trial" resourceId: string permissions?: ("read" | "comment" | "annotate")[] expiresAt?: Date description?: string } ``` - **Output**: ```typescript { id: string studyId: string resourceType: string resourceId: string shareToken: string shareUrl: string permissions: string[] expiresAt?: Date createdAt: Date } ``` - **Auth Required**: Yes (Study owner/researcher) ### `collaboration.getSharedResources` - **Description**: Get resources shared by the current user - **Type**: Query - **Input**: ```typescript { limit?: number offset?: number } ``` - **Output**: Array of shared resources with share URLs - **Auth Required**: Yes ### `collaboration.revokeShare` - **Description**: Revoke a share link - **Type**: Mutation - **Input**: `{ shareId: string }` - **Output**: `{ success: boolean }` - **Auth Required**: Yes (Share creator) ### `collaboration.accessSharedResource` - **Description**: Access a shared resource via token (public endpoint) - **Type**: Query - **Input**: `{ shareToken: string }` - **Output**: ```typescript { resourceType: string resourceId: string permissions: string[] } ``` - **Auth Required**: No (Public endpoint) ## System Administration Routes (`admin`) ### `admin.getSystemStats` - **Description**: Get system statistics - **Type**: Query - **Input**: None - **Output**: ```typescript { userCount: number studyCount: number trialCount: number storageUsed: number activeUsers: number } ``` - **Auth Required**: Yes (Administrator) ### `admin.getSystemSettings` - **Description**: Get system configuration - **Type**: Query - **Input**: None - **Output**: Settings object - **Auth Required**: Yes (Administrator) ### `admin.updateSystemSettings` - **Description**: Update system configuration - **Type**: Mutation - **Input**: ```typescript { key: string value: any } ``` - **Output**: Updated settings - **Auth Required**: Yes (Administrator) ### `admin.getAuditLog` - **Description**: Query audit log - **Type**: Query - **Input**: ```typescript { userId?: string action?: string resourceType?: string startDate?: Date endDate?: Date page?: number limit?: number } ``` - **Output**: Paginated audit entries - **Auth Required**: Yes (Administrator) ### `admin.createBackup` - **Description**: Initiate system backup - **Type**: Mutation - **Input**: ```typescript { includeMedia?: boolean encryptionKey?: string } ``` - **Output**: Backup job object - **Auth Required**: Yes (Administrator) ## WebSocket Events ### Trial Execution Events - `trial.started`: Trial execution began - `trial.action.started`: Action execution started - `trial.action.completed`: Action execution completed - `trial.intervention`: Wizard intervention occurred - `trial.error`: Error during execution - `trial.completed`: Trial finished - `trial.aborted`: Trial was aborted ### Collaboration Events - `study.member.joined`: New member added - `study.member.left`: Member removed - `comment.created`: New comment added - `annotation.created`: New annotation added ### System Events - `plugin.status`: Plugin connection status change - `export.progress`: Export job progress update - `system.maintenance`: System maintenance notification ## Error Handling All routes return consistent error responses: ```typescript { error: { code: string // e.g., 'UNAUTHORIZED', 'NOT_FOUND', 'VALIDATION_ERROR' message: string details?: any } } ``` Common error codes: - `UNAUTHORIZED`: User not authenticated - `FORBIDDEN`: User lacks permission - `NOT_FOUND`: Resource doesn't exist - `VALIDATION_ERROR`: Input validation failed - `CONFLICT`: Resource conflict (e.g., duplicate) - `INTERNAL_ERROR`: Server error ## Rate Limiting - Authentication endpoints: 5 requests per minute - File uploads: 10 per hour per user - Data exports: 5 per hour per study - General API calls: 100 per minute per user