ofapisv1
guide

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.

Next steps

Related guides

All guides
Start free — 250 credits, no card
Generate a token and make your first call in minutes.
Get started