4Based API Reference
Native access to 4based.com creator accounts through the CreatorAPI proxy. One key, the same shape as OnlyFans and Fansly. You never touch 4based's tokens, headers or its /user/{id}/... path layout · CreatorAPI resolves the creator's own id for you and signs every request server side. Native read and write · shorthand aliases for the common reads · self id resolved for you.
How every call works
All native 4based routes are reached through one pattern:
{METHOD} https://api.creator-api.com/v1/{account}/native/{native_path}
{account} is the connected 4based account id. Auth header X-API-Key: <your key>. GET is read only; writes need a full scope key. Billing: read = 1 credit, write = 2 credits.
Set CREATOR_API_KEY to your API key and replace every {account} and other path placeholder before running an example. Native response bodies pass through unchanged; a successful empty response has no JSON to decode. The native route notes below are historical evidence and are not a new live audit of every action.
Shorthands · you do not need the raw paths
4based puts the creator's own id in almost every path (/user/{id}/...). You do not have to know it. Call the shorthand and CreatorAPI rewrites it to the real path and fills in the id. An explicit query param always wins over the default.
| Shorthand | What you get | Rewrites to |
|---|
me | The creator's own 4based profile | /user/{id} |
subscribers | Subscriber list | /user/{id}/subscription |
subscriber-count | Active, cancelled and pending counts | /user/{id}/subscription-count |
tiers | Subscription tiers and prices | /user/{id}/subscription/configuration |
chats | Conversation list | /user/{id}/chat |
feed | The creator's own feed | /base |
vault | Media vault | /user/{id}/vault |
earnings | 4based's own earnings statistics route. It answers empty for every date window we tried, including on an account with a positive payout balance, and /process/sum/netto answers 502. Use payouts for money that is really there. | /user/{id}/process/stats |
payouts | Withdrawable balance and the amount still open | /user/{id}/payout/available |
lists | Fan segmentation lists | /user/{id}/user-lists |
vouchers | Discount/voucher codes | /user/{id}/voucher |
templates | Saved chat reply templates | /user/{id}/chat/configured_message |
payout | Current withdrawable balance | /user/{id}/payout/available |
unread | Unread message count per conversation | /user/{id}/chat/unread-messages |
chat-config | Your DM pricing (unlock price, default message price) | /user/{id}/chat/configuration |
payout-history | Full payout request history | /user/{id}/payout |
postback-urls | Your configured 4based postback/webhook URLs | /user/{id}/postback-url |
interactions | Fans who recently liked/commented/visited | /user/{id}/interaction |
share-config | Your referral/sharing link configuration | /user/{id}/share/configuration |
reels | 4based Reel discovery feed; own-account filtering is not reliable (see below) | /reels (?user_id={id} filled in for you) |
content / posts | Every post you own, any type (feed, vault, moments) | /user/{id}/file-stack |
moments | Just the Moments among your posts | /user/{id}/file-stack (?categories=moment filled in for you) |
blocked | Fans you have blocked | /user/{id}/blocked |
muted | Fans you have muted | /user/{id}/muted |
restricted | Fans you have restricted | /user/{id}/restricted |
following | Accounts you follow | /user/{id}/following |
followers | Fans following you | /user/{id}/follower (yes, singular on 4based's side, the shorthand stays plural) |
activity | Your activity/notification feed | /activity |
partnerships | Your ad-partner partnerships | /partnerships |
search | Search or browse any 4based account | /user |
So GET /v1/{account}/native/subscribers just works, the same way me works on OnlyFans and Fansly. There is no /me route on 4based itself; the shorthand me maps to the real profile route /user/{id}.
4based response notes
- Self id: the id in
/user/{id}/... is the creator's 4based ObjectId. CreatorAPI fills it in for every shorthand, so you never send it. - Default paging:
chats, subscribers and lists require a limit upstream (4based returns 400 without one), so CreatorAPI adds limit=50 when you omit it. Pass your own ?limit= and ?offset= to page. (lists hard-fails without it — "limit is required" — the other two just come back empty instead.) - Empty lists: an account with no subscribers or chats yet returns an empty body, not an error. That is the real 4based response, not a fault. The one exception is the earnings statistics route, which stays empty even when the account has money: that is a 4based side gap, not your account.
- Amounts: money fields (tier
price, earnings) come through exactly as 4based returns them, with the currency field alongside. Read the currency per row before you aggregate.
Account & profile
Get the creator profile
GET /v1/{account}/native/me · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/me"
import os
import requests
CREATOR_API_KEY = os.environ["CREATOR_API_KEY"]
r = requests.get(
"https://api.creator-api.com/v1/{account}/native/me",
headers={"X-API-Key": CREATOR_API_KEY},
)
r.raise_for_status()
print(r.json() if r.content else None)
const r = await fetch(
"https://api.creator-api.com/v1/{account}/native/me",
{ headers: { "X-API-Key": process.env.CREATOR_API_KEY } },
);
console.log(await r.json());
me/profile return the same full object: bio, follower/following counts, verification status, coins, notification settings, last activity, and more · richer than just the basics.
Search or browse accounts
GET /v1/{account}/native/search · 1 credit(s)
Any 4based account, not scoped to yours — for finding a partnership target or resolving a handle. ?search= is free text; ?limit=/?offset= page it.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/search?search=jane&limit=10"
Subscribers
List subscribers
GET /v1/{account}/native/subscribers · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/subscribers?limit=50&offset=0"
import os
import requests
CREATOR_API_KEY = os.environ["CREATOR_API_KEY"]
r = requests.get(
"https://api.creator-api.com/v1/{account}/native/subscribers",
headers={"X-API-Key": CREATOR_API_KEY},
params={"limit": 50, "offset": 0},
)
r.raise_for_status()
print(r.json() if r.content else None)
const r = await fetch(
"https://api.creator-api.com/v1/{account}/native/subscribers?limit=50&offset=0",
{ headers: { "X-API-Key": process.env.CREATOR_API_KEY } },
);
console.log(await r.json());
Subscriber count
GET /v1/{account}/native/subscriber-count · 1 credit(s)
Returns active, cancelled and pending cancelled subscription counts.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/subscriber-count"
Subscription tiers
List tiers and prices
GET /v1/{account}/native/tiers · 1 credit(s)
Each tier carries its price, repeat_days, type, status and currency.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/tiers"
import os
import requests
CREATOR_API_KEY = os.environ["CREATOR_API_KEY"]
r = requests.get(
"https://api.creator-api.com/v1/{account}/native/tiers",
headers={"X-API-Key": CREATOR_API_KEY},
)
r.raise_for_status()
for tier in (r.json() if r.content else []):
print(tier["type"], tier["price"], tier["currency"])
Create a tier · and how bundles actually work
POST /v1/{account}/native/user/{selfId}/subscription/configuration · 2 credit(s) · full scope key
A "promotion bundle" in 4based's own UI is not a separate object · it is one entry in this same request's initial_payment_options array (a discounted multi-month commitment, e.g. 20% off if a fan commits to 3 months). amount is not computed for you, send the discounted total yourself.
Body:
{
"price": 10,
"currency": "USD",
"type": "premium",
"status": "active",
"repeat_days": 28,
"recurring_payment": { "duration_unit": "MONTH", "duration_value": 1, "amount": 10, "description": "Recurring subscription" },
"initial_payment_options": [
{ "discount": 20, "duration_unit": "MONTH", "duration_value": 3, "amount": 24, "description": "Promotion Bundle" }
]
}
initial_payment_options can be an empty array for a plain tier with no bundle. The response echoes back the created tier including a server-assigned _id and a read-only amount_netto per amount (4based's own cut already subtracted) · don't send that field.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"price":10,"currency":"USD","type":"premium","status":"active","repeat_days":28,"recurring_payment":{"duration_unit":"MONTH","duration_value":1,"amount":10,"description":"Recurring subscription"},"initial_payment_options":[]}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/subscription/configuration"
Deactivate a tier
PUT /v1/{account}/native/user/{selfId}/subscription/configuration/{tierId} · 2 credit(s) · full scope key
4based has no hard delete for tiers, this soft-deletes it the same way the platform's own client does on a price change. Body { "status": "deleted", "modification_type": "price_change" }.
curl -X PUT \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"status":"deleted","modification_type":"price_change"}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/subscription/configuration/{tierId}"
Messaging
List conversations
GET /v1/{account}/native/chats · 1 credit(s)
CreatorAPI adds limit=50 when you omit it. Page with ?limit= and ?offset=.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/chats?limit=50"
Read messages in a chat
GET /v1/{account}/native/user/{selfId}/chat/{chatId}/message · 1 credit(s)
The messages route needs the chat id, so it takes the full path. Use the me response to get the creator's _id as {selfId}, and a chat id from chats.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/{chatId}/message?limit=50"
Send a message or PPV
POST /v1/{account}/native/user/{selfId}/chat/{chatId}/message · 2 credit(s) · full scope key
Body { "message": "hey", "file_stack_id": "...", "message_price": 500, "local_id": "..." }. Set message_price above zero for a pay per view message; leave it out for a free message.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"message":"hey there"}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/{chatId}/message"
Get one conversation
GET /v1/{account}/native/user/{selfId}/chat/{chatId} · 1 credit(s)
The chat's own metadata (participants, timestamps), not its messages. Get a {chatId} from chats or from the unread-count shorthand below.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/{chatId}"
Unread message count
GET /v1/{account}/native/unread · 1 credit(s)
One object keyed by chat id: { "<chatId>": <unread_count>, ... }.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/unread"
Your DM pricing
GET /v1/{account}/native/chat-config · 1 credit(s)
Your own configured unlock price and default per-message price.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/chat-config"
Pin or unpin a conversation
POST /v1/{account}/native/user/{selfId}/chat/{chatId}/pin · 2 credit(s) · full scope key
Body { "is_pinned": true }.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"is_pinned":true}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/{chatId}/pin"
Mark a conversation as unread
POST /v1/{account}/native/user/{selfId}/chat/{chatId}/mark-as-unread · 2 credit(s) · full scope key
Only changes anything on a conversation that is currently marked read; 4based returns a conflict if it already has unread messages.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/{chatId}/mark-as-unread"
Edit a sent message
PUT /v1/{account}/native/user/{selfId}/chat/{chatId}/message/{messageId} · 2 credit(s) · full scope key
Body { "text": "corrected message" }.
curl -X PUT \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"corrected message"}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/{chatId}/message/{messageId}"
Delete all messages in a conversation
PUT /v1/{account}/native/user/{selfId}/chat/{chatId}/delete-all-chat-messages-for-user · 2 credit(s) · full scope key
Clears the conversation on your side, no body needed.
Delete an entire conversation
PUT /v1/{account}/native/user/{selfId}/chat/{chatId}/delete-chat-for-user-by-user-id · 2 credit(s) · full scope key
Set your DM pricing
POST /v1/{account}/native/user/{selfId}/chat/configuration · 2 credit(s) · full scope key
The write side of chat-config above (that one is read only). Body { "unlock_price": 10, "message_price": 5 }. Upsert safe · an empty or partial body does not clobber prices you have already set.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"unlock_price":10,"message_price":5}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/configuration"
Mass messaging
4based gates sending on a paid/verified creator plan (a featureerror if your account is not eligible); reading and managing what you have already sent works regardless.
Send a mass message
POST /v1/{account}/native/user/{selfId}/chat/mass-message/ · 2 credit(s) · full scope key
Body { "message": "hey everyone", "file_stack_id": "...", "message_price": 500 }, same shape as a 1:1 message.
List sent mass messages
GET /v1/{account}/native/user/{selfId}/chat/mass-message/ · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/mass-message/"
Edit or cancel a mass message
PUT /v1/{account}/native/user/{selfId}/chat/mass-message/{messageId} · 2 credit(s) · full scope key DELETE /v1/{account}/native/user/{selfId}/chat/mass-message/{messageId} · 2 credit(s) · full scope key
Edit is useful for one still scheduled and not yet sent.
Fan lists
List your fan-segmentation lists
GET /v1/{account}/native/lists · 1 credit(s)
CreatorAPI adds limit=50 when you omit it (4based hard-requires it here). Page with ?limit= and ?offset=.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/lists?limit=50"
Create a list
POST /v1/{account}/native/user/{selfId}/user-lists · 2 credit(s) · full scope key
Body { "name": "VIP whales" }.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"VIP whales"}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/user-lists"
Delete a list
DELETE /v1/{account}/native/user/{selfId}/user-lists/{listId} · 2 credit(s) · full scope key
Fans in one list
GET /v1/{account}/native/user/{selfId}/user-lists/{listId}/users?limit=50 · 1 credit(s)
limit is required upstream.
Rename a list
PUT /v1/{account}/native/user/{selfId}/user-lists/{listId} · 2 credit(s) · full scope key
Body { "name": "New name" }.
Add or remove fans from a list
POST /v1/{account}/native/user/{selfId}/user-lists/{listId}/add-users · 2 credit(s) · full scope key POST /v1/{account}/native/user/{selfId}/user-lists/{listId}/remove-users · 2 credit(s) · full scope key
Body { "user_ids": ["...", "..."] }. 4based only allows adding fans who are already following the creator; adding anyone else is rejected.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"user_ids":["64f0a1b2c3d4e5f678901234"]}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/user-lists/{listId}/add-users"
Check which lists a fan is on
GET /v1/{account}/native/user/{selfId}/user-lists/contains-user/{fanUserId} · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/user-lists/contains-user/{fanUserId}"
Follow and unfollow
POST /v1/{account}/native/user/{fanUserId}/follow · 2 credit(s) · full scope key DELETE /v1/{account}/native/user/{fanUserId}/follow · 2 credit(s) · full scope key
The fan you are following goes in the URL, not the request body, and no body is needed.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{fanUserId}/follow"
curl -X DELETE \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{fanUserId}/follow"
Remove a follower
DELETE /v1/{account}/native/user/{fanUserId}/un-follow · 2 credit(s) · full scope key
Not the reverse of the follow calls above. This removes a fan FROM your own follower list, forcing them to stop following you · you are not unfollowing them, you are removing them as a follower. {fanUserId} is the follower to remove, no body needed.
curl -X DELETE \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{fanUserId}/un-follow"
Followers and following
GET /v1/{account}/native/followers · 1 credit(s) GET /v1/{account}/native/following · 1 credit(s)
Who follows you, and who you follow. Note the underlying 4based route for followers is singular (/follower) · the shorthand stays plural since that reads naturally, CreatorAPI resolves it either way.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/followers?limit=50"
Blocked, muted and restricted fans
GET /v1/{account}/native/blocked · 1 credit(s) GET /v1/{account}/native/muted · 1 credit(s) GET /v1/{account}/native/restricted · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/blocked?limit=50"
Feed & vault
Get the feed
GET /v1/{account}/native/feed · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/feed?limit=50"
List the media vault
GET /v1/{account}/native/vault · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/vault?limit=50"
Content, Reels & Moments
Everything you own
GET /v1/{account}/native/content (alias posts) · 1 credit(s)
Every post you own regardless of where it is surfaced · feed, vault, moments, all of it. Different from feed (the public feed view): this is your own full inventory, including private and subscription-only items. Filter with ?categories=, ?contentType=, ?is_subscription_item=, ?tag=.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/content?limit=50"
Just your Moments
GET /v1/{account}/native/moments · 1 credit(s)
Same endpoint as content above, categories=moment filled in for you. Your own explicit ?categories= still wins if you pass one.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/moments?limit=50"
Your Reels
GET /v1/{account}/native/reels · 1 credit(s)
A separate top-level discovery feed from content. CreatorAPI forwards your own ID as user_id, but in live validation on 2026-10-10, 4based returned other creators despite that filter. Do not use this response as a reliable inventory of your own Reels or as proof that your upload has entered the discovery feed. Read native/posts or native/file-stack/{fileStackId} to verify your own publication.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/reels?limit=10&fileStackType=video&with_source=true&locale=en&random=1"
Get one post
GET /v1/{account}/native/file-stack/{fileStackId} · 1 credit(s)
The full post object · not a metrics sub-resource, the post itself (dimensions, price, categories, is_subscription_item, …).
Private-post exception, observed live on 2026-10-14: a newly uploaded own private=true image returned native HTTP 403 private content on this single-post route. Read your own inventory with GET /v1/{account}/native/content?limit=50&offset=0 and find the returned upload _id; paginate with offset when needed. The private flag, owner ID and changed description were read back successfully through this inventory. Keep the post private; making it public is not required. Use the same exact ID for PUT and DELETE. Both private and public own-image upload, edit, inventory/read-back, delete and subsequent 404 were tested; this does not certify playback, content approval or other media types. Get a {fileStackId} from content, moments, reels or feed.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/file-stack/{fileStackId}"
Create a post
POST /v1/{account}/media/upload · write
Not under /native/ · this is its own route (see media upload for the general pattern shared with OnlyFans and Fansly). Unlike those two, 4based has no separate upload-then-attach step: send the file and it publishes immediately, this call returns the created post.
Multipart form-data: file (required), plus optional categories (comma-separated, defaults to media,image or media,video by mime type), description, price (0 or 300+, minor units · a standalone PPV price), is_subscription_item (true/false), tag (comma-separated), private (true/false), to_be_posted_at (ISO 8601, schedules instead of publishing now).
price and is_subscription_item are mutually exclusive in practice: 4based never prices subscription-included content separately, so setting both keeps price at 0.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-F "file=@photo.jpg;type=image/jpeg" \
-F "description=New drop 🔥" \
-F "price=300" \
"https://api.creator-api.com/v1/{account}/media/upload"
import os
import requests
CREATOR_API_KEY = os.environ["CREATOR_API_KEY"]
r = requests.post(
"https://api.creator-api.com/v1/{account}/media/upload",
headers={"X-API-Key": CREATOR_API_KEY},
files={"file": ("photo.jpg", open("photo.jpg", "rb"), "image/jpeg")},
data={"description": "New drop 🔥", "price": 300},
)
r.raise_for_status()
print(r.json() if r.content else None)
Edit or delete a post
PUT /v1/{account}/native/file-stack/{fileStackId} · 2 credit(s) · full scope key DELETE /v1/{account}/native/file-stack/{fileStackId} · 2 credit(s) · full scope key
PUT body is whatever fields you're changing, e.g. { "description": "...", "price": 500 }.
curl -X PUT \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"price":500}' \
"https://api.creator-api.com/v1/{account}/native/file-stack/{fileStackId}"
Post sale stats
GET /v1/{account}/native/user/{selfId}/file-stack/{fileStackId}/sale/stats · 1 credit(s)
Hour-bucketed sales for one post (distinct from the view stats above). timePeriod is required, same as view stats.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/file-stack/{fileStackId}/sale/stats?timePeriod=day"
Publish a Reel
POST /v1/{account}/media/reels
Reel publishing uses 4based's ordinary free-video upload: the current 4based client says that free videos automatically appear in Reels. There is no separate upstream Reel-creation endpoint in this integration. CreatorAPI validates the actual video before publishing, then returns the original created post. Processing, content approval, and inclusion in the Reel feed are handled by 4based. A successful upload does not mean processing or content approval is complete. The provider status available alone does not prove that viewers can play the video.
This immediately submits content for publication, subject to 4based's content review. Use a connected 4based creator account and a full-scope key. Cost: 2 credits. Staff need media.manage and access to that account.
Send multipart form-data:
| Field | Meaning |
|---|
file | Required video; MP4, MOV, WebM, AVI or Ogg. Actual duration must be at most 120 seconds. CreatorAPI's upload limit is 512 MB. |
description | Optional caption |
tag | Optional comma-separated tags |
price | Must be 0 |
is_subscription_item | Must be false |
private | Must be false |
categories | Optional: media,video (default), or media,vault,video to also save a copy in the creator's Cloud |
to_be_posted_at | Not supported by this immediate Reel upload |
lock / tier_id | Not supported for free Reels |
curl -X POST "https://api.creator-api.com/v1/{account}/media/reels" \
-H "X-API-Key: $CREATORAPI_KEY" \
-F "file=@reel.mp4" \
-F "description=New clip" \
-F "tag=new,video"
Alternatively, send reel=true to the existing POST /v1/{account}/media/upload. Ordinary uploads without that option keep their existing behavior. Verify the created post with GET /v1/{account}/native/file-stack/{fileStackId}. The native/reels discovery feed is provider-controlled and is not a reliable own-account inventory.
The Reel route sends the actual video dimensions and the explicit free-video metadata observed in a manual 4based upload HAR: price=0, is_subscription_item=false, is_teaser=false, and upload item position=0. The website also sends price=0 when its price input is empty. Cloud storage is an explicit option through categories=media,vault,video; adding a Cloud copy is not proven to affect Reel-feed placement. The HAR-aligned Reel route was subsequently verified live on an owner test account: upload with a Cloud copy, returned owner/free-public flags, processing, the provider display-approval condition, and actual browser playback while logged in as that creator. The returned public MP4 was downloaded and decoded in full without errors. This live check does not establish placement in the personalized Reel discovery feed or playback from a separate viewer account.
Images, empty files, unreadable video duration or dimensions, videos longer than 120 seconds, and incompatible pricing/privacy options are rejected before any provider upload. Server-side duration validation requires ffprobe; if unavailable, Reel upload fails with 503 instead of uploading unchecked content.
The upstream contract was inspected in public 4based web client 10.3.7.1 on 2026-10-10. Automated validation uses real local video files and simulated provider responses. Live production validation on a dedicated owner test account confirmed upload through this Reel route, post read-back and provider processing. A model-owned MOV was retained until content approval: the provider first returned status: available with status_media_controlled: ai_declined, then returned status_controlled: ok about three minutes after upload. The automatic-decline flag remained present. A separate logged-in viewer account subsequently saw the post in the creator's profile and successfully played the actual video without a review notice. Earlier disposable tests also verified deletion and a subsequent 404.
Wait for content approval before checking playback. available is processing status, and ai_declined alone is not proof of final rejection. The official client permits display when status_controlled == "ok", or when status_media_controlled == "ok" and status_controlled is either "ok" or absent. A later overall approval can therefore allow playback while the automatic-decline flag remains. The observed three-minute wait is one test result, not an approval-time guarantee.
Upload, approval, profile visibility and viewer playback are live verified; discovery-feed inclusion remains unconfirmed. The retained approved video was not found in a bounded check of the Reel discovery feed using the current client's query parameters, or while advancing through the viewer's Reels feed. These personalized discovery checks cannot establish that a particular post is excluded. Content review and Reel-feed inclusion must be verified separately; CreatorAPI cannot force provider approval or discovery distribution.
Marketing Hub · API 2.0
The current 4based Marketing Hub uses https://rest.4based.com/api/2.0. CreatorAPI exposes the following source-confirmed operations through an explicit native/v2 namespace and resolves the creator's own upstream user ID. Existing native calls keep using API 1.0.
| Method | CreatorAPI path after /v1/{account}/native/ | Operation |
|---|
| GET | v2/promotions | List campaigns, welcome offers and retention offers |
| POST | v2/promotions | Create an offer/campaign with the provider JSON contract |
| GET | v2/promotions/quota | Campaign quota |
| GET | v2/promotions/metrics | Batch metrics; repeated ids[] parameters are preserved |
| GET | v2/promotions/{promotion_id} | Read one offer |
| PUT | v2/promotions/{promotion_id} | Update; body ID must match the path ID |
| PATCH | v2/promotions/{promotion_id} | Partial update |
| DELETE | v2/promotions/{promotion_id} | Delete an offer |
| GET | v2/promotions/{promotion_id}/metrics | Offer metrics |
| POST | v2/promotions/{promotion_id}/activate | Activate; optional boolean queue_if_busy |
| DELETE | v2/promotions/{promotion_id}/activate | Withdraw a queued activation |
| POST | v2/promotions/{promotion_id}/cancel | Cancel a campaign |
Read shorthands: native/promotions and native/promotion-quota. Writes use the explicit native/v2/promotions/... paths. Reads cost 1 credit; writes cost 2 credits. Writes require a full key; staff need native.manage.
List filters observed in the client: type, status, exclude_status, limit, offset. Offer types: targeted_segment, new_followers, subscription_expiry_auto. JSON fields observed in the current client include name, type, status, discount, message, segments, notification_channels, validity_days, schedule, redemption_limit_total, redemption_limit_per_user and cooldown_days_per_fan. The upstream provider validates the complete configuration and current quota/status rules.
curl "https://api.creator-api.com/v1/{account}/native/promotions?type=new_followers" \
-H "X-API-Key: $CREATORAPI_KEY"
curl -g "https://api.creator-api.com/v1/{account}/native/v2/promotions/metrics?ids[]=offer1&ids[]=offer2" \
-H "X-API-Key: $CREATORAPI_KEY"
Creating or activating offers can notify fans through 4based and change their access or prices. Only invoke these actions intentionally. CreatorAPI does not automatically activate an offer or add notification channels. New promotion writes are not automatically retried on provider 429/5xx or transport failures; reconcile the provider state before retrying an ambiguous write yourself.
Responses retain the provider's JSON envelope (commonly data). The promotion list and quota GETs returned HTTP 200 through the public API on an owned account on 2026-10-14. Other operations remain source-confirmed and fixture-tested; no campaign was created or activated. Availability and account eligibility still depend on 4based.
Saved posts and private Collections
These are 4based bookmarks and bookmark collections belonging to the connected account. They are separate from the creator's media vault and fan-segmentation lists. CreatorAPI resolves the own user ID for both reads and writes.
| Method | Path after /v1/{account}/native/ | Body / query |
|---|
| GET | bookmarks | offset, limit, optional search, sort, content_type; default limit 30 |
| POST | bookmarks | {"file_stack_id":"post-id"} |
| POST | bookmarks/remove | {"file_stack_ids":["post-id"]} |
| GET | bookmark-collections | offset, limit; default limit 50 |
| POST | bookmark-collections | {"name":"Favorites"}; name 1–20 characters |
| PUT | bookmark-collections/{collection_id} | Provider collection fields, e.g. {"name":"VIP"} |
| DELETE | bookmark-collections/{collection_id} | No body |
| GET | bookmark-collections/{collection_id}/posts | Same list filters as bookmarks |
| POST | bookmark-collections/{collection_id}/add-posts | {"file_stack_ids":["post-id"]} |
| POST | bookmark-collections/{collection_id}/remove-posts | {"file_stack_ids":["post-id"]} |
Reads cost 1 credit; writes cost 2 credits and require a full key. Responses retain the upstream envelope. Follow/privacy requirements and whether creators may save a particular post are enforced by 4based. These API 1.0 contracts were inspected in the current public client and validated offline. The bookmarks and collection-list GETs additionally returned successful empty native responses on an owned account on 2026-10-14; no bookmark or collection write was tested. New bookmark writes are not automatically retried.
Earnings
Earnings stats
GET /v1/{account}/native/earnings · 1 credit(s)
Optional init_from and init_to (YYYY-MM-DD) narrow the window. Amounts arrive as 4based returns them, with currency alongside.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/earnings"
import os
import requests
CREATOR_API_KEY = os.environ["CREATOR_API_KEY"]
r = requests.get(
"https://api.creator-api.com/v1/{account}/native/earnings",
headers={"X-API-Key": CREATOR_API_KEY},
params={"init_from": "2026-01-01", "init_to": "2026-07-01"},
)
r.raise_for_status()
print(r.json() if r.content else None)
Vouchers
List discount/voucher codes
GET /v1/{account}/native/vouchers · 1 credit(s)
4based vouchers are created per fan (a target_user_id is required to issue one), not a public reusable coupon code.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/vouchers?limit=50"
Redeem a voucher code
POST /v1/{account}/native/voucher/redeem · 2 credit(s) · full scope key
Body { "code": "MYCODE123" }. Not scoped by account in the URL — 4based resolves the redeeming account from your connected session.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"code":"MYCODE123"}' \
"https://api.creator-api.com/v1/{account}/native/voucher/redeem"
Create a voucher for a fan
POST /v1/{account}/native/user/{selfId}/voucher · 2 credit(s) · full scope key
Body needs at least { "target_user_id": "<fanUserId>" } — 4based confirmed this field is required, the full discount/configuration shape is not yet completely mapped, expect to iterate.
Get, update or delete one voucher
GET /v1/{account}/native/user/{selfId}/voucher/{voucherId} · 1 credit(s) PUT /v1/{account}/native/user/{selfId}/voucher/{voucherId} · 2 credit(s) · full scope key DELETE /v1/{account}/native/user/{selfId}/voucher/{voucherId} · 2 credit(s) · full scope key
Get a {voucherId} from the vouchers list above.
Voucher redemption history
GET /v1/{account}/native/voucher/user/history/{voucherId} · 1 credit(s)
How many times / by whom one voucher has been redeemed.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/voucher/user/history/{voucherId}"
Voucher lifecycle events
GET /v1/{account}/native/user/{selfId}/voucher/history/{voucherId} · 1 credit(s)
A different endpoint from redemption history above · the voucher's own history (edits, status changes), not who redeemed it.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/voucher/history/{voucherId}"
Chat templates
List saved reply templates
GET /v1/{account}/native/templates · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/templates"
Payout
Current withdrawable balance
GET /v1/{account}/native/payout · 1 credit(s)
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/payout"
{"amount": 160.94, "amountOpen": 0}
Full payout history
GET /v1/{account}/native/payout-history · 1 credit(s)
Every payout request, not just the current withdrawable balance.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/payout-history"
Request a payout
POST /v1/{account}/native/user/{selfId}/payout/ · 2 credit(s) · full scope key
Requests the full balance shown by payout above · there is no partial-amount option. Real money movement on an account with a payout method configured; 4based returns 403 if none is on file.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/payout/"
Postback URLs
List your configured postback/webhook URLs
GET /v1/{account}/native/postback-urls · 1 credit(s)
4based's own callback mechanism, separate from CreatorAPI's own webhooks.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/postback-urls"
Register a postback URL
POST /v1/{account}/native/user/{selfId}/postback-url · 2 credit(s) · full scope key
Body { "postback_url": "https://your-server.example.com/hook" }.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"postback_url":"https://your-server.example.com/hook"}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/postback-url"
Edit or remove a postback URL
PUT /v1/{account}/native/user/{selfId}/postback-url/{postbackId} · 2 credit(s) · full scope key DELETE /v1/{account}/native/user/{selfId}/postback-url/{postbackId} · 2 credit(s) · full scope key
PUT body same shape as create above.
Fan relationships
Recent interactions
GET /v1/{account}/native/interactions · 1 credit(s)
Users who have recently interacted with you (likes, comments, visits), distinct from your subscriber and follower lists.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/interactions"
Per-fan relationship notes
GET /v1/{account}/native/user/{selfId}/pivot/{fanUserId} · 1 credit(s)
Any relationship metadata you have attached to one specific fan.
Block or unblock a fan
PUT /v1/{account}/native/user/{selfId}/block/{fanUserId} · 2 credit(s) · full scope key DELETE /v1/{account}/native/user/{selfId}/block/{fanUserId} · 2 credit(s) · full scope key
curl -X PUT \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/block/{fanUserId}"
Start a conversation
POST /v1/{account}/native/user/{selfId}/chat/user/{fanUserId} · 2 credit(s) · full scope key
Opens a new chat with a fan who does not have one yet.
Chat read status
Mark one conversation as received
PUT /v1/{account}/native/user/{selfId}/chat/{chatId}/update-messages-status-received · 2 credit(s) · full scope key
Mark every conversation as received
PUT /v1/{account}/native/user/{selfId}/chat-overview/update-all-my-messages-status-received · 2 credit(s) · full scope key
Per-chat pricing
Read a chat's price override
GET /v1/{account}/native/user/{selfId}/chat/{chatId}/price-override · 1 credit(s)
Returns the effective message price for this one conversation, whether it is your global default or a custom override, plus whether a change cooldown is active.
{"data": {"effective_message_price": 10, "is_override": true, "global_message_price": 12, "cooldown_active": true, "cooldown_expires_at": "2026-08-08T10:47:17+00:00"}}
Set or clear a chat's price override
PUT /v1/{account}/native/user/{selfId}/chat/{chatId}/price-override · 2 credit(s) · full scope key DELETE /v1/{account}/native/user/{selfId}/chat/{chatId}/price-override · 2 credit(s) · full scope key
Body for PUT: { "message_price": 500 }. 4based enforces a cooldown after a change before the override can be changed again; a call during the cooldown returns a 409.
curl -X PUT \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"message_price":500}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/{chatId}/price-override"
Publishing
Publish a scheduled or draft post immediately
PUT /v1/{account}/native/file-stack/post-now · 2 credit(s) · full scope key
Not scoped by account in the URL — the file-stack id in the body identifies the post.
curl -X PUT \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"id":"<fileStackId>"}' \
"https://api.creator-api.com/v1/{account}/native/file-stack/post-now"
Add media to the vault
PUT /v1/{account}/native/user/{selfId}/vault · 2 credit(s) · full scope key
Body { "id": "<fileStackId>" }.
Update a vault item
PUT /v1/{account}/native/user/{selfId}/vault/{vaultItemId} · 2 credit(s) · full scope key
Addresses one already-vaulted item directly, unlike the add call above.
Activity feed
Your activity/notifications
GET /v1/{account}/native/activity · 1 credit(s)
Likes, comments, sales, subscriptions, tips and more, newest first. ?since_id= pages forward from a cursor.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/activity?limit=50"
Reset the unread counter
GET /v1/{account}/native/activity/reset · 1 credit(s)
Top-level, not scoped by account in the URL on 4based's side.
Post likes
GET /v1/{account}/native/file-stack/{fileStackId}/like · 1 credit(s) POST /v1/{account}/native/file-stack/{fileStackId}/like · 2 credit(s) · full scope key DELETE /v1/{account}/native/file-stack/{fileStackId}/like · 2 credit(s) · full scope key
Who liked one of your posts, and liking/unliking one as this creator.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/file-stack/{fileStackId}/like"
Fan relationship notes
Set or clear notes on a fan
PUT /v1/{account}/native/user/{selfId}/pivot/{fanUserId} · 2 credit(s) · full scope key DELETE /v1/{account}/native/user/{selfId}/pivot/{fanUserId}/{pivotKey} · 2 credit(s) · full scope key
Write side of the per-fan relationship notes covered under Fan relationships above (that section's GET is read only).
Chat tips and live status
Send or unlock a tip
POST /v1/{account}/native/user/{selfId}/chat/{chatId}/tip · 2 credit(s) · full scope key POST /v1/{account}/native/user/{selfId}/chat/user/{fanUserId}/unlock-tip · 2 credit(s) · full scope key
Body { "amount": 500 } for both.
Typing indicator
POST /v1/{account}/native/user/{selfId}/chat/{chatId}/typing · 2 credit(s) · full scope key
Body { "value": true }.
Delete one message
PUT /v1/{account}/native/user/{selfId}/chat/{chatId}/delete-message-for-users-in-chat · 2 credit(s) · full scope key
Body { "id": "<messageId>" }. Distinct from clearing the whole conversation under Messaging above.
Manage saved reply templates
Write side of templates above (that shorthand is read only).
POST /v1/{account}/native/user/{selfId}/chat/configured_message/ · 2 credit(s) · full scope key PUT /v1/{account}/native/user/{selfId}/chat/configured_message/{templateId} · 2 credit(s) · full scope key DELETE /v1/{account}/native/user/{selfId}/chat/configured_message/{templateId} · 2 credit(s) · full scope key
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Hey! Thanks for subscribing 💕"}' \
"https://api.creator-api.com/v1/{account}/native/user/{selfId}/chat/configured_message/"
Reorder a fan list
PATCH /v1/{account}/native/user/{selfId}/user-lists/{listId}/position · 2 credit(s) · full scope key
Body { "position": 0 }.
Manage a subscriber's subscription
POST /v1/{account}/native/user/{selfId}/subscription/{subscriptionId}/modify · 2 credit(s) · full scope key
Body { "status": "..." }. Get a {subscriptionId} from subscribers above.
Look up a user by handle
GET /v1/{account}/native/user/name/{username} · 1 credit(s)
An alternate lookup key to a raw ObjectId, works for any 4based account.
curl -X GET \
-H "X-API-Key: $CREATOR_API_KEY" \
"https://api.creator-api.com/v1/{account}/native/user/name/{username}"
Ad-partner program
Your partnerships and revenue share
GET /v1/{account}/native/partnerships · 1 credit(s) GET /v1/{account}/native/partnerships/calculate-max-percentage · 1 credit(s)
The second call returns the platform-wide split, e.g. {"owner_percentage":70,"webmaster_share_percentage":10,"webmaster_rev_share_percentage":5}.
Apply, verify or cancel a partnership
POST /v1/{account}/native/partnerships · 2 credit(s) · full scope key GET /v1/{account}/native/partnerships/get-verification-url/{partnershipId} · 1 credit(s) PUT /v1/{account}/native/partnerships/webmaster-cancellation/{partnershipId} · 2 credit(s) · full scope key
Applying is gated to accounts 4based has admitted to its beta for the program; the call is real, expect a 403 until your account is eligible.
Reporting
POST /v1/{account}/native/incident · 2 credit(s) · full scope key POST /v1/{account}/native/file-stack/{fileStackId}/incident · 2 credit(s) · full scope key
Body { "subject": "..." } for both, report a general incident or one specific post.
New-subscriber welcome message
4based has no native equivalent of OnlyFans' welcome-message auto-send, so this is a CreatorAPI-side feature: we store your message and send it ourselves the moment a real new subscription shows up in your activity feed. These three calls are NOT proxied to 4based at all, they talk to CreatorAPI's own storage.
Read, set or clear it
GET /v1/{account}/4based/welcome-message · 1 credit(s) PUT /v1/{account}/4based/welcome-message · 2 credit(s) · full scope key DELETE /v1/{account}/4based/welcome-message · 2 credit(s) · full scope key
Body for PUT: { "text": "Hey! Thanks so much for subscribing 💕", "price": 0, "is_active": true }. price above 0 sends it as a PPV message.
curl -X PUT \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"text":"Hey! Thanks so much for subscribing 💕","is_active":true}' \
"https://api.creator-api.com/v1/{account}/4based/welcome-message"
import os
import requests
CREATOR_API_KEY = os.environ["CREATOR_API_KEY"]
r = requests.put(
"https://api.creator-api.com/v1/{account}/4based/welcome-message",
headers={"X-API-Key": CREATOR_API_KEY},
json={"text": "Hey! Thanks so much for subscribing 💕", "is_active": True},
)
r.raise_for_status()
print(r.json() if r.content else None)
Once set and active, a background job checks your activity feed for new subscriptions and sends it automatically — nothing else to call. Turn is_active off to pause without losing the saved text; delete it entirely to clear it.
Connect a 4based account
The easy way · email and password, no session capture
Unlike OnlyFans and Fansly, 4based's own login is a plain request with no hosted browser needed. Send the creator's 4based email and password once · CreatorAPI exchanges it for a session token in process. By default the password is then discarded, never logged or stored, only the resulting token is kept.
POST /v1/connect/login · full scope key
Body { "platform": "4based", "identifier": "email@example.com", "password": "...", "creator_id": "optional_your_id", "save_password": false }.
If the account has two factor authentication on, this call returns 401 with { "detail": { "code": "2fa_required", "message": "Enter the 6 digit code from your 4based authenticator app" } } instead of a session. Collect the code and call POST /v1/connect/login again with the same body plus "totp_code": "123456" · identifier and password go along again, same round trip 4based's own login page makes.
Optional save_password: true keeps an encrypted copy of the password so the automatic token refresh job can sign back in on your behalf if 4based ever rejects the session, instead of the connection going dark until you manually reconnect. Off by default. If you turn it on, the response includes "password_saved": true. Disconnecting the account (DELETE /v1/accounts/{creator_id}) deletes the stored password immediately, whether or not you ever turned this on.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"platform":"4based","identifier":"creator@example.com","password":"..."}' \
"https://api.creator-api.com/v1/connect/login"
import os
import requests
CREATOR_API_KEY = os.environ["CREATOR_API_KEY"]
r = requests.post(
"https://api.creator-api.com/v1/connect/login",
headers={"X-API-Key": CREATOR_API_KEY},
json={"platform": "4based", "identifier": "creator@example.com", "password": "..."},
)
r.raise_for_status()
print(r.json() if r.content else None)
Advanced · import an already-captured session
If you already have a 4based session token (from your own capture tooling), skip the login call and import it directly. No proxy is required for 4based.
POST /v1/connect/import · full scope key
Body { "creator_id": "your_id", "platform": "4based", "auth": { "token": "...", "resource": "...", "account_id": "..." } }. The three auth fields come from a logged in 4based session. On success the account is verified and attached to your key.
curl -X POST \
-H "X-API-Key: $CREATOR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"creator_id":"my_creator","platform":"4based","auth":{"token":"...","resource":"...","account_id":"..."}}' \
"https://api.creator-api.com/v1/connect/import"
No endpoint matches that filter.