Admin Guide
API Reference
Complete reference for the RokuChannel Platform REST API. The API runs on port 8065 and uses JWT-based authentication. All responses are JSON.
API Request Flow
Figure 8: API Request Flow -- Client through JSON Response
Authentication
All authenticated endpoints require a JWT token obtained from ONETIMELOGIN SSO.
Header Format
http
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
Alternatively, the token can be sent as an access_token cookie.
JWT Claims
| Claim | Description | Example |
|---|---|---|
| sub | User ID | 01905a3b-... |
| User email | admin@example.com | |
| role | User role | ADMIN |
| permissions | Permission list | ["read", "write"] |
| site_code | Site identifier | roku |
| tenant_id | Tenant partition key | default |
Base URL & Versioning
text
Base URL: http://localhost:8065
API Prefix: /api
Version: 1.0.0 (see GET /api/info)
The API does not use URL-based versioning (e.g., /api/v1/). The version is returned in the GET /api/info response. Future breaking changes will be communicated through version bumps.
Error Response Format
All error responses follow a consistent format:
json
{
"detail": "Channel not found"
}
| Status Code | Meaning | Common Causes |
|---|---|---|
| 400 | Bad Request | Invalid input, validation errors |
| 401 | Unauthorized | Missing/invalid JWT token |
| 403 | Forbidden | Insufficient role (admin required) |
| 404 | Not Found | Resource does not exist or is soft-deleted |
| 422 | Unprocessable Entity | Pydantic validation failure |
| 429 | Too Many Requests | Rate limit exceeded (100/min) |
| 500 | Internal Server Error | Server-side failure |
Rate Limiting
The API enforces rate limiting to protect against abuse:
- Default limit: 100 requests per minute per client
- Storage: Redis-backed (falls back to in-memory)
- Response: Returns 429 Too Many Requests when exceeded
- Configuration: Adjustable via rate_limit_default in settings
CSRF protection applies to state-changing methods (POST, PUT, DELETE, PATCH) when using cookie-based auth. API calls with Authorization: Bearer header bypass CSRF checks.
Complete Endpoint Reference
Channel Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/channels | User | Create a new channel |
| GET | /api/channels | User | List all channels (paginated: ?page=1&per_page=20) |
| GET | /api/channels/{id} | User | Get channel by ID |
| PUT | /api/channels/{id} | User | Update a channel (partial update) |
| DELETE | /api/channels/{id} | Admin | Delete channel (soft-delete) |
Video Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/episodes/{id}/video | User | Create or update video asset (upsert) |
| GET | /api/episodes/{id}/video | User | Get video asset for episode |
Homework Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/episodes/{id}/homework | User | Create homework for episode |
| GET | /api/episodes/{id}/homework | User | List homework for episode |
| PUT | /api/episodes/homework/{id} | User | Update homework |
| DELETE | /api/episodes/homework/{id} | User | Delete homework (soft-delete) |
| POST | /api/episodes/homework/{id}/submit | User | Submit homework (student) |
| PUT | /api/episodes/homework/submissions/{id}/grade | User | Grade a homework submission |
Test Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/episodes/{id}/tests | User | Create a test for episode |
| GET | /api/episodes/{id}/tests | User | List tests for episode |
| PUT | /api/episodes/tests/{id} | User | Update a test |
| DELETE | /api/episodes/tests/{id} | User | Delete a test (soft-delete) |
| POST | /api/episodes/tests/{id}/questions | User | Add question to test |
| GET | /api/episodes/tests/{id}/questions | User | List questions in test |
| PUT | /api/episodes/questions/{id} | User | Update a question |
| DELETE | /api/episodes/questions/{id} | User | Delete a question (soft-delete) |
| POST | /api/episodes/tests/{id}/attempt | User | Submit test attempt (auto-grades) |
Student Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/enroll | User | Enroll in a channel (idempotent) |
| GET | /api/enrollments | User | List my enrollments |
| POST | /api/progress | User | Update watch progress (upsert) |
| GET | /api/progress/{episode_id} | User | Get watch progress for episode |
| GET | /api/grades | User | Get all my grades |
| GET | /api/grades/{episode_id} | User | Get grade for specific episode |
Roku Feed Endpoint
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /api/roku/feed/{channel_id} | Public | Public Roku JSON content feed (no auth) |
Innovation Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| POST | /api/innovation/run/{agent_type} | Admin | Trigger innovation agent (content or engagement) |
| GET | /api/innovation/status | User | Get LLM configuration status |
| GET | /api/innovation/suggestions | User | List suggestions (?agent_type=&status=&page=) |
| PUT | /api/innovation/suggestions/{id} | Admin | Review a suggestion |
System Endpoints
| Method | Path | Auth | Description |
|---|---|---|---|
| GET | /health | Public | Health check (DB status, response time) |
| GET | /api/info | Public | API info (name, version, SSO URL) |
| GET | /api/csrf-token | Public | Generate CSRF token + set cookie |
Endpoint Summary
| Category | Count | Auth Level |
|---|---|---|
| Channel API | 5 | User (Delete: Admin) |
| Video API | 2 | User |
| Homework API | 6 | User |
| Test API | 9 | User |
| Student API | 6 | User |
| Roku Feed | 1 | Public |
| Innovation API | 4 | User (Run/Review: Admin) |
| System | 3 | Public |
| Total API Routes | 36 |
In addition to the 36 API routes, the application serves 14 static HTML pages (dashboard, channels, episodes, student views, etc.) for a total of 50 routes.
Pagination
List endpoints support pagination via query parameters:
http
GET /api/channels?page=1&per_page=20
Response:
{
"items": [...],
"total": 42,
"page": 1,
"per_page": 20,
"pages": 3
}
- page -- Page number (starts at 1)
- per_page -- Items per page (default: 20, max: 100)