OnlyFans API Documentation
There is no official OnlyFans developer documentation, because there is no official API — the question of what exists is answered on is there an OnlyFans API. What this page documents is the ofapis reference: a single OpenAPI 3.0 document generated from the running service, the interactive reference rendered from it, and the conventions that hold on every route so you do not have to read all of them.
One document, four ways to read it
The spec is generated at runtime by springdoc from the annotations on the live controllers, which is why it cannot drift from deployed behaviour: if a parameter is not in the code, it is not in the document.
| Surface | Where | Use it for |
|---|---|---|
| Interactive reference | ofapis.com/docs |
Reading, searching, trying calls |
| Same-origin JSON | ofapis.com/docs/openapi |
Generators and browser tooling, no CORS, cached an hour |
| Upstream JSON | api.ofapis.com/v3/api-docs/public |
The canonical document, always current |
| Swagger UI | api.ofapis.com/swagger-ui.html |
A second renderer if you prefer it |
All four serve the public group, which matches /api/public/** only. Internal and webhook-receiver paths are deliberately excluded, so what you see in the reference is exactly the surface your token can reach. The document declares a single production server, https://api.ofapis.com, and a single security scheme named ApiToken — HTTP bearer, no scopes, no flows — which is why generated clients expose one credential argument rather than an OAuth configuration object.
How the reference is organised
Operations are grouped by tag: Me, Chats, Users, Subscribers, Following, Vault, Media, Notifications, Mentions, Lists, Scheduled and Mailings. That is the whole public surface; there is no hidden section.
The naming convention is worth learning before you generate a client, because it becomes your method names. Most capabilities appear twice — getChats and getChatsScoped, sendMessage and sendMessageScoped. The plain form is the legacy unscoped route that resolves to your first active linked account; the Scoped suffix is the /accounts/{accountId}/... variant that names a creator explicitly. If you run more than one creator, use the scoped half exclusively.
Account-scoped ids in the reference are ofapis account ids, shown in examples as 42. The spec's text occasionally refers to a GET /accounts listing to find them — that route does not exist in the public surface, and the ids come from your dashboard.
The conventions that hold everywhere
Learn these once and most of the reference becomes skimmable.
dataon success, everywhere. Every successful response is wrapped in{"data": ...}. Failures are less uniform than the reference implies: the gateway's own refusals carry{"error":{"code","message"}}, while errors raised inside a handler come back as a plain string body with no envelope and no code. Code against the status, not against the body shape.- Four errors attached by annotation.
401 UNAUTHENTICATED,402 INSUFFICIENT_CREDITS,403 NO_ACTIVE_SUBSCRIPTIONand429 RATE_LIMIT_EXCEEDEDcome from one shared annotation, so the reference repeats them on every operation. Per-route codes such as413,415or424appear only where they can occur; the catalogue is in error handling. - Rate-limit headers on 200, not just 429.
X-RateLimit-Limit,-Remainingand-Resetare documented on the success response too, because they are present on both. Per-plan ceilings are in rate limits. - Cost is in the prose. Operation descriptions end with a
**Cost:** N credits per callline, and that is the authoritative per-endpoint weight — there is no separate price field in the spec. - Pagination.
limitandoffset, withlimitclamped server-side to 1–100. Defaultlimitis 20, except on the Lists routes where it is 10. Message history is the exception that uses a cursor,olderThanMessageId. - Idempotency. Any
POSTaccepts anIdempotency-Keyheader. It is handled in the gateway rather than per route, so it is not listed in each operation's parameters.
The Mailings tag breaks the pattern: those operations were annotated separately, so they carry their own error list instead of the shared four, no rate-limit headers, and a **Billing:** note on two routes in place of the **Cost:** line. Mailing cost is per recipient, and POST .../mailings/{id}/preview returns recipientCount and estimatedCost before you trigger. Read its description before relying on it: a mailing with listId null — meaning all subscribers — comes back with recipientCount of -1 and estimatedCost of 0, because the audience is only enumerated at trigger time.
Generating a client
The document is a plain OpenAPI 3.0 file, so point a generator at it rather than hand-writing an SDK:
npx @openapitools/openapi-generator-cli generate \
-i https://api.ofapis.com/v3/api-docs/public \
-g typescript-axios \
-o ./ofapis-client
Swap -g for python, go, java, csharp, php, ruby or rust. Methods are named after the operationIds, so getChatsScoped(accountId, limit, offset) is what you call. The Mailings operations declare no operationId, so the generator falls back to a name derived from the method and path — worth checking rather than guessing.
Generating is not the only route, and on a surface this small it is often not the shorter one. The quickstarts hand-roll a thin typed client instead — Go, Java, C#, Ruby, Rust, PHP — which tends to be less work than patching up a generated one, for the reason in the next paragraph.
One caveat will shape how you use the output. On most tags the handler returns the envelope with a loosely typed payload, so the generated model gives you data as an untyped object, and the concrete field names live in each operation's response example rather than in a schema. Mailings is the inverse: those routes declare real response types, so you get proper models for mailings and runs and nothing useful to copy for the rest.
So generate for paths, parameters, auth and error handling, then hand-write the handful of response types you actually consume, reading field names off the examples. Less work than it sounds: every collection read shares the same list / hasMore / nextOffset shape.
Trying calls before writing any
The reference at /docs is a full playground: paste a token, pick an operation, and it executes against your own linked accounts and shows the request as curl alongside the live JSON. It is the fastest way to confirm a payload shape, and the fastest way to discover that a parameter you assumed exists does not.
Two things to keep in mind. Playground calls are real: they are metered at the same weight as any other call, and a send actually delivers a DM to a real person. And the credit is taken before the handler runs, so a malformed body you submit from the browser still costs its weight — the free failures are the ones refused at the gate, not the ones you authored.
Importing it elsewhere
The same URL imports straight into Postman or Insomnia to scaffold a full collection, or into an IDE HTTP client. A ready-made collection is at Postman. Coding assistants can consume the document too: pointing one at the spec, or at the MCP server, gets you calls drafted against real paths instead of invented ones — which matters on an API where a plausible-looking /statistics or /transactions route simply does not exist.
Where the written guides are
The spec tells you what a route accepts; it does not tell you why you would call three of them in order. That is what the prose is for. How the API works traces one request through the gateway end to end, the language quickstarts give you working code starting with Python, and the full index of task guides is at /guides.
FAQ
Where is the OnlyFans API documentation hosted?
The interactive reference is at ofapis.com/docs, rendered from an OpenAPI 3.0 document served at api.ofapis.com/v3/api-docs/public, with a cached same-origin copy at ofapis.com/docs/openapi for tooling. The document is generated from the running service, so it is the authoritative description of the deployed API.
Can I generate an SDK from it?
Yes. Any OpenAPI 3.0 generator works, and method names follow the operationIds in the spec. Generate for paths, parameters, auth and errors; expect to hand-write the few response payload types you consume, because the payload inside the data envelope is typed loosely.
Does the document include endpoints my token cannot call?
No. The published group matches /api/public/** and nothing else, so internal and webhook-receiver paths never appear. If an operation is in the reference, your token can reach it once you have an active plan and a linked account.
Can I run requests without writing code?
Yes, from the playground in the reference with your own token. Treat it as production: calls execute against your linked accounts, are metered at their normal weight, and a message send delivers for real.
Is any of this official OnlyFans documentation?
No. OnlyFans publishes no public API and no developer documentation. This describes the ofapis REST layer, which is an independent product that maintains the integration on your behalf.