FAQ
Bans, proxies, quotas, Fansly support, and switching from another provider.
The risk is real and it comes almost entirely from request pacing, not from the API itself. We keep sessions stable, sign requests with the current algorithm, and route each account through the proxy you supplied — the things that get accounts flagged when done wrong. (If you supply no proxy, traffic egresses on our server IP; see below.)
What is left to you: pace your live calls. As a reference point, our own background poller runs at roughly 3–5 requests per two minutes per account, and internal sweeps self-throttle to about 1 req/s — that is the shape of traffic the platforms are comfortable with.
The cached routes cost zero platform requests, so read from those and refresh them on a schedule rather than polling live endpoints in a loop.
See Rate limits & quotas.
For OnlyFans, in practice yes — but it is not enforced. Omit it and the session
is created from our server's IP and pinned there, which is what gets accounts flagged
later. A malformed X-Proxy is silently ignored rather than rejected, so a typo
degrades to direct egress without any error.
Use one sticky residential or ISP proxy per account, and keep the exit location stable. Rotating proxies defeat the purpose. See Proxies.
Only requests that actually reach the platform: live reads, refreshes, backfills,
payout calls and every /api2/v2/* call — about 30 of ~145 routes. Cached reads, async-job status polls and background polling are free, in quota as well as in
platform requests.
GET /health and GET /events/stream are also exempt from the per-minute limit.
Check consumption at GET /api/crm/{crm_id}/usage; api_calls_limit: -1 means
unlimited.
The normalized CRM routes are Fansly-aware and return the same shapes for both
platforms. Not supported for Fansly: the /api2/v2/* passthrough (OnlyFans-only by
definition), payout requests, campaign claimers, mass DM, campaign creation,
subscription-price updates, PPV stats, the three referrals routes, and real-time
WebSocket (Fansly is polling-only). Most return 501 with
code: "platform_not_supported" plus platform and feature.
Full matrix in OnlyFans & Fansly.
You are not talking to the API. _notice comes from our honeypot layer on decoy paths — most commonly https://theonlyapi.com/api/health, which is bait and
returns fabricated data. The selection is by path, not by whether you authenticated.
Real API paths are panel-scoped: https://theonlyapi.com/api/crm/{crm_id}/…. A
missing or wrong key there returns a plain 401/403 JSON error with no _notice.
Details in Responses & errors.
It does not. There is no User-Agent check anywhere on the API — a curl request and
a browser-UA request get byte-identical responses, and -A "Mozilla/5.0" changes
nothing. If you are seeing decoy data, you are on a decoy path (see the previous
answer).
OnlyFans write operations are gated per account, off by default:
curl -X PATCH "$BASE/api/crm/$CRM/accounts/$OFUID/polling" \
-H "X-API-Key: $KEY" -H "Content-Type: application/json" \
-d '{"allow_of_write_actions": true}'The gate now covers every OnlyFans or Fansly write performed as the account:
single DM/PPV sends (both platforms), the mass-DM real send, the send_dm
automation action, payout requests, subscription-price changes, the raw
POST /accounts/{of_user_id}/request proxy, and any non-GET request through the /api2/v2/* passthrough. Reads are never gated.
Match on code: "WRITES_DISABLED" rather than the message text.
Almost certainly the pagination quirks. /chats ignores limit and returns 10–14
conversations regardless, and a short page from /messages does not mean the end
of the conversation.
Note the CRM /messages route is offset-paged; the id= cursor works only on the
/api2/v2/chats/{fan_id}/messages passthrough, which is the reliable way to walk a
full history. See Pagination.
Two likely causes. You are summing amount (the gross the fan paid) instead of
net (what the creator received) — that inflates the total by roughly 1.25x. And you
are counting chargebacks: a reversal is the original row relabelled to
status: "undo" / tx_type: "chargeback" with the amount still positive.
For period revenue, exclude chargeback rows — a naive sum overstates by one chargeback, and subtracting double-counts the reversal. For per-fan lifetime spend, subtract them. See the chargeback trap.
First check status — a webhook on an unapproved domain is pending and delivers
nothing at all. Otherwise: five consecutive failed deliveries (each an exhausted
retry ladder) deactivates it until you re-enable it with PATCH /webhooks/{id} and
{"is_active": true}. Check
GET /webhooks/{id}/deliveries for the failures, fix the endpoint, re-enable, then
backfill the gap from GET /events?since=….
See Webhooks.
The session probably died. After five consecutive failures, polling for that
account is paused and a polling_paused event is emitted. Reconnecting clears the
session block but not the pause — re-enable polling explicitly with
PATCH /accounts/{of_user_id}/polling and {"enabled": true}.
Set up a polling_paused automation so you hear about this
before your users do. See Sessions & re-login.
Not with your API key. A key grants full access to the panel, so it must never reach client-side JavaScript — a browser cannot keep a secret.
Cross-origin requests to /api/* are restricted to an allowlist, so a page on
another domain cannot read your panel even if it has a key.
Proxy through your own backend and attach the key server-side. For live events this
is required regardless, because the browser EventSource API cannot set headers —
there is a worked example in Server-sent events.
Not yet. The API is plain REST with a single header, and there is an OpenAPI 3.1 spec you can point a generator at.
For AI-assisted work, the MCP server is usually faster than generating a client.
Three differences to plan for:
- Panel-scoped paths. Every route carries your
crm_id:https://theonlyapi.com/api/crm/{crm_id}/…. Seven unscoped routes are the exception, and they live onapi.theonlyapi.com— see Base URL & panels. - Two surfaces. Providers that only proxy OnlyFans map onto our
/api2/v2/*passthrough. The normalized CRM layer — cached reads, aggregations, events, exports — has no equivalent and is where the value is. See The two surfaces. - Slot pricing, not per-call metering. Paid plans have unlimited API calls; you pay per connected account. So caching is about protecting the platform's limits, not your bill.
Sessions do not transfer. Reconnect each account with session paste — it takes about a minute per account.
Contact us. For a 500, include the
correlation_id from the response body — it maps to the full server-side
traceback, which is deliberately not returned to callers.