API — Fansly sync
The endpoint family the Fansly collection engine itself calls to accept work, claim and report on sync segments, and prove session liveness. Not called by the panel, the extension, or Tease Browser.
These are server-to-server endpoints for the Fansly collection engine, not
client endpoints. Auth is a service signature (X-Engine-Signature
header, verified against a shared service secret via
authorize_engine_service_request) — not a device proof and not a bearer
connect token, both used elsewhere in this API. A bad or missing signature
returns 401 engine_unauthorized.
Mount point is conditional and non-obvious
This router only exists when settings.fansly_engine_enabled is true. It is
built by build_fansly_engine_sync_router() and appended to the router list
inside browser_native_composition.py:361-373 — there is no
include_router(fansly_engine_sync...) call anywhere by that name; the
mount is three hops deep (app/main.py:127 → compose_browser_native →
the conditional append → main.py:129-130's generic loop). Grepping for the
router variable name will not find the mount point — trace the call chain
instead.
All paths below are relative to the router's own prefix:
/api/platform-engine/v1/fansly (fansly_engine_sync.py:207).
A parallel surface, not the desktop one
/api/browser-runtime/v1/sync/* (documented on API — Browser
runtime) uses the same segment
vocabulary — claim, renew, release, permit, result, outcome — for the
desktop app's view of sync. This page is the same vocabulary for the
engine's view, under a completely different prefix and a completely
different auth mechanism. They are not aliases of each other.
Commands and segments
| Endpoint | Purpose |
|---|---|
POST /sync/commands/accept | Engine accepts a dispatched sync command. |
POST /sync/segments/claim | Claims a page/segment of work. |
POST /sync/segments/renew | Renews a claim before it expires. |
POST /sync/segments/release | Releases a claim without completing it. |
POST /sync/segments/permit | Requests the request-governor permit for a segment. |
POST /sync/segments/result | Reports the result of a completed segment. |
POST /sync/segments/outcome | Reports the final outcome for a segment. |
A conflicting or busy claim returns 409 engine_sync_conflict (retryable
conditions are signaled the same way — the engine is expected to back off and
retry, not treat every 409 as terminal). A lock-contention timeout on the
underlying receipt table also surfaces as 409, not a raw 500.
Response version field is deliberately rewritten
Response bodies are built by the same projection code as the desktop
transport, which stamps version: "browser-platform-sync-v1". This router
rewrites that field to "fansly-engine-sync-v1" (ENGINE_SYNC_VERSION)
before returning. The gateway checks this field strictly — losing the
rewrite once made every response product_sync_response_invalid and
silently stopped all collection (permits were granted, zero pages
collected). If you see that error, this is the first thing to check.
Session liveness
POST /sync/session/liveness — the engine reports whether the platform
account's session is still usable: platform_account_id,
credential_generation, a verdict, reason, and the previous_verdict.
This is the authoritative signal behind "connected in the database" versus
"actually collecting" — see
Troubleshooting.
Raw evidence reconciliation
POST /sync/raw/reconcile — reconciles a batch of raw response entries
against the durable raw object store (sync_raw_object_store.py +
platform_sync_raw_snapshots). See
Connections for who else reads that
store.
What's next
For the desktop app's own, differently-authenticated sync surface, see API — Browser runtime.
API — Native login
How the desktop app pairs a device and gets a token — an OAuth-authorization-code-and-PKCE-shaped flow with a device signature bolted on, plus its own in-app consent screen and lost-device recovery.
API — Attached reconnect
Recovering a platform account from a session already attached and live in the browser, instead of a fresh login — begin, discover, prepare, finalize, status, cancel.