One secure contract · every screen
Ship protected playback without putting DRM secrets in your apps.
Package once, authorize each viewer in your backend, and use the same DRM-X Playback Session contract for websites, Android, Android TV, Fire TV, iPhone, iPad, Apple TV, Windows, and compatible Huawei devices.
No article matches that search. Try “policy”, “PHP”, “FairPlay”, or “token proxy”.
Getting started
15-minute Multi-DRM quickstart
The fastest production-shaped path uses one published file, one narrowly scoped API client, one customer backend route, and the DRM-X Universal Player.
- Create your environment.Sign in to DRM-X Console, create a project and environment, and enable only the DRM systems you will test.
- Create a playback API client.Give it only the
license-tokens:create scope. Copy its Site ID, Site Key, and one-time Access Key into your backend secret manager.
- Package and publish a test asset.Use Package content, choose Single Key or Multi-key Quality Tiered, publish to 1AICLOUD or registered object storage, and wait for Published status.
- Add an authenticated playback-session route.Check your own entitlement database, set
subject from the signed-in account, choose a named policy template, and call DRM-X from the server.
- Embed the player.Provide only your same-origin session endpoint and DRM-X Content ID. DRM-X returns the correct registered DASH or HLS manifest.
- Test physical devices.Verify Chrome/Widevine, Edge/PlayReady, Safari/FairPlay, and any Huawei/WisePlay devices you intend to support.
The key ruleYour backend decides who may watch. DRM-X validates the package and policy, signs a short-lived DRM License Token, and enforces the immutable decision at the license service.
Architecture
One flow for browsers, applications, and TVs
Viewer signs in to your service
→ Your backend checks purchase / subscription / course access
→ Your backend selects a named template or complete custom policy
→ POST api6.drm-x.com/api/v1/playback/environments/{siteId}/sessions
→ DRM-X resolves the active published package and registered manifest
→ DRM-X returns Contract v1 + short-lived DRM License Token
→ Player sends the opaque DRM challenge to the returned license URL
→ DRM-X Gateway validates the token and provider enforces its signed policy
→ Player releases the concurrent-stream reservation on stop or replacement
Control planePackaging and configuration
Content, key sets, immutable package releases, registered manifests, API clients, defaults, credentials, and audit evidence.
Data planePlayback and licenses
Short-lived session authorization, DRM License Tokens, license challenges, FairPlay certificates, renewals, and session release.
DRM-X does not become your entitlement database. It receives the decision made by your authenticated backend and signs that request-time decision. Never generate authorization in browser JavaScript, Android code, or an iOS application.
Foundations
Concepts and supported delivery formats
| DRM | Typical clients | Published media | Key system |
| Widevine | Chrome, Firefox, Android, Android TV, Fire TV | DASH + CENC | com.widevine.alpha |
| PlayReady | Microsoft Edge on qualified Windows devices | DASH + CENC | com.microsoft.playready.recommendation |
| FairPlay Streaming | Safari, iPhone, iPad, Apple TV | HLS + CBCS | com.apple.fps |
| WisePlay | Compatible Huawei browsers and devices | DASH + CENC | com.huawei.wiseplay |
Single Key Protection
One key protects the presentation. It maximizes four-platform compatibility, but resolution tiers cannot be cryptographically separated. Use one uniform ALL security rule and maximumQualityTier: "auto".
Multi-key Quality Tiered
Distinct AUDIO, SD, HD, UHD1, and optional UHD2 keys permit different security requirements. A missing rule denies that tier. Use this when UHD must require hardware DRM or stronger output protection.
Account setup
Create the minimum playback credential
Create a project API client in DRM-X Console and grant only license-tokens:create. Inject the following as server-process secrets:
DRMX_PLATFORM_API=https://api6.drm-x.com
DRMX_PLAYBACK_SITE_ID=your-environment-uuid
DRMX_PLAYBACK_SITE_KEY=drmx_your_client_id
DRMX_PLAYBACK_ACCESS_KEY=drmx_secret_your_one_time_secret
DRMX_LICENSE_POLICY_TEMPLATE=multi-tier-standard
Never ship these valuesDo not place the Site Key or Access Key in HTML, JavaScript, an APK, an IPA, application resources, mobile CI variables, URLs, logs, analytics, or downloadable configuration.
Use a different API client for each application or backend service so one credential can be rotated or revoked without interrupting every integration.
Content preparation
Package, upload, and publish protected content
- Open Package content in DRM-X Console and select your source, encoding ladder, audio languages, subtitles, target DRM systems, and destination.
- Choose Single Key · Four-platform compatibility or Multi-key Quality Tiered · Recommended.
- Use managed 1AICLOUD hosting, a registered Amazon S3/Cloudflare R2 destination, or the downloadable DRM-X CLI Packager.
- Wait until validation and upload are complete. Playback authorization resolves only a registered Published protected file.
- Keep your CMS Content ID identical to the DRM-X packaging Content ID. Your application sends that harmless ID—not a storage path or manifest URL.
FairPlay requires a customer certificate deployment approved and activated for the environment. Widevine, PlayReady, and WisePlay use their matching provider routes through the same License Gateway contract.
DRM-X CLI Packager
Windows x64 packaging with one-use Packaging Access Tokens and managed or customer storage upload.
Download CLI preview
Playback validation
Choose the resulting Published protected file and exercise its actual registered manifest and key model.
Open Universal Player
License policy
Use a server-side named policy template
Named templates remove most policy JSON from application code. DRM-X expands the selected name to a canonical v2 policy, validates it against the real package, and signs the result into the DRM License Token.
| Name | Package model | Behavior |
single-software | Single key | Broad compatibility, software DRM, no HDCP minimum. |
single-hdcp | Single key | Software DRM with HDCP 1.x-class output protection. |
single-hardware | Single key | Hardware-secure DRM with HDCP 2.2-class output protection. |
multi-tier-standard | Multi-key | Audio/SD software, HD software + HDCP, UHD1 hardware + HDCP 2.2. |
{
"contentId": "course-12-lesson-4",
"contentType": "vod",
"drmSystem": "widevine",
"subject": "customer-user-1001",
"playbackMode": "streaming",
"licensePolicyTemplate": "multi-tier-standard",
"useEnvironmentDefaults": true,
"maximumQualityTier": "auto"
}
With useEnvironmentDefaults: true, the template supplies security while the saved environment settings control DRM License Token validity, concurrent streams, and renewal. Set it to false when you want the template’s exact operational values.
Applications may discover the current built-ins through GET /api/v1/playback/license-policy-templates. Template names are case-insensitive on input and canonicalized in the request.
License policy
Send a complete custom request-time policy
Use licensePolicy when a named template does not express your business rule. Do not send licensePolicyTemplate in the same request.
{
"policy_version": 2,
"playback_policy": {
"persistent": false,
"license_duration": 14400,
"rental_duration": 0,
"playback_duration": 7200,
"renewal_duration": 300,
"allowed_track_types": "ALL",
"max_stream_per_user": 2
},
"security_policy": [{
"track_type": "ALL",
"widevine": {
"security_level": 1,
"required_hdcp_version": "HDCP_V1",
"disable_analog_output": true
},
"playready": {
"security_level": 2000,
"digital_video_protection_level": 250,
"analog_video_protection_level": 150,
"digital_audio_protection_level": 100
},
"fairplay": {
"hdcp_enforcement": 0,
"allow_airplay": true,
"allow_av_adapter": false
},
"wiseplay": {
"security_level": 1,
"output_control": 1
}
}]
}
Rules that fail closed
- Policy JSON is limited to 16 KiB, must use
policy_version: 2, and may contain at most seven unique track rules.
- Single-key content requires one
ALL rule, allowed_track_types: ALL, and an automatic quality ceiling.
- Multi-key rules may target
AUDIO, SD, HD, UHD1, or UHD2. Omitted tiers receive no key.
max_stream_per_user: 0 disables DRM-X concurrent-stream limiting for that token.
expiresInSeconds is DRM License Token validity (60–7200 seconds). It is separate from DRM license and playback durations.
Customization belongs on your serverMap trusted subscription plans, rental windows, content ratings, or device classes to approved policy objects. Never forward a policy received from browser or mobile input.
API
Create a Universal Playback Session
POST https://api6.drm-x.com/api/v1/playback/environments/{siteId}/sessions
Accept: application/json
Content-Type: application/json
X-DRMX-Client-Id: {siteKey}
X-DRMX-Client-Secret: {accessKey}
{
"contentId": "course-12-lesson-4",
"contentType": "vod",
"drmSystem": "widevine",
"subject": "customer-user-1001",
"sessionId": "new-unpredictable-id-per-playback",
"playbackMode": "streaming",
"licensePolicyTemplate": "multi-tier-standard",
"useEnvironmentDefaults": true,
"applicationId": "customer-web",
"platformCapabilities": {
"clientPlatform": "web",
"drmSystems": ["widevine"],
"manifestTypes": ["dash"],
"maximumHeight": 2160,
"persistentState": false,
"sdkVersion": "1.1.0-preview.10"
}
}
A successful Contract v1 response includes the authoritative manifest, available manifest variants, a DRM-specific license URL, a short-lived DRM License Token or customer proxy authorization, a release route, the licensed maximum height, and allowed tracks. Return it with Cache-Control: no-store.
Use one unpredictable session ID for each real playback attempt. Reusing an ID across devices defeats concurrent-stream counting.
Server tutorials
Call the same endpoint from popular backend languages
In every example, authenticate the viewer and check entitlement before this call. Read credentials from a secret manager and never log the request headers or successful response body.
PHP 8.2+
$payload = [
'contentId' => $trustedContentId,
'contentType' => 'vod',
'drmSystem' => $drmSystem,
'subject' => $authenticatedUserId,
'playbackMode' => 'streaming',
'licensePolicyTemplate' => 'multi-tier-standard',
'useEnvironmentDefaults' => true,
'maximumQualityTier' => 'auto',
];
$curl = curl_init(
getenv('DRMX_PLATFORM_API') . '/api/v1/playback/environments/' .
rawurlencode(getenv('DRMX_PLAYBACK_SITE_ID')) . '/sessions'
);
curl_setopt_array($curl, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload, JSON_THROW_ON_ERROR),
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 12,
CURLOPT_PROTOCOLS => CURLPROTO_HTTPS,
CURLOPT_HTTPHEADER => [
'Accept: application/json',
'Content-Type: application/json',
'X-DRMX-Client-Id: ' . getenv('DRMX_PLAYBACK_SITE_KEY'),
'X-DRMX-Client-Secret: ' . getenv('DRMX_PLAYBACK_ACCESS_KEY'),
],
]);
$body = curl_exec($curl);
Start from the complete executable sample; it includes login, entitlement, direct-token mode, token-proxy mode, bounded diagnostics, and release handling.
Node.js / TypeScript
const response = await fetch(
`${process.env.DRMX_PLATFORM_API}/api/v1/playback/environments/${
encodeURIComponent(process.env.DRMX_PLAYBACK_SITE_ID!)
}/sessions`,
{
method: "POST",
headers: {
"Accept": "application/json",
"Content-Type": "application/json",
"X-DRMX-Client-Id": process.env.DRMX_PLAYBACK_SITE_KEY!,
"X-DRMX-Client-Secret": process.env.DRMX_PLAYBACK_ACCESS_KEY!,
},
body: JSON.stringify({
contentId: trustedContentId,
contentType: "vod",
drmSystem,
subject: authenticatedUser.id,
playbackMode: "streaming",
licensePolicyTemplate: "multi-tier-standard",
useEnvironmentDefaults: true,
maximumQualityTier: "auto",
}),
signal: AbortSignal.timeout(12_000),
},
);
const playback = await response.json();
Python 3.11+
import json, os, urllib.request
payload = json.dumps({
"contentId": trusted_content_id,
"contentType": "vod",
"drmSystem": drm_system,
"subject": authenticated_user_id,
"playbackMode": "streaming",
"licensePolicyTemplate": "multi-tier-standard",
"useEnvironmentDefaults": True,
"maximumQualityTier": "auto",
}).encode("utf-8")
url = (
os.environ["DRMX_PLATFORM_API"] +
"/api/v1/playback/environments/" +
os.environ["DRMX_PLAYBACK_SITE_ID"] + "/sessions"
)
request = urllib.request.Request(url, data=payload, method="POST", headers={
"Accept": "application/json",
"Content-Type": "application/json",
"X-DRMX-Client-Id": os.environ["DRMX_PLAYBACK_SITE_KEY"],
"X-DRMX-Client-Secret": os.environ["DRMX_PLAYBACK_ACCESS_KEY"],
})
with urllib.request.urlopen(request, timeout=12) as response:
playback = json.load(response)
ASP.NET Core / C#
var payload = new {
contentId = trustedContentId,
contentType = "vod",
drmSystem,
subject = authenticatedUserId,
playbackMode = "streaming",
licensePolicyTemplate = "multi-tier-standard",
useEnvironmentDefaults = true,
maximumQualityTier = "auto"
};
using var request = new HttpRequestMessage(HttpMethod.Post,
$"{platformApi}/api/v1/playback/environments/{Uri.EscapeDataString(siteId)}/sessions") {
Content = JsonContent.Create(payload)
};
request.Headers.Add("X-DRMX-Client-Id", siteKey);
request.Headers.Add("X-DRMX-Client-Secret", accessKey);
using var response = await httpClient.SendAsync(request, cancellationToken);
Java 21 / Spring services
String payload = objectMapper.writeValueAsString(Map.of(
"contentId", trustedContentId,
"contentType", "vod",
"drmSystem", drmSystem,
"subject", authenticatedUserId,
"playbackMode", "streaming",
"licensePolicyTemplate", "multi-tier-standard",
"useEnvironmentDefaults", true,
"maximumQualityTier", "auto"
));
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(platformApi + "/api/v1/playback/environments/" +
URLEncoder.encode(siteId, StandardCharsets.UTF_8) + "/sessions"))
.timeout(Duration.ofSeconds(12))
.header("Accept", "application/json")
.header("Content-Type", "application/json")
.header("X-DRMX-Client-Id", siteKey)
.header("X-DRMX-Client-Secret", accessKey)
.POST(HttpRequest.BodyPublishers.ofString(payload))
.build();
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
Go 1.23+
payload, _ := json.Marshal(map[string]any{
"contentId": trustedContentID,
"contentType": "vod",
"drmSystem": drmSystem,
"subject": authenticatedUserID,
"playbackMode": "streaming",
"licensePolicyTemplate": "multi-tier-standard",
"useEnvironmentDefaults": true,
"maximumQualityTier": "auto",
})
url := platformAPI + "/api/v1/playback/environments/" +
url.PathEscape(siteID) + "/sessions"
req, _ := http.NewRequestWithContext(ctx, http.MethodPost, url, bytes.NewReader(payload))
req.Header.Set("Accept", "application/json")
req.Header.Set("Content-Type", "application/json")
req.Header.Set("X-DRMX-Client-Id", siteKey)
req.Header.Set("X-DRMX-Client-Secret", accessKey)
response, err := httpClient.Do(req)
Ruby 3.3+
uri = URI("#{ENV.fetch('DRMX_PLATFORM_API')}/api/v1/playback/environments/" \
"#{ERB::Util.url_encode(ENV.fetch('DRMX_PLAYBACK_SITE_ID'))}/sessions")
request = Net::HTTP::Post.new(uri)
request['Accept'] = 'application/json'
request['Content-Type'] = 'application/json'
request['X-DRMX-Client-Id'] = ENV.fetch('DRMX_PLAYBACK_SITE_KEY')
request['X-DRMX-Client-Secret'] = ENV.fetch('DRMX_PLAYBACK_ACCESS_KEY')
request.body = JSON.generate(
contentId: trusted_content_id,
contentType: 'vod',
drmSystem: drm_system,
subject: authenticated_user_id,
playbackMode: 'streaming',
licensePolicyTemplate: 'multi-tier-standard',
useEnvironmentDefaults: true,
maximumQualityTier: 'auto'
)
response = Net::HTTP.start(uri.host, uri.port, use_ssl: true) { |http| http.request(request) }
Advanced server boundary
Keep the DRM License Token behind your own proxy
Direct-token mode is simplest. Token-proxy mode keeps the real token server-side and returns an opaque, random, expiring handle plus customer-controlled license, FairPlay certificate, and release URLs.
{
"drm": {
"integrationMode": "token-proxy",
"licenseServerUrl": "/api/drmx/license-proxy?kind=license&drm=widevine",
"authorization": {
"headerName": "Authorization",
"scheme": "Bearer",
"value": "opaque-random-customer-handle"
}
},
"release": {
"url": "/api/drmx/playback-release",
"method": "POST",
"authorization": {
"headerName": "Authorization",
"scheme": "Bearer",
"value": "opaque-random-customer-handle"
}
}
}
Bind the handle to the authenticated customer session, Content ID, DRM system, and upstream token expiry. Store it only in a bounded expiring cache, cap request bodies, reject redirects, proxy exact binary challenge/response bytes, and erase it on release or expiry.
The live PHP sample implements both direct-token and token-proxy modes.
Web SDK
HTML5 playback with one Web Component
<script
src="https://drm-x6-cdn.1aicloud.com/shaka-player-5.2.4-drmx.1-9becbaeba461.js"
integrity="sha384-BtpnbWYLUVRwUwz3KcCOydvldeq7iCtzQeRN0RmBl40X9U7+VXn0gOd+WKbv1mFr"
crossorigin="anonymous"></script>
<script
src="https://drm-x6-cdn.1aicloud.com/drmx-universal-player-1.1.0-preview.10-7198f2eb249d.js"
integrity="sha384-xrHjJA/HQwUO+sGAWi0UUpumIT56TpPcq+i1b7XW/tASHzHZzGabPvOqnAGX3uxw"
crossorigin="anonymous"></script>
<drmx-universal-player
content-id="course-12-lesson-4"
content-type="vod"
session-endpoint="/api/drmx/playback-session">
</drmx-universal-player>
The browser calls only your authenticated same-origin endpoint. Auto chooses the appropriate supported DRM and registered DASH/HLS manifest. Bitrate, audio language/channel, subtitles, Picture-in-Picture, fullscreen, and playback speed are built in.
Using Shaka, Video.js, Bitmovin, or another EME player
Request Contract v1 from your backend, load manifestUrl, and add Authorization: Bearer {drmLicenseToken} only to DRM license and FairPlay certificate requests. Preserve the opaque challenge and license response bytes exactly. Use the returned release route when playback ends.
Android SDK
Android, Android TV, Google TV, and Fire TV
The DRM-X Kotlin/Media3 SDK targets API 23+ and uses Android MediaDrm for Widevine. The app calls your authenticated backend; policy and DRM-X credentials stay off the device.
val player = DrmXPlayer(this, playerView)
val capabilities = WidevineCapabilities.playbackCapabilities(
clientPlatform = "android",
displayMetrics = resources.displayMetrics,
applicationVersion = BuildConfig.VERSION_NAME,
)
player.prepare(
endpoint = "https://customer.example/api/drmx/playback-session",
contentId = "course-12-lesson-4",
contentType = "vod", // or "live"
capabilities = capabilities,
customerAuthenticationHeaders = mapOf(
"Authorization" to "Bearer ${customerLogin.accessToken}",
),
)
Call close() from the Activity or Fragment lifecycle. Use the default SurfaceView and protectWindow() for protected screens. Test both certified Widevine L1 hardware and an L3 device or emulator.
Apple SDK
iOS, iPadOS, and tvOS with native FairPlay
The Swift Package targets iOS and tvOS 15+. It uses AVFoundation’s resource loader for the FairPlay certificate, SPC, CKC, and session release flow.
import AVKit
import DrmXFairPlay
let controller = DrmXFairPlayPlayer()
let player = try await controller.prepare(
endpoint: URL(string: "https://customer.example/api/drmx/playback-session")!,
contentId: "course-12-lesson-4",
contentType: .vod,
customerHeaders: ["Authorization": "Bearer \(customerAccessToken)"]
)
playerViewController.player = player
player.play()
Your backend selects the policy template. Do not put a policy, manifest URL, Site Key, Access Key, or long-lived token in the app bundle. Test real HLS/CBCS media on physical iPhone, iPad, and Apple TV devices, including HDMI and AirPlay decisions.
Native integration
Integrate without the DRM-X client SDK
You may consume Contract v1 with platform DRM APIs or a commercial player. The server integration does not change.
| Platform | Native path | Required handling |
| Android / Fire TV | Media3 ExoPlayer + MediaDrm | DASH/CENC, Widevine license callback, returned authorization header, session release. |
| iOS / tvOS | AVPlayer + AVAssetResourceLoaderDelegate | HLS/CBCS, certificate fetch, SPC creation, raw CKC post/response, session release. |
| Windows | Media Foundation, UWP, or EME player | DASH/CENC, PlayReady challenge, returned Bearer authorization, physical SL3000 qualification. |
| Smart TV / console | Vendor EME or native DRM API | Use the supported DRM, registered manifest, exact binary license exchange, and returned policy ceiling. |
Do not decode, reinterpret, or base64-wrap a challenge unless that platform API explicitly requires it. DRM-X license endpoints consume the DRM system’s native bytes.
CMS integrations
WordPress, LearnDash, LearnPress, and Moodle
WordPress
Use [drmx_player], map post metadata to DRM-X Content ID, and connect entitlement through the provided filter or supported LMS access checks. Define DRMX_LICENSE_POLICY_TEMPLATE server-side.
Download plugin
Moodle
Install the filter, enter the environment credential in administrator settings, select a named policy template, and authorize only enrolled learners with course access.
Download filter
CMS configuration is still a server boundary. Never expose plugin secrets through page source, REST discovery, debug output, or downloadable backups.
Live streaming
Use the same contract for Live DRM
Set contentType: "live" and use the active Live DRM Content ID. DRM-X resolves the current published live output and key set. The Web, Android, and Apple SDKs use the same session, authorization, license, renewal, and release fields.
- Use an unpredictable playback session ID for every viewer start.
- Choose a renewal duration appropriate for blocking and entitlement refresh.
- Do not publish a rotating KID until every required license provider can resolve it.
- Test encoder restart, key rotation, late join, renewal, blacklist, and failover behavior before an event.
Troubleshooting
Read failures by stage
| Symptom | Likely boundary | Check |
401 from /sessions | API-client authentication | Environment ID, Site Key, Access Key, scope, and secret rotation. |
| 403 before playback | Customer entitlement or blacklist | Your login/session, entitlement query, subject, device/application blacklist. |
| 404 published package | Content mapping | Exact Content ID, active package, DRM system, and registered manifest type. |
| 400 policy validation | Policy/package mismatch | Single versus multi-key rules, track labels, quality ceiling, provider enum values. |
| Manifest CORS/network error | Storage/CDN | HTTPS, public delivery route, CORS, range requests, content type, cache. |
| License denied on one device | DRM capability/output path | CDM level, secure decoder, OS/browser version, GPU driver, HDCP display/cable/adapter. |
| Concurrent limit reached | Session lifecycle | Unique session IDs and reliable release on stop, error, replacement, and app close. |
Log only correlation IDs, safe lifecycle stages, HTTP status, DRM system, platform, and redacted error codes. Never log tokens, authorization headers, challenges, license bytes, certificate material, KIDs, content keys, or protected URLs.
Production checklist
Keep the integration safe by default
- Authenticate every viewer and perform a fail-closed entitlement query before requesting a session.
- Set
subject only from the authenticated server session; never trust a browser-supplied subject.
- Map harmless Content IDs to trusted catalog records. Never accept arbitrary manifest or license URLs.
- Keep API credentials in a server secret manager and grant only
license-tokens:create.
- Use HTTPS, bounded timeouts, response-size limits,
Cache-Control: no-store, and redirect rejection for proxy routes.
- Never store DRM License Tokens in URLs, cookies, localStorage, sessionStorage, analytics, logs, crash reports, or persistent databases.
- Use named templates or approved server-owned custom policies. Never accept policy JSON from untrusted clients.
- Release concurrent-stream reservations on stop, end, terminal error, route replacement, and app shutdown.
- Qualify every promised DRM/platform combination on physical devices.
Reference and downloads
Continue with a working sample
Complete Web package
Universal Player, qualified Shaka, PHP, ASP.NET Core, declarations, and integration README.
Download ZIP
Live PHP application
Authentication, entitlement, token proxy, player, safe diagnostics, and release lifecycle.
Run sample
Universal Playback Lab
Choose your own Published protected file, inspect its key model, build a policy, and test a fresh token.
Open lab
DRM-X Console
Create projects, credentials, protected packages, FairPlay deployments, environment defaults, and reports.
Open Console
Current public contract: Universal Playback Session Contract v1. Current policy format: DRM-X License Policy JSON v2. Named template catalogue: version 1.