OnlyFans + Manus (Autonomous Agents)
Manus works differently from a chat assistant. You give it an objective, it plans a sequence of steps, and it executes them in its own sandbox over minutes or hours — writing files, running Python, making HTTP requests — without coming back to you between every action. Because ofapis is a Bearer-authed REST API with an OpenAPI 3.0 document at https://api.ofapis.com/v3/api-docs/public, nothing has to be installed for this to work. There is no Manus connector for ofapis and none is needed.
What changes is not the wiring. It is that an unsupervised process holding a write-capable key will, at some point, lose its plan halfway through and improvise. The rest of this page is about surviving that.
Getting the API into the sandbox
Three things, and the agent can discover everything else on its own:
- Base URL
https://api.ofapis.com/api/public/v1 - Header
Authorization: Bearer ofapis_sk_..., no signing, no refresh - The spec URL above, which the agent can fetch and read to find parameters and response shapes
Put the token in the sandbox environment, never in the task prompt — a prompt is replayed into context on every planning step and ends up in transcripts you may later share. Issue a token the agent owns outright so you can revoke it without disturbing other automations. Note what that does and does not buy you: a token is scoped to your ofapis user, not to one OnlyFans account, so it gets its own per-minute rate-limit bucket but draws on the same credit balance as everything else. Account isolation has to be enforced in the code the agent calls, by pinning accountId.
Three things that only break on long runs
The agent loses the thread. A plan that spans an hour gets summarised, compacted and re-derived. The step that said "already sent the win-back to list 7" can quietly stop being in context, and the agent re-plans from the objective — which still says to send the win-back.
Work finishes halfway. A sandbox restarts, a step times out, the run is cancelled. A loop that was writing scheduled posts for the week stops after Wednesday, and the next attempt starts at Monday.
Spend is invisible until it isn't. No single call is expensive. Credits are debited before the handler runs, so 400s from a malformed parameter and 404s from a guessed id are charged and never refunded. A loop that fires those for twenty minutes bills the whole time while appearing to do nothing.
A budgeted client, written once
Have the agent build this before it does any real work, then route every call through it. It encodes the three things a long run needs: a hard ceiling, a persistent ledger, and an allowlist the planner cannot argue with.
import json, os, pathlib, time, httpx
BASE = "https://api.ofapis.com/api/public/v1"
LEDGER = pathlib.Path("run-ledger.jsonl")
BUDGET = 400 # credits this run may spend, total
BLOCKED = ("/trigger",) # operator-only: the mailing trigger, never the agent's
FREE = {401, 402, 403, 429} # refused before metering
REFUNDED = {409, 424} # debited, then returned
def _charged(status):
return status not in FREE and status not in REFUNDED and status < 500
def _spent():
if not LEDGER.exists():
return 0
return sum(json.loads(l)["cost"] for l in LEDGER.read_text().splitlines())
def call(method, path, *, weight=1, key=None, **kw):
if any(b in path for b in BLOCKED):
raise PermissionError(f"{path} is operator-only")
if _spent() + weight > BUDGET:
raise RuntimeError(f"budget exhausted at {_spent()}/{BUDGET} — stop and report")
headers = {"Authorization": f"Bearer {os.environ['OFAPIS_TOKEN']}"}
if key:
headers["Idempotency-Key"] = key
r = httpx.request(method, BASE + path, headers=headers, timeout=30, **kw)
with LEDGER.open("a") as f:
f.write(json.dumps({"at": int(time.time()), "path": path, "key": key,
"status": r.status_code,
"cost": weight if _charged(r.status_code) else 0}) + "\n")
if r.status_code == 429:
time.sleep(int(r.headers.get("Retry-After", 5)))
return call(method, path, weight=weight, key=key, **kw)
return r
Pass the real weight, because they are not flat: a media upload is 5 credits, a scheduled post or scheduled message is 3, an account-scoped chat send is 2, everything else is 1. The per-endpoint credit weights are worth copying into the wrapper verbatim, and the pricing page has the plan allowances those spend against.
The 429 branch is free in both senses — rate-limited requests are refused before metering, and the per-minute ceiling (60 on Free, 100 on Starter, 500 on Pro) is the cheapest brake you will ever get on a runaway loop. Let the agent back off against Retry-After rather than engineering around the limit.
Add DRY_RUN=1 handling on the first outing: return the payload each write would have posted, append it to the ledger with cost 0, and read the file yourself before you let the same plan run for real.
Checkpointing and resume
The ledger above is not just accounting — it is the resume log. Two rules make it one.
Derive idempotency keys deterministically from the work, not randomly. winback-2026-03-list7-user90210 is reproducible across a restart; uuid4() is not. Replaying a POST with a key ofapis has already seen returns the original response with Idempotency-Replayed: true and is not charged twice, which turns "did step 14 actually happen?" from a question into a free no-op.
Then make the first action of every resumed run a read of run-ledger.jsonl, and the instruction in the task prompt explicit: reconcile against the ledger before planning; never re-execute a path+key pair that already returned 2xx.
When the agent loses context mid-run
There is one operation where this goes badly, and it is worth keeping out of the sandbox entirely. A mass mailing's duplicate guard only rejects a second trigger while a run is still IN_PROGRESS. Trigger one that already reached COMPLETED and ofapis recounts the audience, debits again and sends again — every fan gets the message twice. An agent that re-derives its plan after compaction is precisely the thing that does this.
So: the agent may draft the copy and build the audience with the subscribers API, and it may read GET /accounts/{id}/mailings/{id}/runs to report whether a run is PENDING, IN_PROGRESS, PAUSED, COMPLETED or FAILED. You press the trigger. The mass DM reference covers the preview-then-trigger flow, and agency automation covers running it across creators.
Everything else splits cleanly. Unattended reads: the notifications feed, chats, subscribers, mentions, scheduled-post counters. Behind approval: single DMs, scheduled content, media uploads. Never: anything that fans out or deletes.
FAQ
Does Manus need a connector or plugin for OnlyFans?
No. The sandbox makes ordinary HTTPS requests, so httpx, requests or curl with a Bearer header is the whole integration. Pointing the agent at the OpenAPI document is optional but worth doing — it lets the agent look up a parameter instead of guessing one and paying for the 404.
How do I stop an overnight run from spending everything?
Give it a hard credit ceiling in the client wrapper, as above, and have it abort rather than degrade when the ceiling is hit. Do not rely on failures being free: 401, 402, 403 and 429 cost nothing and 409, 424 and 5xx are refunded, but 400, 404, 413, 415 and 422 are charged and stay charged. The status-by-status refund table is the authoritative version.
What should the agent do when a step returns 424?
Stop that branch and report. A 424 means the OnlyFans session for the account is expired or the account is not linked, and no amount of retrying inside the sandbox fixes it — someone has to re-link the account. The credit is refunded, so the cost of detecting it is zero; the cost of retrying it in a loop is wasted wall-clock.
Can the agent keep working while a mailing sends?
Yes. The trigger returns immediately with a runId and a creditsDebited figure, and dispatch continues in the background at roughly two messages a second. The agent polls the run record for successCount and skippedCount instead of blocking, and credits for skipped recipients are refunded when the run completes.
Is an autonomous agent a sensible way to run this at all?
For reads, summaries and drafting, yes — that is most of the value and almost none of the risk. For sends, treat the agent as a proposer and yourself as the approver until you have read a few hundred of its transcripts. For the parts of the job that never needed a model — a welcome DM on every new subscriber, a nightly digest — rule-driven automation is cheaper, and it cannot improvise. If you want the comparison with supervised assistants, start at the assistant overview or the MCP reference, and grab a free token to try either.