Media Permissions
A comprehensive guide on how to attach and restrict media access across the API (Posts, Messages, Automated Messages).
Several endpoints across our Fansly API (such as creating posts, sending DMs, mass messaging, and automated messages) support attaching Fansly media. You can restrict access to this media using powerful permission models, from simple paywalls (PPV) to complex multi-condition locks.
This guide covers the standard media permission structure used throughout the API.
Attaching Media
Media is attached by providing an array of media IDs using the mediaIds property.
{
"mediaIds": ["media_id_1", "media_id_2"]
}Media Previews
If you want to include a "preview" (like a free teaser image or short video) for locked media, you can pass an object containing both the mediaId and previewId instead of just a raw string. Fansly will display the preview to users who haven't unlocked the main media yet.
{
"mediaIds": [
{
"mediaId": "media_id",
"previewId": "preview_media_id"
}
]
}You can seamlessly mix media items that have previews and those that don't within the same array (for instance, when creating a bundle). To do this, simply use objects for media with previews, and either raw strings or objects with previewId: null for media without previews:
{
"mediaIds": [
// 1. Media WITH a free preview
{
"mediaId": "media_id_1",
"previewId": "preview_media_id"
},
// 2. Media WITHOUT a preview (using a simple string)
"media_id_1",
// 3. Media WITHOUT a preview (using an object)
{
"mediaId": "media_id_1"
}
],
"access_type": ["ppv"],
"price": 5.99
}By default, if no access rules are provided, the media is considered unlocked (free for anyone who can see the post or message).
Simple (Root-Level) Permissions
If you only need a single condition for your media (e.g., "Pay $5 to unlock" OR "Must be a subscriber"), you can pass the permission fields directly at the root of your payload alongside the mediaIds.
Available Fields
| Field | Type | Description |
|---|---|---|
access_type | array of string | Required to lock media. Can include: "ppv", "subscription", "follow", "list", "limited_time". |
price | number | Price in dollars (e.g., 5.00). Required if access_type includes "ppv". |
subscriptionTierId | string | Optional if access_type includes "subscription". Omit to lock for all subscription tiers. |
subscriptionTierName | string | Optional if access_type includes "subscription". Omit to lock for all subscription tiers. |
listId | string | Required if access_type includes "list". |
listLabel | string | Required if access_type includes "list". |
validBefore | number | Timestamp. Required if access_type includes "limited_time". |
validAfter | number | Timestamp. Required if access_type includes "limited_time". |
Example: Simple PPV Paywall
{
"mediaIds": ["media_id"],
"access_type": ["ppv"],
"price": 4.99
}Example: Simple Subscription Lock
{
"mediaIds": ["media_id"],
"access_type": ["subscription"],
"subscriptionTierId": "subscription_tier_id",
"subscriptionTierName": "Gold VIP"
}Advanced (Multi-Rule) Permissions
If you want media to be unlockable via multiple different conditions (an "OR" relationship), you must use the permissions array instead of the root-level fields.
When the
permissionsarray is provided in your payload, any root-level permission fields (like a root-levelpriceoraccess_type) are ignored, and the API strictly uses the rules defined in the array.
Each object within the permissions array accepts the exact same fields listed in the table above.
Example: Multiple Unlock Options
In this payload, a user can unlock the attached video if they meet any of the following conditions:
- They are subscribed to the "Gold VIP" tier.
- OR they pay a $5.00 PPV fee.
- OR they are on a specific custom list.
{
"content": "Check out my new exclusive video!",
"mediaIds": ["media_id"],
"permissions": [
{
"access_type": ["subscription"],
"subscriptionTierId": "subscription_tier_id",
"subscriptionTierName": "Gold VIP"
},
{
"access_type": ["ppv"],
"price": 5.00
},
{
"access_type": ["list"],
"listId": "list_id",
"listLabel": "Close Friends"
}
]
}Example: Combined Access Types
You can also combine access types within a single rule if you want to require both conditions to be true (an "AND" relationship within a single rule block, though this is less common).
{
"mediaIds": ["media_id"],
"permissions": [
{
"access_type": ["subscription", "limited_time"],
"subscriptionTierId": "subscription_tier_id",
"subscriptionTierName": "Gold VIP",
"validBefore": 1729483920
}
]
}In the above example, the media can only be unlocked by a Gold VIP subscriber, AND only before the specified Unix timestamp.
Comprehensive Example
The following payload uses all available access_type values and their corresponding fields in a single root-level permission rule:
{
"content": "Check out this exclusive media!",
"mediaIds": [
"media_id_1",
"media_id_2"
],
"access_type": [
"ppv",
"subscription",
"follow",
"list",
"limited_time"
],
"price": 10.00,
"subscriptionTierId": "subscription_tier_id",
"subscriptionTierName": "Sugar Daddy",
"subscriptionTierBefore": 1782485820000,
"subscriptionTierAfter": 1781708220000,
"listId": "list_id",
"listLabel": "VIP Fans",
"validBefore": 1782399840000,
"validAfter": 1781708661247
}