ofapisv1
quickstart

OnlyFans API with curl

ofapis is a plain REST API with Bearer auth, so calling the OnlyFans API with curl is the fastest way to try it — no SDK, no code. These examples pipe responses through jq to pull out fields. Every request goes to https://api.ofapis.com/api/public/v1.

ofapis is an independent, unofficial API for OnlyFans, not affiliated with OnlyFans. Accounts are connected once in the dashboard and the session stays alive server-side, so on the command line you only ever pass your ofapis_sk_... token.

1. Set up

Create a key in the dashboard (start free), then export it and the base URL so the snippets below stay short. Keep the token out of your shell history — a leading space or a secrets manager helps. See authentication.

export OFAPIS_KEY=ofapis_sk_...
export BASE=https://api.ofapis.com/api/public/v1

2. Verify the token — GET /me

-s silences the progress meter, -f makes curl exit non-zero on HTTP errors so a bad token fails your script:

curl -sf "$BASE/me" \
  -H "Authorization: Bearer $OFAPIS_KEY" | jq '.username'

3. List chats

curl -sf "$BASE/chats?limit=50" \
  -H "Authorization: Bearer $OFAPIS_KEY" | jq -r '.data[].id'

jq -r '.data[].id' prints one chat id per line (raw, unquoted) — handy for piping into a loop.

4. Send a message

curl -sf -X POST "$BASE/chats/123/messages" \
  -H "Authorization: Bearer $OFAPIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Thanks for subscribing!"}'

A 200 means delivered and one credit spent. Failed calls — an expired session, a 429, or an upstream 5xx — are never charged, so a retry after failure is free.

5. Handle errors explicitly

-f hides the response body on failure, which makes debugging hard. To branch on the status code instead, capture the HTTP code separately with -w:

code=$(curl -s -o /tmp/out.json -w '%{http_code}' \
  -X POST "$BASE/chats/123/messages" \
  -H "Authorization: Bearer $OFAPIS_KEY" \
  -H "Content-Type: application/json" \
  -d '{"text":"Hi!"}')

case "$code" in
  200) echo "delivered — 1 credit spent" ;;
  401) echo "bad or revoked token"; jq . /tmp/out.json ;;
  429) echo "rate limited — back off and retry" ;;
  *)   echo "send failed: $code"; jq . /tmp/out.json ;;
esac

Fan out with jq

Combine the two calls to message everyone in a list — jq extracts the ids, the shell loops:

for id in $(curl -sf "$BASE/chats?limit=100" \
              -H "Authorization: Bearer $OFAPIS_KEY" | jq -r '.data[].id'); do
  curl -sf -X POST "$BASE/chats/$id/messages" \
    -H "Authorization: Bearer $OFAPIS_KEY" \
    -H "Content-Type: application/json" \
    -d '{"text":"New drop is live!"}'
done

For real mass sends prefer the mass DM API, which batches server-side and respects your plan's rate limit.

Agencies: scope by account

Managing several creators? Address each by id under scoped routes, e.g. curl -sf "$BASE/accounts/42/chats" -H "Authorization: Bearer $OFAPIS_KEY". See agency automation.

FAQ

How do I pass the Bearer token with curl?

Add an Authorization header: -H "Authorization: Bearer $OFAPIS_KEY". Store the token in an environment variable so it never lands in your shell history or scripts.

How do I see the HTTP status code in curl?

Use -w '%{http_code}' and send the body to a file with -o, or add -i to print response headers. Combine with -f if you just want curl to exit non-zero on any 4xx/5xx.

Does a failed curl request cost a credit?

No. Billing is metered per successful call: one 2xx equals one credit. 401s, 429s and upstream 5xx responses are not charged.

Why use jq with the OnlyFans API?

Responses are JSON, and jq lets you extract fields (.data[].id), filter, and reshape output right in the pipeline — no scripting language needed for quick tasks.

Next steps

Related: Postman

Related guides

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