Build an OnlyFans Scheduling Tool
A scheduling tool is a two-queue system. Your app holds the draft queue — the content calendar your team edits — and OnlyFans holds the live queue of items waiting to fire. ofapis is the bridge: you push confirmed items to the live queue with a future timestamp, and pull the counters back to keep your calendar in sync. This is the build; for the raw endpoint surface see the scheduling API reference.
Architecture
Calendar UI → your job store (draft) → worker → ofapis scheduled/* (live on OF)
↑ │
└──────── counters / list sync ──────────┘
Keep your store as the editable source of truth and treat the OnlyFans queue as commit-only: once an item is confirmed, the worker pushes it and records the returned id. That separation lets creators drag things around in your UI without touching OnlyFans until the plan is final.
Push to the live queue
The worker templates each confirmed slot into a scoped create call:
curl -X POST \
https://api.ofapis.com/api/public/v1/accounts/42/scheduled/posts \
-H "Authorization: Bearer ofapis_sk_..." \
-H "Content-Type: application/json" \
-d '{"mediaFiles":[88123],"scheduledAt":"2026-08-14T18:00:00Z"}'
Two rules the worker must enforce:
- Always send
scheduledAtin UTC (Z). Convert from the creator's local timezone in your app; a timezone-naive string is ambiguous and rejected. Store the original local time and the UTC value so the calendar renders correctly wherever it's viewed. - Persist the returned id. You need the
postId(orqueueIdfor messages) to cancel or reschedule later.
Messages queue the same way via POST /accounts/{id}/scheduled/messages, so one worker drives both a feed calendar and a DM calendar.
Reschedule and cancel
There is no in-place edit. A reschedule is a delete-then-create, which keeps your state authoritative:
curl -X DELETE \
https://api.ofapis.com/api/public/v1/accounts/42/scheduled/posts/{postId} \
-H "Authorization: Bearer ofapis_sk_..."
# then POST a new item with the updated scheduledAt
Drive a calendar badge from GET /accounts/{id}/scheduled/posts/counters — poll the cheap counter and only pull the full list when the number moves. Because failed calls aren't billed, a worker that retries a rejected timestamp or an expired session never runs up credit cost.
Build outline
- Model a
slotstable:account_id, local time, UTC time, payload,remote_id,status. - Upload assets first through the vault media API, then reference them at schedule time.
- On confirm, worker POSTs the item and writes back
remote_id+status=queued. - On edit, DELETE the
remote_idand re-POST; on cancel, DELETE and markstatus=cancelled. - Reconcile nightly against the counters so your calendar never drifts from the live queue.
For a multi-creator calendar, scope every call by accountId — one tool, a whole roster, one token.
FAQ
Can I schedule both posts and messages?
Yes. Posts and messages have separate create endpoints (/scheduled/posts and /scheduled/messages), so a single tool can run an independent feed calendar and DM calendar per creator.
How should the tool handle timezones?
Convert the creator's local time to UTC and send scheduledAt with a trailing Z. Store both the local and UTC values so the calendar displays correctly while the API always receives an unambiguous instant.
How do I let users reschedule a post?
Delete the queued item by its postId and create a new one with the updated time — there is no in-place edit. Both calls are cheap, so a drag-to-reschedule interaction is just a delete plus a create under the hood.
What does scheduling cost?
One credit per successful create, and reading the queue or counters is one credit per call. Failed calls — a rejected timestamp or expired session — are never billed. See pricing for plan limits.
Start building: get a free token, follow the scheduling guide, and wire it into a job runner with the Node quickstart.