> For clean Markdown of any page, append .md to the page URL. > For a complete documentation index, see https://mediakind.ferndocs.com/platform/how-to/media/vod-pipeline/llms.txt. > For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://mediakind.ferndocs.com/_mcp/server. # Automate a VOD pipeline This guide walks the complete Video on Demand (VOD) path through the Media API, from a source asset to a playable URL. The individual resources have their own guides; the goal here is to show how they connect so you can build a pipeline with less trial and error. The sequence is: * Create an input asset that points to the source content. * Create or reuse a transform. * Create a job that applies the transform to the input asset. * Wait for the job to finish and the output asset to be ready. * Create a streaming locator on the output asset. * Start a streaming endpoint and call `listPaths` for the playback URLs. You need a project with storage already configured, a personal API token, and source content in that storage. ## Step 1: Create the input asset * Terminal window ```bash curl -X PUT "https://app.mk.io/api/v1/projects//media/assets/input-video-001" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "properties": { "storageAccountName": "primary-azure", "container": "input-video-001", "description": "Source video for transcoding" } }' ``` This asset is the input reference for the job. See Assets for the full set of fields. ## Step 2: Create or reuse the transform Because transforms are reusable, you usually do this once per processing profile, not once per asset. ```bash curl -X PUT "https://app.mk.io/api/v1/projects//media/transforms/standard-encoding" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "properties": { "description": "H.264 1080p multi-bitrate encoding", "outputs": [ { "preset": { "@odata.type": "#Microsoft.Media.BuiltInStandardEncoderPreset", "presetName": "H264MultipleBitrate1080p" }, "relativePriority": "Normal" } ] } }' ``` `presetName` must be one of the documented enum values. See Transforms and jobs for the available presets. ## Step 3: Create the job ```bash curl -X PUT "https://app.mk.io/api/v1/projects//media/transforms/standard-encoding/jobs/job-001" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "properties": { "input": { "@odata.type": "#Microsoft.Media.JobInputAsset", "assetName": "input-video-001" }, "outputs": [ { "@odata.type": "#Microsoft.Media.JobOutputAsset", "assetName": "output-video-001" } ], "description": "Transcode input-video-001 with the standard transform" } }' ``` The job creates and populates the output asset named here. ## Step 4: Wait for the job to finish Poll the job state until it reaches `Finished`: ```bash curl -X GET "https://app.mk.io/api/v1/projects//media/transforms/standard-encoding/jobs/job-001/state" \ -H "Authorization: Bearer " ``` For background automation, subscribe to the `MediaKind.JobStarted` and `MediaKind.JobFinished` webhooks instead of polling. ## Step 5: Publish the output asset Create a streaming locator on the output asset, not the source: ```bash curl -X PUT "https://app.mk.io/api/v1/projects//media/streamingLocators/locator-001" \ -H "Authorization: Bearer " \ -H "Content-Type: application/json" \ -d '{ "properties": { "assetName": "output-video-001", "streamingPolicyName": "Predefined_ClearStreamingOnly" } }' ``` ## Step 6: Start the endpoint and get the URLs Start the streaming endpoint if it is not already running, then list the locator paths: ```bash curl -X POST "https://app.mk.io/api/v1/projects//media/streamingEndpoints/default/start" \ -H "Authorization: Bearer " curl -X POST "https://app.mk.io/api/v1/projects//media/streamingLocators/locator-001/listPaths" \ -H "Authorization: Bearer " ``` Combine each path with the endpoint `hostName` to build the playback URLs. See Streaming and publishing for URL construction. ## What goes wrong Publishing too early. A locator can only publish the asset you point it at. In a VOD pipeline, publish the output asset created by the job, after it reaches `Finished`, not the source asset. * Confusing the endpoint and the locator. The endpoint provides the delivery hostname; the locator provides the asset-specific path. You need both, and the endpoint must be running. ## What comes next * Transforms and jobs: deeper detail on jobs and presets. * Content protection: add DRM to the published output. * Webhooks: replace polling with event-driven completion.