Shop It Docs
Developer Resourcestraining

Training Trailer Videos

Admin upload, replacement, clear, and playback contract for training trailers.

Training Trailer Videos

Training trailers follow the same contract shape as course trailers:

  • trailerRef is the canonical stored key
  • trailerUrl is the backend-resolved playback URL
  • clients should never derive playback URLs from trailerRef

Admin routes

MethodPathPurpose
POST/api/admin/training/:id/trailerUpload or replace a trailer via multipart file
DELETE/api/admin/training/:id/trailerClear trailer and delete prior managed object
PATCH/api/admin/training/:idAlternate path to write trailerRef directly
GET/api/admin/training/:idRead trailerRef plus resolved trailerUrl

Upload and replace flow

  1. Admin uploads a trailer with POST /api/admin/training/:id/trailer
  2. Backend validates MP4 MIME, .mp4 extension, and size limit
  3. Backend uploads the file with UploadType.TRAILER
  4. Backend persists the returned storage key into training.trailerRef
  5. If a previous managed trailer existed under public/trailer/, backend deletes it after the new ref is saved
  6. If persistence fails after storage upload, backend deletes the newly uploaded managed object before returning the error

Multipart request requirements

  • field name: file
  • content type: multipart/form-data
  • accepted MIME: video/mp4
  • accepted extension: .mp4
  • size limit: COURSE_TRAILER_MAX_FILE_SIZE_MB (default 250)

Success example:

{
  "message": "Training trailer uploaded successfully",
  "data": {
    "id": 101,
    "trailerRef": "public/trailer/training/nepse-masterclass.mp4",
    "trailerUrl": "https://cdn.example.com/public/trailer/training/nepse-masterclass.mp4"
  }
}

Clear flow

DELETE /api/admin/training/:id/trailer sets trailerRef to null and best-effort deletes the old managed object.

{
  "message": "Training trailer cleared successfully",
  "data": {
    "id": 101,
    "trailerRef": null,
    "trailerUrl": null
  }
}

Alternate shared-upload path

If you already use the shared upload endpoint:

  1. POST /api/upload?uploadType=trailer&optimize=false
  2. Read relativePath from the upload response
  3. PATCH /api/admin/training/:id with { "trailerRef": "<relativePath>" }

This remains supported, but it does not replace the dedicated trailer lifecycle endpoints when you want backend-managed replacement and cleanup.

Read surfaces

Admin detail

GET /api/admin/training/:id returns both the stored key and the resolved URL:

{
  "id": 101,
  "title": "NEPSE Trading Masterclass",
  "trailerRef": "public/trailer/training/nepse-masterclass.mp4",
  "trailerUrl": "https://cdn.example.com/public/trailer/training/nepse-masterclass.mp4"
}

GET /api/trainings and GET /api/trainings/featured expose preview metadata through TrainingListItemDto:

{
  "id": 101,
  "title": "NEPSE Trading Masterclass",
  "thumbnailRef": "https://cdn.bullhouse.com/training/nepse-masterclass/thumbnail.jpg",
  "trailerRef": "public/trailer/training/nepse-masterclass.mp4",
  "trailerUrl": "https://cdn.example.com/public/trailer/training/nepse-masterclass.mp4"
}

Use trailerUrl directly for preview playback. trailerRef exists so admin and backend integrations can round-trip the canonical storage reference.

Cleanup semantics

  • Managed cleanup is limited to refs under public/trailer/
  • Legacy non-managed refs are left untouched
  • Public preview playback should consume trailerUrl, not a client-computed bucket path

See also