Protected and Non-Protected Variants
Protection variants let you create the opposite delivery mode from an existing
ready content without uploading the media again:
- A protected (
"drm") content can create a non-protected ("clear") variant. - A non-protected (
"clear") content can create a protected ("drm") variant.
The operation creates a separate content with its own content ID, retained
input, processing job, output files and lifecycle. The source remains
unchanged and stays ready; protectionMode is never modified in place.
A clear variant has no DRM and can be downloaded by anyone who has a valid signed delivery URL. Only create one when the media is suitable for non-protected distribution.
Requirements
A variant can be created when all of the following are true:
- The source content is
readyand is a supported video or audio content. - Fastevo retained the source's original input. This is controlled by the project's original-copy retention setting.
- The project is deployed, active and not suspended.
- When the target mode is
clear, clear delivery is enabled for new content. - No content in the same variant family already uses the requested target mode, including a matching content currently in trash.
- The source is not already being copied by another variant operation.
Check Available Variants
In the Dashboard, variant actions appear in the content detail and overflow menu. For a protected content with no linked clear variant, the overflow-menu action Create unprotected version is omitted entirely while clear delivery creation is disabled. The detail card may still explain why creation is unavailable. Disabling the gate does not hide useful actions for an existing linked variant: it can still be opened, restored or retried when applicable.
Use the capability endpoint before displaying a Create protected version or Create non-protected version action:
GET https://api.fastevo.net/api/v1/projects/mediaProtection/contents/{contentId}/variants
Authorization: Bearer <token>Example response:
{
"protectionVariantGroupId": "6b0000000000000000000001",
"originalAvailable": true,
"variants": [
{
"contentId": "6b0000000000000000000010",
"title": "Launch video",
"protectionMode": "drm",
"status": "ready",
"isTrashed": false,
"lifecycleState": "active"
},
{
"contentId": "6b0000000000000000000011",
"title": "Launch video - Clear",
"protectionMode": "clear",
"status": "processing",
"isTrashed": false,
"lifecycleState": "active"
}
],
"capability": {
"allowed": false,
"targetProtectionMode": "clear",
"blockedReason": "TARGET_VARIANT_EXISTS",
"existingContentId": "6b0000000000000000000011"
}
}| Field | Description |
|---|---|
protectionVariantGroupId | Stable ID shared by the protected and non-protected contents in the same family. It may be absent until the first variant is created. |
originalAvailable | Whether the source has a retained original that can be copied. |
variants[] | Every known content in the family, including trashed contents. |
variants[].lifecycleState | Operational state independent from processing status: active, trashing, trashed, restoreQueued or restoring. |
capability.allowed | Whether a new opposite-mode variant can be requested now. |
capability.targetProtectionMode | The only valid target mode for this source: "drm" or "clear". |
capability.blockedReason | Machine-readable reason when allowed is false; otherwise null. |
capability.existingContentId | Existing target content when the variant already exists or is in trash. |
Possible capability blockers are:
blockedReason | Meaning |
|---|---|
TARGET_VARIANT_EXISTS | The opposite variant already exists. Open existingContentId; for an error target, this blocker appears only when repeating the same PUT can safely retry that content. |
TARGET_VARIANT_IN_TRASH | The opposite variant is in trash. Restore it instead of creating a duplicate. |
PROTECTION_VARIANT_RETRY_UNAVAILABLE | The failed opposite variant cannot currently be retried. Permanently delete it to recreate the variant, or contact support if its lifecycle prevents deletion. |
CONTENT_NOT_READY | Variant creation starts only from a ready source. |
UNSUPPORTED_CONTENT_TYPE | The source type cannot be converted to the requested delivery mode. |
ORIGINAL_NOT_RETAINED | There is no retained original to copy. Uploading the original again as new content is required. |
SOURCE_BUSY | Another operation temporarily holds the source original. Retry later. |
PROJECT_NOT_DEPLOYED | The project's delivery infrastructure is not available. |
CLEAR_DELIVERY_CREATION_DISABLED | New clear content is disabled for this project. |
Create a Variant
The target mode is part of the URL and must be the mode opposite to the source:
PUT https://api.fastevo.net/api/v1/projects/mediaProtection/contents/{sourceContentId}/variants/{protectionMode}
Authorization: Bearer <token>
Content-Type: application/jsonprotectionMode must be drm or clear. The request body is optional:
{
"title": "Launch video - Clear",
"priority": 5
}| Field | Type | Rules |
|---|---|---|
title | string | Optional; maximum 100 characters. It uses the standard content-title ASCII character set; Unicode and emoji are rejected. |
priority | integer | Optional; 0 to 10, default 1. It has the same relative scheduling behavior as content creation. |
Example:
curl -X PUT \
"https://api.fastevo.net/api/v1/projects/mediaProtection/contents/6b0000000000000000000010/variants/clear" \
-H "Authorization: Bearer $FASTEVO_TOKEN" \
-H "Content-Type: application/json" \
--data '{"title":"Launch video - Clear","priority":5}'A newly created target returns 201 Created:
HTTP/1.1 201 Created
Location: /api/v1/projects/mediaProtection/contents/6b0000000000000000000011{
"contentId": "6b0000000000000000000011",
"sourceContentId": "6b0000000000000000000010",
"protectionVariantGroupId": "6b0000000000000000000001",
"protectionMode": "clear",
"status": "queued",
"created": true
}Track the returned target contentId through content queries or
callbacks. It follows the
normal queued → processing → ready lifecycle.
Idempotency and Retry
The PUT operation is safe to repeat:
- The first request that creates the target returns
201andcreated: true. - Concurrent requests and later requests for an existing target return
200andcreated: false, with the same targetcontentId. - A repeated request never creates a third content for the same family and protection mode.
- If the target is in
error, the same request retries that same target content. Fastevo creates a new processing job while preserving the failed job's history. The response is200,status: "queued"andcreated: false. - If the target already has an independent retained input whose size and provenance match its storage object, retry does not need the sibling source's original or source lease. Otherwise, Fastevo falls back to the sibling source, reacquires it briefly and creates a fresh independent copy.
Check capability again before retrying. If the independent target input fails
verification and the source fallback is unavailable, the response reports
ORIGINAL_NOT_RETAINED or SOURCE_BUSY. Do not send a regular reprocess
request to change protectionMode; that field remains immutable.
Storage, Processing and Deletion
Fastevo copies the retained original into the target content's own storage namespace before processing. The copy is verified before the source is released, so deleting one variant later does not delete the other's original or outputs.
This also means that variants consume additional resources:
- One retained original is stored for each content.
- Each variant has its own transcoded and packaged outputs.
- Creating or retrying a variant runs a normal processing job and contributes storage and processing usage according to your plan.
During the brief original-copy phase, trash, deletion and reprocessing of the
source are blocked with SOURCE_BUSY. Once the independent target input is
durable, both contents have separate lifecycle controls. Sending a target to
trash does not remove the source, and vice versa.
For large originals, an interrupted server-side multipart copy is safe to retry: a new attempt uses the same target namespace, and incomplete copy parts left by a hard stop become eligible for automatic lifecycle cleanup after one day. They are not published as a content input and do not block the retry.
If the target variant is already in trash, creation returns
TARGET_VARIANT_IN_TRASH with its existingContentId. Use the
trash restore endpoint rather than creating a duplicate.
Restore can be requested immediately after deletion: while the target is still
trashing, the API stores the request and reports restoreQueued. The
Dashboard polls through restoring until the same target returns to active;
it never creates a replacement content or a third family member.
Errors
Errors use the standard API error envelope:
{
"statusCode": 409,
"error": "Conflict",
"message": "The requested protection variant is in trash and must be restored.",
"code": "TARGET_VARIANT_IN_TRASH",
"details": {
"existingContentId": "6b0000000000000000000011"
}
}| Status | Code | Action |
|---|---|---|
409 | CONTENT_NOT_READY | Wait until the source is ready. |
409 | ORIGINAL_NOT_RETAINED | Upload the original as new content; an output rendition is not used as a substitute. |
409 | SOURCE_BUSY | Retry after the current source operation finishes. |
409 | TARGET_PROTECTION_MODE_EQUALS_SOURCE | Request the opposite protection mode. |
409 | TARGET_VARIANT_IN_TRASH | Restore details.existingContentId. |
409 | PROTECTION_VARIANT_RETRY_UNAVAILABLE | Permanently delete the failed target to recreate the variant, or contact support if its lifecycle prevents deletion. |
409 | PROJECT_NOT_DEPLOYED | Wait until the project's delivery infrastructure is deployed. |
403 | CLEAR_DELIVERY_CREATION_DISABLED | Enable clear delivery or request a DRM target. |
422 | UNSUPPORTED_CONTENT_TYPE | Use a supported video or audio source. |
401, 403, 404 | Standard authorization/not-found errors | Verify the token, content-upload permission, project and source content ID. |
Playback
Use each variant as a normal, independent content:
- For a DRM target, generate a playback token with the target content ID and use the Fastevo Player.
- For a clear target, create signed URLs as described in Non-Protected Content.