Skip to content
  • Follow System
  • English
  • 中文

Episodes

An episode is a numbered partition inside a collection — “Season 1 · Episode 3”, “Podcast #12”, “Chapter 5”. Each episode groups its own set of assets (videos, audio, docs, images) and tracks its own status. Episodes are optional: flat collections (like a plain knowledge base) don’t need them, while series-style types (tv_series, movie, audio_drama, comic_drama) are built around them.

The episode model

FieldMeaning
sequenceNoThe episode number. Unique within a collection. Numbering can be dense (1, 2, 3) or sparse (1, 3, 5).
title / descriptionEpisode metadata.
statusdraftgeneratingreadypublishedarchived.
coverImageIdOptional cover image.
assetCount / sizeBytesCached totals for the episode’s assets.

Creating two episodes with the same sequenceNo in one collection is rejected with EPISODE_SEQUENCE_CONFLICT (409) — each number is unique.

Managing episodes

In the dashboard, open a collection and use the Episodes panel to create, reorder (by sequenceNo), edit, and delete episodes, and to filter by status (e.g. show only ready).

For developers, episodes are standard CRUD under a collection (see the API playground):

MethodPathPurpose
POST/v1/collections/{id}/episodesCreate an episode
GET/v1/collections/{id}/episodesList episodes (filter by status, cursor-paginated)
GET/v1/collections/{id}/episodes/{epId}Episode detail
PATCH/v1/collections/{id}/episodes/{epId}Update
DELETE/v1/collections/{id}/episodes/{epId}Soft delete

Attaching assets — the sync flow

To attach already-uploaded resources to an episode in bulk, use episode sync:

POST /v1/collections/{id}/episodes/{epId}/sync
{
"idempotencyKey": "batch-2026-07-04-001",
"assets": [
{ "resourceType": "video", "resourceId": "vid_xxx", "sourceHash": "…" },
{ "resourceType": "doc", "resourceId": "doc_yyy" }
]
}

The response reports each asset’s outcome plus totals:

{
"episodeId": "", "collectionId": "",
"applied": [
{ "resourceType": "video", "resourceId": "vid_xxx", "status": "applied" },
{ "resourceType": "doc", "resourceId": "doc_yyy", "status": "skipped_duplicate", "reason": "natural_key_matched" }
],
"appliedCount": 1, "skippedCount": 1, "failedCount": 0, "totalCount": 2,
"syncedAt": ""
}

Two safety properties make this reliable for automated pipelines:

  • Idempotent — pass an Idempotency-Key (header or body). A repeat of the same batch within 24h replays the original result (X-Idempotent-Replay: true) instead of double-attaching.
  • Double dedup — an asset is skipped if its sourceHash was already seen (source_hash_matched) or if the same (episode, resourceType, resourceId) is already attached (natural_key_matched).
  • Error isolation — one bad asset (e.g. resource_not_found, forbidden) is reported in applied[].reason; it never aborts the rest of the batch. The call returns 200 even on partial failure.

Up to 100 assets per sync request.

Third-party AI pipelines

If you generate media with AI tools (ComfyUI, Replicate, OpenAI Sora, Diffusers…) and want each batch to land as an episode with a full audit trail, the sync flow above is the integration point — but the end-to-end guide, including the SDK calls, OAuth Device Flow for headless CLIs, and the admin audit view, lives in:

AI Video Sync

Next