Developer guide
Integrations
Read stored OnlyFans, MYM and Fanvue data through one project-scoped API. All eight routes below are GET-only. Access depends on current feature eligibility and the explicit integrations.read scope. Existing keys gain no scopes automatically. This reference describes the implemented contract; it does not establish deployment or live account access.
Start here
- Create or edit a project API key in the dashboard and explicitly grant integrations.read.
- List connections and follow pagination.next_cursor.
- Inspect available_data, then read tracking-links, metrics, account, statements or fan-health using the returned connection ID.
- Retain source freshness, currency, actual range and coverage with every number.
See MCP for the equivalent assistant workflow. The separate partner API at /api/partner/v1 has its own daily-statistics contract; do not use partner keys or partner account IDs here.
Freshness and permissions
freshness.last_synced_at is the last successful source pull. observed_at only says when this response was served. A recent failed attempt does not refresh data. next_sync_at is scheduled, not guaranteed completion. Data may end at the stored watermark rather than today. available_data describes provider support, not imported data or permission to see money. Missing, disconnected or foreign connections are refused without revealing their existence. Revenue restrictions remain authoritative; never reconstruct hidden revenue from counters. Credentials, proxy details, account email, fan identities and raw worker errors are excluded.
Common money reading
Every tracking row adds revenue_reading, the common money field across
OnlyFans, MYM and Fanvue. Existing fields remain compatible:
amount,currency: the stored reading in its original currency; no conversion or cross-currency sum. Zero is a measurement; unknown/pending amounts are null.basis:ledger(attributed payments),counter(platform readings), or null when no authorized money reading is available.scope:window,lifetimefor a platform counter, orstored_historyfor the ledger under the lifetime selector. OnlyFans' stored history must never be presented as the platform's lifetime revenue.range: the requested window's dates, null for lifetime/stored-history scope.status:available,pending,unavailable;reasonpreserves the mapping reason or saysawaiting_readings/not_available.floor: null without an amount, true for a recovering map or a counter whose first reading is after the requested start. Other source limitations remain in the surrounding response; false is not a claim of independently audited income.
The response also preserves revenue.since (connection/tracking dates), row
net_since_connection / net_since_tracking, attribution checks, Fanvue
sources and fan_join, and the dated subscriber_split. These are imported
facts; no provider request or new attribution calculation happens on read.
Assistant tracking-link pages are ordered by record_id and may shrink to fit
the response budget. Follow page.next_offset, never offset + limit.
page.total counts the source reading, and totals/caveats stay intact on every
page. This is not a snapshot across sync runs: restart pagination if
connection.freshness.last_synced_at changes. Statements keep a fixed page size;
a response too large to preserve intact is refused with 413. Reduce limit
and restart statement pagination at page 0, or use REST. Fan health likewise
asks for fewer weeks rather than silently discarding weeks.
Two pagination layers
REST connection lists use pagination.next_cursor -> cursor; MCP uses next_after -> after. Tracking-link source coverage is independent of assistant paging: sources without history retain a 300-record cap disclosed by coverage.has_more. MCP page.next_offset only pages through the returned source reading and can advance by less than the requested limit. Finishing those pages does not retrieve capped-out records; REST uses the same source cap. Never add repeated totals. Restart if last_synced_at changes during paging. Statements keep a fixed page size and advance page.index + 1; totals cover the entire filter.
OnlyFans attribution boundary
OnlyFans joins stored subscriber mappings and transactions; it does not publish native per-link revenue counters. Mapping starts at a fixed connection-relative boundary; older stored mappings can survive. A settled map is not proof of complete historical attribution. Preserve revenue.since and reconciliation. MYM/Fanvue use imported counter differences; the first reading is a baseline, and a first reading after the reporting start makes revenue a floor. Compare only matching currencies, scopes, date ranges and bases.
Current cadence and remaining work
| Policy | Base interval | Additional jitter | Minimum private interval |
|---|---|---|---|
| OnlyFans | 10h | Up to 1.5h | 6h |
| MYM | 12h | None | 12h (operational attempt floor) |
| Fanvue | 2h; 1h on Agency | None | 1h |
Partner stats_daily (OnlyFans/MYM) | 24h | Up to 2h | Provider floor; profile restrictions remain |
Fanvue counters have a separate 6h clock, increased if the resolved refresh
interval is slower. Cadence is scheduling policy, not a completion SLA.
next_sync_at is scheduled; failures, cooldowns, leases and processing can delay
completion. Expired or invalid private grants resolve to ordinary policy.
Default service has not been moved to 24h globally.
Private access never adds datasets or revenue permission. The admin writer, audit/concurrency workflow and grant/revoke UI remain unfinished; no REST/MCP tool provisions private offers. Fanvue serializers do not consistently receive the current project plan, although scheduling does: do not infer the paid tier from the reported interval or promise hourly service from it.
Access and size troubleshooting
- Missing tool or 403: check explicit
integrations.read, current feature eligibility, project membership, account rights and disconnected state.integrations.managealone does not grant reads. A refusal is not evidence that the provider lacks revenue support. - Authorized connection but 404 resource: inspect
available_databefore retrying. A provider may not support that record type. - 400: correct IDs, windows, date ranges or unsupported/duplicate arguments.
- MCP 413: reduce statement
limitand restart at page 0, reduce fan-healthweeks, or use REST for an oversized tracking reading. A single oversized tracking row cannot be repaired by requesting fewer rows. - Metrics
transport_limited: daily/breakdown rows were omitted to fit; totals still cover the returned range. Narrowdays,toporbreakdowns, or use REST. Do not recompute totals from partial arrays. - 429: respect the retry delay. An uncertain management response calls for a status read before retrying; reading stale data never authorizes a sync.