Base URL: /wp-json/mediashield-pro/v1/
All endpoints require manage_options unless noted. Authentication uses the X-WP-Nonce header with a wp_rest nonce. Two endpoints differ: /bunny/webhook is public (verified by HMAC signature or shared token), and /drm/license only requires a logged-in user.
| Method |
Route |
Description |
| GET |
/platforms |
List platform connections. Credentials are never returned - the response carries id, platform, extra_config, is_active, connected_by, connected_at |
| POST |
/platforms |
Create a connection. Params: platform (bunny, vimeo, youtube, wistia), api_key, api_secret, extra_config. Bunny requires extra_config.pull_zone_hostname |
| DELETE |
/platforms/{id} |
Remove a connection |
| Method |
Route |
Description |
| GET |
/uploads |
Paginated ms_upload_queue job list. Params: page, per_page, status (pending, uploading, processing, complete, failed) |
Uploads themselves are started through free’s POST /mediashield/v1/upload/init. Pass driver=bunny|vimeo|youtube|wistia to route an upload to a connected platform; the default is self_hosted.
| Method |
Route |
Permission |
Description |
| POST |
/drm/license |
logged_in |
Issue a streaming ClearKey license and return a JWK Set. Params: video_id (required), device_id. Duration comes from ms_drm_license_duration_streaming (default 86400 seconds) |
| POST |
/drm/revoke |
manage_options |
Revoke all licenses for a user+video pair. Params: video_id, user_id (both required) |
There is no offline or persistent-license endpoint. The persistent license type and the PWA offline feature were removed in 1.2.0; WidevineLicense::issue_license() now rejects any type other than streaming, and the ENUM value survives only for historical rows.
/drm/license also returns 404 drm_key_not_found unless a content key exists in ms_drm_keys for the video. Nothing in 1.3.0 generates one automatically - see the DRM notes in the overview.
| Method |
Route |
Description |
| GET |
/bunny/videos |
List Bunny Stream library videos |
| POST |
/bunny/import |
Import Bunny videos into MediaShield |
| GET |
/bunny/collections |
List Bunny collections |
| POST |
/bunny/webhook |
Receive Bunny encoding callbacks (public; HMAC signature or ms_token query arg required) |
| GET |
/youtube/videos |
List YouTube channel videos |
| POST |
/youtube/import |
Import YouTube videos |
| GET |
/youtube/playlists |
List YouTube playlists |
| GET |
/vimeo/videos |
List Vimeo account videos |
| POST |
/vimeo/import |
Import Vimeo videos |
| GET |
/vimeo/folders |
List Vimeo folders |
| GET |
/wistia/videos |
List Wistia project videos |
| POST |
/wistia/import |
Import Wistia videos |
| GET |
/wistia/projects |
List Wistia projects |
| Method |
Route |
Description |
| GET |
/analytics/heatmap/{id} |
10-second bucket heatmap data for a video (from ms_heatmap_cache) |
| GET |
/analytics/playlist-funnel/{playlist_id} |
Drop-off analysis for a playlist. No admin screen consumes this - API only |
| GET |
/analytics/device-breakdown |
Device and browser distribution. Param: period (default 30d) |
| GET |
/realtime/viewers |
Active sessions (is_active = 1 and last heartbeat within 5 minutes) |
| GET |
/analytics/suspicious |
Paginated activity alerts. Params: page, per_page (default 20) |
| PATCH |
/analytics/suspicious/{id}/dismiss |
Dismiss an alert (sets is_dismissed = 1) |
| POST |
/analytics/suspicious/safe-user |
Whitelist a user. Param: user_id. Also dismisses that user’s open alerts |
| Method |
Route |
Description |
| GET |
/milestones/config |
Retrieve milestone action configuration (ms_pro_milestone_config) |
| PUT |
/milestones/config |
Save the configuration. Body: {config: [{threshold, actions: [{type, config}]}]} or a bare array. threshold 1-100, type one of tag, email, webhook |
| POST |
/milestones/test-action |
Fire one action once against the current admin. Body: {type, threshold, config} |
The config has no per-video dimension - a milestone action applies to every video.
| Method |
Route |
Description |
| GET |
/export/csv/{type} |
Stream CSV. {type}: watch_sessions, milestones, users. Params: date_from, date_to, user_id, video_id. No cap on watch-session and milestone exports since 1.3.0 - they keyset-page and export in full. The user export keeps a 200,000-row ceiling and writes a NOTE row into the CSV if it is reached. Requires _wpnonce (the download is a plain anchor navigation, so the nonce travels in the query string) |
| POST |
/export/pdf/report |
Queue an async PDF report. Param: period (7d, 30d, 90d, all; default 30d). Returns 202 with { job_id, status, message } |
| GET |
/export/status/{job_id} |
Check PDF job status. Adds download_url once the job is complete |
| Method |
Route |
Description |
| POST |
/digest/send-test |
Render the weekly digest and send it to the requesting admin’s email, not the configured digest address. Returns sent: false with reason digest_disabled_or_no_recipient when ms_weekly_digest_enabled is off |
| Method |
Route |
Description |
| GET |
/license |
Current license state: key_masked, has_key, status (raw store object), is_valid, has_bypass, item_id, store_url |
| POST |
/license |
Activate a key against the wbcomdesigns.com store |
| DELETE |
/license |
Deactivate the stored key and free the store slot |
All Pro routes use the mediashield-pro/v1 namespace exclusively. No Pro routes are registered under mediashield/v1.