Content protection | MediaKind Docs

Content protection

To configure protected playback with Digital Rights Management (DRM) using the Media API, you combine three resources that meet at the streaming locator:

Separating these resources lets you reuse one key-delivery policy across many assets while choosing a different encryption model for each publication context. You need a content key policy whenever playback must be restricted to entitled viewers or encrypted with DRM, and you can skip it entirely for unprotected playback.

This guide builds a working multi-DRM policy. For conceptual background on each DRM system, see the content protection overview.

How the pieces fit together

The protected playback chain is always the same three steps:

  1. Create or choose a content key policy (the subject of this guide).
  2. Create or choose a streaming policy (predefined policies cover most cases).
  3. Create a streaming locator that references the asset, the streaming policy, and the content key policy.

The rest of this guide builds that chain.

The minimal working policy

A content key policy is a named resource. Its properties.options array holds one or more options, and every option pairs two things:

The most common production setup is multi-DRM (PlayReady and Widevine) gated behind a JSON Web Token (JWT). The request below creates that policy. Replace <PROJECT_NAME> and the verification key with your own values.

curl -X PUT "https://app.mk.io/api/v1/projects/<PROJECT_NAME>/media/contentKeyPolicies/multi-drm-policy" \

-H "Authorization: Bearer <YOUR_TOKEN>" \

-H "Content-Type: application/json" \

-d '{

"properties": {

"description": "PlayReady and Widevine, gated by a JWT token",

"options": [

{

"name": "playready-jwt",

"configuration": {

"@odata.type": "#Microsoft.Media.ContentKeyPolicyPlayReadyConfiguration",

"licenses": [

{

"allowTestDevices": false,

"licenseType": "NonPersistent",

"contentType": "Unspecified",

"contentKeyLocation": {

"@odata.type": "#Microsoft.Media.ContentKeyPolicyPlayReadyContentEncryptionKeyFromHeader"

}

}

]

},

"restriction": {

"@odata.type": "#Microsoft.Media.ContentKeyPolicyTokenRestriction",

"issuer": "https://your-company.com",

"audience": "your-video-app",

"restrictionTokenType": "Jwt",

"primaryVerificationKey": {

"@odata.type": "#Microsoft.Media.ContentKeyPolicySymmetricTokenKey",

"keyValue": "<BASE64_HMAC_SECRET>"

}

}

},

{

"name": "widevine-jwt",

"configuration": {

"@odata.type": "#Microsoft.Media.ContentKeyPolicyWidevineConfiguration",

"widevineTemplate": "{}"

},

"restriction": {

"@odata.type": "#Microsoft.Media.ContentKeyPolicyTokenRestriction",

"issuer": "https://your-company.com",

"audience": "your-video-app",

"restrictionTokenType": "Jwt",

"primaryVerificationKey": {

"@odata.type": "#Microsoft.Media.ContentKeyPolicySymmetricTokenKey",

"keyValue": "<BASE64_HMAC_SECRET>"

}

}

}

]

}

}'

The fields that matter most:

A successful create returns 201 Created with the stored policy. A name that already exists returns 409 Conflict. For the full request and response schema, see the Media API reference.

Choosing the configuration

The configuration block selects the DRM system. Each system covers different platforms, so the choice is driven by the devices you need to reach.

You need to reach Use this configuration @odata.type
Edge, Xbox, Windows PlayReady #Microsoft.Media.ContentKeyPolicyPlayReadyConfiguration
Chrome, Firefox, Android, Android TV Widevine #Microsoft.Media.ContentKeyPolicyWidevineConfiguration
Safari, iOS, tvOS, macOS FairPlay #Microsoft.Media.ContentKeyPolicyFairPlayConfiguration
Basic encryption, lowest latency, no DRM license server Clear Key #Microsoft.Media.ContentKeyPolicyClearKeyConfiguration

