DX DRM-X 6.0Developer documentation
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.

  1. Create your environment.Sign in to DRM-X Console, create a project and environment, and enable only the DRM systems you will test.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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 plane

Packaging and configuration

Content, key sets, immutable package releases, registered manifests, API clients, defaults, credentials, and audit evidence.

Data plane

Playback 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

DRMTypical clientsPublished mediaKey system
WidevineChrome, Firefox, Android, Android TV, Fire TVDASH + CENCcom.widevine.alpha
PlayReadyMicrosoft Edge on qualified Windows devicesDASH + CENCcom.microsoft.playready.recommendation
FairPlay StreamingSafari, iPhone, iPad, Apple TVHLS + CBCScom.apple.fps
WisePlayCompatible Huawei browsers and devicesDASH + CENCcom.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

  1. Open Package content in DRM-X Console and select your source, encoding ladder, audio languages, subtitles, target DRM systems, and destination.
  2. Choose Single Key · Four-platform compatibility or Multi-key Quality Tiered · Recommended.
  3. Use managed 1AICLOUD hosting, a registered Amazon S3/Cloudflare R2 destination, or the downloadable DRM-X CLI Packager.
  4. Wait until validation and upload are complete. Playback authorization resolves only a registered Published protected file.
  5. 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.

NamePackage modelBehavior
single-softwareSingle keyBroad compatibility, software DRM, no HDCP minimum.
single-hdcpSingle keySoftware DRM with HDCP 1.x-class output protection.
single-hardwareSingle keyHardware-secure DRM with HDCP 2.2-class output protection.
multi-tier-standardMulti-keyAudio/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.

PlatformNative pathRequired handling
Android / Fire TVMedia3 ExoPlayer + MediaDrmDASH/CENC, Widevine license callback, returned authorization header, session release.
iOS / tvOSAVPlayer + AVAssetResourceLoaderDelegateHLS/CBCS, certificate fetch, SPC creation, raw CKC post/response, session release.
WindowsMedia Foundation, UWP, or EME playerDASH/CENC, PlayReady challenge, returned Bearer authorization, physical SL3000 qualification.
Smart TV / consoleVendor EME or native DRM APIUse 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

SymptomLikely boundaryCheck
401 from /sessionsAPI-client authenticationEnvironment ID, Site Key, Access Key, scope, and secret rotation.
403 before playbackCustomer entitlement or blacklistYour login/session, entitlement query, subject, device/application blacklist.
404 published packageContent mappingExact Content ID, active package, DRM system, and registered manifest type.
400 policy validationPolicy/package mismatchSingle versus multi-key rules, track labels, quality ceiling, provider enum values.
Manifest CORS/network errorStorage/CDNHTTPS, public delivery route, CORS, range requests, content type, cache.
License denied on one deviceDRM capability/output pathCDM level, secure decoder, OS/browser version, GPU driver, HDCP display/cable/adapter.
Concurrent limit reachedSession lifecycleUnique 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.

DRM-X 6.0 Developer Documentation · Updated 4 September 2026 · Security controls are ISO 27001-aligned; no certification claim is made.