How to Send OnlyFans Messages With an API
This guide shows how to send OnlyFans messages via the API — from token to delivered — in three steps with ofapis.
Step 1 — Get a token
Create an ofapis_sk_... token in the dashboard (start free) and keep it server-side. See authentication for how tokens map to your connected account.
Step 2 — Find the chat
Every message goes to a chatId. List chats to find the fan you want, filtering or paging as needed:
curl "https://api.ofapis.com/api/public/v1/chats?limit=50" \
-H "Authorization: Bearer ofapis_sk_..."
Response (truncated):
{
"data": {
"list": [
{ "withUser": { "id": 98765, "name": "Jane", "username": "fan_jane" }, "unreadMessagesCount": 2, "canSendMessage": true, "lastMessage": { "text": "Hey!", "createdAt": "2026-07-19T12:00:00+00:00" } }
],
"hasMore": false,
"nextOffset": 0
}
}
The conversation is keyed by withUser.id — use it as the chatId when you send.
Step 3 — Send the message
POST the text to /chats/{chatId}/messages:
curl -X POST https://api.ofapis.com/api/public/v1/chats/123/messages \
-H "Authorization: Bearer ofapis_sk_..." \
-H "Content-Type: application/json" \
-d '{"text":"Thanks for subscribing!"}'
A 200 means delivered and one credit spent; failures are not charged. Response:
{ "data": { "id": 444555666, "text": "Thanks for subscribing!", "createdAt": "2026-07-21T09:30:00+00:00", "isFree": true, "price": 0, "fromUser": { "id": 12345678, "username": "creator_handle", "name": "Creator" } } }
In Python:
import requests
r = requests.post(
"https://api.ofapis.com/api/public/v1/chats/123/messages",
headers={"Authorization": "Bearer ofapis_sk_..."},
json={"text": "Thanks for subscribing!"},
)
print(r.status_code, r.json()["data"]["id"])
In Node:
const r = await fetch("https://api.ofapis.com/api/public/v1/chats/123/messages", {
method: "POST",
headers: {
Authorization: "Bearer ofapis_sk_...",
"Content-Type": "application/json",
},
body: JSON.stringify({ text: "Thanks for subscribing!" }),
});
console.log(r.status, (await r.json()).data.id);
Attach media or set a price
Include mediaFiles (vault media ids) from your vault, and add price in cents to send it as pay-to-unlock:
{ "text": "New set 👀", "mediaFiles": [777888999], "price": 1500 }
Common errors
| Status | Meaning | Fix |
|---|---|---|
401 |
Missing or revoked token | Reissue the key in the dashboard |
404 |
Unknown chatId |
Re-list chats; the fan may have unsubscribed |
422 |
Empty body with no text or media | Send at least text or one mediaFiles id |
429 |
Rate limit hit | Back off; see rpm on pricing |
Sending to many fans
Don't loop over chats for a broadcast — that burns credits and rate limit. Use the mass DM API, which sends to a whole segment in one call with a cost preview.
FAQ
How much does sending a message cost?
One credit per successful send. Failed calls (revoked session, upstream error) are not charged. See pricing for plan credit allowances.
Can I send images or pay-to-unlock messages?
Yes. Upload files to the vault, then pass their ids as mediaFiles. Add a price field (in cents) to make the message pay-to-unlock.
How do I message every subscriber at once?
Use the mass DM endpoint against a segment rather than looping over individual chats. It sends in a single call and previews the cost first.
Why did my message fail with a 404?
The chatId no longer exists — usually the fan unsubscribed or blocked the account. Re-fetch the chat list and skip stale ids.