md-platform

scheduled-thumbnails.md
View raw Back to list

Scheduled Video Thumbnails — Frontend Guide

Let a creator (Studio) or an admin change a video's thumbnail at a future time: upload the image now, pick a date/time, and the backend swaps video.thumbnail automatically when that time arrives.

Multiple schedules: a video can have any number of pending schedules; each one fires independently at its own time. If two are pending, the one with the latest time ends up as the final thumbnail. Future only: the scheduled time must be in the future (UTC), otherwise the API returns 400. Cancellable: a schedule can be cancelled any time before it fires. Applied/cancelled rows stay in the list as history. Execution: handled by a Temporal workflow server-side — no polling needed from the frontend.


The big picture

1. Upload the image through the existing asset flow (presigned URL) → you get a publicUrl.
2. POST .../videos/{id}/thumbnail/schedule with { thumbnail: publicUrl, scheduledAt: <future UTC> }.
3. Show pending schedules via GET .../videos/{id}/thumbnail/scheduled (add ?status= for history).
4. Optionally cancel a pending one via POST .../thumbnail/scheduled/{scheduleId}/cancel.
5. At scheduledAt the backend sets video.thumbnail and marks the schedule "Applied".

The current thumbnail on the video is untouched until the schedule fires — scheduling is not the same as saving the thumbnail on the video edit form.


Endpoints

Same shape on both surfaces; only the prefix and auth differ.

Action Studio Admin
Schedule a change POST /studio/v1/videos/{id}/thumbnail/schedule POST /admin/v1/videos/{id}/thumbnail/schedule
List schedules (pending by default) GET /studio/v1/videos/{id}/thumbnail/scheduled GET /admin/v1/videos/{id}/thumbnail/scheduled
Cancel a pending schedule POST /studio/v1/videos/{id}/thumbnail/scheduled/{scheduleId}/cancel POST /admin/v1/videos/{id}/thumbnail/scheduled/{scheduleId}/cancel

1. Upload the thumbnail image (existing flow)

Nothing new here — same as uploading a thumbnail on the video edit page:

POST /studio/v1/assets/            { "fileName": "my-thumb.jpg" }
→ { "uploadUrl": "...", "publicUrl": "https://cdn.../api-assets/<guid>.jpg", ... }

PUT <uploadUrl>                    (raw file bytes)

Optionally run the file through POST /studio/v1/assets/optimize (multipart form, returns the resized 1280×720 JPEG) before uploading. Keep the publicUrl — that's what you send as thumbnail when scheduling.


2. Schedule a change

POST /studio/v1/videos/{id}/thumbnail/schedule
{
  "thumbnail": "https://cdn.example.com/api-assets/3f2a9c1e-....jpg",
  "scheduledAt": "2026-07-03T09:00:00Z"
}

scheduledAt must be an ISO-8601 UTC timestamp in the future. Convert from the user's local timezone before sending (date.toISOString()).

200 response — the created schedule:

{
  "id": "aB3xK9",
  "videoId": "Qw8Zr2",
  "thumbnail": "https://cdn.example.com/api-assets/3f2a9c1e-....jpg",
  "status": 1,
  "scheduledAt": "2026-07-03T09:00:00Z",
  "createdAt": "2026-07-02T08:30:00Z",
  "appliedAt": null,
  "cancelledAt": null
}

3. List schedules

GET /studio/v1/videos/{id}/thumbnail/scheduled

200 response — array of the DTO above, newest scheduledAt first. By default it returns only the pending (cancellable) schedules. Pass the optional status query parameter to fetch another status instead — e.g. the applied history:

GET /studio/v1/videos/{id}/thumbnail/scheduled?status=2

status values

Enums are serialized as numbers:

Value Name Meaning
1 Scheduled Pending — will fire at scheduledAt. Cancellable.
2 Applied Done — the video thumbnail was changed (appliedAt set).
3 Cancelled Cancelled before firing (cancelledAt set).
4 Failed Backend error (e.g. video deleted before firing).

4. Cancel a pending schedule

POST /studio/v1/videos/{id}/thumbnail/scheduled/{scheduleId}/cancel

No body. 200 response: true.

Only status: 1 (Scheduled) entries can be cancelled — anything else returns 400. Hide/disable the cancel button for other statuses.


Errors

Standard API error envelope:

Shape: { "errors": [{ "code": "SERVER_ERROR", "message": "...", "field": null }] }


Suggested UI

On the video edit page (both Studio and Admin):

  1. Next to the thumbnail field, add "Schedule change" → opens a dialog with an image upload + date/time picker (min = now, disallow past).
  2. Under it, list pending schedules (thumbnail preview, local-time date, cancel button) from the GET endpoint; refresh the list after scheduling or cancelling.
  3. After scheduledAt passes, re-fetching the video shows the new thumbnail; the list entry flips to status: 2 (Applied).

Timezone note: the backend works purely in UTC. Always display scheduledAt converted to the user's local time, and label it (e.g. "Jul 3, 2026, 11:00 (your time)") to avoid confusion for creators in different timezones.