OnlyFans API Key
OnlyFans does not issue API keys. There is no developer portal to register in, no application record to create, no field in account settings that reveals one, and no support request that produces one — the platform runs no public API programme, so there is nothing for such a key to authenticate against. "How to get an OnlyFans API key" has no answer because the object does not exist.
What exists is a provider token: a credential from a service that holds the creator's session and puts documented REST in front of it. On ofapis it begins ofapis_sk_. The taxonomy of official API, self-run automation and managed-session provider is in is there an OnlyFans API; this page is about the token.
What the token actually is
The raw value is minted once and is never recoverable afterwards:
| Property | Value |
|---|---|
| Prefix | ofapis_sk_, ten characters, constant |
| Random part | 32 bytes from SecureRandom, base64url unpadded — 43 characters, 256 bits |
| Total length | 53 characters, charset A–Z a–z 0–9 - _ |
| Stored as | SHA-256 hex digest, 64 characters, unique across every token |
| Also stored | the raw value's first 12 characters, for display |
| Expiry | none; no expiry field exists |
| Scopes | none; no scope field exists |
A value not beginning with those ten characters is rejected before any work happens — no digest computed, no row read — so a truncated paste or a trailing newline fails as a shape error, not a lookup miss.
That display prefix is a smaller fingerprint than it sounds, because ten of its twelve characters are the constant — your dashboard tells tokens apart by two random characters, so name each after the process holding it, scheduler-prod or support-bot.
The digest is recomputed and looked up on every request with no cache in front of it, which is why a revoked token stops working on the next call rather than when a TTL lapses. Revoking and deleting differ only in what they leave behind: revoking flips a flag, stamps revokedAt and keeps the named row; deleting removes it. Traffic sees the same 401 either way, since the filter cannot tell an unknown digest from a revoked one — so revoke by default.
No scopes, and what that costs you
A verified token resolves to exactly two facts, your user id and the token's own id, plus a single API-client authority. Nothing downstream inspects anything finer, so authorization is binary: a token reaches the whole public surface or nothing. There is no read-only token, no per-account token and no per-endpoint token.
A holder can enumerate your subscribers, read DM history, send messages that cannot be unsent, push media into the vault at five credits a call, and re-trigger a completed mailing — which recounts, debits again and sends again, as mass DM explains. The ceiling is your credit balance and your per-minute limit, nothing else.
Since scopes cannot narrow that, the token id can. Four things key on the token, not the account:
| Keyed per token | What it buys |
|---|---|
| Revocation state | kill one credential and nothing else notices |
| The per-minute counter | a paging job cannot eat a live worker's slots (rate limits) |
The idempotency record, unique on (tokenId, key) |
two services can both use job-1042 without replaying each other |
| The request logging context | every server-side log line carries the token id behind the call |
The last is the quiet one: without it, "which of our six services sent that DM at 03:14" is unanswerable. Not partitioned: the credit balance, the linked accounts, the plan — a second token buys isolation and burst headroom, never volume.
Sending it
The token travels in Authorization on every call. Use -i while wiring up, because the response headers are the diagnostic:
curl -i https://api.ofapis.com/api/public/v1/notifications/count \
-H "Authorization: Bearer $OFAPIS_KEY"
HTTP/1.1 200
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 99
X-RateLimit-Reset: 1764600000
{"data":{"newCount":3}}
Those headers are written after the token resolved and your plan was read, but before any credit is debited — so seeing them proves the credential is live, the subscription active and the call inside its window, for one default-weight read. A replayed POST is the exception: it short-circuits ahead of the limiter, returning Idempotency-Replayed: true and no X-RateLimit-* headers.
Three conditions produce a 401, and only the message separates them: Missing or invalid Authorization header (none, or not Bearer plus something), Invalid token format (present, not prefixed ofapis_sk_), and Invalid or revoked API token (well-formed, no live row — unknown and revoked deliberately conflated). That body comes from the servlet container, not the API's own error envelope, so read it by eye during setup and branch on the status in code; error codes has every shape.
The other secret, which is not a key at all
People arrive looking for one credential and find two. The second is the creator's OnlyFans session — not a key but a bundle of cookies and signing material — and you never touch it. It is held server-side as AES-256-GCM ciphertext under a versioned envelope with a fresh random IV per write, and a value that fails to decrypt raises a hard error rather than quietly falling back to plaintext. The account holder establishes it by signing in through the dashboard, and no public route accepts OnlyFans credentials, so your token cannot attach, read or export one. The side-by-side and the account states are on authentication; linking is covered in how to authenticate an OnlyFans account.
Rotation and revocation as a procedure
Token management sits behind your dashboard login, not behind the token, so rotation is a deploy step and cannot be a cron job. Mint the replacement named for its service, write it to your secret store, roll the service, confirm it is serving with a -i read, then revoke the old one. Both work until you do, so no gap exists where neither does.
Four things break if you rotate carelessly:
Idempotency records do not follow you. A key is unique per (tokenId, key) and lives 24 hours, so a worker retrying job-1042 after the cutover writes into a fresh namespace and the request runs a second time: a second DM, a second debit. Quiesce POST workers across the swap, or accept that window knowingly. Reads are unaffected.
The new token opens an empty bucket. A backlog the old token was being throttled into shape can land all at once in the first minute on the new one.
Revocation does not cancel work in flight. A request already past the filter runs to completion and bills; a mailing already triggered keeps dispatching.
A half-rotated fleet emits 401s the status cannot triage. Match the display prefix's two distinguishing characters against the instances still failing.
Suspect a leak and you revoke first, investigate after — each debit is recorded against a request id, so the damage reconstructs from the per-call weights.
There is no sandbox key
No test-mode credential exists, and it is not an oversight. There is one token type and one credential record with no test flag on it, and a sandbox would have to be a simulated OnlyFans, which nobody is in a position to run. Every call reaches the real account, every DM reaches a real person, everything meters.
So rehearse rather than simulate. Link a throwaway creator account you own, never a client's: the free tier gives 250 credits a month against one account at 60 requests per minute with no card, so start there. Shape the client against default-weight reads first — /me, /chats, /notifications/count — since 250 credits goes far at weight 1 and evaporates at weight 5 on uploads. To test sending, use a second account you control as the fan, because chatId is that fan's OnlyFans user id. Send an Idempotency-Key from the first experiment rather than from production: a re-run curl is the thing that double-sends. The closest available dry run is the mailing /preview step, which returns recipientCount and estimatedCost and sends nothing. Work the walkthroughs on the blog in that order and you will spend under a hundred credits before anything touches a paying fan.
FAQ
Where do I get an OnlyFans API key?
Not from OnlyFans — it issues none, and no page, form or support channel produces one. You get a token from a provider that holds the creator's session; on ofapis you create it in the dashboard, and the raw value is shown exactly once.
How long is an ofapis API key and what characters can it contain?
53 characters: the fixed ofapis_sk_ prefix plus 43 characters of base64url randomness from 32 secure random bytes. That alphabet includes hyphen and underscore, so a pattern like ^ofapis_sk_[A-Za-z0-9]+$ rejects valid tokens.
Can I create a read-only API key?
No. The token carries no scopes, so it resolves to your user and reaches every public endpoint and every linked account. One token per service plus discipline about which endpoints each calls is the closest approximation, and it limits blame and throttling rather than reach.
Does an OnlyFans API key expire?
Not on ofapis. No expiry field exists on the record, so a token stays valid until you revoke or delete it. Rotation is entirely your schedule to set — which means a key pasted into a repository three years ago is still live unless somebody noticed.
Can I put the token in a browser or mobile app?
No. Anyone who extracts it gets everything your account can do, and shipped client code leaks eventually. Cross-origin calls are restricted to the ofapis documentation origins anyway, so a request from your own front-end fails preflight before it is authenticated.