Composing Posts
Learn how to compose and publish posts with text, media, paywalls, and custom permissions using the Fansly API.
Composing and publishing posts to a creator's wall is a key interaction. A post can consist of simple text, attached media (images/videos), paywalls (PPV), or specific targeting rules (like sending it to the For You Page).
This guide walks you through the step-by-step process of preparing your assets and publishing a post using the Create Post endpoint.
The Workflow Overview
To publish a post, you will follow these general steps:
Obtain Media IDs (If attaching images or videos)
You must upload new files or select existing media from the creator's vault to get their unique identifiers.
Determine the Post Target & Type
Decide whether it is a standard free post, a Pay-Per-View (PPV) post, or targeting the For You Page (FYP).
Set Up Reply Permissions (Optional)
Decide who is allowed to comment on the post (e.g., only active subscribers, followers, or users who tipped).
Publish the Post
Send the final payload to the publishing endpoint.
Step 1: Handling Media Attachments
If you are creating a text-only post, you can skip this step. If your post contains images or videos, you must supply an array of mediaIds. You can obtain these in one of two ways:
Scenario A: Uploading New Media
If you want to attach media that is not yet on Fansly, use the Upload Media endpoints:
-
Initiate the Upload: Make a
POSTrequest to the Initiate Upload endpoint with the file binary:POST /api/fansly/{accountId}/media/uploadThis returns a
jobIdidentifying the queued background upload job. -
Poll the Job Status: Periodically call the Track Upload Status endpoint using your
jobId:GET /api/fansly/media/upload/{jobId}/status -
Grab the Media ID: Once the response
statechanges to"completed", retrieve the unique ID frommediaId(e.g.,123456789). Use this ID in your post payload.
For a complete reference on this flow, visit the Upload Media documentation.
Scenario B: Selecting from Vault Albums
If the creator wants to reuse existing content, you can retrieve media from their Vault:
-
List Vault Albums: Fetch the creator's albums to find the right container:
GET /api/fansly/vault/albums -
Fetch Album Media: Retrieve all media files inside a selected album:
GET /api/fansly/vault/albums/{albumId}/media -
Get the Media ID: Copy the
mediaIdof the target media item from the list response to include in your post.
Step 2: Configure Post Settings & Validation Rules
Depending on the post type, you must structure the request body parameters for the post according to specific validation rules:
1. Free Media Posts
To attach media for free to the wall, simply provide the content text and the mediaIds array. Do not include the access_type or price parameters.
2. Pay-Per-View (PPV) Posts
To put the attached media behind a paywall:
- Include the
mediaIdsof the files you are locking. - Set
access_typeto["ppv"]. - Set
priceto a decimal value in dollars (e.g.,5or9.99for $5.00 or $9.99).
3. For You Page (FYP) Posts
To push the post to the global recommendation feed:
- Set
postToFYPtotrue. - Strict Requirement: You must attach at least one public video that is 3 seconds or longer. If this condition is not met, the API will return an error.
Post Requirements
At least one of content or mediaIds must be populated. You cannot send an empty post.
Step 3: Setting Reply Permissions
You can restrict who is allowed to comment on the post. This is defined in the replyPermissions object:
following:trueallows replies from accounts you follow.subscribed:trueallows replies from active subscribers.tipped:truerestricts replies to users who have tipped you. You can set a minimum requirement withtippedMinAmount(e.g.,5for $5.00).mediaPurchases:truelimits replies to fans who bought your paywalled content. You can set a threshold withmediaPurchasesMinAmount(e.g.,20for $20.00).
Step 4: Publish the Post
Send a POST request to the publishing endpoint:
POST /api/fansly/{account_id}/postsExample Request Payload
Here is a full example of a Pay-Per-View post scheduled to go live in the future:
{
"content": "Check out my exclusive behind-the-scenes video! 🎬",
"mediaIds": ["media_9876543210"],
"access_type": ["ppv"],
"price": 10,
"postToFYP": false,
"scheduledFor": 1779801881000,
"replyPermissions": {
"subscribed": true,
"following": true
}
}(Note: scheduledFor and expiresAt timestamps must be formatted in Unix milliseconds).
Example Response
{
"statusCode": 201,
"message": "Success",
"data": {
"success": true,
"response": {
"id": "post_5544332211",
"accountId": "account_123456",
"content": "Check out my exclusive behind-the-scenes video! 🎬",
"expiresAt": 0,
"attachments": [
{
"contentType": 1,
"contentId": "media_9876543210",
"pos": 0,
"postId": "post_5544332211"
}
],
"wallIds": [],
"pinWallIds": [],
"pinned": 0,
"mediaLikeCount": 0,
"totalTipAmount": 0,
"attachmentTipAmount": 0
}
},
"timestamp": "2026-06-05T20:00:00.000Z"
}