To cover every platform, include all three DRM configurations in one policy, as the minimal example does for two of them. FairPlay is the one configuration that needs extra setup: it requires a certificate (fairPlayPfx), its password (fairPlayPfxPassword), and an application secret key (ask), all Base64-encoded. The other systems work with the fields shown above.

Clear Key uses AES-128 and does not reach the security of the three DRM systems. Do not add Clear Key to a policy intended for DRM, because it lowers the overall protection. For the per-system setup detail, see multi-DRM encryption.

Choosing the restriction

The restriction block decides who receives a license.

Your situation Use this restriction @odata.type
Production: only entitled viewers may play Token restriction #Microsoft.Media.ContentKeyPolicyTokenRestriction
Testing only: anyone with the stream may play Open restriction #Microsoft.Media.ContentKeyPolicyOpenRestriction

An open restriction needs no other fields and is for testing only. A token restriction is the production default and needs issuer, audience, restrictionTokenType, and a primaryVerificationKey.

The verification key type is itself chosen by @odata.type:

Signing approach Key type @odata.type Required fields
Symmetric (HMAC, HS256) Symmetric #Microsoft.Media.ContentKeyPolicySymmetricTokenKey keyValue
Asymmetric (RSA) RSA #Microsoft.Media.ContentKeyPolicyRsaTokenKey modulus, exponent
Certificate (X.509) X.509 #Microsoft.Media.ContentKeyPolicyX509CertificateTokenKey rawBody

Symmetric (HS256) is the default and the simplest. Choose RSA when your security model requires asymmetric keys; see RSA key for token validation.

Attach the policy at the locator

A content key policy takes effect only when a streaming locator references it. The locator joins the asset, a streaming policy, and the content key policy.

curl -X PUT "https://app.mk.io/api/v1/projects/<PROJECT_NAME>/media/streamingLocators/protected-locator" \

-H "Authorization: Bearer <YOUR_TOKEN>" \

-H "Content-Type: application/json" \

-d '{

"properties": {

"assetName": "output-video",

"streamingPolicyName": "Predefined_MultiDrmCencStreaming",

"defaultContentKeyPolicyName": "multi-drm-policy"

}

}'

Use a predefined streaming policy unless you have a reason not to. The predefined policies remove all custom encryption configuration:

Streaming policy Encryption Requires in the content key policy
Predefined_ClearStreamingOnly None Nothing
Predefined_ClearKey Clear Key (AES-128) A Clear Key option
Predefined_MultiDrmCencStreaming PlayReady and Widevine Both PlayReady and Widevine options
Predefined_MultiDrmStreaming PlayReady, Widevine, and FairPlay All three options

The minimal example pairs with Predefined_MultiDrmCencStreaming because it defines PlayReady and Widevine. To add Safari and Apple devices, add a FairPlay option to the policy and switch the locator to Predefined_MultiDrmStreaming.

What goes wrong

For the token flow and the required claims, see JWT token authentication.

Related operations

List the content key policies in a project:

curl -X GET "https://app.mk.io/api/v1/projects/<PROJECT_NAME>/media/contentKeyPolicies" \

-H "Authorization: Bearer <YOUR_TOKEN>"

Retrieve a single policy:

curl -X GET "https://app.mk.io/api/v1/projects/<PROJECT_NAME>/media/contentKeyPolicies/multi-drm-policy" \

-H "Authorization: Bearer <YOUR_TOKEN>"

A standard GET never returns secret values, such as the verification key. When you need to inspect or rotate secrets, use the secrets variant, and only then:

curl -X POST "https://app.mk.io/api/v1/projects/<PROJECT_NAME>/media/contentKeyPolicies/multi-drm-policy/getPolicyPropertiesWithSecrets" \

-H "Authorization: Bearer <YOUR_TOKEN>"

Where to go deeper

For the concepts and platform-level setup behind these requests:

For the complete, field-level request and response schema, including every configuration and restriction variant this guide does not cover:

What comes next