Training Module API & Integration Guide
Full admin and customer/mobile API contract for training, session, cohort, waitlist, and enrollment flows.
Training - API & Integration Guide
Audience: Admin-panel developers, mobile/web client developers, backend integrators
Scope: Auth model, endpoints, DTO contracts, enums, business rules, and integration recipes.
1. How to Read / Quick Metadata
- Module:
Training - Auth models:
- Admin routes:
JwtAuthGuard + RoleGuard + @Permissions(...) - Customer/mobile routes:
JwtAuthGuard
- Admin routes:
- Primary base URLs:
- Admin training:
/api/admin/training - Admin sessions:
/api/admin/training/:trainingId/sessions - Admin cohorts:
/api/admin/training/:trainingId/cohorts - Admin enrollments:
/api/admin/training/enrollments - Customer discovery:
/api/trainings - Mobile-composed discovery:
/api/mobile/trainings - Customer enrollment/access:
/api/training - Mobile-composed enrollment/access:
/api/mobile/training
- Admin training:
- Response envelope: all successful endpoints return
ResponseDto<T> - Swagger tags used by controllers:
Training (Admin)Training Session (Admin)Training Cohort (Admin)Training Enrollment (Admin)Training DiscoveryTraining Enrollment
2. High-Level Overview
Training module manages:
- training metadata and publication lifecycle,
- training sessions,
- cohorts with capacity/waitlist,
- user enrollments and enrollment access fields,
- session access at runtime.
Commerce integration model:
- Training enrollment request creates pending enrollment + training order/payment intent synchronously.
- API returns payment-init payload immediately for gateway handoff.
- Payment success finalizes enrollment (
status = "enrolled") and sets access fields.
Training products bypass cart.
3. Core Concepts and Terminology
- training: Content metadata for a training product.
- training_session: Session entity linked to the training's product ID.
- training_cohort: Capacity-based batch for a training.
- training_cohort_session: Cohort-specific schedule overrides per session.
- training_enrollment: User enrollment state (
pending,enrolled,cancelled).- DB constraint: only one
enrolledrow per(user_id, product_id)via partial unique index. - Compatibility rule:
pendingrows may exist withorderId = nullduring pre-payment lifecycle.
- DB constraint: only one
- training_enrollment_form_config: Optional structured form schema per training.
- training_waitlist: Overflow queue for full cohorts.
- product_access: Entitlement row used across digital products.
Key state fields:
training.status:draft | published | hidden | archivedtraining_session.status:scheduled | live | completed | cancelledtraining_cohort.status:open | closed | full | cancelledtraining_waitlist.status:waiting | promoted | expired | cancelledtraining_enrollment.status:pending | enrolled | cancelled
4. Route Summary
4.1 Admin training endpoints
| Method | Path | Permission | Request DTO | Response DTO |
|---|---|---|---|---|
GET | /api/admin/training | Training_READ | FetchTrainingDto | TrainingListItemDto[] (paginated) |
GET | /api/admin/training/:id | Training_READ | path id | TrainingResponseDto |
POST | /api/admin/training | Training_CREATE | CreateTrainingDto | TrainingResponseDto |
PATCH | /api/admin/training/:id | Training_UPDATE | UpdateTrainingDto | TrainingResponseDto |
POST | /api/admin/training/:id/trailer | Training_UPDATE | multipart file | TrainingResponseDto |
DELETE | /api/admin/training/:id/trailer | Training_UPDATE | path id | TrainingResponseDto |
DELETE | /api/admin/training/:id | Training_DELETE | path id | TrainingDeleteResponseDto |
GET | /api/admin/training/:id/form-config | Training_READ | path id | TrainingFormConfigDto | null |
PUT | /api/admin/training/:id/form-config | Training_UPDATE | UpdateFormConfigDto | TrainingFormConfigDto |
4.2 Admin session endpoints
| Method | Path | Permission |
|---|---|---|
GET | /api/admin/training/:trainingId/sessions | Training_READ |
POST | /api/admin/training/:trainingId/sessions | Training_SESSION_CREATE |
PUT | /api/admin/training/:trainingId/sessions/reorder | Training_SESSION_UPDATE |
GET | /api/admin/training/:trainingId/sessions/:sessionId | Training_READ |
PATCH | /api/admin/training/:trainingId/sessions/:sessionId | Training_SESSION_UPDATE |
PATCH | /api/admin/training/:trainingId/sessions/:sessionId/recording | Training_SESSION_UPDATE |
DELETE | /api/admin/training/:trainingId/sessions/:sessionId | Training_SESSION_DELETE |
4.3 Admin cohort and waitlist endpoints
| Method | Path | Permission |
|---|---|---|
GET | /api/admin/training/:trainingId/cohorts | Training_READ |
POST | /api/admin/training/:trainingId/cohorts | Training_Cohort_CREATE |
GET | /api/admin/training/:trainingId/cohorts/:cohortId | Training_READ |
PATCH | /api/admin/training/:trainingId/cohorts/:cohortId | Training_Cohort_UPDATE |
DELETE | /api/admin/training/:trainingId/cohorts/:cohortId | Training_Cohort_DELETE |
PUT | /api/admin/training/:trainingId/cohorts/:cohortId/sessions | Training_Cohort_UPDATE |
GET | /api/admin/training/:trainingId/cohorts/:cohortId/waitlist | Training_READ |
POST | /api/admin/training/:trainingId/cohorts/:cohortId/waitlist/:waitlistId/promote | Training_Cohort_UPDATE |
4.4 Admin enrollment endpoints
| Method | Path | Permission | Notes |
|---|---|---|---|
GET | /api/admin/training/enrollments | Training_READ | filters + pagination/sort |
GET | /api/admin/training/enrollments/:id | Training_READ | enriched enrollment detail |
PATCH | /api/admin/training/enrollments/:id/status | Training_UPDATE | adjusts cohort counters on transitions |
4.5 Customer/mobile endpoints
| Method | Path | Request DTO | Response DTO |
|---|---|---|---|
POST | /api/mobile/training/enroll | EnrollTrainingDto | PaymentInitResponseDto |
GET | /api/mobile/training/enrollments | QueryDto | TrainingEnrollmentResponseDto[] (paginated) |
GET | /api/mobile/training/enrollments/:id | path id | TrainingEnrollmentResponseDto |
GET | /api/mobile/training/cohorts/:cohortId | path cohortId | CohortEnrollmentDetailDto |
GET | /api/mobile/training/sessions/:sessionId | path sessionId | SessionEnrollmentDetailDto |
GET | /api/mobile/training/:trainingId/sessions | path trainingId | SessionListItemDto[] |
GET | /api/mobile/training/:trainingId/sessions/:sessionId/content | path params | SessionContentResponseDto |
POST | /api/mobile/training/enrollments/:id/request-cancellation | RequestCancellationDto | EnrollmentCancellationResponseDto |
GET | /api/mobile/trainings | TrainingListQueryDto | TrainingListItemDto[] (paginated) |
GET | /api/mobile/trainings/featured | TrainingListQueryDto | TrainingListItemDto[] (paginated) |
Same controllers are also available on non-mobile customer prefixes (/api/training/*, /api/trainings/*).
4.6 Trailer contract notes
trailerRefis the canonical storage key persisted ontraining.trailerReftrailerUrlis resolved by backend reads and should be used directly for playback- Discovery list and featured responses now expose both fields via
TrainingListItemDto - Admin clients may still write
trailerRefthroughPATCH /api/admin/training/:id, but dedicated upload/clear routes are preferred for backend-managed cleanup semantics
5. Query Parameters
5.1 Shared base query (QueryDto)
| Param | Type | Default | Notes |
|---|---|---|---|
pagination | boolean | true | toggles count/page/size metadata and DB limit/offset |
page | number | 1 | minimum 1 |
size | number | 20 | minimum 1, capped by PaginationUtil |
sort | string | updatedAt | endpoint-specific allowed values |
order | asc | desc | desc | ascending/descending |
search | string | optional | trimmed string search |
5.2 Admin training list (FetchTrainingDto)
Additional filters:
status:draft \| published \| hidden \| archivedcategoryId: numbertagId: number- accepted sort:
title \| status \| isFree \| createdAt \| updatedAt \| relevance
5.3 Customer discovery list (TrainingListQueryDto)
Additional filters:
categoryId: numbertagId: number- accepted sort:
title \| isFree \| createdAt \| updatedAt \| relevance
5.4 Admin enrollment list (ListTrainingEnrollmentsQueryDto)
Additional filters:
status:pending \| enrolled \| cancelledproductId: numberuserId: UUID stringcohortId: number- accepted sort:
id \| status \| productId \| userId \| cohortId \| createdAt \| updatedAt
6. Response Shape Examples
6.1 Enrollment init request (EnrollTrainingDto)
{
"productId": 101,
"promoCode": "SUMMER2026",
"gateway": "esewa",
"returnUrl": "https://example.com/payment/return",
"formData": {
"name": "Sita Shrestha",
"email": "sita@example.com",
"phone": "+9779800000000"
},
"cohortId": 1,
"sessionId": 5
}6.2 Training enrollment response (TrainingEnrollmentResponseDto)
{
"id": 1,
"status": "pending",
"userId": "9a824f6a-28d9-44ef-8c61-72d68a8f1b57",
"productId": 101,
"orderId": null,
"cohortId": 1,
"sessionId": 5,
"accessType": null,
"accessValidUntil": null,
"formData": {
"name": "Sita Shrestha"
},
"enrolledAt": null,
"createdAt": "2026-03-17T09:45:00.000Z",
"updatedAt": "2026-03-17T09:45:00.000Z"
}6.3 Admin enrollment detail (TrainingEnrollmentAdminResponseDto)
{
"id": 1,
"status": "enrolled",
"userId": "9a824f6a-28d9-44ef-8c61-72d68a8f1b57",
"productId": 101,
"orderId": 501,
"cohortId": 1,
"sessionId": 5,
"accessType": "time_limited",
"accessValidUntil": "2026-09-17T00:00:00.000Z",
"formData": {
"name": "Sita Shrestha"
},
"enrolledAt": "2026-03-18T10:20:00.000Z",
"createdAt": "2026-03-17T09:45:00.000Z",
"updatedAt": "2026-03-18T10:20:00.000Z",
"orderNumber": "ORD-20260318-001",
"orderTotalPaisa": 5000,
"orderStatus": "paid",
"userName": "Sita Shrestha",
"userEmail": "sita@example.com",
"trainingTitle": "NEPSE Trading Masterclass"
}6.4 Session content response (SessionContentResponseDto)
{
"id": 5,
"title": "Session 3: Risk Management",
"description": "Risk sizing and drawdown controls",
"videoHlsUrl": "https://cdn.bullhouse.com/hls/training/session-3/index.m3u8?token=eyJ...",
"videoTokenExpiresAt": "2026-04-16T14:00:00.000Z",
"liveSessionRef": null,
"durationMinutes": 75,
"type": "both",
"sessionStatus": "completed",
"accessibleVia": "recording"
}Note (Phase 12):
recordingUrlhas been removed from this response. Recorded session playback uses a signed HLS URL (videoHlsUrl) that expires atvideoTokenExpiresAt. UsePOST /mobile/training/{trainingId}/sessions/{sessionId}/video-tokento refresh the token before expiry.
6.5 Standard envelope (ResponseDto)
{
"message": "Training enrollments fetched successfully",
"data": [
{
"id": 1,
"status": "pending",
"userId": "9a824f6a-28d9-44ef-8c61-72d68a8f1b57",
"productId": 101,
"orderId": null,
"cohortId": 1,
"sessionId": 5,
"accessType": null,
"accessValidUntil": null,
"formData": {
"name": "Sita Shrestha"
},
"enrolledAt": null,
"createdAt": "2026-03-17T09:45:00.000Z",
"updatedAt": "2026-03-17T09:45:00.000Z"
}
],
"count": 10,
"page": 1,
"size": 20,
"errorCode": null
}6.6 Trailer response fields
Admin detail and discovery preview surfaces now return:
{
"trailerRef": "public/trailer/training/nepse-masterclass.mp4",
"trailerUrl": "https://cdn.example.com/public/trailer/training/nepse-masterclass.mp4"
}Use trailerUrl directly for playback. Do not derive URLs from trailerRef in the client.
7. Enums
| Enum | Values |
|---|---|
training_status | draft, published, hidden, archived |
training_session_type | recorded, live, both |
training_session_status | scheduled, live, completed, cancelled |
training_cohort_status | open, closed, full, cancelled |
training_waitlist_status | waiting, promoted, expired, cancelled |
training_enrollment_status | pending, enrolled, cancelled |
training_access_type | lifetime, time_limited |
8. Integration Diagram
8.1 Enrollment request and post-payment finalization
8.2 Session access decision flow
9. Caching
Training module uses Redis read-through caching with deterministic keys via CacheKeyUtil.build(...).
9.1 Core cache key prefixes
- Training admin list/detail:
training:admin:list:,training:admin:detail: - Discovery list/featured:
training:customer:list:,training:customer:featured: - Session lists:
training:session:admin:list:,training:session:customer:list: - Cohort and waitlist:
training:cohort:admin:list:,training:cohort:waitlist: - Enrollment list/detail (customer):
training:enrollment:list:,training:enrollment:detail: - Enrollment list/detail (admin):
training:enrollment:admin:list:,training:enrollment:admin:detail: - Product access by user:
training:product-access:user:
9.2 TTL and invalidation
- TTL env:
REDIS_CACHE_TTL_SECONDS - Mutation paths invalidate by prefix using
invalidatePattern(prefix*) - Enrollment and status transitions invalidate enrollment, related session-list, and product-access scopes
10. Error Handling
All business failures use structured { message, errorCode } exceptions and the frontend should branch only on errorCode.
10.1 Validation and domain edge cases
- Training product mismatch ->
TRAINING_PRODUCT_REQUIRED - Product unpublished/unsellable ->
TRAINING_PRODUCT_UNAVAILABLE - Duplicate active enrollment ->
TRAINING_ALREADY_ENROLLED - Invalid or ineligible promo code during training order creation ->
PROMOTION_NOT_APPLICABLE - Missing required dynamic form fields ->
TRAINING_INVALID_FORM_DATA - Cohort full/closed/cancelled ->
TRAINING_COHORT_FULL/TRAINING_COHORT_CLOSED/TRAINING_COHORT_CANCELLED - Session mismatch with training ->
TRAINING_SESSION_MISMATCH - Pending cancellation request ->
TRAINING_ENROLLMENT_CANCEL_NOT_ALLOWED - Session content before live or recording availability ->
TRAINING_SESSION_NOT_LIVE/TRAINING_RECORDING_NOT_AVAILABLE
10.2 Common flow recipes and client behavior
Admin setup flow:
- Create training via
POST /api/admin/training. - Create sessions via
POST /api/admin/training/:trainingId/sessions. - Create cohort via
POST /api/admin/training/:trainingId/cohorts. - Assign sessions to cohort via
PUT /api/admin/training/:trainingId/cohorts/:cohortId/sessions. - Configure enrollment form via
PUT /api/admin/training/:id/form-config.
Customer enrollment flow:
- Optionally validate coupon via
POST /api/mobile/promotions/applywithcode+productId. - Submit enrollment request via
POST /api/mobile/training/enroll(optionalpromoCode). - Use returned payment-init payload to start gateway payment.
- Poll enrollment list/detail while payment is pending.
- After payment success in order flow, enrollment becomes
enrolledand session access is enabled.
Client integration guidelines:
- Use
errorCodefor business branching. - Treat
pendingenrollment as non-access state. - For pending enrollments, session list may include
paymentStatusNote; do not expose content links until enrolled. - Use pagination params for list endpoints and read count/page/size only when pagination is enabled.
10.3 Testing scenarios and operational integration
Recommended scenario coverage:
- Admin lifecycle: create training -> update status -> archive.
- Session ordering and reorder payload validation.
- Cohort creation and duplicate cohort-name conflict.
- Waitlist promote idempotency and mismatch rejection.
- Enrollment idempotency for repeated enroll request.
- Pending vs enrolled session access behavior.
- Cancellation path with cohort seat decrement.
- Admin enrollment status update effect on seat counts.
Transactional notification integration:
- Order lifecycle events:
ORDER_PLACED_CHECKOUT,ORDER_PLACED_BUYNOW,ORDER_PAYMENT_RECEIVED_CHECKOUT,ORDER_PAYMENT_RECEIVED_BUYNOW,ORDER_PAYMENT_FAILED,ORDER_CANCELLED,ORDER_REFUND_* - Enrollment confirmation event:
TRAINING_ENROLLMENT_CONFIRMED - Emission boundary: confirmation is emitted after successful post-payment finalization; notification delivery failure is fail-open and does not block enrollment/access writes.
Related docs:
Time fields in this module are stored as timezone-aware values and should be handled as ISO-8601 instants by API consumers.
See Also
- Feature Guide: See Training - Feature List Section 6 (State Models) for training lifecycle diagram.
- Backend Reference: See Training - Backend Documentation Section 9 for system architecture diagram.
- Trailer Guide: See Training Trailer Videos for upload, clear, and playback-field semantics.