Skip to content

Privacy & Access Control

Free + Pro - Core functionality is included free. Features marked with (Pro) require MediaVerse Pro.

MediaVerse provides privacy levels for media items, albums, and collections. Access checks run on every REST API call and on the explore archive query.

The six levels below are the ones the upload form offers. The full vocabulary a write is allowed to store is PrivacyService::supported_levels() - as of 2.4.0 public, members, loggedin, friends, group, space, private, dm and custom, filterable through mvs_privacy_levels. A level not in that list is refused at the edge rather than stored and silently ignored.

Level Value Who Can View
Public public Everyone, including logged-out visitors
Members Only members Any logged-in WordPress user
Friends friends BuddyPress friends of the media owner (requires BuddyPress active)
Group group Members of a specific BuddyPress group (requires BuddyPress active)
Private private Only the media owner and users with moderate_mvs_media
Custom custom A specific list of user IDs defined via access grants

Pro documents add one more level, this space (space) - visible to members of the Space the document’s drive belongs to. It applies to documents; media items are not space-scoped by default, though a document (or media) can be bound to a Space drive with the mvs_media_drive filter.

Media owners (the post_author) and users with the moderate_mvs_media capability bypass all privacy checks. They can view all media regardless of its privacy level.

Set the privacy field when creating media via REST API:

Terminal window
curl -X POST https://yoursite.com/wp-json/mvs/v1/media \
-H "X-WP-Nonce: NONCE" \
-F "file=@photo.jpg" \
-F "privacy=friends"

For group privacy, also include group_id:

Terminal window
-F "privacy=group" \
-F "group_id=42"
Terminal window
curl -X PUT https://yoursite.com/wp-json/mvs/v1/media/123 \
-H "X-WP-Nonce: NONCE" \
-H "Content-Type: application/json" \
-d '{"privacy": "private"}'

For custom privacy, grant access to specific users:

Terminal window
curl -X POST https://yoursite.com/wp-json/mvs/v1/media/123/grant \
-H "X-WP-Nonce: NONCE" \
-H "Content-Type: application/json" \
-d '{
"user_id": 55,
"expires_at": "2026-01-01T00:00:00Z"
}'

Access grants can have optional expiry dates. Expired grants are cleaned up via wp mvs cleanup-expired or via cron.

For media stored with a non-public privacy level, MediaVerse can generate time-limited signed URLs:

Terminal window
curl https://yoursite.com/wp-json/mvs/v1/media/123/signed-url \
-H "X-WP-Nonce: NONCE"

Response:

{
"url": "https://yoursite.com/wp-content/uploads/wpmediaverse/2025/03/photo.jpg?token=abc123&expires=1743000000",
"expires_at": "2025-03-27T13:00:00Z"
}

The signed URL TTL defaults to 3600 seconds (1 hour) and is configurable in Media > Settings > Storage > Signed URL Expiry (seconds).

Use the mvs_privacy_can_view filter to extend or override access logic:

add_filter( 'mvs_privacy_can_view', function( $result, $media_id, $user_id, $privacy ) {
// Grant access to premium subscribers regardless of privacy level.
if ( null === $result && wcs_user_has_subscription( $user_id, '', 'active' ) ) {
return true;
}
return $result;
}, 10, 4 );

Return null to let the built-in logic run. Return true or false to override it.

On the explore archive (/media/), MediaVerse applies automatic privacy filtering through a SQL clause on its own mvs_media_index table (a privacy IN (...) OR post_author = current gate shared by every explore surface), not a WordPress posts_where filter:

  • Logged-out users see only public media.
  • Logged-in non-moderators see public, members media, and their own media (any privacy level).
  • Moderators (moderate_mvs_media capability) see all media.